1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - 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 <bluetooth/log.h>
19 #include <com_android_bluetooth_flags.h>
20 #include <flag_macros.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24
25 #include <chrono>
26
27 #include "bta/csis/csis_types.h"
28 #include "bta_gatt_api_mock.h"
29 #include "bta_gatt_queue_mock.h"
30 #include "bta_groups.h"
31 #include "bta_le_audio_api.h"
32 #include "bta_le_audio_broadcaster_api.h"
33 #include "btif_storage_mock.h"
34 #include "btm_api_mock.h"
35 #include "btm_iso_api.h"
36 #include "common/message_loop_thread.h"
37 #include "fake_osi.h"
38 #include "gatt/database_builder.h"
39 #include "gmock/gmock.h"
40 #include "hardware/bt_gatt_types.h"
41 #include "hci/controller_interface_mock.h"
42 #include "internal_include/stack_config.h"
43 #include "le_audio/codec_manager.h"
44 #include "le_audio_health_status.h"
45 #include "le_audio_set_configuration_provider.h"
46 #include "le_audio_types.h"
47 #include "mock_codec_manager.h"
48 #include "mock_csis_client.h"
49 #include "mock_device_groups.h"
50 #include "mock_state_machine.h"
51 #include "test/common/mock_functions.h"
52 #include "test/mock/mock_main_shim_entry.h"
53 #include "test/mock/mock_stack_btm_iso.h"
54
55 #define TEST_BT com::android::bluetooth::flags
56
57 using testing::_;
58 using testing::AnyNumber;
59 using testing::AtLeast;
60 using testing::AtMost;
61 using testing::DoAll;
62 using testing::Expectation;
63 using testing::InSequence;
64 using testing::Invoke;
65 using testing::Matcher;
66 using testing::Mock;
67 using testing::MockFunction;
68 using testing::NiceMock;
69 using testing::NotNull;
70 using testing::Return;
71 using testing::SaveArg;
72 using testing::SetArgPointee;
73 using testing::Test;
74 using testing::WithArg;
75
76 using bluetooth::Uuid;
77
78 using namespace bluetooth::le_audio;
79
80 using bluetooth::le_audio::LeAudioCodecConfiguration;
81 using bluetooth::le_audio::LeAudioDeviceGroup;
82 using bluetooth::le_audio::LeAudioHealthStatus;
83 using bluetooth::le_audio::LeAudioSinkAudioHalClient;
84 using bluetooth::le_audio::LeAudioSourceAudioHalClient;
85
86 using bluetooth::le_audio::DsaMode;
87 using bluetooth::le_audio::DsaModes;
88 using bluetooth::le_audio::types::AudioContexts;
89 using bluetooth::le_audio::types::BidirectionalPair;
90 using bluetooth::le_audio::types::LeAudioContextType;
91
92 extern struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_;
93
94 constexpr int max_num_of_ases = 5;
95 constexpr bluetooth::le_audio::types::LeAudioContextType
96 kLeAudioDefaultConfigurationContext =
97 bluetooth::le_audio::types::LeAudioContextType::UNSPECIFIED;
98
99 static constexpr char kNotifyUpperLayerAboutGroupBeingInIdleDuringCall[] =
100 "persist.bluetooth.leaudio.notify.idle.during.call";
101 const char* test_flags[] = {
102 "INIT_default_log_level_str=LOG_VERBOSE",
103 "INIT_leaudio_targeted_announcement_reconnection_mode=true",
104 "INIT_leaudio_enable_health_based_actions=false",
105 "INIT_leaudio_broadcast_audio_handover_policies=false",
106 nullptr,
107 };
108
109 const char* test_flags_with_health_status[] = {
110 "INIT_default_log_level_str=LOG_VERBOSE",
111 "INIT_leaudio_targeted_announcement_reconnection_mode=true",
112 "INIT_leaudio_enable_health_based_actions=true",
113 "INIT_leaudio_broadcast_audio_handover_policies=false",
114 nullptr,
115 };
116
117 const char* test_flags_with_handover_mode[] = {
118 "INIT_default_log_level_str=LOG_VERBOSE",
119 "INIT_leaudio_targeted_announcement_reconnection_mode=true",
120 "INIT_leaudio_enable_health_based_actions=false",
121 "INIT_leaudio_broadcast_audio_handover_policies=true",
122 nullptr,
123 };
124
125 void osi_property_set_bool(const char* key, bool value);
126
127 // Disables most likely false-positives from base::SplitString()
__asan_default_options()128 extern "C" const char* __asan_default_options() {
129 return "detect_container_overflow=0";
130 }
131
132 std::atomic<int> num_async_tasks;
133 static base::MessageLoop* message_loop_;
134 bluetooth::common::MessageLoopThread message_loop_thread("test message loop");
get_main_thread()135 bluetooth::common::MessageLoopThread* get_main_thread() {
136 return &message_loop_thread;
137 }
138
do_in_main_thread(const base::Location & from_here,base::OnceClosure task)139 bt_status_t do_in_main_thread(const base::Location& from_here,
140 base::OnceClosure task) {
141 if (!message_loop_) return BT_STATUS_FAIL;
142
143 // Wrap the task with task counter so we could later know if there are
144 // any callbacks scheduled and we should wait before performing some actions
145 if (!message_loop_thread.DoInThread(
146 from_here,
147 base::BindOnce(
148 [](base::OnceClosure task, std::atomic<int>& num_async_tasks) {
149 std::move(task).Run();
150 num_async_tasks--;
151 },
152 std::move(task), std::ref(num_async_tasks)))) {
153 bluetooth::log::error("failed from {}", from_here.ToString());
154 return BT_STATUS_FAIL;
155 }
156 num_async_tasks++;
157 return BT_STATUS_SUCCESS;
158 }
159
do_in_main_thread_delayed(const base::Location & from_here,base::OnceClosure task,std::chrono::microseconds delay)160 bt_status_t do_in_main_thread_delayed(const base::Location& from_here,
161 base::OnceClosure task,
162 std::chrono::microseconds delay) {
163 /* For testing purpose it is ok to just skip delay */
164 return do_in_main_thread(from_here, std::move(task));
165 }
166
get_main_message_loop()167 base::MessageLoop* get_main_message_loop() { return message_loop_; }
168
init_message_loop_thread()169 static void init_message_loop_thread() {
170 num_async_tasks = 0;
171 message_loop_thread.StartUp();
172 if (!message_loop_thread.IsRunning()) {
173 FAIL() << "unable to create message loop thread.";
174 }
175
176 if (!message_loop_thread.EnableRealTimeScheduling())
177 bluetooth::log::error("Unable to set real time scheduling");
178
179 message_loop_ = message_loop_thread.message_loop();
180 if (message_loop_ == nullptr) FAIL() << "unable to get message loop.";
181 }
182
cleanup_message_loop_thread()183 static void cleanup_message_loop_thread() {
184 message_loop_ = nullptr;
185 message_loop_thread.ShutDown();
186 }
187
invoke_switch_codec_cb(bool is_low_latency_buffer_size)188 void invoke_switch_codec_cb(bool is_low_latency_buffer_size) {}
invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size)189 void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) {}
190
191 const std::string kSmpOptions("mock smp options");
get_pts_avrcp_test(void)192 bool get_pts_avrcp_test(void) { return false; }
get_pts_secure_only_mode(void)193 bool get_pts_secure_only_mode(void) { return false; }
get_pts_conn_updates_disabled(void)194 bool get_pts_conn_updates_disabled(void) { return false; }
get_pts_crosskey_sdp_disable(void)195 bool get_pts_crosskey_sdp_disable(void) { return false; }
get_pts_smp_options(void)196 const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
get_pts_smp_failure_case(void)197 int get_pts_smp_failure_case(void) { return 123; }
get_pts_force_eatt_for_notifications(void)198 bool get_pts_force_eatt_for_notifications(void) { return false; }
get_pts_connect_eatt_unconditionally(void)199 bool get_pts_connect_eatt_unconditionally(void) { return false; }
get_pts_connect_eatt_before_encryption(void)200 bool get_pts_connect_eatt_before_encryption(void) { return false; }
get_pts_unencrypt_broadcast(void)201 bool get_pts_unencrypt_broadcast(void) { return false; }
get_pts_eatt_peripheral_collision_support(void)202 bool get_pts_eatt_peripheral_collision_support(void) { return false; }
get_pts_force_le_audio_multiple_contexts_metadata(void)203 bool get_pts_force_le_audio_multiple_contexts_metadata(void) { return false; }
get_pts_le_audio_disable_ases_before_stopping(void)204 bool get_pts_le_audio_disable_ases_before_stopping(void) { return false; }
get_all(void)205 config_t* get_all(void) { return nullptr; }
206
207 stack_config_t mock_stack_config{
208 .get_pts_avrcp_test = get_pts_avrcp_test,
209 .get_pts_secure_only_mode = get_pts_secure_only_mode,
210 .get_pts_conn_updates_disabled = get_pts_conn_updates_disabled,
211 .get_pts_crosskey_sdp_disable = get_pts_crosskey_sdp_disable,
212 .get_pts_smp_options = get_pts_smp_options,
213 .get_pts_smp_failure_case = get_pts_smp_failure_case,
214 .get_pts_force_eatt_for_notifications =
215 get_pts_force_eatt_for_notifications,
216 .get_pts_connect_eatt_unconditionally =
217 get_pts_connect_eatt_unconditionally,
218 .get_pts_connect_eatt_before_encryption =
219 get_pts_connect_eatt_before_encryption,
220 .get_pts_unencrypt_broadcast = get_pts_unencrypt_broadcast,
221 .get_pts_eatt_peripheral_collision_support =
222 get_pts_eatt_peripheral_collision_support,
223 .get_pts_force_le_audio_multiple_contexts_metadata =
224 get_pts_force_le_audio_multiple_contexts_metadata,
225 .get_pts_le_audio_disable_ases_before_stopping =
226 get_pts_le_audio_disable_ases_before_stopping,
227 .get_all = get_all,
228 };
stack_config_get_interface(void)229 const stack_config_t* stack_config_get_interface(void) {
230 return &mock_stack_config;
231 }
232
IsLeAudioBroadcasterRunning()233 bool LeAudioBroadcaster::IsLeAudioBroadcasterRunning() { return false; }
234
235 namespace server_configurable_flags {
GetServerConfigurableFlag(const std::string & experiment_category_name,const std::string & experiment_flag_name,const std::string & default_value)236 std::string GetServerConfigurableFlag(
237 const std::string& experiment_category_name,
238 const std::string& experiment_flag_name, const std::string& default_value) {
239 return "";
240 }
241 } // namespace server_configurable_flags
242
243 namespace bluetooth::le_audio {
244 class MockLeAudioSourceHalClient;
245 MockLeAudioSourceHalClient* mock_le_audio_source_hal_client_;
246 std::unique_ptr<LeAudioSourceAudioHalClient>
247 owned_mock_le_audio_source_hal_client_;
248 bool is_audio_unicast_source_acquired;
249
250 std::unique_ptr<LeAudioSourceAudioHalClient>
AcquireUnicast()251 LeAudioSourceAudioHalClient::AcquireUnicast() {
252 if (is_audio_unicast_source_acquired) return nullptr;
253 is_audio_unicast_source_acquired = true;
254 return std::move(owned_mock_le_audio_source_hal_client_);
255 }
256
DebugDump(int fd)257 void LeAudioSourceAudioHalClient::DebugDump(int fd) {}
258
259 class MockLeAudioSinkHalClient;
260 MockLeAudioSinkHalClient* mock_le_audio_sink_hal_client_;
261 std::unique_ptr<LeAudioSinkAudioHalClient> owned_mock_le_audio_sink_hal_client_;
262 bool is_audio_unicast_sink_acquired;
263
264 std::unique_ptr<LeAudioSinkAudioHalClient>
AcquireUnicast()265 LeAudioSinkAudioHalClient::AcquireUnicast() {
266 if (is_audio_unicast_sink_acquired) return nullptr;
267 is_audio_unicast_sink_acquired = true;
268 return std::move(owned_mock_le_audio_sink_hal_client_);
269 }
270
DebugDump(int fd)271 void LeAudioSinkAudioHalClient::DebugDump(int fd) {}
272
273 class MockAudioHalClientCallbacks
274 : public bluetooth::le_audio::LeAudioClientCallbacks {
275 public:
276 MOCK_METHOD((void), OnInitialized, (), (override));
277 MOCK_METHOD((void), OnConnectionState,
278 (ConnectionState state, const RawAddress& address), (override));
279 MOCK_METHOD((void), OnGroupStatus, (int group_id, GroupStatus group_status),
280 (override));
281 MOCK_METHOD((void), OnGroupStreamStatus,
282 (int group_id, GroupStreamStatus group_stream_status),
283 (override));
284 MOCK_METHOD((void), OnGroupNodeStatus,
285 (const RawAddress& bd_addr, int group_id,
286 GroupNodeStatus node_status),
287 (override));
288 MOCK_METHOD((void), OnAudioConf,
289 (uint8_t direction, int group_id, uint32_t snk_audio_location,
290 uint32_t src_audio_location, uint16_t avail_cont),
291 (override));
292 MOCK_METHOD((void), OnSinkAudioLocationAvailable,
293 (const RawAddress& bd_addr, uint32_t snk_audio_location),
294 (override));
295 MOCK_METHOD(
296 (void), OnAudioLocalCodecCapabilities,
297 (std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
298 std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf),
299 (override));
300 MOCK_METHOD((void), OnAudioGroupCurrentCodecConf,
301 (int group_id, btle_audio_codec_config_t input_codec_conf,
302 btle_audio_codec_config_t output_codec_conf),
303 (override));
304 MOCK_METHOD(
305 (void), OnAudioGroupSelectableCodecConf,
306 (int group_id,
307 std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
308 std::vector<btle_audio_codec_config_t> output_selectable_codec_conf),
309 (override));
310 MOCK_METHOD((void), OnHealthBasedRecommendationAction,
311 (const RawAddress& address, LeAudioHealthBasedAction action),
312 (override));
313 MOCK_METHOD((void), OnHealthBasedGroupRecommendationAction,
314 (int group_id, LeAudioHealthBasedAction action), (override));
315 MOCK_METHOD((void), OnUnicastMonitorModeStatus,
316 (uint8_t direction, UnicastMonitorModeStatus status));
317 };
318
319 class MockLeAudioSinkHalClient : public LeAudioSinkAudioHalClient {
320 public:
321 MockLeAudioSinkHalClient() = default;
322 MOCK_METHOD((bool), Start,
323 (const LeAudioCodecConfiguration& codecConfiguration,
324 LeAudioSinkAudioHalClient::Callbacks* audioReceiver,
325 DsaModes dsa_modes),
326 (override));
327 MOCK_METHOD((void), Stop, (), (override));
328 MOCK_METHOD((size_t), SendData, (uint8_t * data, uint16_t size), (override));
329 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
330 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
331 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
332 MOCK_METHOD((void), UpdateAudioConfigToHal,
333 (const ::bluetooth::le_audio::offload_config&), (override));
334 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
335 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
336
337 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSinkHalClient()338 virtual ~MockLeAudioSinkHalClient() override { OnDestroyed(); }
339 };
340
341 class MockLeAudioSourceHalClient : public LeAudioSourceAudioHalClient {
342 public:
343 MockLeAudioSourceHalClient() = default;
344 MOCK_METHOD((bool), Start,
345 (const LeAudioCodecConfiguration& codecConfiguration,
346 LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
347 DsaModes dsa_modes),
348 (override));
349 MOCK_METHOD((void), Stop, (), (override));
350 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
351 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
352 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
353 MOCK_METHOD((void), UpdateAudioConfigToHal,
354 (const ::bluetooth::le_audio::offload_config&), (override));
355 MOCK_METHOD(
356 (std::optional<broadcaster::BroadcastConfiguration>), GetBroadcastConfig,
357 ((const std::vector<std::pair<types::LeAudioContextType, uint8_t>>&),
358 (const std::optional<
359 std::vector<::bluetooth::le_audio::types::acs_ac_record>>&)),
360 (const override));
361 MOCK_METHOD(
362 (std::optional<
363 ::bluetooth::le_audio::set_configurations::AudioSetConfiguration>),
364 GetUnicastConfig, (const CodecManager::UnicastConfigurationRequirements&),
365 (const override));
366 MOCK_METHOD((void), UpdateBroadcastAudioConfigToHal,
367 (const ::bluetooth::le_audio::broadcast_offload_config&),
368 (override));
369 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
370 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
371
372 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSourceHalClient()373 virtual ~MockLeAudioSourceHalClient() override { OnDestroyed(); }
374 };
375
376 class UnicastTestNoInit : public Test {
377 public:
378 bool use_health_status = false;
379 bool use_handover_mode = false;
380
381 protected:
RegisterSourceHalClientMock()382 void RegisterSourceHalClientMock() {
383 owned_mock_le_audio_source_hal_client_.reset(
384 new NiceMock<MockLeAudioSourceHalClient>());
385 mock_le_audio_source_hal_client_ =
386 (MockLeAudioSourceHalClient*)
387 owned_mock_le_audio_source_hal_client_.get();
388
389 is_audio_unicast_source_acquired = false;
390 ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _))
391 .WillByDefault(
392 [this](const LeAudioCodecConfiguration& codec_configuration,
393 LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
394 DsaModes dsa_modes) {
395 unicast_source_hal_cb_ = audioReceiver;
396 return true;
397 });
398 ON_CALL(*mock_le_audio_source_hal_client_, OnDestroyed).WillByDefault([]() {
399 mock_le_audio_source_hal_client_ = nullptr;
400 is_audio_unicast_source_acquired = false;
401 });
402 }
403
RegisterSinkHalClientMock()404 void RegisterSinkHalClientMock() {
405 owned_mock_le_audio_sink_hal_client_.reset(
406 new NiceMock<MockLeAudioSinkHalClient>());
407 mock_le_audio_sink_hal_client_ =
408 (MockLeAudioSinkHalClient*)owned_mock_le_audio_sink_hal_client_.get();
409
410 is_audio_unicast_sink_acquired = false;
411 ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _))
412 .WillByDefault(
413 [this](const LeAudioCodecConfiguration& codec_configuration,
414 LeAudioSinkAudioHalClient::Callbacks* audioReceiver,
415 DsaModes dsa_modes) {
416 unicast_sink_hal_cb_ = audioReceiver;
417 return true;
418 });
419 ON_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed).WillByDefault([]() {
420 mock_le_audio_sink_hal_client_ = nullptr;
421 is_audio_unicast_sink_acquired = false;
422 });
423 }
424
SetUpMockAudioHal()425 void SetUpMockAudioHal() {
426 if (use_health_status) {
427 bluetooth::common::InitFlags::Load(test_flags_with_health_status);
428 } else if (use_handover_mode) {
429 bluetooth::common::InitFlags::Load(test_flags_with_handover_mode);
430 } else {
431 bluetooth::common::InitFlags::Load(test_flags);
432 }
433
434 /* Since these are returned by the Acquire() methods as unique_ptrs, we
435 * will not free them manually.
436 */
437 RegisterSourceHalClientMock();
438
439 owned_mock_le_audio_sink_hal_client_.reset(
440 new NiceMock<MockLeAudioSinkHalClient>());
441 mock_le_audio_sink_hal_client_ =
442 (MockLeAudioSinkHalClient*)owned_mock_le_audio_sink_hal_client_.get();
443
444 owned_mock_le_audio_source_hal_client_.reset(
445 new NiceMock<MockLeAudioSourceHalClient>());
446 mock_le_audio_source_hal_client_ =
447 (MockLeAudioSourceHalClient*)
448 owned_mock_le_audio_source_hal_client_.get();
449
450 is_audio_unicast_source_acquired = false;
451 ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _))
452 .WillByDefault(
453 [this](const LeAudioCodecConfiguration& codec_configuration,
454 LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
455 DsaModes dsa_modes) {
456 unicast_source_hal_cb_ = audioReceiver;
457 return true;
458 });
459 ON_CALL(*mock_le_audio_source_hal_client_, OnDestroyed).WillByDefault([]() {
460 mock_le_audio_source_hal_client_ = nullptr;
461 is_audio_unicast_source_acquired = false;
462 });
463
464 is_audio_unicast_sink_acquired = false;
465 ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _))
466 .WillByDefault(
467 [this](const LeAudioCodecConfiguration& codec_configuration,
468 LeAudioSinkAudioHalClient::Callbacks* audioReceiver,
469 DsaModes dsa_modes) {
470 unicast_sink_hal_cb_ = audioReceiver;
471 return true;
472 });
473 ON_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed).WillByDefault([]() {
474 mock_le_audio_sink_hal_client_ = nullptr;
475 is_audio_unicast_sink_acquired = false;
476 });
477
478 ON_CALL(*mock_le_audio_sink_hal_client_, SendData)
479 .WillByDefault([](uint8_t* data, uint16_t size) { return size; });
480
481 // HAL
482 ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool {
483 return true;
484 });
485 }
486
InjectGroupDeviceRemoved(const RawAddress & address,int group_id)487 void InjectGroupDeviceRemoved(const RawAddress& address, int group_id) {
488 group_callbacks_->OnGroupMemberRemoved(address, group_id);
489 }
490
InjectGroupDeviceAdded(const RawAddress & address,int group_id)491 void InjectGroupDeviceAdded(const RawAddress& address, int group_id) {
492 bluetooth::Uuid uuid = bluetooth::le_audio::uuid::kCapServiceUuid;
493
494 int group_members_num = 0;
495 for (const auto& [addr, id] : groups) {
496 if (id == group_id) group_members_num++;
497 }
498
499 bool first_device = (group_members_num == 1);
500 do_in_main_thread(
501 FROM_HERE,
502 base::BindOnce(
503 [](const RawAddress& addr, int group_id, bluetooth::Uuid uuid,
504 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks,
505 bool first_device) {
506 if (first_device) {
507 group_callbacks->OnGroupAdded(addr, uuid, group_id);
508 } else {
509 group_callbacks->OnGroupMemberAdded(addr, group_id);
510 }
511 },
512 address, group_id, uuid, base::Unretained(this->group_callbacks_),
513 first_device));
514 }
515
InjectServiceChangedEvent(const RawAddress & address,uint16_t conn_id)516 void InjectServiceChangedEvent(const RawAddress& address, uint16_t conn_id) {
517 tBTA_GATTC_SERVICE_CHANGED event_data = {.remote_bda = address,
518 .conn_id = conn_id};
519
520 do_in_main_thread(FROM_HERE,
521 base::BindOnce(
522 [](tBTA_GATTC_CBACK* gatt_callback,
523 tBTA_GATTC_SERVICE_CHANGED event_data) {
524 gatt_callback(BTA_GATTC_SRVC_CHG_EVT,
525 (tBTA_GATTC*)&event_data);
526 },
527 base::Unretained(this->gatt_callback), event_data));
528 }
529
InjectConnectedEvent(const RawAddress & address,uint16_t conn_id,tGATT_STATUS status=GATT_SUCCESS)530 void InjectConnectedEvent(const RawAddress& address, uint16_t conn_id,
531 tGATT_STATUS status = GATT_SUCCESS) {
532 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
533 tBTA_GATTC_OPEN event_data = {
534 .status = status,
535 .conn_id = conn_id,
536 .client_if = gatt_if,
537 .remote_bda = address,
538 .transport = GATT_TRANSPORT_LE,
539 .mtu = 240,
540 };
541
542 if (status == GATT_SUCCESS) {
543 ASSERT_NE(peer_devices.count(conn_id), 0u);
544 peer_devices.at(conn_id)->connected = true;
545 }
546
547 do_in_main_thread(
548 FROM_HERE,
549 base::BindOnce(
550 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_OPEN event_data) {
551 gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
552 },
553 base::Unretained(this->gatt_callback), event_data));
554 }
555
InjectEncryptionChangedEvent(const RawAddress & address)556 void InjectEncryptionChangedEvent(const RawAddress& address) {
557 tBTA_GATTC_ENC_CMPL_CB event_data = {
558 .client_if = gatt_if,
559 .remote_bda = address,
560 };
561
562 do_in_main_thread(FROM_HERE,
563 base::BindOnce(
564 [](tBTA_GATTC_CBACK* gatt_callback,
565 tBTA_GATTC_ENC_CMPL_CB event_data) {
566 gatt_callback(BTA_GATTC_ENC_CMPL_CB_EVT,
567 (tBTA_GATTC*)&event_data);
568 },
569 base::Unretained(this->gatt_callback), event_data));
570 }
571
InjectDisconnectedEvent(uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST)572 void InjectDisconnectedEvent(
573 uint16_t conn_id,
574 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) {
575 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
576 ASSERT_NE(peer_devices.count(conn_id), 0u);
577
578 tBTA_GATTC_CLOSE event_data = {
579 .conn_id = conn_id,
580 .status = GATT_SUCCESS,
581 .client_if = gatt_if,
582 .remote_bda = peer_devices.at(conn_id)->addr,
583 .reason = reason,
584 };
585
586 peer_devices.at(conn_id)->connected = false;
587 do_in_main_thread(
588 FROM_HERE,
589 base::BindOnce(
590 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_CLOSE event_data) {
591 gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
592 },
593 base::Unretained(this->gatt_callback), event_data));
594 }
595
InjectPhyChangedEvent(uint16_t conn_id,uint8_t tx_phy,uint8_t rx_phy,tGATT_STATUS status)596 void InjectPhyChangedEvent(uint16_t conn_id, uint8_t tx_phy, uint8_t rx_phy,
597 tGATT_STATUS status) {
598 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
599 tBTA_GATTC_PHY_UPDATE event_data = {
600 .conn_id = conn_id,
601 .tx_phy = tx_phy,
602 .rx_phy = rx_phy,
603 .status = status,
604 };
605
606 do_in_main_thread(FROM_HERE,
607 base::BindOnce(
608 [](tBTA_GATTC_CBACK* gatt_callback,
609 tBTA_GATTC_PHY_UPDATE event_data) {
610 gatt_callback(BTA_GATTC_PHY_UPDATE_EVT,
611 (tBTA_GATTC*)&event_data);
612 },
613 base::Unretained(this->gatt_callback), event_data));
614 }
615
InjectSearchCompleteEvent(uint16_t conn_id)616 void InjectSearchCompleteEvent(uint16_t conn_id) {
617 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
618 tBTA_GATTC_SEARCH_CMPL event_data = {
619 .conn_id = conn_id,
620 .status = GATT_SUCCESS,
621 };
622
623 do_in_main_thread(FROM_HERE,
624 base::BindOnce(
625 [](tBTA_GATTC_CBACK* gatt_callback,
626 tBTA_GATTC_SEARCH_CMPL event_data) {
627 gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT,
628 (tBTA_GATTC*)&event_data);
629 },
630 base::Unretained(this->gatt_callback), event_data));
631 }
632
InjectNotificationEvent(const RawAddress & test_address,uint16_t conn_id,uint16_t handle,std::vector<uint8_t> value)633 void InjectNotificationEvent(const RawAddress& test_address, uint16_t conn_id,
634 uint16_t handle, std::vector<uint8_t> value) {
635 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
636 tBTA_GATTC_NOTIFY event_data = {
637 .conn_id = conn_id,
638 .bda = test_address,
639 .handle = handle,
640 .len = (uint8_t)value.size(),
641 .is_notify = true,
642 };
643
644 std::copy(value.begin(), value.end(), event_data.value);
645 do_in_main_thread(
646 FROM_HERE,
647 base::BindOnce(
648 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_NOTIFY event_data) {
649 gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
650 },
651 base::Unretained(this->gatt_callback), event_data));
652 }
653
InjectContextTypes(const RawAddress & test_address,uint16_t conn_id,uint16_t handle,AudioContexts sink_ctxs,AudioContexts source_ctxs)654 void InjectContextTypes(const RawAddress& test_address, uint16_t conn_id,
655 uint16_t handle, AudioContexts sink_ctxs,
656 AudioContexts source_ctxs) {
657 std::vector<uint8_t> contexts = {
658 (uint8_t)(sink_ctxs.value()), (uint8_t)(sink_ctxs.value() >> 8),
659 (uint8_t)(source_ctxs.value()), (uint8_t)(source_ctxs.value() >> 8)};
660
661 InjectNotificationEvent(test_address, conn_id, handle, contexts);
662 }
663
InjectSupportedContextTypes(const RawAddress & test_address,uint16_t conn_id,AudioContexts sink_ctxs,AudioContexts source_ctxs)664 void InjectSupportedContextTypes(const RawAddress& test_address,
665 uint16_t conn_id, AudioContexts sink_ctxs,
666 AudioContexts source_ctxs) {
667 /* 0x0077 pacs->supp_contexts_char + 1 */
668 InjectContextTypes(test_address, conn_id, 0x0077, sink_ctxs, source_ctxs);
669 SyncOnMainLoop();
670 }
671
InjectAvailableContextTypes(const RawAddress & test_address,uint16_t conn_id,AudioContexts sink_ctxs,AudioContexts source_ctxs,bool sync_on_mainloop=true)672 void InjectAvailableContextTypes(const RawAddress& test_address,
673 uint16_t conn_id, AudioContexts sink_ctxs,
674 AudioContexts source_ctxs,
675 bool sync_on_mainloop = true) {
676 /* 0x0074 is pacs->avail_contexts_char + 1 */
677 InjectContextTypes(test_address, conn_id, 0x0074, sink_ctxs, source_ctxs);
678 if (sync_on_mainloop) {
679 SyncOnMainLoop();
680 }
681 }
682
SetUpMockGatt()683 void SetUpMockGatt() {
684 // default action for GetCharacteristic function call
685 ON_CALL(mock_gatt_interface_, GetCharacteristic(_, _))
686 .WillByDefault(
687 Invoke([&](uint16_t conn_id,
688 uint16_t handle) -> const gatt::Characteristic* {
689 std::list<gatt::Service>& services =
690 peer_devices.at(conn_id)->services;
691 for (auto const& service : services) {
692 for (auto const& characteristic : service.characteristics) {
693 if (characteristic.value_handle == handle) {
694 return &characteristic;
695 }
696 }
697 }
698
699 return nullptr;
700 }));
701
702 // default action for GetOwningService function call
703 ON_CALL(mock_gatt_interface_, GetOwningService(_, _))
704 .WillByDefault(Invoke(
705 [&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
706 std::list<gatt::Service>& services =
707 peer_devices.at(conn_id)->services;
708 for (auto const& service : services) {
709 if (service.handle <= handle && service.end_handle >= handle) {
710 return &service;
711 }
712 }
713
714 return nullptr;
715 }));
716
717 // default action for ServiceSearchRequest function call
718 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
719 .WillByDefault(WithArg<0>(Invoke(
720 [&](uint16_t conn_id) { InjectSearchCompleteEvent(conn_id); })));
721
722 // default action for GetServices function call
723 ON_CALL(mock_gatt_interface_, GetServices(_))
724 .WillByDefault(WithArg<0>(
725 Invoke([&](uint16_t conn_id) -> std::list<gatt::Service>* {
726 return &peer_devices.at(conn_id)->services;
727 })));
728
729 // default action for RegisterForNotifications function call
730 ON_CALL(mock_gatt_interface_, RegisterForNotifications(gatt_if, _, _))
731 .WillByDefault(Return(GATT_SUCCESS));
732
733 // default action for DeregisterForNotifications function call
734 ON_CALL(mock_gatt_interface_, DeregisterForNotifications(gatt_if, _, _))
735 .WillByDefault(Return(GATT_SUCCESS));
736
737 // default action for WriteDescriptor function call
738 ON_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _))
739 .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle,
740 std::vector<uint8_t> value,
741 tGATT_WRITE_TYPE write_type,
742 GATT_WRITE_OP_CB cb,
743 void* cb_data) -> void {
744 auto& ascs = peer_devices.at(conn_id)->ascs;
745 uint8_t idx;
746
747 if (handle == ascs->ctp_ccc) {
748 value = UINT16_TO_VEC_UINT8(ascs->ctp_ccc_val);
749 } else {
750 for (idx = 0; idx < max_num_of_ases; idx++) {
751 if (handle == ascs->sink_ase_ccc[idx] + 1) {
752 value = UINT16_TO_VEC_UINT8(ascs->sink_ase_ccc_val[idx]);
753 break;
754 }
755 if (handle == ascs->source_ase_char[idx] + 1) {
756 value = UINT16_TO_VEC_UINT8(ascs->source_ase_ccc_val[idx]);
757 break;
758 }
759 }
760 }
761
762 if (cb)
763 do_in_main_thread(
764 FROM_HERE,
765 base::BindOnce(
766 [](GATT_WRITE_OP_CB cb, uint16_t conn_id, uint16_t handle,
767 uint16_t len, uint8_t* value, void* cb_data) {
768 cb(conn_id, GATT_SUCCESS, handle, len, value, cb_data);
769 },
770 cb, conn_id, handle, value.size(), value.data(), cb_data));
771 }));
772
773 global_conn_id = 1;
774 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
775 .WillByDefault(
776 Invoke([&](tGATT_IF client_if, const RawAddress& remote_bda,
777 bool is_direct, bool opportunistic) {
778 InjectConnectedEvent(remote_bda, global_conn_id++);
779 }));
780
781 ON_CALL(mock_gatt_interface_, Close(_))
782 .WillByDefault(Invoke([&](uint16_t conn_id) {
783 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
784 InjectDisconnectedEvent(conn_id);
785 }));
786
787 // default Characteristic read handler dispatches requests to service mocks
788 ON_CALL(mock_gatt_queue_, ReadCharacteristic(_, _, _, _))
789 .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle,
790 GATT_READ_OP_CB cb, void* cb_data) {
791 do_in_main_thread(
792 FROM_HERE,
793 base::BindOnce(
794 [](std::map<uint16_t,
795 std::unique_ptr<NiceMock<MockDeviceWrapper>>>*
796 peer_devices,
797 uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
798 void* cb_data) -> void {
799 if (peer_devices->count(conn_id)) {
800 auto& device = peer_devices->at(conn_id);
801 auto svc = std::find_if(
802 device->services.begin(), device->services.end(),
803 [handle](const gatt::Service& svc) {
804 return (handle >= svc.handle) &&
805 (handle <= svc.end_handle);
806 });
807 if (svc == device->services.end()) return;
808
809 // Dispatch to mockable handler functions
810 if (svc->handle == device->csis->start) {
811 device->csis->OnReadCharacteristic(handle, cb, cb_data);
812 } else if (svc->handle == device->cas->start) {
813 device->cas->OnReadCharacteristic(handle, cb, cb_data);
814 } else if (svc->handle == device->ascs->start) {
815 device->ascs->OnReadCharacteristic(handle, cb, cb_data);
816 } else if (svc->handle == device->pacs->start) {
817 device->pacs->OnReadCharacteristic(handle, cb, cb_data);
818 }
819 }
820 },
821 &peer_devices, conn_id, handle, cb, cb_data));
822 }));
823 }
824
SetUpMockGroups()825 void SetUpMockGroups() {
826 MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
827 MockDeviceGroups::SetMockInstanceForTesting(&mock_groups_module_);
828 MockLeAudioGroupStateMachine::SetMockInstanceForTesting(
829 &mock_state_machine_);
830
831 ON_CALL(mock_csis_client_module_, Get())
832 .WillByDefault(Return(&mock_csis_client_module_));
833
834 // Store group callbacks so that we could inject grouping events
835 group_callbacks_ = nullptr;
836 ON_CALL(mock_groups_module_, Initialize(_))
837 .WillByDefault(SaveArg<0>(&group_callbacks_));
838
839 ON_CALL(mock_groups_module_, GetGroupId(_, _))
840 .WillByDefault([this](const RawAddress& addr, bluetooth::Uuid uuid) {
841 if (groups.find(addr) != groups.end()) return groups.at(addr);
842 return bluetooth::groups::kGroupUnknown;
843 });
844
845 ON_CALL(mock_groups_module_, RemoveDevice(_, _))
846 .WillByDefault([this](const RawAddress& addr, int group_id_) {
847 int group_id = -1;
848 if (groups.find(addr) != groups.end()) {
849 group_id = groups[addr];
850 groups.erase(addr);
851 }
852 if (group_id < 0) return;
853
854 do_in_main_thread(
855 FROM_HERE,
856 base::BindOnce(
857 [](const RawAddress& address, int group_id,
858 bluetooth::groups::DeviceGroupsCallbacks*
859 group_callbacks) {
860 group_callbacks->OnGroupMemberRemoved(address, group_id);
861 },
862 addr, group_id, base::Unretained(group_callbacks_)));
863 });
864
865 // Our test devices have unique LSB - use it for unique grouping when
866 // devices added with a non-CIS context and no grouping info
867 ON_CALL(mock_groups_module_,
868 AddDevice(_, bluetooth::le_audio::uuid::kCapServiceUuid, _))
869 .WillByDefault(
870 [this](const RawAddress& addr,
871 bluetooth::Uuid uuid =
872 bluetooth::le_audio::uuid::kCapServiceUuid,
873 int group_id = bluetooth::groups::kGroupUnknown) -> int {
874 if (group_id == bluetooth::groups::kGroupUnknown) {
875 /* Generate group id from address */
876 groups[addr] = addr.address[RawAddress::kLength - 1];
877 group_id = groups[addr];
878 } else {
879 groups[addr] = group_id;
880 }
881
882 InjectGroupDeviceAdded(addr, groups[addr]);
883 return addr.address[RawAddress::kLength - 1];
884 });
885
886 ON_CALL(mock_state_machine_, Initialize(_))
887 .WillByDefault(SaveArg<0>(&state_machine_callbacks_));
888
889 ON_CALL(mock_state_machine_, ConfigureStream(_, _, _, _))
890 .WillByDefault(
891 [this](LeAudioDeviceGroup* group,
892 types::LeAudioContextType context_type,
893 types::BidirectionalPair<types::AudioContexts>
894 metadata_context_types,
895 types::BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
896 bool isReconfiguration = group->IsPendingConfiguration();
897
898 /* This shall be called only for user reconfiguration */
899 if (!isReconfiguration) return false;
900
901 /* Do what ReleaseCisIds(group) does: start */
902 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
903 while (leAudioDevice != nullptr) {
904 for (auto& ase : leAudioDevice->ases_) {
905 ase.cis_id = bluetooth::le_audio::kInvalidCisId;
906 }
907 leAudioDevice = group->GetNextDevice(leAudioDevice);
908 }
909 group->ClearAllCises();
910 /* end */
911
912 if (!group->Configure(context_type, metadata_context_types,
913 ccid_lists)) {
914 log::error(
915 "Could not configure ASEs for group {} content type {}",
916 group->group_id_, int(context_type));
917
918 return false;
919 }
920
921 group->cig.GenerateCisIds(context_type);
922
923 for (LeAudioDevice* device = group->GetFirstDevice();
924 device != nullptr; device = group->GetNextDevice(device)) {
925 for (auto& ase : device->ases_) {
926 ase.cis_state = types::CisState::IDLE;
927 ase.data_path_state = types::DataPathState::IDLE;
928 ase.active = false;
929 ase.state =
930 types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
931 }
932 }
933
934 // Inject the state
935 group->SetTargetState(
936 types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
937 group->SetState(group->GetTargetState());
938 group->ClearPendingConfiguration();
939 do_in_main_thread(
940 FROM_HERE,
941 base::BindOnce(
942 [](int group_id,
943 bluetooth::le_audio::LeAudioGroupStateMachine::
944 Callbacks* state_machine_callbacks) {
945 state_machine_callbacks->StatusReportCb(
946 group_id, GroupStreamStatus::CONFIGURED_BY_USER);
947 },
948 group->group_id_,
949 base::Unretained(this->state_machine_callbacks_)));
950 return true;
951 });
952
953 ON_CALL(mock_state_machine_, AttachToStream(_, _, _))
954 .WillByDefault([this](LeAudioDeviceGroup* group,
955 LeAudioDevice* leAudioDevice,
956 types::BidirectionalPair<std::vector<uint8_t>>
957 ccids) {
958 if (group->GetState() !=
959 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
960 if (group->GetTargetState() ==
961 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
962 attach_to_stream_scheduled = true;
963 }
964
965 return false;
966 }
967
968 group->Configure(group->GetConfigurationContextType(),
969 group->GetMetadataContexts(), ccids);
970 if (!group->cig.AssignCisIds(leAudioDevice)) return false;
971 group->AssignCisConnHandlesToAses(leAudioDevice);
972
973 auto* stream_conf = &group->stream_conf;
974
975 for (auto& ase : leAudioDevice->ases_) {
976 if (!ase.active) continue;
977
978 // And also skip the ase establishment procedure which should
979 // be tested as part of the state machine unit tests
980 ase.cis_state = types::CisState::CONNECTED;
981 ase.data_path_state = types::DataPathState::CONFIGURED;
982 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
983
984 uint16_t cis_conn_hdl = ase.cis_conn_hdl;
985 auto core_config = ase.codec_config.GetAsCoreCodecConfig();
986
987 /* Copied from state_machine.cc ProcessHciNotifSetupIsoDataPath */
988 if (ase.direction ==
989 bluetooth::le_audio::types::kLeAudioDirectionSource) {
990 auto iter = std::find_if(
991 stream_conf->stream_params.source.stream_locations.begin(),
992 stream_conf->stream_params.source.stream_locations.end(),
993 [cis_conn_hdl](auto& pair) {
994 return cis_conn_hdl == pair.first;
995 });
996
997 if (iter ==
998 stream_conf->stream_params.source.stream_locations.end()) {
999 stream_conf->stream_params.source.stream_locations.emplace_back(
1000 std::make_pair(ase.cis_conn_hdl,
1001 *core_config.audio_channel_allocation));
1002
1003 stream_conf->stream_params.source.num_of_devices++;
1004 stream_conf->stream_params.source.num_of_channels +=
1005 ase.channel_count;
1006
1007 log::info(
1008 "Added Source Stream Configuration. CIS Connection Handle: "
1009 "{}, Audio Channel Allocation: {}, Source Number Of "
1010 "Devices: {}, Source Number Of Channels: {}",
1011 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1012 stream_conf->stream_params.source.num_of_devices,
1013 stream_conf->stream_params.source.num_of_channels);
1014 }
1015 } else {
1016 auto iter = std::find_if(
1017 stream_conf->stream_params.sink.stream_locations.begin(),
1018 stream_conf->stream_params.sink.stream_locations.end(),
1019 [cis_conn_hdl](auto& pair) {
1020 return cis_conn_hdl == pair.first;
1021 });
1022
1023 if (iter ==
1024 stream_conf->stream_params.sink.stream_locations.end()) {
1025 stream_conf->stream_params.sink.stream_locations.emplace_back(
1026 std::make_pair(ase.cis_conn_hdl,
1027 *core_config.audio_channel_allocation));
1028
1029 stream_conf->stream_params.sink.num_of_devices++;
1030 stream_conf->stream_params.sink.num_of_channels +=
1031 ase.channel_count;
1032
1033 log::info(
1034 "Added Sink Stream Configuration. CIS Connection Handle: "
1035 "{}, Audio Channel Allocation: {}, Sink Number Of Devices: "
1036 "{}, Sink Number Of Channels: {}",
1037 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1038 stream_conf->stream_params.sink.num_of_devices,
1039 stream_conf->stream_params.sink.num_of_channels);
1040 }
1041 }
1042 }
1043
1044 return true;
1045 });
1046
1047 ON_CALL(mock_state_machine_, StartStream(_, _, _, _))
1048 .WillByDefault([this](LeAudioDeviceGroup* group,
1049 types::LeAudioContextType context_type,
1050 types::BidirectionalPair<types::AudioContexts>
1051 metadata_context_types,
1052 types::BidirectionalPair<std::vector<uint8_t>>
1053 ccid_lists) {
1054 /* Do nothing if already streaming - the implementation would
1055 * probably update the metadata.
1056 */
1057 if (group->GetState() ==
1058 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
1059 return true;
1060 }
1061
1062 /* Do what ReleaseCisIds(group) does: start */
1063 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
1064 while (leAudioDevice != nullptr) {
1065 for (auto& ase : leAudioDevice->ases_) {
1066 ase.cis_id = bluetooth::le_audio::kInvalidCisId;
1067 }
1068 leAudioDevice = group->GetNextDevice(leAudioDevice);
1069 }
1070 group->ClearAllCises();
1071 /* end */
1072
1073 if (!group->Configure(context_type, metadata_context_types,
1074 ccid_lists)) {
1075 log::error("failed to set ASE configuration");
1076 return false;
1077 }
1078
1079 if (group->GetState() ==
1080 types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {
1081 group->cig.GenerateCisIds(context_type);
1082
1083 std::vector<uint16_t> conn_handles;
1084 for (uint8_t i = 0; i < (uint8_t)(group->cig.cises.size()); i++) {
1085 conn_handles.push_back(iso_con_counter_++);
1086 }
1087 group->cig.AssignCisConnHandles(conn_handles);
1088 for (LeAudioDevice* device = group->GetFirstActiveDevice();
1089 device != nullptr;
1090 device = group->GetNextActiveDevice(device)) {
1091 if (!group->cig.AssignCisIds(device)) return false;
1092 group->AssignCisConnHandlesToAses(device);
1093 }
1094 }
1095
1096 auto* stream_conf = &group->stream_conf;
1097
1098 // Fake ASE configuration
1099 for (LeAudioDevice* device = group->GetFirstActiveDevice();
1100 device != nullptr; device = group->GetNextActiveDevice(device)) {
1101 for (auto& ase : device->ases_) {
1102 if (!ase.active) continue;
1103
1104 // And also skip the ase establishment procedure which should
1105 // be tested as part of the state machine unit tests
1106 ase.cis_state = types::CisState::CONNECTED;
1107 ase.data_path_state = types::DataPathState::CONFIGURED;
1108 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
1109 ase.qos_preferences.pres_delay_min = 2500;
1110 ase.qos_preferences.pres_delay_max = 2500;
1111 ase.qos_preferences.preferred_pres_delay_min = 2500;
1112 ase.qos_preferences.preferred_pres_delay_max = 2500;
1113 auto core_config = ase.codec_config.GetAsCoreCodecConfig();
1114
1115 uint16_t cis_conn_hdl = ase.cis_conn_hdl;
1116
1117 /* Copied from state_machine.cc ProcessHciNotifSetupIsoDataPath */
1118 if (ase.direction ==
1119 bluetooth::le_audio::types::kLeAudioDirectionSource) {
1120 auto iter = std::find_if(
1121 stream_conf->stream_params.source.stream_locations.begin(),
1122 stream_conf->stream_params.source.stream_locations.end(),
1123 [cis_conn_hdl](auto& pair) {
1124 return cis_conn_hdl == pair.first;
1125 });
1126
1127 if (iter ==
1128 stream_conf->stream_params.source.stream_locations.end()) {
1129 stream_conf->stream_params.source.stream_locations
1130 .emplace_back(std::make_pair(
1131 ase.cis_conn_hdl,
1132 *core_config.audio_channel_allocation));
1133
1134 stream_conf->stream_params.source.num_of_devices++;
1135 stream_conf->stream_params.source.num_of_channels +=
1136 ase.channel_count;
1137 stream_conf->stream_params.source.audio_channel_allocation |=
1138 *core_config.audio_channel_allocation;
1139
1140 if (stream_conf->stream_params.source.sample_frequency_hz ==
1141 0) {
1142 stream_conf->stream_params.source.sample_frequency_hz =
1143 core_config.GetSamplingFrequencyHz();
1144 } else {
1145 log::assert_that(
1146 stream_conf->stream_params.source.sample_frequency_hz ==
1147 core_config.GetSamplingFrequencyHz(),
1148 "sample freq mismatch: {}!={}",
1149 stream_conf->stream_params.source.sample_frequency_hz,
1150 core_config.GetSamplingFrequencyHz());
1151 }
1152
1153 if (stream_conf->stream_params.source
1154 .octets_per_codec_frame == 0) {
1155 stream_conf->stream_params.source.octets_per_codec_frame =
1156 *core_config.octets_per_codec_frame;
1157 } else {
1158 log::assert_that(stream_conf->stream_params.source
1159 .octets_per_codec_frame ==
1160 *core_config.octets_per_codec_frame,
1161 "octets per frame mismatch: {}!={}",
1162 stream_conf->stream_params.source
1163 .octets_per_codec_frame,
1164 *core_config.octets_per_codec_frame);
1165 }
1166
1167 if (stream_conf->stream_params.source
1168 .codec_frames_blocks_per_sdu == 0) {
1169 stream_conf->stream_params.source
1170 .codec_frames_blocks_per_sdu =
1171 *core_config.codec_frames_blocks_per_sdu;
1172 } else {
1173 log::assert_that(
1174 stream_conf->stream_params.source
1175 .codec_frames_blocks_per_sdu ==
1176 *core_config.codec_frames_blocks_per_sdu,
1177 "codec_frames_blocks_per_sdu: {}!={}",
1178 stream_conf->stream_params.source
1179 .codec_frames_blocks_per_sdu,
1180 *core_config.codec_frames_blocks_per_sdu);
1181 }
1182
1183 log::info(
1184 "Added Source Stream Configuration. CIS Connection "
1185 "Handle: {}, Audio Channel Allocation: {}, Source Number "
1186 "Of Devices: {}, Source Number Of Channels: {}",
1187 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1188 stream_conf->stream_params.source.num_of_devices,
1189 stream_conf->stream_params.source.num_of_channels);
1190 }
1191 } else {
1192 auto iter = std::find_if(
1193 stream_conf->stream_params.sink.stream_locations.begin(),
1194 stream_conf->stream_params.sink.stream_locations.end(),
1195 [cis_conn_hdl](auto& pair) {
1196 return cis_conn_hdl == pair.first;
1197 });
1198
1199 if (iter ==
1200 stream_conf->stream_params.sink.stream_locations.end()) {
1201 stream_conf->stream_params.sink.stream_locations.emplace_back(
1202 std::make_pair(ase.cis_conn_hdl,
1203 *core_config.audio_channel_allocation));
1204
1205 stream_conf->stream_params.sink.num_of_devices++;
1206 stream_conf->stream_params.sink.num_of_channels +=
1207 ase.channel_count;
1208
1209 stream_conf->stream_params.sink.audio_channel_allocation |=
1210 *core_config.audio_channel_allocation;
1211
1212 if (stream_conf->stream_params.sink.sample_frequency_hz ==
1213 0) {
1214 stream_conf->stream_params.sink.sample_frequency_hz =
1215 core_config.GetSamplingFrequencyHz();
1216 } else {
1217 log::assert_that(
1218 stream_conf->stream_params.sink.sample_frequency_hz ==
1219 core_config.GetSamplingFrequencyHz(),
1220 "sample freq mismatch: {}!={}",
1221 stream_conf->stream_params.sink.sample_frequency_hz,
1222 core_config.GetSamplingFrequencyHz());
1223 }
1224
1225 if (stream_conf->stream_params.sink.octets_per_codec_frame ==
1226 0) {
1227 stream_conf->stream_params.sink.octets_per_codec_frame =
1228 *core_config.octets_per_codec_frame;
1229 } else {
1230 log::assert_that(
1231 stream_conf->stream_params.sink
1232 .octets_per_codec_frame ==
1233 *core_config.octets_per_codec_frame,
1234 "octets per frame mismatch: {}!={}",
1235 stream_conf->stream_params.sink.octets_per_codec_frame,
1236 *core_config.octets_per_codec_frame);
1237 }
1238
1239 if (stream_conf->stream_params.sink
1240 .codec_frames_blocks_per_sdu == 0) {
1241 stream_conf->stream_params.sink
1242 .codec_frames_blocks_per_sdu =
1243 *core_config.codec_frames_blocks_per_sdu;
1244 } else {
1245 log::assert_that(
1246 stream_conf->stream_params.sink
1247 .codec_frames_blocks_per_sdu ==
1248 *core_config.codec_frames_blocks_per_sdu,
1249 "codec_frames_blocks_per_sdu: {}!={}",
1250 stream_conf->stream_params.sink
1251 .codec_frames_blocks_per_sdu,
1252 *core_config.codec_frames_blocks_per_sdu);
1253 }
1254
1255 log::info(
1256 "Added Sink Stream Configuration. CIS Connection Handle: "
1257 "{}, Audio Channel Allocation: {}, Sink Number Of "
1258 "Devices: {}, Sink Number Of Channels: {}",
1259 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1260 stream_conf->stream_params.sink.num_of_devices,
1261 stream_conf->stream_params.sink.num_of_channels);
1262 }
1263 }
1264 }
1265 }
1266
1267 // Inject the state
1268 group->SetTargetState(
1269 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1270 group->SetState(
1271 types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1272 streaming_groups[group->group_id_] = group;
1273
1274 /* Assume CIG is created */
1275 group->cig.SetState(bluetooth::le_audio::types::CigState::CREATED);
1276
1277 if (block_streaming_state_callback) return true;
1278
1279 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1280 do_in_main_thread(
1281 FROM_HERE,
1282 base::BindOnce(
1283 [](int group_id,
1284 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
1285 state_machine_callbacks) {
1286 state_machine_callbacks->StatusReportCb(
1287 group_id, GroupStreamStatus::STREAMING);
1288 },
1289 group->group_id_,
1290 base::Unretained(this->state_machine_callbacks_)));
1291 return true;
1292 });
1293
1294 ON_CALL(mock_state_machine_, SuspendStream(_))
1295 .WillByDefault([this](LeAudioDeviceGroup* group) {
1296 // Fake ASE state
1297 for (LeAudioDevice* device = group->GetFirstDevice();
1298 device != nullptr; device = group->GetNextDevice(device)) {
1299 for (auto& ase : device->ases_) {
1300 ase.cis_state = types::CisState::CONNECTED;
1301 ase.active = false;
1302 ase.state =
1303 types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED;
1304 }
1305 }
1306
1307 // Inject the state
1308 group->SetTargetState(
1309 types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1310 group->SetState(group->GetTargetState());
1311 state_machine_callbacks_->StatusReportCb(
1312 group->group_id_, GroupStreamStatus::SUSPENDED);
1313 });
1314
1315 ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
1316 .WillByDefault([this](LeAudioDeviceGroup* group,
1317 LeAudioDevice* leAudioDevice) {
1318 if (!group) return;
1319 auto* stream_conf = &group->stream_conf;
1320 if (!stream_conf->stream_params.sink.stream_locations.empty() ||
1321 !stream_conf->stream_params.source.stream_locations.empty()) {
1322 stream_conf->stream_params.sink.stream_locations.erase(
1323 std::remove_if(
1324 stream_conf->stream_params.sink.stream_locations.begin(),
1325 stream_conf->stream_params.sink.stream_locations.end(),
1326 [leAudioDevice, &stream_conf](auto& pair) {
1327 auto ases =
1328 leAudioDevice->GetAsesByCisConnHdl(pair.first);
1329 if (ases.sink) {
1330 stream_conf->stream_params.sink.num_of_devices--;
1331 stream_conf->stream_params.sink.num_of_channels -=
1332 ases.sink->channel_count;
1333
1334 log::info(
1335 ", Source Number Of Devices: {}"
1336 ", Source Number Of Channels: {}",
1337 stream_conf->stream_params.source.num_of_devices,
1338 stream_conf->stream_params.source.num_of_channels);
1339 }
1340 return ases.sink;
1341 }),
1342 stream_conf->stream_params.sink.stream_locations.end());
1343
1344 stream_conf->stream_params.source.stream_locations.erase(
1345 std::remove_if(
1346 stream_conf->stream_params.source.stream_locations.begin(),
1347 stream_conf->stream_params.source.stream_locations.end(),
1348 [leAudioDevice, &stream_conf](auto& pair) {
1349 auto ases =
1350 leAudioDevice->GetAsesByCisConnHdl(pair.first);
1351 if (ases.source) {
1352 stream_conf->stream_params.source.num_of_devices--;
1353 stream_conf->stream_params.source.num_of_channels -=
1354 ases.source->channel_count;
1355
1356 log::info(
1357 ", Source Number Of Devices: {}, Source Number Of "
1358 "Channels: {}",
1359 stream_conf->stream_params.source.num_of_devices,
1360 stream_conf->stream_params.source.num_of_channels);
1361 }
1362 return ases.source;
1363 }),
1364 stream_conf->stream_params.source.stream_locations.end());
1365 }
1366
1367 group->cig.UnassignCis(leAudioDevice);
1368
1369 if (group->IsEmpty()) {
1370 group->cig.SetState(bluetooth::le_audio::types::CigState::NONE);
1371 InjectCigRemoved(group->group_id_);
1372 }
1373 });
1374
1375 ON_CALL(mock_state_machine_, ProcessHciNotifCisDisconnected(_, _, _))
1376 .WillByDefault([](LeAudioDeviceGroup* group,
1377 LeAudioDevice* leAudioDevice,
1378 const bluetooth::hci::iso_manager::
1379 cis_disconnected_evt* event) {
1380 if (!group) return;
1381 auto ases_pair =
1382 leAudioDevice->GetAsesByCisConnHdl(event->cis_conn_hdl);
1383 if (ases_pair.sink) {
1384 ases_pair.sink->cis_state = types::CisState::ASSIGNED;
1385 ases_pair.sink->active = false;
1386 }
1387 if (ases_pair.source) {
1388 ases_pair.source->active = false;
1389 ases_pair.source->cis_state = types::CisState::ASSIGNED;
1390 }
1391 /* Invalidate stream configuration if needed */
1392 auto* stream_conf = &group->stream_conf;
1393 if (!stream_conf->stream_params.sink.stream_locations.empty() ||
1394 !stream_conf->stream_params.source.stream_locations.empty()) {
1395 stream_conf->stream_params.sink.stream_locations.erase(
1396 std::remove_if(
1397 stream_conf->stream_params.sink.stream_locations.begin(),
1398 stream_conf->stream_params.sink.stream_locations.end(),
1399 [leAudioDevice, &stream_conf](auto& pair) {
1400 auto ases =
1401 leAudioDevice->GetAsesByCisConnHdl(pair.first);
1402
1403 log::info(
1404 ", sink ase to delete. Cis handle: {}, ase pointer: "
1405 "{}",
1406 (int)(pair.first), fmt::ptr(+ases.sink));
1407 if (ases.sink) {
1408 stream_conf->stream_params.sink.num_of_devices--;
1409 stream_conf->stream_params.sink.num_of_channels -=
1410 ases.sink->channel_count;
1411
1412 log::info(
1413 "Sink Number Of Devices: {}, Sink Number Of "
1414 "Channels: {}",
1415 stream_conf->stream_params.sink.num_of_devices,
1416 stream_conf->stream_params.sink.num_of_channels);
1417 }
1418 return ases.sink;
1419 }),
1420 stream_conf->stream_params.sink.stream_locations.end());
1421
1422 stream_conf->stream_params.source.stream_locations.erase(
1423 std::remove_if(
1424 stream_conf->stream_params.source.stream_locations.begin(),
1425 stream_conf->stream_params.source.stream_locations.end(),
1426 [leAudioDevice, &stream_conf](auto& pair) {
1427 auto ases =
1428 leAudioDevice->GetAsesByCisConnHdl(pair.first);
1429
1430 log::info(
1431 ", source to delete. Cis handle: {}, ase pointer: {}",
1432 (int)(pair.first), fmt::ptr(ases.source));
1433 if (ases.source) {
1434 stream_conf->stream_params.source.num_of_devices--;
1435 stream_conf->stream_params.source.num_of_channels -=
1436 ases.source->channel_count;
1437
1438 log::info(
1439 ", Source Number Of Devices: {}, Source Number Of "
1440 "Channels: {}",
1441 stream_conf->stream_params.source.num_of_devices,
1442 stream_conf->stream_params.source.num_of_channels);
1443 }
1444 return ases.source;
1445 }),
1446 stream_conf->stream_params.source.stream_locations.end());
1447 }
1448
1449 group->cig.UnassignCis(leAudioDevice);
1450 });
1451
1452 ON_CALL(mock_state_machine_, StopStream(_))
1453 .WillByDefault([this](LeAudioDeviceGroup* group) {
1454 for (LeAudioDevice* device = group->GetFirstDevice();
1455 device != nullptr; device = group->GetNextDevice(device)) {
1456 /* Invalidate stream configuration if needed */
1457 auto* stream_conf = &group->stream_conf;
1458 if (!stream_conf->stream_params.sink.stream_locations.empty() ||
1459 !stream_conf->stream_params.source.stream_locations.empty()) {
1460 stream_conf->stream_params.sink.stream_locations.erase(
1461 std::remove_if(
1462 stream_conf->stream_params.sink.stream_locations.begin(),
1463 stream_conf->stream_params.sink.stream_locations.end(),
1464 [device, &stream_conf](auto& pair) {
1465 auto ases = device->GetAsesByCisConnHdl(pair.first);
1466
1467 log::info(
1468 ", sink ase to delete. Cis handle: {}, ase "
1469 "pointer: {}",
1470 (int)(pair.first), fmt::ptr(+ases.sink));
1471 if (ases.sink) {
1472 stream_conf->stream_params.sink.num_of_devices--;
1473 stream_conf->stream_params.sink.num_of_channels -=
1474 ases.sink->channel_count;
1475
1476 log::info(
1477 "Sink Number Of Devices: {}, Sink Number Of "
1478 "Channels: {}",
1479 stream_conf->stream_params.sink.num_of_devices,
1480 stream_conf->stream_params.sink.num_of_channels);
1481 }
1482 return ases.sink;
1483 }),
1484 stream_conf->stream_params.sink.stream_locations.end());
1485
1486 stream_conf->stream_params.source.stream_locations.erase(
1487 std::remove_if(
1488 stream_conf->stream_params.source.stream_locations
1489 .begin(),
1490 stream_conf->stream_params.source.stream_locations.end(),
1491 [device, &stream_conf](auto& pair) {
1492 auto ases = device->GetAsesByCisConnHdl(pair.first);
1493
1494 log::info(
1495 ", source to delete. Cis handle: {}, ase pointer: "
1496 "{}",
1497 (int)(pair.first), fmt::ptr(+ases.source));
1498 if (ases.source) {
1499 stream_conf->stream_params.source.num_of_devices--;
1500 stream_conf->stream_params.source.num_of_channels -=
1501 ases.source->channel_count;
1502
1503 log::info(
1504 ", Source Number Of Devices: {}, Source Number "
1505 "Of Channels: {}",
1506 stream_conf->stream_params.source.num_of_devices,
1507 stream_conf->stream_params.source
1508 .num_of_channels);
1509 }
1510 return ases.source;
1511 }),
1512 stream_conf->stream_params.source.stream_locations.end());
1513 }
1514
1515 group->cig.UnassignCis(device);
1516
1517 for (auto& ase : device->ases_) {
1518 ase.cis_state = types::CisState::IDLE;
1519 ase.data_path_state = types::DataPathState::IDLE;
1520 ase.active = false;
1521 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
1522 ase.cis_id = 0;
1523 ase.cis_conn_hdl = 0;
1524 }
1525 }
1526
1527 // Inject the state
1528 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
1529 group->SetState(group->GetTargetState());
1530 state_machine_callbacks_->StatusReportCb(
1531 group->group_id_, GroupStreamStatus::RELEASING);
1532
1533 do_in_main_thread(
1534 FROM_HERE,
1535 base::BindOnce(
1536 [](bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
1537 cb,
1538 int group_id) {
1539 cb->StatusReportCb(group_id, GroupStreamStatus::IDLE);
1540 },
1541 state_machine_callbacks_, group->group_id_));
1542 });
1543 }
1544
SetUp()1545 void SetUp() override {
1546 __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
1547 init_message_loop_thread();
1548 ON_CALL(controller_, SupportsBleConnectedIsochronousStreamCentral)
1549 .WillByDefault(Return(true));
1550 ON_CALL(controller_, SupportsBleConnectedIsochronousStreamPeripheral)
1551 .WillByDefault(Return(true));
1552 ON_CALL(controller_, SupportsBle2mPhy).WillByDefault(Return(true));
1553 bluetooth::hci::testing::mock_controller_ = &controller_;
1554 bluetooth::manager::SetMockBtmInterface(&mock_btm_interface_);
1555 gatt::SetMockBtaGattInterface(&mock_gatt_interface_);
1556 gatt::SetMockBtaGattQueue(&mock_gatt_queue_);
1557 bluetooth::storage::SetMockBtifStorageInterface(&mock_btif_storage_);
1558
1559 iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
1560 ASSERT_NE(iso_manager_, nullptr);
1561 iso_manager_->Start();
1562
1563 mock_iso_manager_ = MockIsoManager::GetInstance();
1564 ON_CALL(*mock_iso_manager_, RegisterCigCallbacks(_))
1565 .WillByDefault(SaveArg<0>(&cig_callbacks_));
1566
1567 ON_CALL(mock_btm_interface_, IsLinkKeyKnown(_, _))
1568 .WillByDefault(DoAll(Return(true)));
1569
1570 // Required since we call OnAudioDataReady()
1571 const auto codec_location =
1572 ::bluetooth::le_audio::types::CodecLocation::HOST;
1573
1574 SetUpMockAudioHal();
1575 SetUpMockGroups();
1576 SetUpMockGatt();
1577 SetUpMockCodecManager(codec_location);
1578
1579 block_streaming_state_callback = false;
1580
1581 available_snk_context_types_ = 0xffff;
1582 available_src_context_types_ = 0xffff;
1583 supported_snk_context_types_ = 0xffff;
1584 supported_src_context_types_ = 0xffff;
1585
1586 empty_source_pack_ = false;
1587 empty_sink_pack_ = false;
1588
1589 bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(
1590 codec_location);
1591 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
1592 }
1593
SetUpMockCodecManager(types::CodecLocation location)1594 void SetUpMockCodecManager(types::CodecLocation location) {
1595 codec_manager_ = bluetooth::le_audio::CodecManager::GetInstance();
1596 ASSERT_NE(codec_manager_, nullptr);
1597 std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
1598 mock_offloading_preference(0);
1599 codec_manager_->Start(mock_offloading_preference);
1600 mock_codec_manager_ = MockCodecManager::GetInstance();
1601 ASSERT_NE((void*)mock_codec_manager_, (void*)codec_manager_);
1602 ASSERT_NE(mock_codec_manager_, nullptr);
1603 ON_CALL(*mock_codec_manager_, GetCodecLocation())
1604 .WillByDefault(Return(location));
1605 ON_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(_, _, _))
1606 .WillByDefault(Return(true));
1607 ON_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(_, _))
1608 .WillByDefault(Return(true));
1609 // Turn on the dual bidir SWB support
1610 ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported)
1611 .WillByDefault(Return(true));
1612 // Regardless of the codec location, return all the possible configurations
1613 ON_CALL(*mock_codec_manager_, GetCodecConfig)
1614 .WillByDefault(
1615 Invoke([](const CodecManager::UnicastConfigurationRequirements&
1616 requirements,
1617 CodecManager::UnicastConfigurationVerifier verifier) {
1618 auto filtered =
1619 *le_audio::AudioSetConfigurationProvider::Get()
1620 ->GetConfigurations(requirements.audio_context_type);
1621 // Filter out the dual bidir SWB configurations
1622 if (!bluetooth::le_audio::CodecManager::GetInstance()
1623 ->IsDualBiDirSwbSupported()) {
1624 filtered.erase(
1625 std::remove_if(filtered.begin(), filtered.end(),
1626 [](auto const& el) {
1627 if (el->confs.source.empty()) return false;
1628 return AudioSetConfigurationProvider::Get()
1629 ->CheckConfigurationIsDualBiDirSwb(
1630 *el);
1631 }),
1632 filtered.end());
1633 }
1634 auto cptr = verifier(requirements, &filtered);
1635 return cptr
1636 ? std::make_unique<
1637 set_configurations::AudioSetConfiguration>(*cptr)
1638 : nullptr;
1639 }));
1640 }
1641
TearDown()1642 void TearDown() override {
1643 if (is_audio_unicast_source_acquired) {
1644 if (unicast_source_hal_cb_ != nullptr) {
1645 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(1);
1646 }
1647 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
1648 }
1649
1650 if (is_audio_unicast_sink_acquired) {
1651 if (unicast_sink_hal_cb_ != nullptr) {
1652 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop).Times(1);
1653 }
1654 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
1655 }
1656
1657 // Message loop cleanup should wait for all the 'till now' scheduled calls
1658 // so it should be called right at the very begginning of teardown.
1659 cleanup_message_loop_thread();
1660
1661 // This is required since Stop() and Cleanup() may trigger some callbacks or
1662 // drop unique pointers to mocks we have raw pointer for and we want to
1663 // verify them all.
1664 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1665
1666 if (LeAudioClient::IsLeAudioClientRunning()) {
1667 EXPECT_CALL(mock_gatt_interface_, AppDeregister(gatt_if)).Times(1);
1668 LeAudioClient::Cleanup();
1669 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
1670 }
1671
1672 owned_mock_le_audio_sink_hal_client_.reset();
1673 owned_mock_le_audio_source_hal_client_.reset();
1674
1675 if (bluetooth::le_audio::AudioSetConfigurationProvider::Get())
1676 bluetooth::le_audio::AudioSetConfigurationProvider::Cleanup();
1677
1678 iso_manager_->Stop();
1679 bluetooth::hci::testing::mock_controller_ = nullptr;
1680 }
1681
1682 protected:
1683 class MockDeviceWrapper {
1684 class IGattHandlers {
1685 public:
1686 // IGattHandlers() = default;
1687 virtual ~IGattHandlers() = default;
1688 virtual void OnReadCharacteristic(uint16_t handle, GATT_READ_OP_CB cb,
1689 void* cb_data) = 0;
1690 virtual void OnWriteCharacteristic(uint16_t handle,
1691 std::vector<uint8_t> value,
1692 tGATT_WRITE_TYPE write_type,
1693 GATT_WRITE_OP_CB cb,
1694 void* cb_data) = 0;
1695 };
1696
1697 public:
1698 struct csis_mock : public IGattHandlers {
1699 uint16_t start = 0;
1700 uint16_t end = 0;
1701 uint16_t sirk_char = 0;
1702 uint16_t sirk_ccc = 0;
1703 uint16_t size_char = 0;
1704 uint16_t size_ccc = 0;
1705 uint16_t lock_char = 0;
1706 uint16_t lock_ccc = 0;
1707 uint16_t rank_char = 0;
1708
1709 int rank = 0;
1710 int size = 0;
1711
1712 MOCK_METHOD((void), OnReadCharacteristic,
1713 (uint16_t handle, GATT_READ_OP_CB cb, void* cb_data),
1714 (override));
1715 MOCK_METHOD((void), OnWriteCharacteristic,
1716 (uint16_t handle, std::vector<uint8_t> value,
1717 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1718 void* cb_data),
1719 (override));
1720 };
1721
1722 struct cas_mock : public IGattHandlers {
1723 uint16_t start = 0;
1724 uint16_t end = 0;
1725 uint16_t csis_include = 0;
1726
1727 MOCK_METHOD((void), OnReadCharacteristic,
1728 (uint16_t handle, GATT_READ_OP_CB cb, void* cb_data),
1729 (override));
1730 MOCK_METHOD((void), OnWriteCharacteristic,
1731 (uint16_t handle, std::vector<uint8_t> value,
1732 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1733 void* cb_data),
1734 (override));
1735 };
1736
1737 struct pacs_mock : public IGattHandlers {
1738 uint16_t start = 0;
1739 uint16_t sink_pac_char = 0;
1740 uint16_t sink_pac_ccc = 0;
1741 uint16_t sink_audio_loc_char = 0;
1742 uint16_t sink_audio_loc_ccc = 0;
1743 uint16_t source_pac_char = 0;
1744 uint16_t source_pac_ccc = 0;
1745 uint16_t source_audio_loc_char = 0;
1746 uint16_t source_audio_loc_ccc = 0;
1747 uint16_t avail_contexts_char = 0;
1748 uint16_t avail_contexts_ccc = 0;
1749 uint16_t supp_contexts_char = 0;
1750 uint16_t supp_contexts_ccc = 0;
1751 uint16_t end = 0;
1752
1753 MOCK_METHOD((void), OnReadCharacteristic,
1754 (uint16_t handle, GATT_READ_OP_CB cb, void* cb_data),
1755 (override));
1756 MOCK_METHOD((void), OnWriteCharacteristic,
1757 (uint16_t handle, std::vector<uint8_t> value,
1758 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1759 void* cb_data),
1760 (override));
1761 };
1762
1763 struct ascs_mock : public IGattHandlers {
1764 uint16_t start = 0;
1765 uint16_t sink_ase_char[max_num_of_ases] = {0};
1766 uint16_t sink_ase_ccc[max_num_of_ases] = {0};
1767 uint16_t sink_ase_ccc_val[max_num_of_ases] = {0};
1768 uint16_t source_ase_char[max_num_of_ases] = {0};
1769 uint16_t source_ase_ccc[max_num_of_ases] = {0};
1770 uint16_t source_ase_ccc_val[max_num_of_ases] = {0};
1771 uint16_t ctp_char = 0;
1772 uint16_t ctp_ccc = 0;
1773 uint16_t ctp_ccc_val = 0;
1774 uint16_t end = 0;
1775
1776 MOCK_METHOD((void), OnReadCharacteristic,
1777 (uint16_t handle, GATT_READ_OP_CB cb, void* cb_data),
1778 (override));
1779 MOCK_METHOD((void), OnWriteCharacteristic,
1780 (uint16_t handle, std::vector<uint8_t> value,
1781 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1782 void* cb_data),
1783 (override));
1784 };
1785
MockDeviceWrapper(RawAddress addr,const std::list<gatt::Service> & services,std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs)1786 MockDeviceWrapper(
1787 RawAddress addr, const std::list<gatt::Service>& services,
1788 std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,
1789 std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,
1790 std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,
1791 std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs)
1792 : addr(addr) {
1793 this->services = services;
1794 this->csis = std::move(csis);
1795 this->cas = std::move(cas);
1796 this->ascs = std::move(ascs);
1797 this->pacs = std::move(pacs);
1798 }
1799
~MockDeviceWrapper()1800 ~MockDeviceWrapper() {
1801 Mock::VerifyAndClearExpectations(csis.get());
1802 Mock::VerifyAndClearExpectations(cas.get());
1803 Mock::VerifyAndClearExpectations(ascs.get());
1804 Mock::VerifyAndClearExpectations(pacs.get());
1805 }
1806
1807 RawAddress addr;
1808 bool connected = false;
1809
1810 // A list of services and their useful params
1811 std::list<gatt::Service> services;
1812 std::unique_ptr<csis_mock> csis;
1813 std::unique_ptr<cas_mock> cas;
1814 std::unique_ptr<ascs_mock> ascs;
1815 std::unique_ptr<pacs_mock> pacs;
1816 };
1817
SyncOnMainLoop()1818 void SyncOnMainLoop() {
1819 // Wait for the main loop to flush
1820 // WARNING: Not tested with Timers pushing periodic tasks to the main loop
1821 while (num_async_tasks > 0)
1822 ;
1823 }
1824
ConnectLeAudio(const RawAddress & address,bool isEncrypted=true,bool expect_connected_event=true)1825 void ConnectLeAudio(const RawAddress& address, bool isEncrypted = true,
1826 bool expect_connected_event = true) {
1827 // by default indicate link as encrypted
1828 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(address, _))
1829 .WillByDefault(DoAll(Return(isEncrypted)));
1830
1831 ON_CALL(mock_btm_interface_, IsLinkKeyKnown(address, _))
1832 .WillByDefault(DoAll(Return(true)));
1833
1834 EXPECT_CALL(mock_gatt_interface_,
1835 Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, _))
1836 .Times(1);
1837
1838 /* If connected event is not expected to arrive, don't test those two below
1839 */
1840 if (expect_connected_event) {
1841 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, address, false));
1842 EXPECT_CALL(
1843 mock_gatt_interface_,
1844 Open(gatt_if, address, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
1845 .Times(1);
1846 }
1847
1848 do_in_main_thread(
1849 FROM_HERE,
1850 base::BindOnce(&LeAudioClient::Connect,
1851 base::Unretained(LeAudioClient::Get()), address));
1852
1853 SyncOnMainLoop();
1854 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1855 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1856 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1857 }
1858
DisconnectLeAudioWithGattClose(const RawAddress & address,uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST)1859 void DisconnectLeAudioWithGattClose(
1860 const RawAddress& address, uint16_t conn_id,
1861 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) {
1862 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1863 OnConnectionState(ConnectionState::DISCONNECTED, address))
1864 .Times(1);
1865
1866 // For test purpose use the acl handle same as conn_id
1867 ON_CALL(mock_btm_interface_, GetHCIConnHandle(address, _))
1868 .WillByDefault([conn_id](RawAddress const& bd_addr,
1869 tBT_TRANSPORT transport) { return conn_id; });
1870 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _))
1871 .Times(0);
1872 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
1873
1874 do_in_main_thread(
1875 FROM_HERE, base::Bind(&LeAudioClient::Disconnect,
1876 base::Unretained(LeAudioClient::Get()), address));
1877 SyncOnMainLoop();
1878 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1879 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1880 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1881 }
1882
DisconnectLeAudioWithAclClose(const RawAddress & address,uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST)1883 void DisconnectLeAudioWithAclClose(
1884 const RawAddress& address, uint16_t conn_id,
1885 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) {
1886 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1887 OnConnectionState(ConnectionState::DISCONNECTED, address))
1888 .Times(1);
1889
1890 // For test purpose use the acl handle same as conn_id
1891 ON_CALL(mock_btm_interface_, GetHCIConnHandle(address, _))
1892 .WillByDefault([conn_id](RawAddress const& bd_addr,
1893 tBT_TRANSPORT transport) { return conn_id; });
1894 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _))
1895 .WillOnce([this, &reason](uint16_t handle, tHCI_STATUS rs) {
1896 InjectDisconnectedEvent(handle, reason);
1897 });
1898 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(0);
1899
1900 do_in_main_thread(
1901 FROM_HERE, base::Bind(&LeAudioClient::Disconnect,
1902 base::Unretained(LeAudioClient::Get()), address));
1903 SyncOnMainLoop();
1904 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1905 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1906 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1907 }
1908
DisconnectLeAudioNoDisconnectedEvtExpected(const RawAddress & address,uint16_t conn_id)1909 void DisconnectLeAudioNoDisconnectedEvtExpected(const RawAddress& address,
1910 uint16_t conn_id) {
1911 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(0);
1912 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _))
1913 .Times(1);
1914 do_in_main_thread(
1915 FROM_HERE,
1916 base::BindOnce(&LeAudioClient::Disconnect,
1917 base::Unretained(LeAudioClient::Get()), address));
1918 SyncOnMainLoop();
1919 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1920 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1921 }
1922
ConnectCsisDevice(const RawAddress & addr,uint16_t conn_id,uint32_t sink_audio_allocation,uint32_t source_audio_allocation,uint8_t group_size,int group_id,uint8_t rank,bool connect_through_csis=false,bool new_device=true)1923 void ConnectCsisDevice(const RawAddress& addr, uint16_t conn_id,
1924 uint32_t sink_audio_allocation,
1925 uint32_t source_audio_allocation, uint8_t group_size,
1926 int group_id, uint8_t rank,
1927 bool connect_through_csis = false,
1928 bool new_device = true) {
1929 SetSampleDatabaseEarbudsValid(conn_id, addr, sink_audio_allocation,
1930 source_audio_allocation, default_channel_cnt,
1931 default_channel_cnt,
1932 0x0004, /* source sample freq 16khz */
1933 true, /*add_csis*/
1934 true, /*add_cas*/
1935 true, /*add_pacs*/
1936 true, /*add_ascs*/
1937 group_size, rank);
1938 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1939 OnConnectionState(ConnectionState::CONNECTED, addr))
1940 .Times(1);
1941
1942 if (new_device) {
1943 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1944 OnGroupNodeStatus(addr, group_id, GroupNodeStatus::ADDED))
1945 .Times(1);
1946 }
1947
1948 if (connect_through_csis) {
1949 // Add it the way CSIS would do: add to group and then connect
1950 do_in_main_thread(FROM_HERE,
1951 base::BindOnce(&LeAudioClient::GroupAddNode,
1952 base::Unretained(LeAudioClient::Get()),
1953 group_id, addr));
1954 ConnectLeAudio(addr);
1955 } else {
1956 // The usual connect
1957 // Since device has CSIS, lets add it here to groups already now
1958 groups[addr] = group_id;
1959 ConnectLeAudio(addr);
1960 InjectGroupDeviceAdded(addr, group_id);
1961 }
1962 }
1963
ConnectNonCsisDevice(const RawAddress & addr,uint16_t conn_id,uint32_t sink_audio_allocation,uint32_t source_audio_allocation)1964 void ConnectNonCsisDevice(const RawAddress& addr, uint16_t conn_id,
1965 uint32_t sink_audio_allocation,
1966 uint32_t source_audio_allocation) {
1967 SetSampleDatabaseEarbudsValid(
1968 conn_id, addr, sink_audio_allocation, source_audio_allocation,
1969 default_channel_cnt, default_channel_cnt, 0x0004,
1970 /* source sample freq 16khz */ false, /*add_csis*/
1971 true, /*add_cas*/
1972 true, /*add_pacs*/
1973 true, /*add_ascs*/
1974 0, 0);
1975 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1976 OnConnectionState(ConnectionState::CONNECTED, addr))
1977 .Times(1);
1978
1979 ConnectLeAudio(addr);
1980 }
1981
UpdateLocalSourceMetadata(std::vector<struct playback_track_metadata> tracks,bool reconfigure_existing_stream=false)1982 void UpdateLocalSourceMetadata(
1983 std::vector<struct playback_track_metadata> tracks,
1984 bool reconfigure_existing_stream = false) {
1985 std::vector<playback_track_metadata_v7> tracks_vec;
1986 tracks_vec.reserve(tracks.size());
1987 for (const auto& track : tracks) {
1988 playback_track_metadata_v7 desc_track = {
1989 .base =
1990 {
1991 .usage = static_cast<audio_usage_t>(track.usage),
1992 .content_type =
1993 static_cast<audio_content_type_t>(track.content_type),
1994 .gain = track.gain,
1995 },
1996 };
1997 if (test_tags_ptr_) {
1998 memcpy(desc_track.tags, test_tags_ptr_, strlen(test_tags_ptr_));
1999 }
2000
2001 tracks_vec.push_back(desc_track);
2002 }
2003
2004 ASSERT_NE(nullptr, mock_le_audio_source_hal_client_);
2005 /* Local Source may reconfigure once the metadata is updated */
2006 if (reconfigure_existing_stream) {
2007 Expectation reconfigure = EXPECT_CALL(*mock_le_audio_source_hal_client_,
2008 SuspendedForReconfiguration())
2009 .Times(1);
2010 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest())
2011 .Times(1);
2012 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
2013 .Times(1)
2014 .After(reconfigure);
2015 } else {
2016 EXPECT_CALL(*mock_le_audio_source_hal_client_,
2017 SuspendedForReconfiguration())
2018 .Times(0);
2019 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
2020 .Times(0);
2021 }
2022
2023 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2024 unicast_source_hal_cb_->OnAudioMetadataUpdate(std::move(tracks_vec),
2025 DsaMode::DISABLED);
2026 }
2027
UpdateLocalSourceMetadata(audio_usage_t usage,audio_content_type_t content_type,bool reconfigure_existing_stream=false)2028 void UpdateLocalSourceMetadata(audio_usage_t usage,
2029 audio_content_type_t content_type,
2030 bool reconfigure_existing_stream = false) {
2031 std::vector<struct playback_track_metadata> tracks = {
2032 {{AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0},
2033 {AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0}}};
2034
2035 tracks[0].usage = usage;
2036 tracks[0].content_type = content_type;
2037 UpdateLocalSourceMetadata(tracks, reconfigure_existing_stream);
2038 }
2039
UpdateLocalSinkMetadata(audio_source_t audio_source)2040 void UpdateLocalSinkMetadata(audio_source_t audio_source) {
2041 std::vector<struct record_track_metadata> tracks = {
2042 {{AUDIO_SOURCE_INVALID, 0.5, AUDIO_DEVICE_NONE, "00:11:22:33:44:55"},
2043 {AUDIO_SOURCE_MIC, 0.7, AUDIO_DEVICE_OUT_BLE_HEADSET,
2044 "AA:BB:CC:DD:EE:FF"}}};
2045
2046 tracks[1].source = audio_source;
2047
2048 std::vector<record_track_metadata_v7> tracks_vec;
2049 tracks_vec.reserve(tracks.size());
2050 for (const auto& track : tracks) {
2051 record_track_metadata_v7 desc_track = {
2052 .base =
2053 {
2054 .source = static_cast<audio_source_t>(track.source),
2055 .gain = track.gain,
2056 .dest_device =
2057 static_cast<audio_devices_t>(track.dest_device),
2058 },
2059 };
2060
2061 strcpy(desc_track.base.dest_device_address, track.dest_device_address);
2062 tracks_vec.push_back(desc_track);
2063 }
2064
2065 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
2066 unicast_sink_hal_cb_->OnAudioMetadataUpdate(std::move(tracks_vec));
2067 }
2068
LocalAudioSourceSuspend(void)2069 void LocalAudioSourceSuspend(void) {
2070 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2071 unicast_source_hal_cb_->OnAudioSuspend();
2072 SyncOnMainLoop();
2073 }
2074
LocalAudioSourceResume(bool expected_confirmation=true,bool expected_cancel=false)2075 void LocalAudioSourceResume(bool expected_confirmation = true,
2076 bool expected_cancel = false) {
2077 ASSERT_NE(nullptr, mock_le_audio_source_hal_client_);
2078 if (expected_confirmation) {
2079 EXPECT_CALL(*mock_le_audio_source_hal_client_, ConfirmStreamingRequest())
2080 .Times(1);
2081 }
2082
2083 if (expected_cancel) {
2084 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest())
2085 .Times(1);
2086 }
2087
2088 do_in_main_thread(FROM_HERE,
2089 base::BindOnce(
2090 [](LeAudioSourceAudioHalClient::Callbacks* cb) {
2091 if (cb) cb->OnAudioResume();
2092 },
2093 unicast_source_hal_cb_));
2094
2095 SyncOnMainLoop();
2096 Mock::VerifyAndClearExpectations(&*mock_le_audio_source_hal_client_);
2097 }
2098
LocalAudioSinkSuspend(void)2099 void LocalAudioSinkSuspend(void) {
2100 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2101 unicast_sink_hal_cb_->OnAudioSuspend();
2102 SyncOnMainLoop();
2103 }
2104
LocalAudioSinkResume(void)2105 void LocalAudioSinkResume(void) {
2106 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2107 do_in_main_thread(FROM_HERE,
2108 base::BindOnce(
2109 [](LeAudioSinkAudioHalClient::Callbacks* cb) {
2110 cb->OnAudioResume();
2111 },
2112 unicast_sink_hal_cb_));
2113
2114 SyncOnMainLoop();
2115 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
2116 }
2117
StartStreaming(audio_usage_t usage,audio_content_type_t content_type,int group_id,audio_source_t audio_source=AUDIO_SOURCE_INVALID,bool reconfigure_existing_stream=false,bool expected_resume_confirmation=true)2118 void StartStreaming(audio_usage_t usage, audio_content_type_t content_type,
2119 int group_id,
2120 audio_source_t audio_source = AUDIO_SOURCE_INVALID,
2121 bool reconfigure_existing_stream = false,
2122 bool expected_resume_confirmation = true) {
2123 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2124
2125 UpdateLocalSourceMetadata(usage, content_type, reconfigure_existing_stream);
2126 if (audio_source != AUDIO_SOURCE_INVALID) {
2127 UpdateLocalSinkMetadata(audio_source);
2128 }
2129
2130 /* Stream has been automatically restarted on UpdateLocalSourceMetadata */
2131 if (reconfigure_existing_stream) return;
2132
2133 LocalAudioSourceResume(expected_resume_confirmation);
2134 SyncOnMainLoop();
2135 Mock::VerifyAndClearExpectations(&mock_state_machine_);
2136
2137 if (usage == AUDIO_USAGE_VOICE_COMMUNICATION ||
2138 audio_source != AUDIO_SOURCE_INVALID) {
2139 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2140 do_in_main_thread(FROM_HERE,
2141 base::BindOnce(
2142 [](LeAudioSinkAudioHalClient::Callbacks* cb) {
2143 cb->OnAudioResume();
2144 },
2145 unicast_sink_hal_cb_));
2146 }
2147 SyncOnMainLoop();
2148 }
2149
StopStreaming(int group_id,bool suspend_source=false)2150 void StopStreaming(int group_id, bool suspend_source = false) {
2151 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2152
2153 /* TODO We should have a way to confirm Stop() otherwise, audio framework
2154 * might have different state that it is in the le_audio code - as tearing
2155 * down CISes might take some time
2156 */
2157 /* It's enough to call only one resume even if it'll be bi-directional
2158 * streaming. First suspend will trigger GroupStop.
2159 *
2160 * There is no - 'only source receiver' scenario (e.g. single microphone).
2161 * If there will be such test oriented scenario, such resume choose logic
2162 * should be applied.
2163 */
2164 unicast_source_hal_cb_->OnAudioSuspend();
2165
2166 if (suspend_source) {
2167 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2168 unicast_sink_hal_cb_->OnAudioSuspend();
2169 }
2170 SyncOnMainLoop();
2171 }
2172
set_sample_database(uint16_t conn_id,RawAddress addr,std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs)2173 void set_sample_database(
2174 uint16_t conn_id, RawAddress addr,
2175 std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,
2176 std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,
2177 std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,
2178 std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs) {
2179 gatt::DatabaseBuilder bob;
2180
2181 /* Generic Access Service */
2182 bob.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
2183 /* Device Name Char. */
2184 bob.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00),
2185 GATT_CHAR_PROP_BIT_READ);
2186
2187 if (csis->start) {
2188 bool is_primary = true;
2189 bob.AddService(csis->start, csis->end, bluetooth::csis::kCsisServiceUuid,
2190 is_primary);
2191 if (csis->sirk_char) {
2192 bob.AddCharacteristic(
2193 csis->sirk_char, csis->sirk_char + 1,
2194 bluetooth::csis::kCsisSirkUuid,
2195 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
2196 if (csis->sirk_ccc)
2197 bob.AddDescriptor(csis->sirk_ccc,
2198 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2199 }
2200
2201 if (csis->size_char) {
2202 bob.AddCharacteristic(
2203 csis->size_char, csis->size_char + 1,
2204 bluetooth::csis::kCsisSizeUuid,
2205 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
2206 if (csis->size_ccc)
2207 bob.AddDescriptor(csis->size_ccc,
2208 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2209 }
2210
2211 if (csis->lock_char) {
2212 bob.AddCharacteristic(csis->lock_char, csis->lock_char + 1,
2213 bluetooth::csis::kCsisLockUuid,
2214 GATT_CHAR_PROP_BIT_READ |
2215 GATT_CHAR_PROP_BIT_NOTIFY |
2216 GATT_CHAR_PROP_BIT_WRITE);
2217 if (csis->lock_ccc)
2218 bob.AddDescriptor(csis->lock_ccc,
2219 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2220 }
2221
2222 if (csis->rank_char)
2223 bob.AddCharacteristic(csis->rank_char, csis->rank_char + 1,
2224 bluetooth::csis::kCsisRankUuid,
2225 GATT_CHAR_PROP_BIT_READ);
2226 }
2227
2228 if (cas->start) {
2229 bool is_primary = true;
2230 bob.AddService(cas->start, cas->end,
2231 bluetooth::le_audio::uuid::kCapServiceUuid, is_primary);
2232 // Include CSIS service inside
2233 if (cas->csis_include)
2234 bob.AddIncludedService(cas->csis_include,
2235 bluetooth::csis::kCsisServiceUuid, csis->start,
2236 csis->end);
2237 }
2238
2239 if (pacs->start) {
2240 bool is_primary = true;
2241 bob.AddService(
2242 pacs->start, pacs->end,
2243 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid,
2244 is_primary);
2245
2246 if (pacs->sink_pac_char) {
2247 bob.AddCharacteristic(
2248 pacs->sink_pac_char, pacs->sink_pac_char + 1,
2249 bluetooth::le_audio::uuid::
2250 kSinkPublishedAudioCapabilityCharacteristicUuid,
2251 GATT_CHAR_PROP_BIT_READ);
2252 if (pacs->sink_pac_ccc)
2253 bob.AddDescriptor(pacs->sink_pac_ccc,
2254 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2255 }
2256
2257 if (pacs->sink_audio_loc_char) {
2258 bob.AddCharacteristic(
2259 pacs->sink_audio_loc_char, pacs->sink_audio_loc_char + 1,
2260 bluetooth::le_audio::uuid::kSinkAudioLocationCharacteristicUuid,
2261 GATT_CHAR_PROP_BIT_READ);
2262 if (pacs->sink_audio_loc_ccc)
2263 bob.AddDescriptor(pacs->sink_audio_loc_ccc,
2264 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2265 }
2266
2267 if (pacs->source_pac_char) {
2268 bob.AddCharacteristic(
2269 pacs->source_pac_char, pacs->source_pac_char + 1,
2270 bluetooth::le_audio::uuid::
2271 kSourcePublishedAudioCapabilityCharacteristicUuid,
2272 GATT_CHAR_PROP_BIT_READ);
2273 if (pacs->source_pac_ccc)
2274 bob.AddDescriptor(pacs->source_pac_ccc,
2275 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2276 }
2277
2278 if (pacs->source_audio_loc_char) {
2279 bob.AddCharacteristic(
2280 pacs->source_audio_loc_char, pacs->source_audio_loc_char + 1,
2281 bluetooth::le_audio::uuid::kSourceAudioLocationCharacteristicUuid,
2282 GATT_CHAR_PROP_BIT_READ);
2283 if (pacs->source_audio_loc_ccc)
2284 bob.AddDescriptor(pacs->source_audio_loc_ccc,
2285 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2286 }
2287
2288 if (pacs->avail_contexts_char) {
2289 bob.AddCharacteristic(pacs->avail_contexts_char,
2290 pacs->avail_contexts_char + 1,
2291 bluetooth::le_audio::uuid::
2292 kAudioContextAvailabilityCharacteristicUuid,
2293 GATT_CHAR_PROP_BIT_READ);
2294 if (pacs->avail_contexts_ccc)
2295 bob.AddDescriptor(pacs->avail_contexts_ccc,
2296 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2297 }
2298
2299 if (pacs->supp_contexts_char) {
2300 bob.AddCharacteristic(
2301 pacs->supp_contexts_char, pacs->supp_contexts_char + 1,
2302 bluetooth::le_audio::uuid::kAudioSupportedContextCharacteristicUuid,
2303 GATT_CHAR_PROP_BIT_READ);
2304 if (pacs->supp_contexts_ccc)
2305 bob.AddDescriptor(pacs->supp_contexts_ccc,
2306 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2307 }
2308 }
2309
2310 if (ascs->start) {
2311 bool is_primary = true;
2312 bob.AddService(ascs->start, ascs->end,
2313 bluetooth::le_audio::uuid::kAudioStreamControlServiceUuid,
2314 is_primary);
2315 for (int i = 0; i < max_num_of_ases; i++) {
2316 if (ascs->sink_ase_char[i]) {
2317 bob.AddCharacteristic(
2318 ascs->sink_ase_char[i], ascs->sink_ase_char[i] + 1,
2319 bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid,
2320 GATT_CHAR_PROP_BIT_READ);
2321 if (ascs->sink_ase_ccc[i])
2322 bob.AddDescriptor(ascs->sink_ase_ccc[i],
2323 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2324 }
2325 if (ascs->source_ase_char[i]) {
2326 bob.AddCharacteristic(
2327 ascs->source_ase_char[i], ascs->source_ase_char[i] + 1,
2328 bluetooth::le_audio::uuid::kSourceAudioStreamEndpointUuid,
2329 GATT_CHAR_PROP_BIT_READ);
2330 if (ascs->source_ase_ccc[i])
2331 bob.AddDescriptor(ascs->source_ase_ccc[i],
2332 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2333 }
2334 }
2335 if (ascs->ctp_char) {
2336 bob.AddCharacteristic(
2337 ascs->ctp_char, ascs->ctp_char + 1,
2338 bluetooth::le_audio::uuid::
2339 kAudioStreamEndpointControlPointCharacteristicUuid,
2340 GATT_CHAR_PROP_BIT_READ);
2341 if (ascs->ctp_ccc)
2342 bob.AddDescriptor(ascs->ctp_ccc,
2343 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2344 }
2345 }
2346
2347 // Assign conn_id to a certain device - this does not mean it is connected
2348 auto dev_wrapper = std::make_unique<NiceMock<MockDeviceWrapper>>(
2349 addr, bob.Build().Services(), std::move(csis), std::move(cas),
2350 std::move(ascs), std::move(pacs));
2351 peer_devices.emplace(conn_id, std::move(dev_wrapper));
2352 }
2353
SetSampleDatabaseEmpty(uint16_t conn_id,RawAddress addr)2354 void SetSampleDatabaseEmpty(uint16_t conn_id, RawAddress addr) {
2355 auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
2356 auto cas = std::make_unique<NiceMock<MockDeviceWrapper::cas_mock>>();
2357 auto pacs = std::make_unique<NiceMock<MockDeviceWrapper::pacs_mock>>();
2358 auto ascs = std::make_unique<NiceMock<MockDeviceWrapper::ascs_mock>>();
2359 set_sample_database(conn_id, addr, std::move(csis), std::move(cas),
2360 std::move(ascs), std::move(pacs));
2361 }
2362
SetSampleDatabaseEarbudsValid(uint16_t conn_id,RawAddress addr,uint32_t sink_audio_allocation,uint32_t source_audio_allocation,uint8_t sink_channel_cnt=0x03,uint8_t source_channel_cnt=0x03,uint16_t sample_freq_mask=0x0004,bool add_csis=true,bool add_cas=true,bool add_pacs=true,int add_ascs_cnt=1,uint8_t set_size=2,uint8_t rank=1,GattStatus gatt_status=GATT_SUCCESS)2363 void SetSampleDatabaseEarbudsValid(
2364 uint16_t conn_id, RawAddress addr, uint32_t sink_audio_allocation,
2365 uint32_t source_audio_allocation, uint8_t sink_channel_cnt = 0x03,
2366 uint8_t source_channel_cnt = 0x03, uint16_t sample_freq_mask = 0x0004,
2367 bool add_csis = true, bool add_cas = true, bool add_pacs = true,
2368 int add_ascs_cnt = 1, uint8_t set_size = 2, uint8_t rank = 1,
2369 GattStatus gatt_status = GATT_SUCCESS) {
2370 auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
2371 if (add_csis) {
2372 // attribute handles
2373 csis->start = 0x0010;
2374 csis->sirk_char = 0x0020;
2375 csis->sirk_ccc = 0x0022;
2376 csis->size_char = 0x0023;
2377 csis->size_ccc = 0x0025;
2378 csis->lock_char = 0x0026;
2379 csis->lock_ccc = 0x0028;
2380 csis->rank_char = 0x0029;
2381 csis->end = 0x0030;
2382 // other params
2383 csis->size = set_size;
2384 csis->rank = rank;
2385 }
2386
2387 auto cas = std::make_unique<NiceMock<MockDeviceWrapper::cas_mock>>();
2388 if (add_cas) {
2389 // attribute handles
2390 cas->start = 0x0040;
2391 if (add_csis) cas->csis_include = 0x0041;
2392 cas->end = 0x0050;
2393 // other params
2394 }
2395
2396 auto pacs = std::make_unique<NiceMock<MockDeviceWrapper::pacs_mock>>();
2397 if (add_pacs) {
2398 // attribute handles
2399 pacs->start = 0x0060;
2400 pacs->sink_pac_char = 0x0061;
2401 pacs->sink_pac_ccc = 0x0063;
2402 pacs->sink_audio_loc_char = 0x0064;
2403 pacs->sink_audio_loc_ccc = 0x0066;
2404 pacs->source_pac_char = 0x0067;
2405 pacs->source_pac_ccc = 0x0069;
2406 pacs->source_audio_loc_char = 0x0070;
2407 pacs->source_audio_loc_ccc = 0x0072;
2408 pacs->avail_contexts_char = 0x0073;
2409 pacs->avail_contexts_ccc = 0x0075;
2410 pacs->supp_contexts_char = 0x0076;
2411 pacs->supp_contexts_ccc = 0x0078;
2412 pacs->end = 0x0080;
2413 // other params
2414 }
2415
2416 auto ascs = std::make_unique<NiceMock<MockDeviceWrapper::ascs_mock>>();
2417 if (add_ascs_cnt > 0) {
2418 // attribute handles
2419 ascs->start = 0x0090;
2420 uint16_t handle = 0x0091;
2421 for (int i = 0; i < add_ascs_cnt; i++) {
2422 if (sink_audio_allocation != 0) {
2423 ascs->sink_ase_char[i] = handle;
2424 handle += 2;
2425 ascs->sink_ase_ccc[i] = handle;
2426 handle++;
2427 }
2428
2429 if (source_audio_allocation != 0) {
2430 ascs->source_ase_char[i] = handle;
2431 handle += 2;
2432 ascs->source_ase_ccc[i] = handle;
2433 handle++;
2434 }
2435 }
2436 ascs->ctp_char = handle;
2437 handle += 2;
2438 ascs->ctp_ccc = handle;
2439 handle++;
2440 ascs->end = handle;
2441 // other params
2442 }
2443
2444 set_sample_database(conn_id, addr, std::move(csis), std::move(cas),
2445 std::move(ascs), std::move(pacs));
2446
2447 if (add_pacs) {
2448 uint8_t snk_allocation[4];
2449 uint8_t src_allocation[4];
2450
2451 snk_allocation[0] = (uint8_t)(sink_audio_allocation);
2452 snk_allocation[1] = (uint8_t)(sink_audio_allocation >> 8);
2453 snk_allocation[2] = (uint8_t)(sink_audio_allocation >> 16);
2454 snk_allocation[3] = (uint8_t)(sink_audio_allocation >> 24);
2455
2456 src_allocation[0] = (uint8_t)(source_audio_allocation);
2457 src_allocation[1] = (uint8_t)(source_audio_allocation >> 8);
2458 src_allocation[2] = (uint8_t)(source_audio_allocation >> 16);
2459 src_allocation[3] = (uint8_t)(source_audio_allocation >> 24);
2460
2461 uint8_t sample_freq[2];
2462 sample_freq[0] = (uint8_t)(sample_freq_mask);
2463 sample_freq[1] = (uint8_t)(sample_freq_mask >> 8);
2464
2465 // Set pacs default read values
2466 ON_CALL(*peer_devices.at(conn_id)->pacs, OnReadCharacteristic(_, _, _))
2467 .WillByDefault([this, conn_id, snk_allocation, src_allocation,
2468 sample_freq, sink_channel_cnt, source_channel_cnt,
2469 gatt_status](uint16_t handle, GATT_READ_OP_CB cb,
2470 void* cb_data) {
2471 auto& pacs = peer_devices.at(conn_id)->pacs;
2472 std::vector<uint8_t> value;
2473 if (gatt_status == GATT_SUCCESS) {
2474 if (handle == pacs->sink_pac_char + 1) {
2475 if (empty_sink_pack_) {
2476 value = {0x00};
2477 } else {
2478 value = {
2479 // Num records
2480 0x02,
2481 // Codec_ID
2482 0x06,
2483 0x00,
2484 0x00,
2485 0x00,
2486 0x00,
2487 // Codec Spec. Caps. Len
2488 0x10,
2489 0x03, /* sample freq */
2490 0x01,
2491 sample_freq[0],
2492 sample_freq[1],
2493 0x02,
2494 0x02, /* frame duration */
2495 0x03,
2496 0x02, /* channel count */
2497 0x03,
2498 sink_channel_cnt,
2499 0x05,
2500 0x04,
2501 0x1E,
2502 0x00,
2503 0x78,
2504 0x00,
2505 // Metadata Length
2506 0x00,
2507 // Codec_ID
2508 0x06,
2509 0x00,
2510 0x00,
2511 0x00,
2512 0x00,
2513 // Codec Spec. Caps. Len
2514 0x10,
2515 0x03, /* sample freq */
2516 0x01,
2517 0x80, /* 48kHz */
2518 0x00,
2519 0x02, /* frame duration */
2520 0x02,
2521 0x03,
2522 0x02, /* channel count */
2523 0x03,
2524 sink_channel_cnt,
2525 0x05, /* octects per frame */
2526 0x04,
2527 0x78,
2528 0x00,
2529 0x78,
2530 0x00,
2531 // Metadata Length
2532 0x00,
2533 };
2534 }
2535 } else if (handle == pacs->sink_audio_loc_char + 1) {
2536 value = {
2537 // Audio Locations
2538 snk_allocation[0],
2539 snk_allocation[1],
2540 snk_allocation[2],
2541 snk_allocation[3],
2542 };
2543 } else if (handle == pacs->source_pac_char + 1) {
2544 if (empty_source_pack_) {
2545 value = {0x00};
2546 } else {
2547 value = {
2548 // Num records
2549 0x02,
2550 // Codec_ID
2551 0x06,
2552 0x00,
2553 0x00,
2554 0x00,
2555 0x00,
2556 // Codec Spec. Caps. Len
2557 0x10,
2558 0x03,
2559 0x01,
2560 sample_freq[0],
2561 sample_freq[1],
2562 0x02,
2563 0x02,
2564 0x03,
2565 0x02,
2566 0x03,
2567 source_channel_cnt,
2568 0x05,
2569 0x04,
2570 0x1E,
2571 0x00,
2572 0x78,
2573 0x00,
2574 // Metadata Length
2575 0x00,
2576 // Codec_ID
2577 0x06,
2578 0x00,
2579 0x00,
2580 0x00,
2581 0x00,
2582 // Codec Spec. Caps. Len
2583 0x10,
2584 0x03,
2585 0x01,
2586 0x24,
2587 0x00,
2588 0x02,
2589 0x02,
2590 0x03,
2591 0x02,
2592 0x03,
2593 source_channel_cnt,
2594 0x05,
2595 0x04,
2596 0x1E,
2597 0x00,
2598 0x50,
2599 0x00,
2600 // Metadata Length
2601 0x00,
2602 };
2603 }
2604 } else if (handle == pacs->source_audio_loc_char + 1) {
2605 value = {
2606 // Audio Locations
2607 src_allocation[0],
2608 src_allocation[1],
2609 src_allocation[2],
2610 src_allocation[3],
2611 };
2612 } else if (handle == pacs->avail_contexts_char + 1) {
2613 value = {
2614 // Sink Avail Contexts
2615 (uint8_t)(available_snk_context_types_),
2616 (uint8_t)(available_snk_context_types_ >> 8),
2617 // Source Avail Contexts
2618 (uint8_t)(available_src_context_types_),
2619 (uint8_t)(available_src_context_types_ >> 8),
2620 };
2621 } else if (handle == pacs->supp_contexts_char + 1) {
2622 value = {
2623 // Sink Supp Contexts
2624 (uint8_t)(supported_snk_context_types_),
2625 (uint8_t)(supported_snk_context_types_ >> 8),
2626 // Source Supp Contexts
2627 (uint8_t)(supported_src_context_types_),
2628 (uint8_t)(supported_src_context_types_ >> 8),
2629 };
2630 }
2631 }
2632 cb(conn_id, gatt_status, handle, value.size(), value.data(),
2633 cb_data);
2634 });
2635 }
2636
2637 if (add_ascs_cnt > 0) {
2638 // Set ascs default read values
2639 ON_CALL(*peer_devices.at(conn_id)->ascs, OnReadCharacteristic(_, _, _))
2640 .WillByDefault([this, conn_id, gatt_status](uint16_t handle,
2641 GATT_READ_OP_CB cb,
2642 void* cb_data) {
2643 auto& ascs = peer_devices.at(conn_id)->ascs;
2644 std::vector<uint8_t> value;
2645 bool is_ase_sink_request = false;
2646 bool is_ase_src_request = false;
2647 uint8_t idx;
2648
2649 if (handle == ascs->ctp_ccc && ccc_stored_byte_val_.has_value()) {
2650 value = {*ccc_stored_byte_val_, 00};
2651 cb(conn_id, gatt_read_ctp_ccc_status_, handle, value.size(),
2652 value.data(), cb_data);
2653 return;
2654 }
2655
2656 if (gatt_status == GATT_SUCCESS) {
2657 if (handle == ascs->ctp_ccc) {
2658 value = UINT16_TO_VEC_UINT8(ascs->ctp_ccc_val);
2659 } else {
2660 for (idx = 0; idx < max_num_of_ases; idx++) {
2661 if (handle == ascs->sink_ase_ccc[idx] + 1) {
2662 value = UINT16_TO_VEC_UINT8(ascs->sink_ase_ccc_val[idx]);
2663 break;
2664 }
2665 if (handle == ascs->source_ase_char[idx] + 1) {
2666 value = UINT16_TO_VEC_UINT8(ascs->source_ase_ccc_val[idx]);
2667 break;
2668 }
2669 }
2670 }
2671
2672 for (idx = 0; idx < max_num_of_ases; idx++) {
2673 if (handle == ascs->sink_ase_char[idx] + 1) {
2674 is_ase_sink_request = true;
2675 break;
2676 }
2677 if (handle == ascs->source_ase_char[idx] + 1) {
2678 is_ase_src_request = true;
2679 break;
2680 }
2681 }
2682
2683 if (is_ase_sink_request) {
2684 value = {
2685 // ASE ID
2686 static_cast<uint8_t>(idx + 1),
2687 // State
2688 static_cast<uint8_t>(bluetooth::le_audio::types::AseState::
2689 BTA_LE_AUDIO_ASE_STATE_IDLE),
2690 // No Additional ASE params for IDLE state
2691 };
2692 } else if (is_ase_src_request) {
2693 value = {
2694 // ASE ID
2695 static_cast<uint8_t>(idx + 6),
2696 // State
2697 static_cast<uint8_t>(bluetooth::le_audio::types::AseState::
2698 BTA_LE_AUDIO_ASE_STATE_IDLE),
2699 // No Additional ASE params for IDLE state
2700 };
2701 }
2702 }
2703 cb(conn_id, gatt_status, handle, value.size(), value.data(),
2704 cb_data);
2705 });
2706 }
2707 }
2708
TestAudioDataTransfer(int group_id,uint8_t cis_count_out,uint8_t cis_count_in,int data_len,int in_data_len=40,uint16_t decoded_in_data_len=0)2709 void TestAudioDataTransfer(int group_id, uint8_t cis_count_out,
2710 uint8_t cis_count_in, int data_len,
2711 int in_data_len = 40,
2712 uint16_t decoded_in_data_len = 0) {
2713 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2714 ASSERT_NE(mock_le_audio_sink_hal_client_, nullptr);
2715
2716 // Expect two channels ISO Data to be sent
2717 std::vector<uint16_t> handles;
2718 if (cis_count_out) {
2719 EXPECT_CALL(*mock_iso_manager_, SendIsoData(_, _, _))
2720 .Times(cis_count_out)
2721 .WillRepeatedly(
2722 [&handles](uint16_t iso_handle, const uint8_t* data,
2723 uint16_t data_len) { handles.push_back(iso_handle); });
2724 }
2725 std::vector<uint8_t> data(data_len);
2726 unicast_source_hal_cb_->OnAudioDataReady(data);
2727
2728 // Inject microphone data from group (2 CISes - pass stereo data in 1 call)
2729 if (decoded_in_data_len) {
2730 EXPECT_CALL(*mock_le_audio_sink_hal_client_,
2731 SendData(_, decoded_in_data_len))
2732 .Times(cis_count_in > 0 ? 1 : 0);
2733 } else {
2734 EXPECT_CALL(*mock_le_audio_sink_hal_client_, SendData(_, _))
2735 .Times(cis_count_in > 0 ? 1 : 0);
2736 }
2737 ASSERT_EQ(streaming_groups.count(group_id), 1u);
2738
2739 if (cis_count_in) {
2740 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2741
2742 ASSERT_NE(0lu, streaming_groups.count(group_id));
2743 auto group = streaming_groups.at(group_id);
2744 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
2745 device = group->GetNextDevice(device)) {
2746 for (auto& ase : device->ases_) {
2747 if (ase.direction ==
2748 bluetooth::le_audio::types::kLeAudioDirectionSource) {
2749 InjectIncomingIsoData(group_id, ase.cis_conn_hdl, in_data_len);
2750 --cis_count_in;
2751 if (!cis_count_in) break;
2752 }
2753 }
2754 if (!cis_count_in) break;
2755 }
2756 }
2757
2758 SyncOnMainLoop();
2759 std::sort(handles.begin(), handles.end());
2760 ASSERT_EQ(cis_count_in, 0);
2761 handles.clear();
2762
2763 Mock::VerifyAndClearExpectations(mock_iso_manager_);
2764 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
2765 }
2766
InjectIncomingIsoData(uint16_t cig_id,uint16_t cis_con_hdl,size_t payload_size)2767 void InjectIncomingIsoData(uint16_t cig_id, uint16_t cis_con_hdl,
2768 size_t payload_size) {
2769 BT_HDR* bt_hdr = (BT_HDR*)malloc(sizeof(BT_HDR) + payload_size);
2770
2771 bt_hdr->offset = 0;
2772 bt_hdr->len = payload_size;
2773
2774 bluetooth::hci::iso_manager::cis_data_evt cis_evt;
2775 cis_evt.cig_id = cig_id;
2776 cis_evt.cis_conn_hdl = cis_con_hdl;
2777 cis_evt.ts = 0;
2778 cis_evt.evt_lost = 0;
2779 cis_evt.p_msg = bt_hdr;
2780
2781 ASSERT_NE(cig_callbacks_, nullptr);
2782 cig_callbacks_->OnCisEvent(
2783 bluetooth::hci::iso_manager::kIsoEventCisDataAvailable, &cis_evt);
2784 free(bt_hdr);
2785 }
2786
InjectCisDisconnected(uint16_t cig_id,uint16_t cis_con_hdl,uint8_t reason=0)2787 void InjectCisDisconnected(uint16_t cig_id, uint16_t cis_con_hdl,
2788 uint8_t reason = 0) {
2789 bluetooth::hci::iso_manager::cis_disconnected_evt cis_evt;
2790 cis_evt.cig_id = cig_id;
2791 cis_evt.cis_conn_hdl = cis_con_hdl;
2792 cis_evt.reason = reason;
2793
2794 ASSERT_NE(cig_callbacks_, nullptr);
2795 cig_callbacks_->OnCisEvent(
2796 bluetooth::hci::iso_manager::kIsoEventCisDisconnected, &cis_evt);
2797 }
2798
InjectCigRemoved(uint8_t cig_id)2799 void InjectCigRemoved(uint8_t cig_id) {
2800 bluetooth::hci::iso_manager::cig_remove_cmpl_evt evt;
2801 evt.status = 0;
2802 evt.cig_id = cig_id;
2803
2804 ASSERT_NE(cig_callbacks_, nullptr);
2805 cig_callbacks_->OnCisEvent(
2806 bluetooth::hci::iso_manager::kIsoEventCigOnRemoveCmpl, &evt);
2807 }
2808
2809 NiceMock<MockAudioHalClientCallbacks> mock_audio_hal_client_callbacks_;
2810 LeAudioSourceAudioHalClient::Callbacks* unicast_source_hal_cb_ = nullptr;
2811 LeAudioSinkAudioHalClient::Callbacks* unicast_sink_hal_cb_ = nullptr;
2812
2813 uint8_t default_channel_cnt = 0x03;
2814 uint8_t default_ase_cnt = 1;
2815
2816 NiceMock<MockCsisClient> mock_csis_client_module_;
2817 NiceMock<MockDeviceGroups> mock_groups_module_;
2818 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks_;
2819 NiceMock<MockLeAudioGroupStateMachine> mock_state_machine_;
2820
2821 NiceMock<MockFunction<void()>> mock_storage_load;
2822 NiceMock<MockFunction<bool()>> mock_hal_2_1_verifier;
2823
2824 NiceMock<bluetooth::manager::MockBtmInterface> mock_btm_interface_;
2825 NiceMock<gatt::MockBtaGattInterface> mock_gatt_interface_;
2826 NiceMock<gatt::MockBtaGattQueue> mock_gatt_queue_;
2827 tBTA_GATTC_CBACK* gatt_callback;
2828 const uint8_t gatt_if = 0xfe;
2829 uint16_t global_conn_id = 1;
2830 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
2831 state_machine_callbacks_;
2832 std::map<int, LeAudioDeviceGroup*> streaming_groups;
2833 bool block_streaming_state_callback = false;
2834
2835 bool attach_to_stream_scheduled = false;
2836
2837 bluetooth::hci::IsoManager* iso_manager_;
2838 MockIsoManager* mock_iso_manager_;
2839 bluetooth::hci::iso_manager::CigCallbacks* cig_callbacks_ = nullptr;
2840 uint16_t iso_con_counter_ = 1;
2841
2842 bluetooth::le_audio::CodecManager* codec_manager_;
2843 MockCodecManager* mock_codec_manager_;
2844
2845 uint16_t available_snk_context_types_ = 0xffff;
2846 uint16_t available_src_context_types_ = 0xffff;
2847 uint16_t supported_snk_context_types_ = 0xffff;
2848 uint16_t supported_src_context_types_ = 0xffff;
2849
2850 bool empty_source_pack_;
2851 bool empty_sink_pack_;
2852
2853 NiceMock<bluetooth::storage::MockBtifStorageInterface> mock_btif_storage_;
2854
2855 std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>> peer_devices;
2856 std::list<int> group_locks;
2857 std::map<RawAddress, int> groups;
2858
2859 /* CCC descriptor data */
2860 tGATT_STATUS gatt_read_ctp_ccc_status_ = GATT_SUCCESS;
2861 std::optional<uint8_t> ccc_stored_byte_val_ = std::nullopt;
2862
2863 /* Audio track metadata */
2864 char* test_tags_ptr_ = nullptr;
2865 NiceMock<bluetooth::hci::testing::MockControllerInterface> controller_;
2866 };
2867
2868 class UnicastTest : public UnicastTestNoInit {
2869 protected:
SetUp()2870 void SetUp() override {
2871 UnicastTestNoInit::SetUp();
2872
2873 EXPECT_CALL(mock_hal_2_1_verifier, Call()).Times(1);
2874 EXPECT_CALL(mock_storage_load, Call()).Times(1);
2875
2876 ON_CALL(mock_btm_interface_, GetHCIConnHandle(_, _))
2877 .WillByDefault([this](RawAddress const& bd_addr,
2878 tBT_TRANSPORT transport) -> uint16_t {
2879 for (auto const& [conn_id, dev_wrapper] : peer_devices) {
2880 if (dev_wrapper->addr == bd_addr) {
2881 return conn_id;
2882 }
2883 }
2884 log::error("GetHCIConnHandle Mock: not a valid test device!");
2885 return 0x00FE;
2886 });
2887 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
2888 .WillByDefault([this](uint16_t handle, tHCI_STATUS rs) {
2889 ASSERT_NE(handle, GATT_INVALID_CONN_ID);
2890 InjectDisconnectedEvent(handle, GATT_CONN_TERMINATE_LOCAL_HOST);
2891 });
2892
2893 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
2894 framework_encode_preference;
2895 BtaAppRegisterCallback app_register_callback;
2896 EXPECT_CALL(mock_gatt_interface_, AppRegister(_, _, _))
2897 .WillOnce(DoAll(SaveArg<0>(&gatt_callback),
2898 SaveArg<1>(&app_register_callback)));
2899 LeAudioClient::Initialize(
2900 &mock_audio_hal_client_callbacks_,
2901 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
2902 &mock_storage_load),
2903 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2904 &mock_hal_2_1_verifier),
2905 framework_encode_preference);
2906
2907 SyncOnMainLoop();
2908 ASSERT_TRUE(gatt_callback);
2909 ASSERT_TRUE(group_callbacks_);
2910 ASSERT_TRUE(app_register_callback);
2911 app_register_callback.Run(gatt_if, GATT_SUCCESS);
2912 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
2913 }
2914
TearDown()2915 void TearDown() override {
2916 // Clear the default actions before the parent class teardown is called
2917 Mock::VerifyAndClear(&mock_btm_interface_);
2918 Mock::VerifyAndClear(&mock_gatt_interface_);
2919 Mock::VerifyAndClear(&mock_audio_hal_client_callbacks_);
2920 groups.clear();
2921 UnicastTestNoInit::TearDown();
2922 }
2923 };
2924
2925 class UnicastTestHealthStatus : public UnicastTest {
2926 protected:
SetUp()2927 void SetUp() override {
2928 use_health_status = true;
2929 UnicastTest::SetUp();
2930 group_ = new LeAudioDeviceGroup(group_id_);
2931 }
2932
TearDown()2933 void TearDown() override {
2934 delete group_;
2935 UnicastTest::TearDown();
2936 }
2937
2938 const int group_id_ = 0;
2939 LeAudioDeviceGroup* group_ = nullptr;
2940 };
2941
2942 class UnicastTestHandoverMode : public UnicastTest {
2943 protected:
SetUp()2944 void SetUp() override {
2945 use_handover_mode = true;
2946 UnicastTest::SetUp();
2947 group_ = new LeAudioDeviceGroup(group_id_);
2948 }
2949
TearDown()2950 void TearDown() override {
2951 delete group_;
2952 UnicastTest::TearDown();
2953 }
2954
2955 const int group_id_ = 0;
2956 LeAudioDeviceGroup* group_ = nullptr;
2957 };
2958
GetTestAddress(uint8_t index)2959 RawAddress GetTestAddress(uint8_t index) {
2960 EXPECT_LT(index, UINT8_MAX);
2961 RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}};
2962 return result;
2963 }
2964
TEST_F(UnicastTest,Initialize)2965 TEST_F(UnicastTest, Initialize) {
2966 ASSERT_NE(LeAudioClient::Get(), nullptr);
2967 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
2968 }
2969
TEST_F(UnicastTestNoInit,InitializeNoHal_2_1)2970 TEST_F(UnicastTestNoInit, InitializeNoHal_2_1) {
2971 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
2972
2973 // Report False when asked for Audio HAL 2.1 support
2974 ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool {
2975 return false;
2976 });
2977
2978 BtaAppRegisterCallback app_register_callback;
2979 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
2980 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
2981 SaveArg<1>(&app_register_callback)));
2982 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
2983 framework_encode_preference;
2984
2985 EXPECT_DEATH(
2986 LeAudioClient::Initialize(
2987 &mock_audio_hal_client_callbacks_,
2988 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
2989 &mock_storage_load),
2990 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2991 &mock_hal_2_1_verifier),
2992 framework_encode_preference),
2993 "LE Audio Client requires Bluetooth Audio HAL V2.1 at least. Either "
2994 "disable LE Audio Profile, or update your HAL");
2995 }
2996
TEST_F(UnicastTest,ConnectAndSetupPhy)2997 TEST_F(UnicastTest, ConnectAndSetupPhy) {
2998 const RawAddress test_address0 = GetTestAddress(0);
2999 uint16_t conn_id = 1;
3000 SetSampleDatabaseEarbudsValid(
3001 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3002 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3003 default_channel_cnt, 0x0004,
3004 /* source sample freq 16khz */ true, /*add_csis*/
3005 true, /*add_cas*/
3006 true, /*add_pacs*/
3007 default_ase_cnt /*add_ascs*/);
3008
3009 EXPECT_CALL(mock_btm_interface_,
3010 BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0))
3011 .Times(1);
3012 ConnectLeAudio(test_address0, false);
3013 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3014
3015 EXPECT_CALL(mock_btm_interface_,
3016 BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0))
3017 .Times(1);
3018 InjectPhyChangedEvent(conn_id, 0, 0, GATT_REQ_NOT_SUPPORTED);
3019 SyncOnMainLoop();
3020 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3021 .WillByDefault(DoAll(Return(true)));
3022 InjectEncryptionChangedEvent(test_address0);
3023 SyncOnMainLoop();
3024 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3025
3026 /* Make sure flag `acl_phy_update_done_` is cleared after disconnect.
3027 * Just repeat previous steps after reconnection
3028 */
3029 InjectDisconnectedEvent(conn_id);
3030 SyncOnMainLoop();
3031
3032 EXPECT_CALL(mock_btm_interface_,
3033 BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0))
3034 .Times(1);
3035
3036 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3037 .WillByDefault(DoAll(Return(false)));
3038 InjectConnectedEvent(test_address0, 1);
3039 SyncOnMainLoop();
3040 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3041
3042 EXPECT_CALL(mock_btm_interface_,
3043 BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0))
3044 .Times(1);
3045 InjectPhyChangedEvent(conn_id, 0, 0, GATT_REQ_NOT_SUPPORTED);
3046 SyncOnMainLoop();
3047 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3048 .WillByDefault(DoAll(Return(true)));
3049 InjectEncryptionChangedEvent(test_address0);
3050 SyncOnMainLoop();
3051 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3052 }
3053
TEST_F(UnicastTest,ConnectOneEarbudEmpty)3054 TEST_F(UnicastTest, ConnectOneEarbudEmpty) {
3055 const RawAddress test_address0 = GetTestAddress(0);
3056 SetSampleDatabaseEmpty(1, test_address0);
3057 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3058 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3059 .Times(1);
3060 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3061 ConnectLeAudio(test_address0);
3062 }
3063
TEST_F(UnicastTest,ConnectOneEarbudNoPacs)3064 TEST_F(UnicastTest, ConnectOneEarbudNoPacs) {
3065 const RawAddress test_address0 = GetTestAddress(0);
3066 SetSampleDatabaseEarbudsValid(
3067 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3068 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3069 default_channel_cnt, 0x0004,
3070 /* source sample freq 16khz */ true, /*add_csis*/
3071 true, /*add_cas*/
3072 false, /*add_pacs*/
3073 default_ase_cnt /*add_ascs*/);
3074 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3075 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3076 .Times(1);
3077 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3078 ConnectLeAudio(test_address0);
3079 }
3080
TEST_F(UnicastTest,ConnectOneEarbudNoAscs)3081 TEST_F(UnicastTest, ConnectOneEarbudNoAscs) {
3082 const RawAddress test_address0 = GetTestAddress(0);
3083 SetSampleDatabaseEarbudsValid(
3084 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3085 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3086 default_channel_cnt, 0x0004,
3087 /* source sample freq 16khz */ true, /*add_csis*/
3088 true, /*add_cas*/
3089 true, /*add_pacs*/
3090 0 /*add_ascs*/);
3091 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3092 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3093 .Times(1);
3094 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3095 ConnectLeAudio(test_address0);
3096 }
3097
TEST_F(UnicastTest,ConnectOneEarbudNoCas)3098 TEST_F(UnicastTest, ConnectOneEarbudNoCas) {
3099 const RawAddress test_address0 = GetTestAddress(0);
3100 uint16_t conn_id = 1;
3101 SetSampleDatabaseEarbudsValid(
3102 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3103 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3104 default_channel_cnt, 0x0004,
3105 /* source sample freq 16khz */ true, /*add_csis*/
3106 false, /*add_cas*/
3107 true, /*add_pacs*/
3108 default_ase_cnt /*add_ascs*/);
3109
3110 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3111 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3112 .Times(1);
3113 ConnectLeAudio(test_address0);
3114 }
3115
TEST_F(UnicastTest,ConnectOneEarbudNoCsis)3116 TEST_F(UnicastTest, ConnectOneEarbudNoCsis) {
3117 const RawAddress test_address0 = GetTestAddress(0);
3118 SetSampleDatabaseEarbudsValid(
3119 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3120 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3121 default_channel_cnt, 0x0004,
3122 /* source sample freq 16khz */ false, /*add_csis*/
3123 true, /*add_cas*/
3124 true, /*add_pacs*/
3125 default_ase_cnt /*add_ascs*/);
3126 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3127 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3128 .Times(1);
3129 ConnectLeAudio(test_address0);
3130 }
3131
TEST_F(UnicastTest,ConnectOneEarbudWithInvalidCsis)3132 TEST_F(UnicastTest, ConnectOneEarbudWithInvalidCsis) {
3133 const RawAddress test_address0 = GetTestAddress(0);
3134 SetSampleDatabaseEarbudsValid(
3135 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3136 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3137 default_channel_cnt, 0x0004,
3138 /* source sample freq 16khz */ true, /*add_csis*/
3139 true, /*add_cas*/
3140 true, /*add_pacs*/
3141 default_ase_cnt /*add_ascs*/);
3142 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3143 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3144 .Times(1);
3145 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3146
3147 // Report working CSIS
3148 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
3149 .WillByDefault(Return(true));
3150
3151 /* Make sure Group has not knowledge about the device */
3152 ON_CALL(mock_groups_module_, GetGroupId(_, _))
3153 .WillByDefault([](const RawAddress& addr, bluetooth::Uuid uuid) {
3154 return bluetooth::groups::kGroupUnknown;
3155 });
3156
3157 ConnectLeAudio(test_address0);
3158 SyncOnMainLoop();
3159 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3160 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3161 }
3162
TEST_F_WITH_FLAGS(UnicastTestHealthStatus,ConnectOneEarbudEmpty_withHealthStatus,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_enable_health_based_actions)))3163 TEST_F_WITH_FLAGS(UnicastTestHealthStatus,
3164 ConnectOneEarbudEmpty_withHealthStatus,
3165 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
3166 TEST_BT, leaudio_enable_health_based_actions))) {
3167 const RawAddress test_address0 = GetTestAddress(0);
3168 SetSampleDatabaseEmpty(1, test_address0);
3169 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3170 OnHealthBasedRecommendationAction(
3171 test_address0, LeAudioHealthBasedAction::DISABLE))
3172 .Times(1);
3173 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3174 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3175 .Times(1);
3176 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3177 ConnectLeAudio(test_address0);
3178 SyncOnMainLoop();
3179 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3180 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3181
3182 LeAudioHealthStatus::Get()->RemoveStatistics(
3183 test_address0, bluetooth::groups::kGroupUnknown);
3184 }
3185
TEST_F_WITH_FLAGS(UnicastTestHealthStatus,ConnectOneEarbudNoPacs_withHealthStatus,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_enable_health_based_actions)))3186 TEST_F_WITH_FLAGS(UnicastTestHealthStatus,
3187 ConnectOneEarbudNoPacs_withHealthStatus,
3188 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
3189 TEST_BT, leaudio_enable_health_based_actions))) {
3190 const RawAddress test_address0 = GetTestAddress(0);
3191 SetSampleDatabaseEarbudsValid(
3192 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3193 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3194 default_channel_cnt, 0x0004,
3195 /* source sample freq 16khz */ true, /*add_csis*/
3196 true, /*add_cas*/
3197 false, /*add_pacs*/
3198 default_ase_cnt /*add_ascs*/);
3199 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3200 OnHealthBasedRecommendationAction(
3201 test_address0, LeAudioHealthBasedAction::DISABLE))
3202 .Times(1);
3203 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3204 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3205 .Times(1);
3206 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3207 ConnectLeAudio(test_address0);
3208 SyncOnMainLoop();
3209 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3210 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3211
3212 LeAudioHealthStatus::Get()->RemoveStatistics(
3213 test_address0, bluetooth::groups::kGroupUnknown);
3214 }
3215
TEST_F_WITH_FLAGS(UnicastTestHealthStatus,ConnectOneEarbudNoAscs_withHealthStatus,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_enable_health_based_actions)))3216 TEST_F_WITH_FLAGS(UnicastTestHealthStatus,
3217 ConnectOneEarbudNoAscs_withHealthStatus,
3218 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
3219 TEST_BT, leaudio_enable_health_based_actions))) {
3220 const RawAddress test_address0 = GetTestAddress(0);
3221 SetSampleDatabaseEarbudsValid(
3222 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3223 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3224 default_channel_cnt, 0x0004,
3225 /* source sample freq 16khz */ true, /*add_csis*/
3226 true, /*add_cas*/
3227 true, /*add_pacs*/
3228 0 /*add_ascs*/);
3229 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3230 OnHealthBasedRecommendationAction(
3231 test_address0, LeAudioHealthBasedAction::DISABLE))
3232 .Times(1);
3233 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3234 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3235 .Times(1);
3236 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3237 ConnectLeAudio(test_address0);
3238 SyncOnMainLoop();
3239 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3240 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3241
3242 LeAudioHealthStatus::Get()->RemoveStatistics(
3243 test_address0, bluetooth::groups::kGroupUnknown);
3244 }
3245
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoCas_withHealthStatus)3246 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoCas_withHealthStatus) {
3247 const RawAddress test_address0 = GetTestAddress(0);
3248 uint16_t conn_id = 1;
3249 SetSampleDatabaseEarbudsValid(
3250 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3251 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3252 default_channel_cnt, 0x0004,
3253 /* source sample freq 16khz */ true, /*add_csis*/
3254 false, /*add_cas*/
3255 true, /*add_pacs*/
3256 default_ase_cnt /*add_ascs*/);
3257
3258 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3259 OnHealthBasedRecommendationAction(
3260 test_address0, LeAudioHealthBasedAction::DISABLE))
3261 .Times(0);
3262 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3263 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3264 .Times(1);
3265 ConnectLeAudio(test_address0);
3266 SyncOnMainLoop();
3267 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3268
3269 LeAudioHealthStatus::Get()->RemoveStatistics(
3270 test_address0, bluetooth::groups::kGroupUnknown);
3271 }
3272
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoCsis_withHealthStatus)3273 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoCsis_withHealthStatus) {
3274 const RawAddress test_address0 = GetTestAddress(0);
3275 SetSampleDatabaseEarbudsValid(
3276 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3277 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3278 default_channel_cnt, 0x0004,
3279 /* source sample freq 16khz */ false, /*add_csis*/
3280 true, /*add_cas*/
3281 true, /*add_pacs*/
3282 default_ase_cnt /*add_ascs*/);
3283 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3284 OnHealthBasedRecommendationAction(
3285 test_address0, LeAudioHealthBasedAction::DISABLE))
3286 .Times(0);
3287 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3288 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3289 .Times(1);
3290 ConnectLeAudio(test_address0);
3291 SyncOnMainLoop();
3292 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3293
3294 LeAudioHealthStatus::Get()->RemoveStatistics(
3295 test_address0, bluetooth::groups::kGroupUnknown);
3296 }
3297
TEST_F_WITH_FLAGS(UnicastTestHealthStatus,ConnectOneEarbudWithInvalidCsis_withHealthStatus,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_enable_health_based_actions)))3298 TEST_F_WITH_FLAGS(UnicastTestHealthStatus,
3299 ConnectOneEarbudWithInvalidCsis_withHealthStatus,
3300 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
3301 TEST_BT, leaudio_enable_health_based_actions))) {
3302 const RawAddress test_address0 = GetTestAddress(0);
3303 SetSampleDatabaseEarbudsValid(
3304 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3305 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3306 default_channel_cnt, 0x0004,
3307 /* source sample freq 16khz */ true, /*add_csis*/
3308 true, /*add_cas*/
3309 true, /*add_pacs*/
3310 default_ase_cnt /*add_ascs*/);
3311 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3312 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3313 .Times(1);
3314 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3315 OnHealthBasedRecommendationAction(
3316 test_address0, LeAudioHealthBasedAction::DISABLE))
3317 .Times(1);
3318
3319 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3320
3321 // Report working CSIS
3322 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
3323 .WillByDefault(Return(true));
3324
3325 /* Make sure Group has not knowledge about the device */
3326 ON_CALL(mock_groups_module_, GetGroupId(_, _))
3327 .WillByDefault([](const RawAddress& addr, bluetooth::Uuid uuid) {
3328 return bluetooth::groups::kGroupUnknown;
3329 });
3330
3331 ConnectLeAudio(test_address0);
3332 SyncOnMainLoop();
3333 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3334 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3335
3336 LeAudioHealthStatus::Get()->RemoveStatistics(
3337 test_address0, bluetooth::groups::kGroupUnknown);
3338 }
3339
TEST_F_WITH_FLAGS(UnicastTestHealthStatus,ConnectOneEarbudDisable_withHealthStatus,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_enable_health_based_actions)))3340 TEST_F_WITH_FLAGS(UnicastTestHealthStatus,
3341 ConnectOneEarbudDisable_withHealthStatus,
3342 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
3343 TEST_BT, leaudio_enable_health_based_actions))) {
3344 const RawAddress test_address0 = GetTestAddress(0);
3345 int conn_id = 1;
3346
3347 SetSampleDatabaseEarbudsValid(
3348 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3349 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3350 default_channel_cnt, 0x0004, false);
3351 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3352 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3353 .Times(1);
3354
3355 ConnectLeAudio(test_address0);
3356 SyncOnMainLoop();
3357 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3358
3359 LeAudioClient::Get()->GroupSetActive(group_id_);
3360 auto device = std::make_shared<LeAudioDevice>(
3361 test_address0, DeviceConnectState::DISCONNECTED);
3362 group_->AddNode(device);
3363 SyncOnMainLoop();
3364
3365 auto health_status = LeAudioHealthStatus::Get();
3366
3367 /* Inject stream error */
3368 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3369 OnHealthBasedGroupRecommendationAction(
3370 group_id_, LeAudioHealthBasedAction::DISABLE))
3371 .Times(1);
3372 health_status->AddStatisticForGroup(
3373 group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3374 health_status->AddStatisticForGroup(
3375 group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3376
3377 /* Do not act on disconnect */
3378 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
3379 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
3380 .WillByDefault(DoAll(Return()));
3381
3382 state_machine_callbacks_->OnStateTransitionTimeout(group_id_);
3383 SyncOnMainLoop();
3384 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3385
3386 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3387 OnHealthBasedGroupRecommendationAction(
3388 group_id_, LeAudioHealthBasedAction::DISABLE))
3389 .Times(0);
3390 health_status->AddStatisticForGroup(
3391 group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3392 health_status->AddStatisticForGroup(
3393 group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3394 SyncOnMainLoop();
3395 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3396 }
3397
TEST_F_WITH_FLAGS(UnicastTestHealthStatus,ConnectOneEarbudConsiderDisabling_withHealthStatus,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_enable_health_based_actions)))3398 TEST_F_WITH_FLAGS(UnicastTestHealthStatus,
3399 ConnectOneEarbudConsiderDisabling_withHealthStatus,
3400 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
3401 TEST_BT, leaudio_enable_health_based_actions))) {
3402 const RawAddress test_address0 = GetTestAddress(0);
3403 int conn_id = 1;
3404
3405 SetSampleDatabaseEarbudsValid(
3406 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3407 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3408 default_channel_cnt, 0x0004, false);
3409 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3410 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3411 .Times(1);
3412
3413 ConnectLeAudio(test_address0);
3414 SyncOnMainLoop();
3415 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3416
3417 LeAudioClient::Get()->GroupSetActive(group_id_);
3418 auto device = std::make_shared<LeAudioDevice>(
3419 test_address0, DeviceConnectState::DISCONNECTED);
3420 group_->AddNode(device);
3421 SyncOnMainLoop();
3422
3423 auto health_status = LeAudioHealthStatus::Get();
3424
3425 /* Inject stream success and error */
3426 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3427 OnHealthBasedGroupRecommendationAction(
3428 group_id_, LeAudioHealthBasedAction::CONSIDER_DISABLING))
3429 .Times(1);
3430 health_status->AddStatisticForGroup(
3431 group_, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
3432 health_status->AddStatisticForGroup(
3433 group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3434 health_status->AddStatisticForGroup(
3435 group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3436
3437 /* Do not act on disconnect */
3438 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
3439 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
3440 .WillByDefault(DoAll(Return()));
3441
3442 state_machine_callbacks_->OnStateTransitionTimeout(group_id_);
3443 SyncOnMainLoop();
3444 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3445
3446 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3447 OnHealthBasedGroupRecommendationAction(
3448 1, LeAudioHealthBasedAction::CONSIDER_DISABLING))
3449 .Times(0);
3450 health_status->AddStatisticForGroup(
3451 group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3452 health_status->AddStatisticForGroup(
3453 group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3454 SyncOnMainLoop();
3455 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3456 }
3457
TEST_F(UnicastTest,ConnectDisconnectOneEarbud)3458 TEST_F(UnicastTest, ConnectDisconnectOneEarbud) {
3459 const RawAddress test_address0 = GetTestAddress(0);
3460 SetSampleDatabaseEarbudsValid(1, test_address0,
3461 codec_spec_conf::kLeAudioLocationStereo,
3462 codec_spec_conf::kLeAudioLocationStereo);
3463 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3464 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3465 .Times(1);
3466 ConnectLeAudio(test_address0);
3467 DisconnectLeAudioWithAclClose(test_address0, 1);
3468 }
3469
TEST_F(UnicastTest,ConnectRemoteServiceDiscoveryCompleteBeforeEncryption)3470 TEST_F(UnicastTest, ConnectRemoteServiceDiscoveryCompleteBeforeEncryption) {
3471 const RawAddress test_address0 = GetTestAddress(0);
3472 uint16_t conn_id = 1;
3473 SetSampleDatabaseEarbudsValid(conn_id, test_address0,
3474 codec_spec_conf::kLeAudioLocationStereo,
3475 codec_spec_conf::kLeAudioLocationStereo);
3476 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3477 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3478 .Times(0);
3479 ConnectLeAudio(test_address0, false);
3480 InjectSearchCompleteEvent(conn_id);
3481
3482 SyncOnMainLoop();
3483 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3484
3485 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3486 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3487 .Times(1);
3488 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3489 .WillByDefault(DoAll(Return(true)));
3490 InjectEncryptionChangedEvent(test_address0);
3491 SyncOnMainLoop();
3492 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3493 }
3494
TEST_F(UnicastTest,DisconnectWhenLinkKeyIsGone)3495 TEST_F(UnicastTest, DisconnectWhenLinkKeyIsGone) {
3496 const RawAddress test_address0 = GetTestAddress(0);
3497 uint16_t conn_id = 1;
3498 SetSampleDatabaseEarbudsValid(conn_id, test_address0,
3499 codec_spec_conf::kLeAudioLocationStereo,
3500 codec_spec_conf::kLeAudioLocationStereo);
3501 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3502 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3503 .Times(1);
3504
3505 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3506 .WillByDefault(DoAll(Return(false)));
3507
3508 ON_CALL(mock_btm_interface_, SetEncryption(test_address0, _, _, _, _))
3509 .WillByDefault(Return(BTM_ERR_KEY_MISSING));
3510
3511 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3512 do_in_main_thread(
3513 FROM_HERE,
3514 base::BindOnce(&LeAudioClient::Connect,
3515 base::Unretained(LeAudioClient::Get()), test_address0));
3516
3517 SyncOnMainLoop();
3518 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3519 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3520 }
3521
3522 /* same as above case except the disconnect is initiated by remote */
TEST_F(UnicastTest,ConnectRemoteDisconnectOneEarbud)3523 TEST_F(UnicastTest, ConnectRemoteDisconnectOneEarbud) {
3524 const RawAddress test_address0 = GetTestAddress(0);
3525 SetSampleDatabaseEarbudsValid(1, test_address0,
3526 codec_spec_conf::kLeAudioLocationStereo,
3527 codec_spec_conf::kLeAudioLocationStereo);
3528 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3529 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3530 .Times(1);
3531 ConnectLeAudio(test_address0);
3532 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3533
3534 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3535 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3536 .Times(1);
3537 /* Make sure when remote device disconnects us, TA is used */
3538 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _))
3539 .Times(1);
3540 EXPECT_CALL(mock_gatt_interface_,
3541 Open(gatt_if, test_address0,
3542 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3543 .Times(1);
3544
3545 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
3546 SyncOnMainLoop();
3547
3548 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3549
3550 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3551 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3552 .Times(1);
3553
3554 /* When reconnected, we always remove background connect, as we do not track
3555 * which type (allow list or TA) was used and then make sure the TA is used.
3556 */
3557 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _))
3558 .Times(1);
3559 EXPECT_CALL(mock_gatt_interface_,
3560 Open(gatt_if, test_address0,
3561 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3562 .Times(1);
3563
3564 /* For background connect, test needs to Inject Connected Event */
3565 InjectConnectedEvent(test_address0, 1);
3566 SyncOnMainLoop();
3567 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3568 }
3569
3570 /* same as above case except the disconnect is initiated by remote */
TEST_F(UnicastTest,ConnectRemoteDisconnectOnTimeoutOneEarbud)3571 TEST_F(UnicastTest, ConnectRemoteDisconnectOnTimeoutOneEarbud) {
3572 const RawAddress test_address0 = GetTestAddress(0);
3573 SetSampleDatabaseEarbudsValid(1, test_address0,
3574 codec_spec_conf::kLeAudioLocationStereo,
3575 codec_spec_conf::kLeAudioLocationStereo);
3576 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3577 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3578 .Times(1);
3579 ConnectLeAudio(test_address0);
3580 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3581 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3582 .Times(1);
3583
3584 /* Remove default action on the direct connect */
3585 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
3586 .WillByDefault(Return());
3587
3588 /* For remote disconnection, expect stack to try background re-connect */
3589 EXPECT_CALL(mock_gatt_interface_,
3590 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3591 .Times(1);
3592
3593 InjectDisconnectedEvent(1, GATT_CONN_TIMEOUT);
3594 SyncOnMainLoop();
3595
3596 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3597
3598 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3599 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3600 .Times(1);
3601
3602 /* For background connect, test needs to Inject Connected Event */
3603 InjectConnectedEvent(test_address0, 1);
3604 SyncOnMainLoop();
3605 }
3606
TEST_F(UnicastTest,ConnectTwoEarbudsCsisGrouped)3607 TEST_F(UnicastTest, ConnectTwoEarbudsCsisGrouped) {
3608 uint8_t group_size = 2;
3609 int group_id = 2;
3610
3611 // Report working CSIS
3612 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
3613 .WillByDefault(Return(true));
3614
3615 // First earbud
3616 const RawAddress test_address0 = GetTestAddress(0);
3617 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3618 .Times(1);
3619 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
3620 codec_spec_conf::kLeAudioLocationFrontLeft,
3621 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
3622 group_id, 1 /* rank*/);
3623
3624 // Second earbud
3625 const RawAddress test_address1 = GetTestAddress(1);
3626 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
3627 .Times(1);
3628 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
3629 codec_spec_conf::kLeAudioLocationFrontRight,
3630 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
3631 group_id, 2 /* rank*/, true /*connect_through_csis*/);
3632
3633 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3634
3635 /* for Target announcements AutoConnect is always there, until
3636 * device is removed
3637 */
3638 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false))
3639 .Times(0);
3640 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
3641 .Times(0);
3642
3643 // Verify grouping information
3644 std::vector<RawAddress> devs =
3645 LeAudioClient::Get()->GetGroupDevices(group_id);
3646 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3647 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3648
3649 DisconnectLeAudioWithAclClose(test_address0, 1);
3650 DisconnectLeAudioWithAclClose(test_address1, 2);
3651 }
3652
TEST_F(UnicastTest,ConnectTwoEarbudsCsisGroupUnknownAtConnect)3653 TEST_F(UnicastTest, ConnectTwoEarbudsCsisGroupUnknownAtConnect) {
3654 uint8_t group_size = 2;
3655 uint8_t group_id = 2;
3656
3657 // Report working CSIS
3658 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
3659 .WillByDefault(Return(true));
3660
3661 // First earbud connects without known grouping
3662 const RawAddress test_address0 = GetTestAddress(0);
3663 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3664 .Times(1);
3665 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
3666 codec_spec_conf::kLeAudioLocationFrontLeft,
3667 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
3668 group_id, 1 /* rank*/);
3669
3670 // Second earbud
3671 const RawAddress test_address1 = GetTestAddress(1);
3672 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
3673 .Times(1);
3674 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
3675 codec_spec_conf::kLeAudioLocationFrontRight,
3676 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
3677 group_id, 2 /* rank*/, true /*connect_through_csis*/);
3678
3679 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3680
3681 // Verify grouping information
3682 std::vector<RawAddress> devs =
3683 LeAudioClient::Get()->GetGroupDevices(group_id);
3684 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3685 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3686
3687 /* for Target announcements AutoConnect is always there, until
3688 * device is removed
3689 */
3690 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false))
3691 .Times(0);
3692 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
3693 .Times(0);
3694 DisconnectLeAudioWithAclClose(test_address0, 1);
3695 DisconnectLeAudioWithAclClose(test_address1, 2);
3696 }
3697
TEST_F(UnicastTestNoInit,ConnectFailedDueToInvalidParameters)3698 TEST_F(UnicastTestNoInit, ConnectFailedDueToInvalidParameters) {
3699 // Prepare two devices
3700 uint8_t group_size = 2;
3701 uint8_t group_id = 2;
3702
3703 /* Prepare mock to not inject connect event so the device can stay in
3704 * CONNECTING state*/
3705 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3706 .WillByDefault(DoAll(Return()));
3707
3708 const RawAddress test_address0 = GetTestAddress(0);
3709 SetSampleDatabaseEarbudsValid(
3710 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3711 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3712 default_channel_cnt, 0x0004,
3713 /* source sample freq 16khz */ true, /*add_csis*/
3714 true, /*add_cas*/
3715 true, /*add_pacs*/
3716 default_ase_cnt, /*add_ascs_cnt*/
3717 group_size, 1);
3718
3719 const RawAddress test_address1 = GetTestAddress(1);
3720 SetSampleDatabaseEarbudsValid(
3721 2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
3722 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
3723 default_channel_cnt, 0x0004,
3724 /* source sample freq 16khz */ true, /*add_csis*/
3725 true, /*add_cas*/
3726 true, /*add_pacs*/
3727 default_ase_cnt, /*add_ascs_cnt*/
3728 group_size, 2);
3729
3730 // Load devices from the storage when storage API is called
3731 bool autoconnect = true;
3732
3733 /* Common storage values */
3734 std::vector<uint8_t> handles;
3735 LeAudioClient::GetHandlesForStorage(test_address0, handles);
3736
3737 std::vector<uint8_t> ases;
3738 LeAudioClient::GetAsesForStorage(test_address0, ases);
3739
3740 std::vector<uint8_t> src_pacs;
3741 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
3742
3743 std::vector<uint8_t> snk_pacs;
3744 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
3745
3746 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
3747 do_in_main_thread(
3748 FROM_HERE,
3749 base::Bind(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
3750 codec_spec_conf::kLeAudioLocationFrontLeft,
3751 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
3752 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
3753 std::move(ases)));
3754 do_in_main_thread(
3755 FROM_HERE,
3756 base::Bind(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
3757 codec_spec_conf::kLeAudioLocationFrontRight,
3758 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
3759 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
3760 std::move(ases)));
3761 });
3762
3763 // Expect stored device0 to connect automatically (first directed connection )
3764 EXPECT_CALL(mock_gatt_interface_,
3765 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3766 .Times(1);
3767
3768 // Expect stored device1 to connect automatically (first direct connection)
3769 EXPECT_CALL(mock_gatt_interface_,
3770 Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
3771 .Times(1);
3772
3773 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
3774 .WillByDefault(DoAll(Return(true)));
3775 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3776 .WillByDefault(DoAll(Return(true)));
3777
3778 ON_CALL(mock_groups_module_, GetGroupId(_, _))
3779 .WillByDefault(DoAll(Return(group_id)));
3780
3781 ON_CALL(mock_btm_interface_,
3782 GetSecurityFlagsByTransport(test_address0, NotNull(), _))
3783 .WillByDefault(
3784 DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
3785
3786 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
3787 framework_encode_preference;
3788
3789 // Initialize
3790 BtaAppRegisterCallback app_register_callback;
3791 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
3792 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
3793 SaveArg<1>(&app_register_callback)));
3794 LeAudioClient::Initialize(
3795 &mock_audio_hal_client_callbacks_,
3796 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
3797 &mock_storage_load),
3798 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
3799 &mock_hal_2_1_verifier),
3800 framework_encode_preference);
3801 if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS);
3802
3803 // We need to wait for the storage callback before verifying stuff
3804 SyncOnMainLoop();
3805 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
3806 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3807
3808 // Simulate connect parameters are invalid and phone does not fallback
3809 // to background connect.
3810 EXPECT_CALL(mock_gatt_interface_,
3811 Open(gatt_if, test_address0,
3812 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3813 .Times(0);
3814
3815 EXPECT_CALL(mock_gatt_interface_,
3816 Open(gatt_if, test_address1,
3817 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3818 .Times(0);
3819
3820 // Devices not found
3821 InjectConnectedEvent(test_address0, 0, GATT_ILLEGAL_PARAMETER);
3822 InjectConnectedEvent(test_address1, 0, GATT_ILLEGAL_PARAMETER);
3823
3824 SyncOnMainLoop();
3825 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3826 }
3827
TEST_F(UnicastTestNoInit,LoadStoredEarbudsBroakenStorage)3828 TEST_F(UnicastTestNoInit, LoadStoredEarbudsBroakenStorage) {
3829 // Prepare two devices
3830 uint8_t group_size = 2;
3831 uint8_t group_id = 2;
3832 /* If the storage has been broken, make sure device will be rediscovered after
3833 * reconnection
3834 */
3835
3836 /* Prepare mock to not inject connect event so the device can stay in
3837 * CONNECTING state*/
3838 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3839 .WillByDefault(DoAll(Return()));
3840
3841 const RawAddress test_address0 = GetTestAddress(0);
3842 SetSampleDatabaseEarbudsValid(
3843 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3844 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3845 default_channel_cnt, 0x0004,
3846 /* source sample freq 16khz */ true, /*add_csis*/
3847 true, /*add_cas*/
3848 true, /*add_pacs*/
3849 default_ase_cnt, /*add_ascs_cnt*/
3850 group_size, 1);
3851
3852 const RawAddress test_address1 = GetTestAddress(1);
3853 SetSampleDatabaseEarbudsValid(
3854 2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
3855 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
3856 default_channel_cnt, 0x0004,
3857 /* source sample freq 16khz */ true, /*add_csis*/
3858 true, /*add_cas*/
3859 true, /*add_pacs*/
3860 default_ase_cnt, /*add_ascs_cnt*/
3861 group_size, 2);
3862
3863 // Load devices from the storage when storage API is called
3864 bool autoconnect = true;
3865 std::vector<uint8_t> empty_buf;
3866
3867 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
3868 do_in_main_thread(
3869 FROM_HERE,
3870 base::BindOnce(&LeAudioClient::AddFromStorage, test_address0,
3871 autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft,
3872 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
3873 std::move(empty_buf), std::move(empty_buf),
3874 std::move(empty_buf), std::move(empty_buf)));
3875 do_in_main_thread(
3876 FROM_HERE,
3877 base::BindOnce(&LeAudioClient::AddFromStorage, test_address1,
3878 autoconnect, codec_spec_conf::kLeAudioLocationFrontRight,
3879 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
3880 std::move(empty_buf), std::move(empty_buf),
3881 std::move(empty_buf), std::move(empty_buf)));
3882 SyncOnMainLoop();
3883 });
3884
3885 // Expect stored device0 to connect automatically (first directed connection )
3886 EXPECT_CALL(mock_gatt_interface_,
3887 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3888 .Times(1);
3889
3890 // Expect stored device1 to connect automatically (first direct connection)
3891 EXPECT_CALL(mock_gatt_interface_,
3892 Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
3893 .Times(1);
3894
3895 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
3896 .WillByDefault(DoAll(Return(true)));
3897 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3898 .WillByDefault(DoAll(Return(true)));
3899
3900 ON_CALL(mock_groups_module_, GetGroupId(_, _))
3901 .WillByDefault(DoAll(Return(group_id)));
3902
3903 ON_CALL(mock_btm_interface_,
3904 GetSecurityFlagsByTransport(test_address0, NotNull(), _))
3905 .WillByDefault(
3906 DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
3907
3908 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
3909 framework_encode_preference;
3910
3911 // Initialize
3912 BtaAppRegisterCallback app_register_callback;
3913 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
3914 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
3915 SaveArg<1>(&app_register_callback)));
3916 LeAudioClient::Initialize(
3917 &mock_audio_hal_client_callbacks_,
3918 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
3919 &mock_storage_load),
3920 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
3921 &mock_hal_2_1_verifier),
3922 framework_encode_preference);
3923 if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS);
3924
3925 // We need to wait for the storage callback before verifying stuff
3926 SyncOnMainLoop();
3927 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
3928 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3929
3930 // Simulate devices are not there and phone fallbacks to targeted
3931 // announcements
3932 EXPECT_CALL(mock_gatt_interface_,
3933 Open(gatt_if, test_address0,
3934 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3935 .Times(1);
3936
3937 EXPECT_CALL(mock_gatt_interface_,
3938 Open(gatt_if, test_address1,
3939 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3940 .Times(1);
3941
3942 // Devices not found
3943 InjectConnectedEvent(test_address0, 0, GATT_ERROR);
3944 InjectConnectedEvent(test_address1, 0, GATT_ERROR);
3945
3946 SyncOnMainLoop();
3947 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3948
3949 /* Stack should rediscover services as storage is broken */
3950 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(2, _)).Times(1);
3951 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(1, _)).Times(1);
3952
3953 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3954 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3955 .Times(1);
3956
3957 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3958 OnConnectionState(ConnectionState::CONNECTED, test_address1))
3959 .Times(1);
3960
3961 /* For background connect, test needs to Inject Connected Event */
3962 InjectConnectedEvent(test_address0, 1);
3963 InjectConnectedEvent(test_address1, 2);
3964 SyncOnMainLoop();
3965
3966 // Verify if all went well and we got the proper group
3967 std::vector<RawAddress> devs =
3968 LeAudioClient::Get()->GetGroupDevices(group_id);
3969 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3970 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3971
3972 DisconnectLeAudioWithAclClose(test_address0, 1);
3973 DisconnectLeAudioWithAclClose(test_address1, 2);
3974 }
3975
TEST_F(UnicastTestNoInit,LoadStoredEarbudsCsisGrouped)3976 TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) {
3977 // Prepare two devices
3978 uint8_t group_size = 2;
3979 uint8_t group_id = 2;
3980
3981 /* Prepare mock to not inject connect event so the device can stay in
3982 * CONNECTING state*/
3983 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3984 .WillByDefault(DoAll(Return()));
3985
3986 const RawAddress test_address0 = GetTestAddress(0);
3987 SetSampleDatabaseEarbudsValid(
3988 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3989 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3990 default_channel_cnt, 0x0004,
3991 /* source sample freq 16khz */ true, /*add_csis*/
3992 true, /*add_cas*/
3993 true, /*add_pacs*/
3994 default_ase_cnt, /*add_ascs_cnt*/
3995 group_size, 1);
3996
3997 const RawAddress test_address1 = GetTestAddress(1);
3998 SetSampleDatabaseEarbudsValid(
3999 2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
4000 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
4001 default_channel_cnt, 0x0004,
4002 /* source sample freq 16khz */ true, /*add_csis*/
4003 true, /*add_cas*/
4004 true, /*add_pacs*/
4005 default_ase_cnt, /*add_ascs_cnt*/
4006 group_size, 2);
4007
4008 // Load devices from the storage when storage API is called
4009 bool autoconnect = true;
4010
4011 /* Common storage values */
4012 std::vector<uint8_t> handles;
4013 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4014
4015 std::vector<uint8_t> ases;
4016 LeAudioClient::GetAsesForStorage(test_address0, ases);
4017
4018 std::vector<uint8_t> src_pacs;
4019 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4020
4021 std::vector<uint8_t> snk_pacs;
4022 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4023
4024 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4025 do_in_main_thread(
4026 FROM_HERE,
4027 base::BindOnce(&LeAudioClient::AddFromStorage, test_address0,
4028 autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft,
4029 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
4030 std::move(handles), std::move(snk_pacs),
4031 std::move(src_pacs), std::move(ases)));
4032 do_in_main_thread(
4033 FROM_HERE,
4034 base::BindOnce(&LeAudioClient::AddFromStorage, test_address1,
4035 autoconnect, codec_spec_conf::kLeAudioLocationFrontRight,
4036 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
4037 std::move(handles), std::move(snk_pacs),
4038 std::move(src_pacs), std::move(ases)));
4039 SyncOnMainLoop();
4040 });
4041
4042 // Expect stored device0 to connect automatically (first directed connection )
4043 EXPECT_CALL(mock_gatt_interface_,
4044 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
4045 .Times(1);
4046
4047 // Expect stored device1 to connect automatically (first direct connection)
4048 EXPECT_CALL(mock_gatt_interface_,
4049 Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
4050 .Times(1);
4051
4052 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4053 .WillByDefault(DoAll(Return(true)));
4054 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4055 .WillByDefault(DoAll(Return(true)));
4056
4057 ON_CALL(mock_groups_module_, GetGroupId(_, _))
4058 .WillByDefault(DoAll(Return(group_id)));
4059
4060 ON_CALL(mock_btm_interface_,
4061 GetSecurityFlagsByTransport(test_address0, NotNull(), _))
4062 .WillByDefault(
4063 DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
4064
4065 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
4066 framework_encode_preference;
4067
4068 // Initialize
4069 BtaAppRegisterCallback app_register_callback;
4070 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
4071 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
4072 SaveArg<1>(&app_register_callback)));
4073 LeAudioClient::Initialize(
4074 &mock_audio_hal_client_callbacks_,
4075 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
4076 &mock_storage_load),
4077 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
4078 &mock_hal_2_1_verifier),
4079 framework_encode_preference);
4080 if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS);
4081
4082 // We need to wait for the storage callback before verifying stuff
4083 SyncOnMainLoop();
4084 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4085 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4086
4087 // Simulate devices are not there and phone fallbacks to targeted
4088 // announcements
4089 EXPECT_CALL(mock_gatt_interface_,
4090 Open(gatt_if, test_address0,
4091 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4092 .Times(1);
4093
4094 EXPECT_CALL(mock_gatt_interface_,
4095 Open(gatt_if, test_address1,
4096 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4097 .Times(1);
4098
4099 // Devices not found
4100 InjectConnectedEvent(test_address0, 0, GATT_ERROR);
4101 InjectConnectedEvent(test_address1, 0, GATT_ERROR);
4102
4103 SyncOnMainLoop();
4104 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4105
4106 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4107 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4108 .Times(1);
4109
4110 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4111 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4112 .Times(1);
4113
4114 /* For background connect, test needs to Inject Connected Event */
4115 InjectConnectedEvent(test_address0, 1);
4116 InjectConnectedEvent(test_address1, 2);
4117 SyncOnMainLoop();
4118
4119 // Verify if all went well and we got the proper group
4120 std::vector<RawAddress> devs =
4121 LeAudioClient::Get()->GetGroupDevices(group_id);
4122 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4123 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4124
4125 DisconnectLeAudioWithAclClose(test_address0, 1);
4126 DisconnectLeAudioWithAclClose(test_address1, 2);
4127 }
4128
TEST_F(UnicastTestNoInit,ServiceChangedBeforeServiceIsConnected)4129 TEST_F(UnicastTestNoInit, ServiceChangedBeforeServiceIsConnected) {
4130 // Prepare two devices
4131 uint8_t group_size = 2;
4132 uint8_t group_id = 2;
4133
4134 /* Prepare mock to not inject connect event so the device can stay in
4135 * CONNECTING state*/
4136 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
4137 .WillByDefault(DoAll(Return()));
4138
4139 const RawAddress test_address0 = GetTestAddress(0);
4140 SetSampleDatabaseEarbudsValid(
4141 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
4142 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
4143 default_channel_cnt, 0x0004,
4144 /* source sample freq 16khz */ true, /*add_csis*/
4145 true, /*add_cas*/
4146 true, /*add_pacs*/
4147 default_ase_cnt, /*add_ascs_cnt*/
4148 group_size, 1);
4149
4150 const RawAddress test_address1 = GetTestAddress(1);
4151 SetSampleDatabaseEarbudsValid(
4152 2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
4153 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
4154 default_channel_cnt, 0x0004,
4155 /* source sample freq 16khz */ true, /*add_csis*/
4156 true, /*add_cas*/
4157 true, /*add_pacs*/
4158 default_ase_cnt, /*add_ascs_cnt*/
4159 group_size, 2);
4160
4161 // Load devices from the storage when storage API is called
4162 bool autoconnect = true;
4163
4164 /* Common storage values */
4165 std::vector<uint8_t> handles;
4166 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4167
4168 std::vector<uint8_t> ases;
4169 LeAudioClient::GetAsesForStorage(test_address0, ases);
4170
4171 std::vector<uint8_t> src_pacs;
4172 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4173
4174 std::vector<uint8_t> snk_pacs;
4175 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4176
4177 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4178 do_in_main_thread(
4179 FROM_HERE,
4180 base::BindOnce(&LeAudioClient::AddFromStorage, test_address0,
4181 autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft,
4182 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
4183 std::move(handles), std::move(snk_pacs),
4184 std::move(src_pacs), std::move(ases)));
4185 do_in_main_thread(
4186 FROM_HERE,
4187 base::BindOnce(&LeAudioClient::AddFromStorage, test_address1,
4188 autoconnect, codec_spec_conf::kLeAudioLocationFrontRight,
4189 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
4190 std::move(handles), std::move(snk_pacs),
4191 std::move(src_pacs), std::move(ases)));
4192 SyncOnMainLoop();
4193 });
4194
4195 // Expect stored device0 to connect automatically (first directed connection )
4196 EXPECT_CALL(mock_gatt_interface_,
4197 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
4198 .Times(1);
4199
4200 // Expect stored device1 to connect automatically (first direct connection)
4201 EXPECT_CALL(mock_gatt_interface_,
4202 Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
4203 .Times(1);
4204
4205 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4206 .WillByDefault(DoAll(Return(true)));
4207 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4208 .WillByDefault(DoAll(Return(true)));
4209
4210 ON_CALL(mock_groups_module_, GetGroupId(_, _))
4211 .WillByDefault(DoAll(Return(group_id)));
4212
4213 ON_CALL(mock_btm_interface_,
4214 GetSecurityFlagsByTransport(test_address0, NotNull(), _))
4215 .WillByDefault(
4216 DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
4217
4218 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
4219 framework_encode_preference;
4220
4221 // Initialize
4222 BtaAppRegisterCallback app_register_callback;
4223 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
4224 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
4225 SaveArg<1>(&app_register_callback)));
4226 LeAudioClient::Initialize(
4227 &mock_audio_hal_client_callbacks_,
4228 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
4229 &mock_storage_load),
4230 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
4231 &mock_hal_2_1_verifier),
4232 framework_encode_preference);
4233 if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS);
4234
4235 // We need to wait for the storage callback before verifying stuff
4236 SyncOnMainLoop();
4237 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4238 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4239
4240 /* Inject Service Changed */
4241 InjectServiceChangedEvent(test_address1, 0xffff);
4242 SyncOnMainLoop();
4243 InjectServiceChangedEvent(test_address0, 0xffff);
4244 SyncOnMainLoop();
4245 /* Stack should rediscover services as storage is broken */
4246 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(2, _)).Times(1);
4247 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(1, _)).Times(1);
4248
4249 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4250 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4251 .Times(1);
4252
4253 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4254 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4255 .Times(1);
4256
4257 /* For background connect, test needs to Inject Connected Event */
4258 InjectConnectedEvent(test_address0, 1);
4259 InjectConnectedEvent(test_address1, 2);
4260 SyncOnMainLoop();
4261
4262 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4263 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4264 }
4265
TEST_F(UnicastTestNoInit,LoadStoredEarbudsCsisGroupedDifferently)4266 TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGroupedDifferently) {
4267 // Prepare two devices
4268 uint8_t group_size = 1;
4269
4270 // Device 0
4271 uint8_t group_id0 = 2;
4272 bool autoconnect0 = true;
4273 const RawAddress test_address0 = GetTestAddress(0);
4274 SetSampleDatabaseEarbudsValid(
4275 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
4276 codec_spec_conf::kLeAudioLocationFrontLeft, 0x0004,
4277 /* source sample freq 16khz */ true, /*add_csis*/
4278 true, /*add_cas*/
4279 true, /*add_pacs*/
4280 true, /*add_ascs*/
4281 group_size, 1);
4282
4283 ON_CALL(mock_groups_module_, GetGroupId(test_address0, _))
4284 .WillByDefault(DoAll(Return(group_id0)));
4285
4286 // Device 1
4287 uint8_t group_id1 = 3;
4288 bool autoconnect1 = false;
4289 const RawAddress test_address1 = GetTestAddress(1);
4290 SetSampleDatabaseEarbudsValid(
4291 2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
4292 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
4293 default_channel_cnt, 0x0004,
4294 /* source sample freq 16khz */ true, /*add_csis*/
4295 true, /*add_cas*/
4296 true, /*add_pacs*/
4297 default_ase_cnt, /*add_ascs_cnt*/
4298 group_size, 2);
4299
4300 ON_CALL(mock_groups_module_, GetGroupId(test_address1, _))
4301 .WillByDefault(DoAll(Return(group_id1)));
4302
4303 /* Commont storage values */
4304 std::vector<uint8_t> handles;
4305 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4306
4307 std::vector<uint8_t> ases;
4308 LeAudioClient::GetAsesForStorage(test_address0, ases);
4309
4310 std::vector<uint8_t> src_pacs;
4311 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4312
4313 std::vector<uint8_t> snk_pacs;
4314 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4315
4316 // Load devices from the storage when storage API is called
4317 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4318 do_in_main_thread(
4319 FROM_HERE,
4320 base::BindOnce(&LeAudioClient::AddFromStorage, test_address0,
4321 autoconnect0, codec_spec_conf::kLeAudioLocationFrontLeft,
4322 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
4323 std::move(handles), std::move(snk_pacs),
4324 std::move(src_pacs), std::move(ases)));
4325 do_in_main_thread(
4326 FROM_HERE,
4327 base::BindOnce(&LeAudioClient::AddFromStorage, test_address1,
4328 autoconnect1,
4329 codec_spec_conf::kLeAudioLocationFrontRight,
4330 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
4331 std::move(handles), std::move(snk_pacs),
4332 std::move(src_pacs), std::move(ases)));
4333 });
4334
4335 // Expect stored device0 to connect automatically
4336 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4337 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4338 .Times(1);
4339 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4340 .WillByDefault(DoAll(Return(true)));
4341
4342 // First device will got connected
4343 EXPECT_CALL(mock_gatt_interface_,
4344 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
4345 .Times(1);
4346 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _))
4347 .Times(1);
4348 EXPECT_CALL(mock_gatt_interface_,
4349 Open(gatt_if, test_address0,
4350 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4351 .Times(1);
4352
4353 // Expect stored device1 to NOT connect automatically
4354 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4355 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4356 .Times(0);
4357 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4358 .WillByDefault(DoAll(Return(true)));
4359
4360 EXPECT_CALL(mock_gatt_interface_,
4361 Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
4362 .Times(0);
4363
4364 // Initialize
4365 BtaAppRegisterCallback app_register_callback;
4366 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
4367 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
4368 SaveArg<1>(&app_register_callback)));
4369 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
4370 framework_encode_preference;
4371 LeAudioClient::Initialize(
4372 &mock_audio_hal_client_callbacks_,
4373 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
4374 &mock_storage_load),
4375 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
4376 &mock_hal_2_1_verifier),
4377 framework_encode_preference);
4378 if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS);
4379
4380 // We need to wait for the storage callback before verifying stuff
4381 SyncOnMainLoop();
4382 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4383 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4384 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4385
4386 // Simulate device is not there and phone fallbacks to targeted announcements
4387 EXPECT_CALL(mock_gatt_interface_,
4388 Open(gatt_if, test_address0,
4389 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4390 .Times(1);
4391
4392 // Devices 0 is connected. Disconnect it
4393 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
4394
4395 SyncOnMainLoop();
4396 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4397
4398 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _))
4399 .Times(1);
4400 EXPECT_CALL(mock_gatt_interface_,
4401 Open(gatt_if, test_address0,
4402 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4403 .Times(1);
4404
4405 /* Keep device in Getting Ready state */
4406 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4407 .WillByDefault(DoAll(Return(false)));
4408 ON_CALL(mock_btm_interface_, SetEncryption(test_address0, _, _, _, _))
4409 .WillByDefault(Return(BTM_SUCCESS));
4410
4411 /* For background connect, test needs to Inject Connected Event */
4412 InjectConnectedEvent(test_address0, 1);
4413
4414 // We need to wait for the storage callback before verifying stuff
4415 SyncOnMainLoop();
4416 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4417 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4418
4419 std::vector<RawAddress> devs =
4420 LeAudioClient::Get()->GetGroupDevices(group_id0);
4421 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4422 ASSERT_EQ(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4423
4424 devs = LeAudioClient::Get()->GetGroupDevices(group_id1);
4425 ASSERT_EQ(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4426 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4427
4428 /* Disconnects while being in getting ready state */
4429 DisconnectLeAudioWithGattClose(test_address0, 1);
4430 }
4431
TEST_F(UnicastTest,GroupingAddRemove)4432 TEST_F(UnicastTest, GroupingAddRemove) {
4433 // Earbud connects without known grouping
4434 uint8_t group_id0 = bluetooth::groups::kGroupUnknown;
4435 const RawAddress test_address0 = GetTestAddress(0);
4436
4437 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
4438 .Times(1);
4439 ConnectNonCsisDevice(test_address0, 1 /*conn_id*/,
4440 codec_spec_conf::kLeAudioLocationFrontLeft,
4441 codec_spec_conf::kLeAudioLocationFrontLeft);
4442
4443 group_id0 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
4444
4445 // Earbud connects without known grouping
4446 uint8_t group_id1 = bluetooth::groups::kGroupUnknown;
4447 const RawAddress test_address1 = GetTestAddress(1);
4448 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
4449 .Times(1);
4450 ConnectNonCsisDevice(test_address1, 2 /*conn_id*/,
4451 codec_spec_conf::kLeAudioLocationFrontRight,
4452 codec_spec_conf::kLeAudioLocationFrontRight);
4453
4454 group_id1 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
4455
4456 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
4457
4458 // Verify individual groups
4459 ASSERT_NE(group_id0, bluetooth::groups::kGroupUnknown);
4460 ASSERT_NE(group_id1, bluetooth::groups::kGroupUnknown);
4461 ASSERT_NE(group_id0, group_id1);
4462 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 1u);
4463 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 1u);
4464
4465 // Expectations on reassigning second earbud to the first group
4466 int dev1_storage_group = bluetooth::groups::kGroupUnknown;
4467 int dev1_new_group = bluetooth::groups::kGroupUnknown;
4468
4469 EXPECT_CALL(
4470 mock_audio_hal_client_callbacks_,
4471 OnGroupNodeStatus(test_address1, group_id1, GroupNodeStatus::REMOVED))
4472 .Times(AtLeast(1));
4473 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4474 OnGroupNodeStatus(test_address1, _, GroupNodeStatus::ADDED))
4475 .WillRepeatedly(SaveArg<1>(&dev1_new_group));
4476 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id1))
4477 .Times(AtLeast(1));
4478 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, _))
4479 .Times(AnyNumber());
4480
4481 LeAudioClient::Get()->GroupRemoveNode(group_id1, test_address1);
4482 SyncOnMainLoop();
4483
4484 Mock::VerifyAndClearExpectations(&mock_groups_module_);
4485 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
4486
4487 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, group_id0))
4488 .Times(1);
4489
4490 LeAudioClient::Get()->GroupAddNode(group_id0, test_address1);
4491 SyncOnMainLoop();
4492 Mock::VerifyAndClearExpectations(&mock_groups_module_);
4493
4494 dev1_storage_group =
4495 MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
4496
4497 // Verify regrouping results
4498 EXPECT_EQ(dev1_new_group, group_id0);
4499 EXPECT_EQ(dev1_new_group, dev1_storage_group);
4500 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 0u);
4501 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 2u);
4502 std::vector<RawAddress> devs =
4503 LeAudioClient::Get()->GetGroupDevices(group_id0);
4504 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4505 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4506 }
4507
TEST_F(UnicastTest,DoubleResumeFromAF)4508 TEST_F(UnicastTest, DoubleResumeFromAF) {
4509 const RawAddress test_address0 = GetTestAddress(0);
4510 int group_id = bluetooth::groups::kGroupUnknown;
4511
4512 SetSampleDatabaseEarbudsValid(
4513 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4514 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4515 default_channel_cnt, 0x0004,
4516 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4517 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4518 0 /*rank*/);
4519 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4520 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4521 .Times(1);
4522 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4523 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4524 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4525
4526 ConnectLeAudio(test_address0);
4527 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4528
4529 constexpr int gmcs_ccid = 1;
4530 constexpr int gtbs_ccid = 2;
4531
4532 // Audio sessions are started only when device gets active
4533 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4534 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4535 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
4536 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
4537 LeAudioClient::Get()->GroupSetActive(group_id);
4538 SyncOnMainLoop();
4539
4540 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
4541 .source = {}};
4542 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
4543
4544 block_streaming_state_callback = true;
4545
4546 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
4547 LocalAudioSourceResume(false);
4548
4549 SyncOnMainLoop();
4550 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4551 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4552
4553 // Additional resume shall be ignored.
4554 LocalAudioSourceResume(false, false);
4555
4556 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
4557
4558 do_in_main_thread(
4559 FROM_HERE,
4560 base::BindOnce(
4561 [](int group_id,
4562 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
4563 state_machine_callbacks) {
4564 state_machine_callbacks->StatusReportCb(
4565 group_id, GroupStreamStatus::STREAMING);
4566 },
4567 group_id, base::Unretained(state_machine_callbacks_)));
4568 SyncOnMainLoop();
4569 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4570
4571 // Verify Data transfer on one audio source cis
4572 constexpr uint8_t cis_count_out = 1;
4573 constexpr uint8_t cis_count_in = 0;
4574 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4575 }
4576
TEST_F(UnicastTest,DoubleResumeFromAFOnLocalSink)4577 TEST_F(UnicastTest, DoubleResumeFromAFOnLocalSink) {
4578 const RawAddress test_address0 = GetTestAddress(0);
4579 int group_id = bluetooth::groups::kGroupUnknown;
4580
4581 default_channel_cnt = 1;
4582
4583 SetSampleDatabaseEarbudsValid(
4584 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4585 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4586 default_channel_cnt, 0x0004,
4587 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4588 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4589 0 /*rank*/);
4590 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4591 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4592 .Times(1);
4593 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4594 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4595 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4596
4597 ConnectLeAudio(test_address0);
4598 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4599
4600 // Audio sessions are started only when device gets active
4601 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4602 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4603 LeAudioClient::Get()->GroupSetActive(group_id);
4604 SyncOnMainLoop();
4605
4606 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4607
4608 block_streaming_state_callback = true;
4609
4610 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
4611 LocalAudioSinkResume();
4612
4613 SyncOnMainLoop();
4614 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4615 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4616
4617 EXPECT_CALL(*mock_le_audio_sink_hal_client_, CancelStreamingRequest())
4618 .Times(0);
4619
4620 // Actuall test here: send additional resume which shall be ignored.
4621 LocalAudioSinkResume();
4622
4623 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
4624
4625 do_in_main_thread(
4626 FROM_HERE,
4627 base::BindOnce(
4628 [](int group_id,
4629 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
4630 state_machine_callbacks) {
4631 state_machine_callbacks->StatusReportCb(
4632 group_id, GroupStreamStatus::STREAMING);
4633 },
4634 group_id, base::Unretained(state_machine_callbacks_)));
4635 SyncOnMainLoop();
4636 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4637
4638 // Verify Data transfer on local audio sink which is started
4639 constexpr uint8_t cis_count_out = 0;
4640 constexpr uint8_t cis_count_in = 1;
4641 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
4642 }
4643
TEST_F(UnicastTest,HandleResumeWithoutMetadataUpdateOnLocalSink)4644 TEST_F(UnicastTest, HandleResumeWithoutMetadataUpdateOnLocalSink) {
4645 const RawAddress test_address0 = GetTestAddress(0);
4646 int group_id = bluetooth::groups::kGroupUnknown;
4647
4648 /**
4649 * In this test we want to make sure that if MetadataUpdate is
4650 * not called before Resume, but the context type is supported,
4651 * stream should be created
4652 */
4653
4654 default_channel_cnt = 1;
4655
4656 SetSampleDatabaseEarbudsValid(
4657 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4658 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4659 default_channel_cnt, 0x0004,
4660 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4661 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4662 0 /*rank*/);
4663 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4664 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4665 .Times(1);
4666 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4667 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4668 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4669
4670 ConnectLeAudio(test_address0);
4671 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4672
4673 // Audio sessions are started only when device gets active
4674 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4675 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4676 LeAudioClient::Get()->GroupSetActive(group_id);
4677 SyncOnMainLoop();
4678
4679 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4680
4681 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
4682 LocalAudioSinkResume();
4683
4684 SyncOnMainLoop();
4685 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4686 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4687 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4688
4689 // Verify Data transfer on local audio sink which is started
4690 constexpr uint8_t cis_count_out = 0;
4691 constexpr uint8_t cis_count_in = 1;
4692 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
4693
4694 SyncOnMainLoop();
4695 /* Clear cache by changing context types, this is required for the test
4696 * as setting active device actually generate cache
4697 */
4698 auto sink_available_context = types::kLeAudioContextAllRemoteSinkOnly;
4699 auto source_available_context = types::kLeAudioContextAllRemoteSource;
4700 InjectAvailableContextTypes(test_address0, 1, sink_available_context,
4701 source_available_context);
4702
4703 StopStreaming(group_id, true);
4704 SyncOnMainLoop();
4705
4706 // simulate suspend timeout passed, alarm executing
4707 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
4708 SyncOnMainLoop();
4709
4710 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4711
4712 // Resume without metadata update while cached configuration is cleared
4713 LocalAudioSinkResume();
4714 SyncOnMainLoop();
4715 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4716 }
4717
TEST_F(UnicastTest,GroupSetActiveNonConnectedGroup)4718 TEST_F(UnicastTest, GroupSetActiveNonConnectedGroup) {
4719 const RawAddress test_address0 = GetTestAddress(0);
4720 int group_id = bluetooth::groups::kGroupUnknown;
4721
4722 /**
4723 * In this test we want to make sure that Available context change reach Java
4724 * when group is in Configured state
4725 */
4726
4727 default_channel_cnt = 1;
4728 int conn_id = 1;
4729 SetSampleDatabaseEarbudsValid(
4730 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4731 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4732 default_channel_cnt, 0x0004,
4733 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4734 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4735 0 /*rank*/);
4736 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4737 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4738 .Times(1);
4739 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4740 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4741 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4742
4743 ConnectLeAudio(test_address0);
4744 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4745
4746 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4747
4748 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4749 OnGroupStatus(group_id, GroupStatus::INACTIVE))
4750 .Times(1);
4751
4752 InjectDisconnectedEvent(conn_id);
4753 SyncOnMainLoop();
4754
4755 // Audio sessions are started only when device gets active
4756 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4757 OnAudioGroupSelectableCodecConf(group_id, _, _))
4758 .Times(0);
4759 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4760 OnAudioGroupCurrentCodecConf(group_id, _, _))
4761 .Times(0);
4762 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(0);
4763 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(0);
4764
4765 // try to set active group on non connected group
4766
4767 LeAudioClient::Get()->GroupSetActive(group_id);
4768 SyncOnMainLoop();
4769 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4770 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4771 }
4772
TEST_F_WITH_FLAGS(UnicastTest,GroupSetActive_CurrentCodecSentOfActive,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_codec_config_callback_order_fix)))4773 TEST_F_WITH_FLAGS(UnicastTest, GroupSetActive_CurrentCodecSentOfActive,
4774 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
4775 TEST_BT, leaudio_codec_config_callback_order_fix))) {
4776 const RawAddress test_address0 = GetTestAddress(0);
4777 int group_id = bluetooth::groups::kGroupUnknown;
4778
4779 /**
4780 * In this test we want to make sure that Available context change reach Java
4781 * when group is in Configured state
4782 */
4783
4784 default_channel_cnt = 1;
4785
4786 SetSampleDatabaseEarbudsValid(
4787 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4788 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4789 default_channel_cnt, 0x0004,
4790 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4791 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4792 0 /*rank*/);
4793 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4794 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4795 .Times(1);
4796 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4797 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4798 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4799
4800 ConnectLeAudio(test_address0);
4801 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4802
4803 // Audio sessions are started only when device gets active
4804 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4805 OnAudioGroupSelectableCodecConf(group_id, _, _))
4806 .Times(1);
4807 btle_audio_codec_config_t empty_conf{};
4808 btle_audio_codec_config_t output_config = {
4809 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
4810 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
4811 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
4812 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
4813 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
4814 .octets_per_frame = 120};
4815
4816 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4817 OnAudioGroupCurrentCodecConf(group_id, empty_conf, output_config))
4818 .Times(1);
4819
4820 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4821 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4822 LeAudioClient::Get()->GroupSetActive(group_id);
4823 SyncOnMainLoop();
4824 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4825 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4826 }
4827
TEST_F(UnicastTest,GroupSetActive)4828 TEST_F(UnicastTest, GroupSetActive) {
4829 const RawAddress test_address0 = GetTestAddress(0);
4830 int group_id = bluetooth::groups::kGroupUnknown;
4831
4832 /**
4833 * In this test we want to make sure that Available context change reach Java
4834 * when group is in Configured state
4835 */
4836
4837 default_channel_cnt = 1;
4838
4839 SetSampleDatabaseEarbudsValid(
4840 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4841 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4842 default_channel_cnt, 0x0004,
4843 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4844 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4845 0 /*rank*/);
4846 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4847 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4848 .Times(1);
4849 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4850 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4851 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4852
4853 ConnectLeAudio(test_address0);
4854 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4855
4856 // Audio sessions are started only when device gets active
4857 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4858 OnAudioGroupSelectableCodecConf(group_id, _, _))
4859 .Times(1);
4860 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4861 OnGroupStatus(group_id, GroupStatus::ACTIVE))
4862 .Times(1);
4863 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4864 OnGroupStatus(_, GroupStatus::INACTIVE))
4865 .Times(0);
4866 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4867 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4868
4869 EXPECT_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(
4870 mock_le_audio_source_hal_client_,
4871 mock_le_audio_sink_hal_client_, true))
4872 .Times(1);
4873
4874 LeAudioClient::Get()->GroupSetActive(group_id);
4875 SyncOnMainLoop();
4876 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4877 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4878 Mock::VerifyAndClearExpectations(mock_codec_manager_);
4879 }
4880
TEST_F(UnicastTest,GroupSetActive_SinkPacksEmpty)4881 TEST_F(UnicastTest, GroupSetActive_SinkPacksEmpty) {
4882 const RawAddress test_address0 = GetTestAddress(0);
4883 int group_id = bluetooth::groups::kGroupUnknown;
4884 empty_sink_pack_ = true;
4885
4886 /**
4887 * In this test we want to make sure that Available context change reach Java
4888 * when group is in Configured state
4889 */
4890
4891 default_channel_cnt = 1;
4892
4893 SetSampleDatabaseEarbudsValid(
4894 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4895 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4896 default_channel_cnt, 0x0004,
4897 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4898 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4899 0 /*rank*/);
4900 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4901 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4902 .Times(1);
4903 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4904 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4905 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4906
4907 ConnectLeAudio(test_address0);
4908 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4909
4910 // Audio sessions are started only when device gets active
4911 std::vector<btle_audio_codec_config_t> empty_confs;
4912
4913 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4914 OnAudioGroupSelectableCodecConf(group_id, _, empty_confs))
4915 .Times(1);
4916 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4917 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4918
4919 EXPECT_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(
4920 mock_le_audio_source_hal_client_,
4921 mock_le_audio_sink_hal_client_, true))
4922 .Times(1);
4923
4924 LeAudioClient::Get()->GroupSetActive(group_id);
4925 SyncOnMainLoop();
4926 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4927 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4928 Mock::VerifyAndClearExpectations(mock_codec_manager_);
4929 }
4930
TEST_F(UnicastTest,GroupSetActive_SourcePacksEmpty)4931 TEST_F(UnicastTest, GroupSetActive_SourcePacksEmpty) {
4932 const RawAddress test_address0 = GetTestAddress(0);
4933 int group_id = bluetooth::groups::kGroupUnknown;
4934 empty_source_pack_ = true;
4935
4936 /**
4937 * In this test we want to make sure that Available context change reach Java
4938 * when group is in Configured state
4939 */
4940
4941 default_channel_cnt = 1;
4942
4943 SetSampleDatabaseEarbudsValid(
4944 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4945 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4946 default_channel_cnt, 0x0004,
4947 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4948 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4949 0 /*rank*/);
4950 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4951 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4952 .Times(1);
4953 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4954 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4955 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4956
4957 ConnectLeAudio(test_address0);
4958 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4959
4960 // Audio sessions are started only when device gets active
4961 std::vector<btle_audio_codec_config_t> empty_confs;
4962
4963 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4964 OnAudioGroupSelectableCodecConf(group_id, empty_confs, _))
4965 .Times(1);
4966 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4967 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4968 LeAudioClient::Get()->GroupSetActive(group_id);
4969 SyncOnMainLoop();
4970 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4971 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4972 }
4973
TEST_F(UnicastTest,ChangeAvailableContextTypeWhenInCodecConfigured)4974 TEST_F(UnicastTest, ChangeAvailableContextTypeWhenInCodecConfigured) {
4975 const RawAddress test_address0 = GetTestAddress(0);
4976 int group_id = bluetooth::groups::kGroupUnknown;
4977
4978 /**
4979 * In this test we want to make sure that Available context change reach Java
4980 * when group is in Configured state
4981 */
4982
4983 default_channel_cnt = 1;
4984
4985 SetSampleDatabaseEarbudsValid(
4986 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4987 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4988 default_channel_cnt, 0x0004,
4989 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4990 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4991 0 /*rank*/);
4992 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4993 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4994 .Times(1);
4995 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4996 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4997 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4998
4999 ConnectLeAudio(test_address0);
5000 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5001
5002 // Audio sessions are started only when device gets active
5003 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5004 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5005 LeAudioClient::Get()->GroupSetActive(group_id);
5006 SyncOnMainLoop();
5007
5008 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5009
5010 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
5011 LocalAudioSinkResume();
5012
5013 SyncOnMainLoop();
5014 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5015 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5016 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5017
5018 // Verify Data transfer on local audio sink which is started
5019 constexpr uint8_t cis_count_out = 0;
5020 constexpr uint8_t cis_count_in = 1;
5021 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
5022
5023 // Remember group to set the state after stopping the stream
5024 ASSERT_NE(0lu, streaming_groups.count(group_id));
5025 auto group = streaming_groups.at(group_id);
5026
5027 SyncOnMainLoop();
5028 StopStreaming(group_id, true);
5029 SyncOnMainLoop();
5030
5031 // simulate suspend timeout passed, alarm executing
5032 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
5033 SyncOnMainLoop();
5034
5035 // Simulate state Configured
5036 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
5037
5038 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioConf(_, _, _, _, _));
5039
5040 /* Check if available context will be sent to Java */
5041 auto sink_available_context = types::kLeAudioContextAllRemoteSinkOnly;
5042 auto source_available_context = types::kLeAudioContextAllRemoteSource;
5043
5044 InjectAvailableContextTypes(test_address0, 1, sink_available_context,
5045 source_available_context);
5046
5047 SyncOnMainLoop();
5048 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5049 }
5050
TEST_F(UnicastTest,TestUpdateConfigurationCallbackWhileStreaming)5051 TEST_F(UnicastTest, TestUpdateConfigurationCallbackWhileStreaming) {
5052 const RawAddress test_address0 = GetTestAddress(0);
5053 int group_id = bluetooth::groups::kGroupUnknown;
5054
5055 SetSampleDatabaseEarbudsValid(
5056 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5057 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5058 default_channel_cnt, 0x0004,
5059 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5060 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5061 0 /*rank*/);
5062 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5063 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5064 .Times(1);
5065 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5066 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5067 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5068
5069 ConnectLeAudio(test_address0);
5070 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5071
5072 // Start streaming
5073 LeAudioClient::Get()->GroupSetActive(group_id);
5074 SyncOnMainLoop();
5075
5076 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5077 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5078 OnAudioGroupCurrentCodecConf(group_id, _, _))
5079 .Times(1);
5080 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5081
5082 SyncOnMainLoop();
5083 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5084 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5085 SyncOnMainLoop();
5086
5087 // When metadata update happen, there should be no configuration change
5088 // callback sent
5089 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5090 OnAudioGroupCurrentCodecConf(group_id, _, _))
5091 .Times(0);
5092
5093 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5094 UpdateLocalSourceMetadata(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN);
5095
5096 // Inject STREAMING Status from state machine.
5097 auto group = streaming_groups.at(group_id);
5098 do_in_main_thread(
5099 FROM_HERE,
5100 base::BindOnce(
5101 [](int group_id,
5102 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
5103 state_machine_callbacks,
5104 LeAudioDeviceGroup* group) {
5105 state_machine_callbacks->StatusReportCb(
5106 group_id, GroupStreamStatus::STREAMING);
5107 },
5108 group_id, base::Unretained(this->state_machine_callbacks_),
5109 std::move(group)));
5110
5111 SyncOnMainLoop();
5112 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5113 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5114 }
5115
TEST_F(UnicastTest,RemoveNodeWhileStreaming)5116 TEST_F(UnicastTest, RemoveNodeWhileStreaming) {
5117 const RawAddress test_address0 = GetTestAddress(0);
5118 int group_id = bluetooth::groups::kGroupUnknown;
5119
5120 SetSampleDatabaseEarbudsValid(
5121 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5122 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5123 default_channel_cnt, 0x0004,
5124 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5125 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5126 0 /*rank*/);
5127 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5128 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5129 .Times(1);
5130 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5131 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5132 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5133
5134 ConnectLeAudio(test_address0);
5135 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5136
5137 // Start streaming
5138 constexpr uint8_t cis_count_out = 1;
5139 constexpr uint8_t cis_count_in = 0;
5140
5141 constexpr int gmcs_ccid = 1;
5142 constexpr int gtbs_ccid = 2;
5143
5144 // Audio sessions are started only when device gets active
5145 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5146 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5147 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5148 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5149 LeAudioClient::Get()->GroupSetActive(group_id);
5150 SyncOnMainLoop();
5151
5152 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
5153 .source = {}};
5154 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5155
5156 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5157
5158 SyncOnMainLoop();
5159 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5160 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5161 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5162 SyncOnMainLoop();
5163
5164 // Verify Data transfer on one audio source cis
5165 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5166
5167 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id))
5168 .Times(1);
5169 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5170 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
5171 .Times(1);
5172 EXPECT_CALL(
5173 mock_audio_hal_client_callbacks_,
5174 OnGroupNodeStatus(test_address0, group_id, GroupNodeStatus::REMOVED));
5175 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5176 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5177 .Times(1);
5178
5179 LeAudioClient::Get()->GroupRemoveNode(group_id, test_address0);
5180
5181 SyncOnMainLoop();
5182 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5183 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5184 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5185 }
5186
TEST_F(UnicastTest,InactiveDeviceOnInternalStateMachineError)5187 TEST_F(UnicastTest, InactiveDeviceOnInternalStateMachineError) {
5188 const RawAddress test_address0 = GetTestAddress(0);
5189 int group_id = bluetooth::groups::kGroupUnknown;
5190
5191 SetSampleDatabaseEarbudsValid(
5192 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5193 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5194 default_channel_cnt, 0x0004,
5195 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5196 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5197 0 /*rank*/);
5198 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5199 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5200 .Times(1);
5201 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5202 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5203 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5204
5205 ConnectLeAudio(test_address0);
5206 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5207
5208 // Start streaming
5209 constexpr uint8_t cis_count_out = 1;
5210 constexpr uint8_t cis_count_in = 0;
5211
5212 constexpr int gmcs_ccid = 1;
5213 constexpr int gtbs_ccid = 2;
5214
5215 // Audio sessions are started only when device gets active
5216 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5217 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5218 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5219 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5220 LeAudioClient::Get()->GroupSetActive(group_id);
5221 SyncOnMainLoop();
5222
5223 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
5224 .source = {}};
5225 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5226
5227 btle_audio_codec_config_t empty_conf{};
5228 btle_audio_codec_config_t output_config = {
5229 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
5230 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
5231 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
5232 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_2,
5233 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
5234 .octets_per_frame = 120};
5235
5236 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5237 OnAudioGroupCurrentCodecConf(group_id, empty_conf, output_config))
5238 .Times(1);
5239
5240 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5241
5242 SyncOnMainLoop();
5243 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5244 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5245 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
5246 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5247 SyncOnMainLoop();
5248
5249 // Verify Data transfer on one audio source cis
5250 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5251
5252 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
5253 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
5254
5255 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5256 OnGroupStatus(group_id, GroupStatus::INACTIVE))
5257 .Times(1);
5258
5259 /* This is internal error of the state machine */
5260 state_machine_callbacks_->StatusReportCb(group_id,
5261 GroupStreamStatus::RELEASING);
5262
5263 SyncOnMainLoop();
5264 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5265 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5266 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
5267 }
5268
TEST_F(UnicastTest,GroupingAddTwiceNoRemove)5269 TEST_F(UnicastTest, GroupingAddTwiceNoRemove) {
5270 // Earbud connects without known grouping
5271 uint8_t group_id0 = bluetooth::groups::kGroupUnknown;
5272 const RawAddress test_address0 = GetTestAddress(0);
5273 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
5274 .WillOnce(Return())
5275 .RetiresOnSaturation();
5276 ConnectNonCsisDevice(test_address0, 1 /*conn_id*/,
5277 codec_spec_conf::kLeAudioLocationFrontLeft,
5278 codec_spec_conf::kLeAudioLocationFrontLeft);
5279
5280 group_id0 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
5281
5282 // Earbud connects without known grouping
5283 uint8_t group_id1 = bluetooth::groups::kGroupUnknown;
5284 const RawAddress test_address1 = GetTestAddress(1);
5285 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
5286 .WillOnce(Return())
5287 .RetiresOnSaturation();
5288 ConnectNonCsisDevice(test_address1, 2 /*conn_id*/,
5289 codec_spec_conf::kLeAudioLocationFrontRight,
5290 codec_spec_conf::kLeAudioLocationFrontRight);
5291
5292 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5293
5294 group_id1 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
5295 // Verify individual groups
5296 ASSERT_NE(group_id0, bluetooth::groups::kGroupUnknown);
5297 ASSERT_NE(group_id1, bluetooth::groups::kGroupUnknown);
5298 ASSERT_NE(group_id0, group_id1);
5299 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 1u);
5300 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 1u);
5301
5302 // Expectations on reassigning second earbud to the first group
5303 int dev1_storage_group = bluetooth::groups::kGroupUnknown;
5304 int dev1_new_group = bluetooth::groups::kGroupUnknown;
5305
5306 EXPECT_CALL(
5307 mock_audio_hal_client_callbacks_,
5308 OnGroupNodeStatus(test_address1, group_id1, GroupNodeStatus::REMOVED))
5309 .Times(AtLeast(1));
5310 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5311 OnGroupNodeStatus(test_address1, _, GroupNodeStatus::ADDED))
5312 .WillRepeatedly(SaveArg<1>(&dev1_new_group));
5313
5314 // FIXME: We should expect removal with group_id context. No such API exists.
5315 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id1))
5316 .Times(AtLeast(1));
5317 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, _))
5318 .Times(AnyNumber());
5319 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, group_id0))
5320 .Times(1);
5321
5322 // Regroup device: assign new group without removing it from the first one
5323 LeAudioClient::Get()->GroupAddNode(group_id0, test_address1);
5324 SyncOnMainLoop();
5325 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5326
5327 dev1_storage_group =
5328 MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
5329
5330 // Verify regrouping results
5331 EXPECT_EQ(dev1_new_group, group_id0);
5332 EXPECT_EQ(dev1_new_group, dev1_storage_group);
5333 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 0u);
5334 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 2u);
5335 std::vector<RawAddress> devs =
5336 LeAudioClient::Get()->GetGroupDevices(group_id0);
5337 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
5338 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
5339 }
5340
TEST_F(UnicastTest,RemoveTwoEarbudsCsisGrouped)5341 TEST_F(UnicastTest, RemoveTwoEarbudsCsisGrouped) {
5342 uint8_t group_size = 2;
5343 int group_id0 = 2;
5344 int group_id1 = 3;
5345
5346 // Report working CSIS
5347 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
5348 .WillByDefault(Return(true));
5349
5350 // First group - First earbud
5351 const RawAddress test_address0 = GetTestAddress(0);
5352 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
5353 .Times(1);
5354 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
5355 codec_spec_conf::kLeAudioLocationFrontLeft,
5356 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
5357 group_id0, 1 /* rank*/);
5358
5359 // First group - Second earbud
5360 const RawAddress test_address1 = GetTestAddress(1);
5361 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
5362 .Times(1);
5363 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
5364 codec_spec_conf::kLeAudioLocationFrontRight,
5365 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
5366 group_id0, 2 /* rank*/, true /*connect_through_csis*/);
5367
5368 // Second group - First earbud
5369 const RawAddress test_address2 = GetTestAddress(2);
5370 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address2, true))
5371 .Times(1);
5372 ConnectCsisDevice(test_address2, 3 /*conn_id*/,
5373 codec_spec_conf::kLeAudioLocationFrontLeft,
5374 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
5375 group_id1, 1 /* rank*/);
5376
5377 // Second group - Second earbud
5378 const RawAddress test_address3 = GetTestAddress(3);
5379 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address3, true))
5380 .Times(1);
5381 ConnectCsisDevice(test_address3, 4 /*conn_id*/,
5382 codec_spec_conf::kLeAudioLocationFrontRight,
5383 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
5384 group_id1, 2 /* rank*/, true /*connect_through_csis*/);
5385
5386 // First group - verify grouping information
5387 std::vector<RawAddress> group0_devs =
5388 LeAudioClient::Get()->GetGroupDevices(group_id0);
5389 ASSERT_NE(std::find(group0_devs.begin(), group0_devs.end(), test_address0),
5390 group0_devs.end());
5391 ASSERT_NE(std::find(group0_devs.begin(), group0_devs.end(), test_address1),
5392 group0_devs.end());
5393
5394 // Second group - verify grouping information
5395 std::vector<RawAddress> group1_devs =
5396 LeAudioClient::Get()->GetGroupDevices(group_id1);
5397 ASSERT_NE(std::find(group1_devs.begin(), group1_devs.end(), test_address2),
5398 group1_devs.end());
5399 ASSERT_NE(std::find(group1_devs.begin(), group1_devs.end(), test_address3),
5400 group1_devs.end());
5401 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5402
5403 // Expect one of the groups to be dropped and devices to be disconnected
5404 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id0))
5405 .Times(1);
5406 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id0))
5407 .Times(1);
5408 EXPECT_CALL(
5409 mock_audio_hal_client_callbacks_,
5410 OnGroupNodeStatus(test_address0, group_id0, GroupNodeStatus::REMOVED));
5411 EXPECT_CALL(
5412 mock_audio_hal_client_callbacks_,
5413 OnGroupNodeStatus(test_address1, group_id0, GroupNodeStatus::REMOVED));
5414 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5415 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5416 .Times(1);
5417 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5418 OnConnectionState(ConnectionState::DISCONNECTED, test_address1))
5419 .Times(1);
5420
5421 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
5422 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(2, _)).Times(1);
5423
5424 // Expect the other groups to be left as is
5425 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id1, _))
5426 .Times(0);
5427 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5428 OnConnectionState(ConnectionState::DISCONNECTED, test_address2))
5429 .Times(0);
5430 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5431 OnConnectionState(ConnectionState::DISCONNECTED, test_address3))
5432 .Times(0);
5433
5434 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(3, _)).Times(0);
5435 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(4, _)).Times(0);
5436
5437 do_in_main_thread(
5438 FROM_HERE,
5439 base::BindOnce(&LeAudioClient::GroupDestroy,
5440 base::Unretained(LeAudioClient::Get()), group_id0));
5441
5442 SyncOnMainLoop();
5443 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5444 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
5445 }
5446
TEST_F(UnicastTest,ConnectAfterRemove)5447 TEST_F(UnicastTest, ConnectAfterRemove) {
5448 const RawAddress test_address0 = GetTestAddress(0);
5449 int group_id = bluetooth::groups::kGroupUnknown;
5450 uint16_t conn_id = 1;
5451
5452 SetSampleDatabaseEarbudsValid(
5453 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5454 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5455 default_channel_cnt, 0x0004,
5456 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5457 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5458 0 /*rank*/);
5459 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5460 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5461 .Times(1);
5462
5463 /* RemoveDevice */
5464 do_in_main_thread(FROM_HERE, base::BindOnce(
5465 [](LeAudioClient* client,
5466 const RawAddress& test_address0) {
5467 client->RemoveDevice(test_address0);
5468 },
5469 LeAudioClient::Get(), test_address0));
5470 SyncOnMainLoop();
5471
5472 ON_CALL(mock_btm_interface_, IsLinkKeyKnown(_, _))
5473 .WillByDefault(DoAll(Return(false)));
5474
5475 do_in_main_thread(
5476 FROM_HERE,
5477 base::BindOnce(&LeAudioClient::Connect,
5478 base::Unretained(LeAudioClient::Get()), test_address0));
5479 SyncOnMainLoop();
5480
5481 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5482 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5483 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5484 }
5485
TEST_F(UnicastTest,RemoveDeviceWhenConnected)5486 TEST_F(UnicastTest, RemoveDeviceWhenConnected) {
5487 const RawAddress test_address0 = GetTestAddress(0);
5488 int group_id = bluetooth::groups::kGroupUnknown;
5489 uint16_t conn_id = 1;
5490
5491 SetSampleDatabaseEarbudsValid(
5492 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5493 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5494 default_channel_cnt, 0x0004,
5495 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5496 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5497 0 /*rank*/);
5498 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5499 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5500 .Times(1);
5501 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5502 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5503 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5504 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
5505 .Times(1);
5506 ConnectLeAudio(test_address0);
5507 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5508
5509 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5510 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5511
5512 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
5513 .Times(1);
5514 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5515 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
5516
5517 /*
5518 * StopStream will put calls on main_loop so to keep the correct order
5519 * of operations and to avoid races we put the test command on main_loop as
5520 * well.
5521 */
5522 do_in_main_thread(FROM_HERE, base::BindOnce(
5523 [](LeAudioClient* client,
5524 const RawAddress& test_address0) {
5525 client->RemoveDevice(test_address0);
5526 },
5527 LeAudioClient::Get(), test_address0));
5528 SyncOnMainLoop();
5529
5530 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5531 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5532 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5533 }
5534
TEST_F(UnicastTest,RemoveDeviceWhenConnecting)5535 TEST_F(UnicastTest, RemoveDeviceWhenConnecting) {
5536 const RawAddress test_address0 = GetTestAddress(0);
5537 uint16_t conn_id = 1;
5538
5539 /* Prepare mock to not inject connect event so the device can stay in
5540 * CONNECTING state*/
5541 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
5542 .WillByDefault(DoAll(Return()));
5543
5544 SetSampleDatabaseEarbudsValid(
5545 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5546 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5547 default_channel_cnt, 0x0004,
5548 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5549 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5550 0 /*rank*/);
5551 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5552 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5553 .Times(0);
5554 ConnectLeAudio(test_address0, true, false);
5555
5556 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5557
5558 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true))
5559 .Times(1);
5560 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
5561 .Times(1);
5562 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _))
5563 .Times(0);
5564
5565 /*
5566 * StopStream will put calls on main_loop so to keep the correct order
5567 * of operations and to avoid races we put the test command on main_loop as
5568 * well.
5569 */
5570 do_in_main_thread(FROM_HERE, base::BindOnce(
5571 [](LeAudioClient* client,
5572 const RawAddress& test_address0) {
5573 client->RemoveDevice(test_address0);
5574 },
5575 LeAudioClient::Get(), test_address0));
5576
5577 SyncOnMainLoop();
5578
5579 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5580 }
5581
TEST_F(UnicastTest,RemoveDeviceWhenGettingConnectionReady)5582 TEST_F(UnicastTest, RemoveDeviceWhenGettingConnectionReady) {
5583 const RawAddress test_address0 = GetTestAddress(0);
5584 uint16_t conn_id = 1;
5585
5586 /* Prepare mock to not inject Service Search Complete*/
5587 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
5588 .WillByDefault(DoAll(Return()));
5589
5590 SetSampleDatabaseEarbudsValid(
5591 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5592 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5593 default_channel_cnt, 0x0004,
5594 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5595 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5596 0 /*rank*/);
5597 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5598 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5599 .Times(0);
5600 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
5601 .Times(0);
5602 ConnectLeAudio(test_address0);
5603
5604 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5605 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5606
5607 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5608 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
5609
5610 /* Cancel should be called in RemoveDevice */
5611 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
5612 .Times(1);
5613 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _))
5614 .Times(0);
5615
5616 /*
5617 * StopStream will put calls on main_loop so to keep the correct order
5618 * of operations and to avoid races we put the test command on main_loop as
5619 * well.
5620 */
5621 do_in_main_thread(FROM_HERE, base::BindOnce(
5622 [](LeAudioClient* client,
5623 const RawAddress& test_address0) {
5624 client->RemoveDevice(test_address0);
5625 },
5626 LeAudioClient::Get(), test_address0));
5627
5628 SyncOnMainLoop();
5629
5630 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5631 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5632 }
5633
TEST_F(UnicastTest,DisconnectDeviceWhenConnected)5634 TEST_F(UnicastTest, DisconnectDeviceWhenConnected) {
5635 const RawAddress test_address0 = GetTestAddress(0);
5636 int group_id = bluetooth::groups::kGroupUnknown;
5637 uint16_t conn_id = 1;
5638
5639 SetSampleDatabaseEarbudsValid(
5640 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5641 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5642 default_channel_cnt, 0x0004,
5643 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5644 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5645 0 /*rank*/);
5646 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5647 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5648 .Times(1);
5649 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5650 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5651 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5652 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
5653 .Times(1);
5654 ConnectLeAudio(test_address0);
5655 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5656
5657 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5658 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5659
5660 /* for Target announcements AutoConnect is always there, until
5661 * device is removed
5662 */
5663 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
5664 .Times(0);
5665 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5666 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
5667
5668 LeAudioClient::Get()->Disconnect(test_address0);
5669 SyncOnMainLoop();
5670
5671 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5672 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5673 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5674 }
5675
TEST_F(UnicastTest,DisconnectDeviceWhenConnecting)5676 TEST_F(UnicastTest, DisconnectDeviceWhenConnecting) {
5677 const RawAddress test_address0 = GetTestAddress(0);
5678 uint16_t conn_id = 1;
5679
5680 /* Prepare mock to not inject connect event so the device can stay in
5681 * CONNECTING state*/
5682 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
5683 .WillByDefault(DoAll(Return()));
5684
5685 SetSampleDatabaseEarbudsValid(
5686 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5687 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5688 default_channel_cnt, 0x0004,
5689 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5690 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5691 0 /*rank*/);
5692 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5693 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5694 .Times(0);
5695 ConnectLeAudio(test_address0, true, false);
5696
5697 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5698
5699 /* Prepare on call mock on Close - to not trigger Inject Disconnection, as it
5700 * is done in default mock.
5701 */
5702 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
5703 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true))
5704 .Times(1);
5705 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _))
5706 .Times(0);
5707
5708 LeAudioClient::Get()->Disconnect(test_address0);
5709 SyncOnMainLoop();
5710
5711 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5712 }
5713
TEST_F(UnicastTest,DisconnectDeviceWhenGettingConnectionReady)5714 TEST_F(UnicastTest, DisconnectDeviceWhenGettingConnectionReady) {
5715 const RawAddress test_address0 = GetTestAddress(0);
5716 uint16_t conn_id = global_conn_id;
5717
5718 /* Prepare mock to not inject Service Search Complete*/
5719 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
5720 .WillByDefault(DoAll(Return()));
5721
5722 SetSampleDatabaseEarbudsValid(
5723 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5724 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5725 default_channel_cnt, 0x0004,
5726 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5727 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5728 0 /*rank*/);
5729 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5730 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5731 .Times(0);
5732 ConnectLeAudio(test_address0);
5733
5734 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5735 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5736
5737 /* TA reconnect is enabled in ConnectLeAudio. Make sure this is not removed */
5738 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5739 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
5740 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _))
5741 .Times(0);
5742 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _))
5743 .Times(0);
5744
5745 LeAudioClient::Get()->Disconnect(test_address0);
5746 SyncOnMainLoop();
5747
5748 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5749 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5750 }
5751
TEST_F(UnicastTest,RemoveWhileStreaming)5752 TEST_F(UnicastTest, RemoveWhileStreaming) {
5753 const RawAddress test_address0 = GetTestAddress(0);
5754 int group_id = bluetooth::groups::kGroupUnknown;
5755
5756 SetSampleDatabaseEarbudsValid(
5757 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5758 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5759 default_channel_cnt, 0x0004,
5760 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5761 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5762 0 /*rank*/);
5763 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5764 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5765 .Times(1);
5766 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5767 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5768 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5769
5770 ConnectLeAudio(test_address0);
5771 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5772
5773 // Start streaming
5774 constexpr uint8_t cis_count_out = 1;
5775 constexpr uint8_t cis_count_in = 0;
5776
5777 constexpr int gmcs_ccid = 1;
5778 constexpr int gtbs_ccid = 2;
5779
5780 // Audio sessions are started only when device gets active
5781 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5782 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5783 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5784 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5785 LeAudioClient::Get()->GroupSetActive(group_id);
5786 SyncOnMainLoop();
5787
5788 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
5789 .source = {}};
5790 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5791
5792 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5793
5794 SyncOnMainLoop();
5795 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5796 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5797 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5798 SyncOnMainLoop();
5799
5800 // Verify Data transfer on one audio source cis
5801 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5802
5803 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id))
5804 .Times(1);
5805
5806 LeAudioDeviceGroup* group = nullptr;
5807 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
5808 .WillOnce(DoAll(SaveArg<0>(&group)));
5809 EXPECT_CALL(
5810 mock_audio_hal_client_callbacks_,
5811 OnGroupNodeStatus(test_address0, group_id, GroupNodeStatus::REMOVED));
5812
5813 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5814 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5815 .Times(1);
5816
5817 /*
5818 * StopStream will put calls on main_loop so to keep the correct order
5819 * of operations and to avoid races we put the test command on main_loop as
5820 * well.
5821 */
5822 do_in_main_thread(FROM_HERE, base::BindOnce(
5823 [](LeAudioClient* client,
5824 const RawAddress& test_address0) {
5825 client->RemoveDevice(test_address0);
5826 },
5827 LeAudioClient::Get(), test_address0));
5828
5829 SyncOnMainLoop();
5830 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5831 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5832 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5833
5834 ASSERT_EQ(group, nullptr);
5835 }
5836
TEST_F(UnicastTest,DisconnecteWhileAlmostStreaming)5837 TEST_F(UnicastTest, DisconnecteWhileAlmostStreaming) {
5838 const RawAddress test_address0 = GetTestAddress(0);
5839 int group_id = bluetooth::groups::kGroupUnknown;
5840
5841 SetSampleDatabaseEarbudsValid(
5842 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5843 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
5844 default_channel_cnt, 0x0004,
5845 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
5846 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
5847 0 /*rank*/);
5848 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5849 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5850 .Times(1);
5851 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5852 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5853 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5854
5855 ConnectLeAudio(test_address0);
5856 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5857
5858 constexpr int gmcs_ccid = 1;
5859 constexpr int gtbs_ccid = 2;
5860
5861 // Audio sessions are started only when device gets active
5862 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5863 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5864 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5865 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5866 LeAudioClient::Get()->GroupSetActive(group_id);
5867 SyncOnMainLoop();
5868
5869 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
5870 .source = {}};
5871 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5872
5873 /* We want here to CIS be established but device not being yet in streaming
5874 * state
5875 */
5876 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5877
5878 SyncOnMainLoop();
5879 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5880 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5881 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5882 SyncOnMainLoop();
5883
5884 /* This is test code, which will change the group state to the one which
5885 * is required by test
5886 */
5887 ASSERT_NE(0lu, streaming_groups.count(group_id));
5888 auto group_inject = streaming_groups.at(group_id);
5889 group_inject->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING);
5890
5891 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5892
5893 LeAudioDeviceGroup* group = nullptr;
5894 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
5895 .WillOnce(DoAll(SaveArg<0>(&group)));
5896
5897 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5898 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5899 .Times(1);
5900
5901 /*
5902 * StopStream will put calls on main_loop so to keep the correct order
5903 * of operations and to avoid races we put the test command on main_loop as
5904 * well.
5905 */
5906 do_in_main_thread(FROM_HERE, base::BindOnce(
5907 [](LeAudioClient* client,
5908 const RawAddress& test_address0) {
5909 client->Disconnect(test_address0);
5910 },
5911 LeAudioClient::Get(), test_address0));
5912
5913 SyncOnMainLoop();
5914 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5915 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5916 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5917
5918 ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5919 }
5920
TEST_F(UnicastTest,EarbudsTwsStyleStreaming)5921 TEST_F(UnicastTest, EarbudsTwsStyleStreaming) {
5922 const RawAddress test_address0 = GetTestAddress(0);
5923 int group_id = bluetooth::groups::kGroupUnknown;
5924
5925 SetSampleDatabaseEarbudsValid(
5926 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5927 codec_spec_conf::kLeAudioLocationStereo, 0x01, 0x01,
5928 codec_spec_caps::kLeAudioSamplingFreq16000Hz, false /*add_csis*/,
5929 true /*add_cas*/, true /*add_pacs*/, 2 /*add_asc_cnt*/, 1 /*set_size*/,
5930 0 /*rank*/);
5931 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5932 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5933 .Times(1);
5934 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5935 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5936 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5937
5938 ConnectLeAudio(test_address0);
5939 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5940
5941 // Start streaming
5942 uint8_t cis_count_out = 2;
5943 uint8_t cis_count_in = 0;
5944
5945 // Audio sessions are started only when device gets active
5946 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5947 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5948 LeAudioClient::Get()->GroupSetActive(group_id);
5949 SyncOnMainLoop();
5950
5951 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5952
5953 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5954 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5955 SyncOnMainLoop();
5956
5957 // Verify Data transfer on one audio source cis
5958 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5959
5960 // Suspend
5961 /*TODO Need a way to verify STOP */
5962 LeAudioClient::Get()->GroupSuspend(group_id);
5963 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5964 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5965
5966 // Resume
5967 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5968 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5969 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5970
5971 // Stop
5972 StopStreaming(group_id);
5973 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5974
5975 // Release
5976 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
5977 EXPECT_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(
5978 mock_le_audio_source_hal_client_,
5979 mock_le_audio_sink_hal_client_, false))
5980 .Times(1);
5981
5982 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
5983 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
5984 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
5985 SyncOnMainLoop();
5986 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5987 Mock::VerifyAndClearExpectations(mock_codec_manager_);
5988 }
5989
TEST_F(UnicastTest,SpeakerFailedConversationalStreaming)5990 TEST_F(UnicastTest, SpeakerFailedConversationalStreaming) {
5991 const RawAddress test_address0 = GetTestAddress(0);
5992 int group_id = bluetooth::groups::kGroupUnknown;
5993
5994 available_src_context_types_ = 0;
5995 supported_src_context_types_ =
5996 available_src_context_types_ |
5997 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
5998 available_snk_context_types_ = 0x0004;
5999 supported_snk_context_types_ =
6000 available_snk_context_types_ |
6001 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
6002
6003 SetSampleDatabaseEarbudsValid(
6004 1, test_address0, codec_spec_conf::kLeAudioLocationStereo, 0,
6005 default_channel_cnt, default_channel_cnt, 0x0004,
6006 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
6007 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
6008 0 /*rank*/);
6009 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6010 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6011 .Times(1);
6012 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6013 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6014 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6015
6016 ConnectLeAudio(test_address0);
6017 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6018
6019 // Audio sessions are started only when device gets active
6020 LeAudioClient::Get()->GroupSetActive(group_id);
6021 SyncOnMainLoop();
6022
6023 /* Nothing to do - expect no crash */
6024 }
6025
TEST_F(UnicastTest,SpeakerStreaming)6026 TEST_F(UnicastTest, SpeakerStreaming) {
6027 const RawAddress test_address0 = GetTestAddress(0);
6028 int group_id = bluetooth::groups::kGroupUnknown;
6029
6030 SetSampleDatabaseEarbudsValid(
6031 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6032 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
6033 default_channel_cnt, 0x0004,
6034 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
6035 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
6036 0 /*rank*/);
6037 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6038 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6039 .Times(1);
6040 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6041 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6042 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6043
6044 ConnectLeAudio(test_address0);
6045 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6046
6047 // Start streaming
6048 uint8_t cis_count_out = 1;
6049 uint8_t cis_count_in = 0;
6050
6051 // Audio sessions are started only when device gets active
6052 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6053 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6054 LeAudioClient::Get()->GroupSetActive(group_id);
6055 SyncOnMainLoop();
6056
6057 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6058
6059 SyncOnMainLoop();
6060 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6061 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6062
6063 // Verify Data transfer on one audio source cis
6064 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6065
6066 // Suspend
6067 /*TODO Need a way to verify STOP */
6068 LeAudioClient::Get()->GroupSuspend(group_id);
6069 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6070 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6071
6072 // Resume
6073 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6074 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6075 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6076
6077 // Stop
6078 StopStreaming(group_id);
6079 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6080
6081 // Release
6082 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6083
6084 EXPECT_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(
6085 mock_le_audio_source_hal_client_,
6086 mock_le_audio_sink_hal_client_, false))
6087 .Times(1);
6088
6089 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6090 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6091 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6092 SyncOnMainLoop();
6093 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6094 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6095 }
6096
TEST_F(UnicastTest,SpeakerStreamingNonDefault)6097 TEST_F(UnicastTest, SpeakerStreamingNonDefault) {
6098 const RawAddress test_address0 = GetTestAddress(0);
6099 int group_id = bluetooth::groups::kGroupUnknown;
6100
6101 /**
6102 * Scenario test steps
6103 * 1. Set group active and stream VOICEASSISTANT
6104 * 2. Suspend group and resume with VOICEASSISTANT
6105 * 3. Stop Stream and make group inactive
6106 * 4. Start stream without setting metadata.
6107 * 5. Verify that UNSPECIFIED context type is used.
6108 */
6109
6110 available_snk_context_types_ = (types::LeAudioContextType::VOICEASSISTANTS |
6111 types::LeAudioContextType::MEDIA |
6112 types::LeAudioContextType::UNSPECIFIED)
6113 .value();
6114 supported_snk_context_types_ = available_snk_context_types_;
6115
6116 SetSampleDatabaseEarbudsValid(
6117 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6118 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
6119 default_channel_cnt, 0x0004,
6120 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
6121 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
6122 0 /*rank*/);
6123 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6124 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6125 .Times(1);
6126 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6127 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6128 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6129
6130 ConnectLeAudio(test_address0);
6131 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6132
6133 // Start streaming
6134 uint8_t cis_count_out = 1;
6135 uint8_t cis_count_in = 0;
6136
6137 // Audio sessions are started only when device gets active
6138 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6139 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6140 LeAudioClient::Get()->GroupSetActive(group_id);
6141 SyncOnMainLoop();
6142
6143 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6144
6145 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6146 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6147 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6148 SyncOnMainLoop();
6149
6150 // Verify Data transfer on one audio source cis
6151 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6152
6153 // Suspend
6154 /*TODO Need a way to verify STOP */
6155 LeAudioClient::Get()->GroupSuspend(group_id);
6156 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6157 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6158
6159 // Resume
6160 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6161 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6162 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6163
6164 // Stop
6165 StopStreaming(group_id);
6166 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6167
6168 // Release
6169 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6170 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6171 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6172 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6173 SyncOnMainLoop();
6174 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6175
6176 /* When session is closed, the hal client mocks are freed - get new ones */
6177 SetUpMockAudioHal();
6178 /* Expect the previous release to clear the old audio session metadata */
6179 LeAudioClient::Get()->GroupSetActive(group_id);
6180 SyncOnMainLoop();
6181 EXPECT_CALL(mock_state_machine_,
6182 StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, _, _))
6183 .Times(0);
6184 EXPECT_CALL(mock_state_machine_,
6185 StartStream(_, kLeAudioDefaultConfigurationContext, _, _))
6186 .Times(1);
6187 LocalAudioSourceResume();
6188 }
6189
TEST_F_WITH_FLAGS(UnicastTest,TestUnidirectionalVoiceAssistant_Sink,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,le_audio_support_unidirectional_voice_assistant)))6190 TEST_F_WITH_FLAGS(UnicastTest, TestUnidirectionalVoiceAssistant_Sink,
6191 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
6192 TEST_BT,
6193 le_audio_support_unidirectional_voice_assistant))) {
6194 const RawAddress test_address0 = GetTestAddress(0);
6195 int group_id = bluetooth::groups::kGroupUnknown;
6196
6197 /**
6198 * Scenario test steps
6199 * 1. Configure group to support VOICEASSISTANT only on SINK
6200 * 2. Start stream
6201 * 5. Verify that Unidirectional VOICEASSISTANT has been created
6202 */
6203
6204 available_snk_context_types_ = (types::LeAudioContextType::VOICEASSISTANTS |
6205 types::LeAudioContextType::MEDIA |
6206 types::LeAudioContextType::UNSPECIFIED)
6207 .value();
6208 supported_snk_context_types_ = available_snk_context_types_;
6209
6210 available_src_context_types_ =
6211 (types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED)
6212 .value();
6213 supported_src_context_types_ = available_src_context_types_;
6214
6215 SetSampleDatabaseEarbudsValid(
6216 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6217 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
6218 default_channel_cnt, 0x0004,
6219 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
6220 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
6221 0 /*rank*/);
6222 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6223 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6224 .Times(1);
6225 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6226 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6227 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6228
6229 types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
6230 .sink = types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS),
6231 .source = types::AudioContexts()};
6232 EXPECT_CALL(mock_state_machine_,
6233 StartStream(_, types::LeAudioContextType::INSTRUCTIONAL,
6234 metadata_contexts, _))
6235 .Times(1);
6236 ConnectLeAudio(test_address0);
6237 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6238
6239 // Start streaming
6240 uint8_t cis_count_out = 1;
6241 uint8_t cis_count_in = 0;
6242
6243 // Audio sessions are started only when device gets active
6244 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6245 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6246
6247 EXPECT_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(
6248 mock_le_audio_source_hal_client_,
6249 mock_le_audio_sink_hal_client_, true))
6250 .Times(1);
6251
6252 LeAudioClient::Get()->GroupSetActive(group_id);
6253 SyncOnMainLoop();
6254
6255 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6256
6257 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6258 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6259 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6260 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6261 SyncOnMainLoop();
6262
6263 // Verify Data transfer on one local audio source cis
6264 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6265 SyncOnMainLoop();
6266 }
6267
TEST_F_WITH_FLAGS(UnicastTest,TestUnidirectionalVoiceAssistant_Source,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,le_audio_support_unidirectional_voice_assistant)))6268 TEST_F_WITH_FLAGS(UnicastTest, TestUnidirectionalVoiceAssistant_Source,
6269 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
6270 TEST_BT,
6271 le_audio_support_unidirectional_voice_assistant))) {
6272 const RawAddress test_address0 = GetTestAddress(0);
6273 int group_id = bluetooth::groups::kGroupUnknown;
6274
6275 /**
6276 * Scenario test steps
6277 * 1. Configure group to support VOICEASSISTANT only on SOURCE
6278 * 2. Start stream
6279 * 5. Verify that bi-direction VOICEASSISTANT has been created
6280 */
6281
6282 available_snk_context_types_ = (types::LeAudioContextType::MEDIA |
6283 types::LeAudioContextType::UNSPECIFIED)
6284 .value();
6285 supported_snk_context_types_ = available_snk_context_types_;
6286
6287 available_src_context_types_ =
6288 (types::LeAudioContextType::VOICEASSISTANTS |
6289 types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED)
6290 .value();
6291 supported_src_context_types_ = available_src_context_types_;
6292
6293 SetSampleDatabaseEarbudsValid(
6294 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeftOfCenter,
6295 codec_spec_conf::kLeAudioLocationFrontLeftOfCenter, default_channel_cnt,
6296 default_channel_cnt, 0x0004,
6297 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
6298 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 2 /*set_size*/,
6299 1 /*rank*/);
6300 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6301 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6302 .Times(1);
6303 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6304 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6305 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6306
6307 types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
6308 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
6309 .source =
6310 types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS)};
6311 EXPECT_CALL(mock_state_machine_,
6312 StartStream(_, types::LeAudioContextType::VOICEASSISTANTS,
6313 metadata_contexts, _))
6314 .Times(1);
6315 ConnectLeAudio(test_address0);
6316 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6317
6318 // Start streaming
6319 uint8_t cis_count_out = 1;
6320 uint8_t cis_count_in = 1;
6321
6322 // Audio sessions are started only when device gets active
6323 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6324 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6325 LeAudioClient::Get()->GroupSetActive(group_id);
6326 SyncOnMainLoop();
6327
6328 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id,
6329 AUDIO_SOURCE_VOICE_RECOGNITION);
6330
6331 // Verify Data transfer on one local audio source cis
6332 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6333
6334 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6335 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6336 SyncOnMainLoop();
6337 }
6338
TEST_F(UnicastTest,SpeakerStreamingAutonomousRelease)6339 TEST_F(UnicastTest, SpeakerStreamingAutonomousRelease) {
6340 const RawAddress test_address0 = GetTestAddress(0);
6341 int group_id = bluetooth::groups::kGroupUnknown;
6342
6343 SetSampleDatabaseEarbudsValid(
6344 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6345 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
6346 default_channel_cnt, 0x0004,
6347 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
6348 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
6349 0 /*rank*/);
6350 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6351 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6352 .Times(1);
6353 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6354 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6355 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6356
6357 ConnectLeAudio(test_address0);
6358 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6359
6360 // Start streaming
6361 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6362 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6363 LeAudioClient::Get()->GroupSetActive(group_id);
6364 SyncOnMainLoop();
6365
6366 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6367
6368 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6369 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6370 SyncOnMainLoop();
6371
6372 // Verify Data transfer on one audio source cis
6373 TestAudioDataTransfer(group_id, 1 /* cis_count_out */, 0 /* cis_count_in */,
6374 1920);
6375
6376 // Inject the IDLE state as if an autonomous release happened
6377 ASSERT_NE(0lu, streaming_groups.count(group_id));
6378 auto group = streaming_groups.at(group_id);
6379 ASSERT_NE(group, nullptr);
6380 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
6381 device = group->GetNextDevice(device)) {
6382 for (auto& ase : device->ases_) {
6383 ase.cis_state = types::CisState::IDLE;
6384 ase.data_path_state = types::DataPathState::IDLE;
6385 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
6386 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
6387 }
6388 }
6389
6390 // Verify no Data transfer after the autonomous release
6391 TestAudioDataTransfer(group_id, 0 /* cis_count_out */, 0 /* cis_count_in */,
6392 1920);
6393 }
6394
TEST_F(UnicastTest,TwoEarbudsStreaming)6395 TEST_F(UnicastTest, TwoEarbudsStreaming) {
6396 uint8_t group_size = 2;
6397 int group_id = 2;
6398
6399 // Report working CSIS
6400 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
6401 .WillByDefault(Return(true));
6402 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6403 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
6404
6405 // First earbud
6406 const RawAddress test_address0 = GetTestAddress(0);
6407 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
6408 .Times(1);
6409 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
6410 codec_spec_conf::kLeAudioLocationFrontLeft,
6411 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
6412 group_id, 1 /* rank*/);
6413
6414 // Second earbud
6415 const RawAddress test_address1 = GetTestAddress(1);
6416 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
6417 .Times(1);
6418 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
6419 codec_spec_conf::kLeAudioLocationFrontRight,
6420 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
6421 group_id, 2 /* rank*/, true /*connect_through_csis*/);
6422
6423 // Start streaming
6424 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6425 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6426 LeAudioClient::Get()->GroupSetActive(group_id);
6427 SyncOnMainLoop();
6428
6429 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6430
6431 /* Make sure configurations are non empty */
6432 btle_audio_codec_config_t call_config = {
6433 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6434 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
6435 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
6436 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
6437 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
6438 .octets_per_frame = 40};
6439
6440 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6441 OnAudioGroupCurrentCodecConf(group_id, call_config, call_config))
6442 .Times(1);
6443
6444 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
6445 group_id);
6446
6447 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6448 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6449 SyncOnMainLoop();
6450
6451 // Verify Data transfer on two peer sinks and one source
6452 uint8_t cis_count_out = 2;
6453 uint8_t cis_count_in = 2;
6454 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
6455
6456 // Suspend
6457 LeAudioClient::Get()->GroupSuspend(group_id);
6458 SyncOnMainLoop();
6459
6460 // Resume
6461 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
6462 group_id);
6463 SyncOnMainLoop();
6464 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6465
6466 // Verify Data transfer still works
6467 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
6468
6469 ASSERT_NE(0lu, streaming_groups.count(group_id));
6470 auto group = streaming_groups.at(group_id);
6471
6472 // Stop
6473 StopStreaming(group_id, true);
6474 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6475
6476 // Check if cache configuration is still present
6477 ASSERT_TRUE(
6478 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
6479 ->confs.get(le_audio::types::kLeAudioDirectionSink)
6480 .size());
6481 ASSERT_TRUE(
6482 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
6483 ->confs.get(le_audio::types::kLeAudioDirectionSource)
6484 .size());
6485
6486 // Release
6487 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6488 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6489 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
6490 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6491 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6492 SyncOnMainLoop();
6493
6494 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6495
6496 // Setting group inactive, shall not change cached configuration
6497 ASSERT_TRUE(
6498 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
6499 ->confs.get(le_audio::types::kLeAudioDirectionSink)
6500 .size());
6501 ASSERT_TRUE(
6502 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
6503 ->confs.get(le_audio::types::kLeAudioDirectionSource)
6504 .size());
6505 }
6506
TEST_F(UnicastTest,StreamingVxAospSampleSound)6507 TEST_F(UnicastTest, StreamingVxAospSampleSound) {
6508 uint8_t group_size = 2;
6509 int group_id = 2;
6510
6511 /* Test to verify that tag VX_AOSP_SAMPLESOUND is always mapped to
6512 * LeAudioContextType::SOUNDEFFECTS
6513 */
6514
6515 // Report working CSIS
6516 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
6517 .WillByDefault(Return(true));
6518
6519 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6520 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
6521
6522 // First earbud
6523 const RawAddress test_address0 = GetTestAddress(0);
6524 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
6525 .Times(1);
6526 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
6527 codec_spec_conf::kLeAudioLocationFrontLeft,
6528 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
6529 group_id, 1 /* rank*/);
6530
6531 // Second earbud
6532 const RawAddress test_address1 = GetTestAddress(1);
6533 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
6534 .Times(1);
6535 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
6536 codec_spec_conf::kLeAudioLocationFrontRight,
6537 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
6538 group_id, 2 /* rank*/, true /*connect_through_csis*/);
6539
6540 // Start streaming
6541 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6542 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6543 LeAudioClient::Get()->GroupSetActive(group_id);
6544 SyncOnMainLoop();
6545
6546 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6547
6548 // Set a test TAG
6549 char test_tag[] = "TEST_TAG2;VX_AOSP_SAMPLESOUND;TEST_TAG1";
6550
6551 test_tags_ptr_ = test_tag;
6552
6553 auto initial_context = types::LeAudioContextType::SOUNDEFFECTS;
6554 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {},
6555 .source = {}};
6556 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, _, ccids))
6557 .Times(1);
6558 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
6559 group_id);
6560
6561 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6562 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6563 SyncOnMainLoop();
6564
6565 // Verify Data transfer on two peer sinks and one source
6566 uint8_t cis_count_out = 2;
6567 uint8_t cis_count_in = 0;
6568 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 0);
6569 }
6570
TEST_F(UnicastTest,UpdateActiveAudioConfigForLocalSinkSource)6571 TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSinkSource) {
6572 uint8_t group_size = 2;
6573 int group_id = 2;
6574
6575 // Report working CSIS
6576 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
6577 .WillByDefault(Return(true));
6578
6579 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6580 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
6581
6582 // First earbud
6583 const RawAddress test_address0 = GetTestAddress(0);
6584 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
6585 .Times(1);
6586 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
6587 codec_spec_conf::kLeAudioLocationFrontLeft,
6588 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
6589 group_id, 1 /* rank*/);
6590
6591 // Second earbud
6592 const RawAddress test_address1 = GetTestAddress(1);
6593 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
6594 .Times(1);
6595 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
6596 codec_spec_conf::kLeAudioLocationFrontRight,
6597 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
6598 group_id, 2 /* rank*/, true /*connect_through_csis*/);
6599
6600 // Set group as active
6601 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6602 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6603 LeAudioClient::Get()->GroupSetActive(group_id);
6604 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6605
6606 // Start streaming
6607 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_))
6608 .Times(1);
6609 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_))
6610 .Times(1);
6611 EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
6612 .Times(1)
6613 .WillOnce(
6614 [](const types::BidirectionalPair<stream_parameters>& stream_params,
6615 types::BidirectionalPair<uint16_t> delays_ms,
6616 std::function<void(const offload_config& config,
6617 uint8_t direction)>
6618 update_receiver) {
6619 bluetooth::le_audio::offload_config unicast_cfg;
6620 if (delays_ms.sink != 0) {
6621 update_receiver(
6622 unicast_cfg,
6623 bluetooth::le_audio::types::kLeAudioDirectionSink);
6624 }
6625 if (delays_ms.source != 0) {
6626 update_receiver(
6627 unicast_cfg,
6628 bluetooth::le_audio::types::kLeAudioDirectionSource);
6629 }
6630 });
6631 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
6632 group_id);
6633
6634 SyncOnMainLoop();
6635 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6636 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6637 Mock::VerifyAndClearExpectations(&mock_codec_manager_);
6638
6639 // Verify Data transfer on two peer sinks and two sources
6640 uint8_t cis_count_out = 2;
6641 uint8_t cis_count_in = 2;
6642 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
6643
6644 // Suspend
6645 LeAudioClient::Get()->GroupSuspend(group_id);
6646 SyncOnMainLoop();
6647 }
6648
TEST_F(UnicastTest,UpdateActiveAudioConfigForLocalSource)6649 TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSource) {
6650 uint8_t group_size = 2;
6651 int group_id = 2;
6652
6653 // Report working CSIS
6654 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
6655 .WillByDefault(Return(true));
6656
6657 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6658 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
6659
6660 // First earbud
6661 const RawAddress test_address0 = GetTestAddress(0);
6662 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
6663 .Times(1);
6664 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
6665 codec_spec_conf::kLeAudioLocationFrontLeft,
6666 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
6667 group_id, 1 /* rank*/);
6668
6669 // Second earbud
6670 const RawAddress test_address1 = GetTestAddress(1);
6671 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
6672 .Times(1);
6673 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
6674 codec_spec_conf::kLeAudioLocationFrontRight,
6675 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
6676 group_id, 2 /* rank*/, true /*connect_through_csis*/);
6677
6678 // Set group as active
6679 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6680 LeAudioClient::Get()->GroupSetActive(group_id);
6681 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6682
6683 // Start streaming
6684 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_))
6685 .Times(1);
6686 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_))
6687 .Times(0);
6688 EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
6689 .Times(1)
6690 .WillOnce(
6691 [](const types::BidirectionalPair<stream_parameters>& stream_params,
6692 types::BidirectionalPair<uint16_t> delays_ms,
6693 std::function<void(const offload_config& config,
6694 uint8_t direction)>
6695 update_receiver) {
6696 bluetooth::le_audio::offload_config unicast_cfg;
6697 if (delays_ms.sink != 0) {
6698 update_receiver(
6699 unicast_cfg,
6700 bluetooth::le_audio::types::kLeAudioDirectionSink);
6701 }
6702 if (delays_ms.source != 0) {
6703 update_receiver(
6704 unicast_cfg,
6705 bluetooth::le_audio::types::kLeAudioDirectionSource);
6706 }
6707 });
6708 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6709
6710 SyncOnMainLoop();
6711 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6712 Mock::VerifyAndClearExpectations(&mock_codec_manager_);
6713
6714 // Verify Data transfer on two peer sinks and no source
6715 uint8_t cis_count_out = 2;
6716 uint8_t cis_count_in = 0;
6717 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
6718
6719 // Suspend
6720 LeAudioClient::Get()->GroupSuspend(group_id);
6721 SyncOnMainLoop();
6722 }
6723
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchNoReconfigure)6724 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) {
6725 uint8_t group_size = 2;
6726 int group_id = 2;
6727
6728 // Report working CSIS
6729 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
6730 .WillByDefault(Return(true));
6731
6732 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6733 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
6734
6735 // First earbud
6736 const RawAddress test_address0 = GetTestAddress(0);
6737 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
6738 .Times(1);
6739 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
6740 codec_spec_conf::kLeAudioLocationFrontLeft,
6741 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
6742 group_id, 1 /* rank*/);
6743
6744 // Second earbud
6745 const RawAddress test_address1 = GetTestAddress(1);
6746 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
6747 .Times(1);
6748 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
6749 codec_spec_conf::kLeAudioLocationFrontRight,
6750 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
6751 group_id, 2 /* rank*/, true /*connect_through_csis*/);
6752
6753 // Start streaming
6754 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6755 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6756 LeAudioClient::Get()->GroupSetActive(group_id);
6757 SyncOnMainLoop();
6758 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6759
6760 // Start streaming with new metadata, there was no previous stream so start
6761 // with this new configuration
6762 auto initial_context = types::LeAudioContextType::NOTIFICATIONS;
6763 types::BidirectionalPair<types::AudioContexts> contexts = {
6764 .sink = types::AudioContexts(initial_context),
6765 .source = types::AudioContexts()};
6766 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _))
6767 .Times(1);
6768
6769 StartStreaming(AUDIO_USAGE_NOTIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN,
6770 group_id);
6771
6772 SyncOnMainLoop();
6773 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6774 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6775 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6776
6777 // Do a metadata content switch to ALERTS but stay on previous configuration
6778 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
6779 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
6780 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
6781 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::ALERTS),
6782 .source = types::AudioContexts()};
6783 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _))
6784 .Times(1);
6785 UpdateLocalSourceMetadata(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN);
6786
6787 SyncOnMainLoop();
6788 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6789 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6790 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6791
6792 // Do a metadata content switch to EMERGENCY but stay on previous
6793 // configuration
6794 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
6795 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
6796 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
6797
6798 contexts = {
6799 .sink = types::AudioContexts(types::LeAudioContextType::EMERGENCYALARM),
6800 .source = types::AudioContexts()};
6801 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _))
6802 .Times(1);
6803 UpdateLocalSourceMetadata(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN);
6804
6805 SyncOnMainLoop();
6806 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6807 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6808
6809 // Do a metadata content switch to INSTRUCTIONAL but stay on previous
6810 // configuration
6811 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
6812 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
6813 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
6814 contexts = {
6815 .sink = types::AudioContexts(types::LeAudioContextType::INSTRUCTIONAL),
6816 .source = types::AudioContexts()};
6817 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _))
6818 .Times(1);
6819 UpdateLocalSourceMetadata(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
6820 AUDIO_CONTENT_TYPE_UNKNOWN);
6821
6822 SyncOnMainLoop();
6823 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6824 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6825 }
6826
TEST_F(UnicastTest,TwoEarbudsStopConversational_StartStreamSonification)6827 TEST_F(UnicastTest, TwoEarbudsStopConversational_StartStreamSonification) {
6828 uint8_t group_size = 2;
6829 int group_id = 2;
6830
6831 // Report working CSIS
6832 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
6833 .WillByDefault(Return(true));
6834
6835 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6836 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
6837
6838 // First earbud
6839 const RawAddress test_address0 = GetTestAddress(0);
6840 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
6841 .Times(1);
6842 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
6843 codec_spec_conf::kLeAudioLocationFrontLeft,
6844 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
6845 group_id, 1 /* rank*/);
6846
6847 // Second earbud
6848 const RawAddress test_address1 = GetTestAddress(1);
6849 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
6850 .Times(1);
6851 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
6852 codec_spec_conf::kLeAudioLocationFrontRight,
6853 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
6854 group_id, 2 /* rank*/, true /*connect_through_csis*/);
6855
6856 // Start streaming
6857 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6858 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6859 LeAudioClient::Get()->GroupSetActive(group_id);
6860 SyncOnMainLoop();
6861 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6862
6863 // Start streaming with CONVERSATIONAL, there was no previous stream so start
6864 // with this new configuration
6865 auto initial_context = types::LeAudioContextType::CONVERSATIONAL;
6866 types::BidirectionalPair<types::AudioContexts> contexts = {
6867 .sink = types::AudioContexts(initial_context),
6868 .source = types::AudioContexts(initial_context)};
6869 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _))
6870 .Times(1);
6871
6872 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
6873 group_id);
6874
6875 SyncOnMainLoop();
6876 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6877 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6878 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6879
6880 // Stop the stream but KEEP cis UP
6881 StopStreaming(group_id, true);
6882 SyncOnMainLoop();
6883 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6884
6885 types::BidirectionalPair<types::AudioContexts> reconfigure_contexts = {
6886 .sink = types::AudioContexts(types::LeAudioContextType::ALERTS),
6887 .source = types::AudioContexts()};
6888
6889 EXPECT_CALL(mock_state_machine_,
6890 StartStream(_, initial_context, reconfigure_contexts, _))
6891 .Times(1);
6892
6893 // Change context type but expect configuration to by as previous
6894 StartStreaming(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6895
6896 SyncOnMainLoop();
6897 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6898
6899 // Stop the stream and drop CISes
6900 StopStreaming(group_id, true);
6901 SyncOnMainLoop();
6902 // simulate suspend timeout passed, alarm executing
6903 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
6904 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6905
6906 auto reconfigure_context = types::LeAudioContextType::ALERTS;
6907
6908 EXPECT_CALL(mock_state_machine_,
6909 StartStream(_, reconfigure_context, reconfigure_contexts, _))
6910 .Times(1);
6911
6912 // Update metadata
6913 StartStreaming(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6914 SyncOnMainLoop();
6915 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6916 }
6917
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchReconfigure)6918 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) {
6919 uint8_t group_size = 2;
6920 int group_id = 2;
6921
6922 // Report working CSIS
6923 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
6924 .WillByDefault(Return(true));
6925
6926 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6927 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
6928
6929 // First earbud
6930 const RawAddress test_address0 = GetTestAddress(0);
6931 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
6932 .Times(1);
6933 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
6934 codec_spec_conf::kLeAudioLocationFrontLeft,
6935 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
6936 group_id, 1 /* rank*/);
6937
6938 // Second earbud
6939 const RawAddress test_address1 = GetTestAddress(1);
6940 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
6941 .Times(1);
6942 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
6943 codec_spec_conf::kLeAudioLocationFrontRight,
6944 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
6945 group_id, 2 /* rank*/, true /*connect_through_csis*/);
6946
6947 constexpr int gmcs_ccid = 1;
6948 constexpr int gtbs_ccid = 2;
6949
6950 // Start streaming MEDIA
6951 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6952 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6953 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
6954 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
6955 LeAudioClient::Get()->GroupSetActive(group_id);
6956 SyncOnMainLoop();
6957
6958 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
6959 .source = {}};
6960 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
6961 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6962
6963 SyncOnMainLoop();
6964 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6965 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6966 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6967
6968 // Verify Data transfer on two peer sinks
6969 uint8_t cis_count_out = 2;
6970 uint8_t cis_count_in = 0;
6971 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6972
6973 // Stop
6974 StopStreaming(group_id);
6975 // simulate suspend timeout passed, alarm executing
6976 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
6977 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6978
6979 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
6980 LeAudioClient::Get()->SetInCall(true);
6981
6982 // Conversational is a bidirectional scenario so expect GTBS CCID
6983 // in the metadata for both directions. Can be called twice when one
6984 // direction resume after the other and metadata is updated.
6985 ccids = {.sink = {gtbs_ccid}, .source = {gtbs_ccid}};
6986 EXPECT_CALL(
6987 mock_state_machine_,
6988 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
6989 .Times(AtLeast(1));
6990 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
6991 group_id);
6992
6993 SyncOnMainLoop();
6994 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6995 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6996
6997 // Verify Data transfer on two peer sinks and one source
6998 cis_count_out = 2;
6999 cis_count_in = 2;
7000 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
7001
7002 LeAudioClient::Get()->SetInCall(false);
7003 // Stop
7004 StopStreaming(group_id, true);
7005
7006 // Switch back to MEDIA
7007 ccids = {.sink = {gmcs_ccid}, .source = {}};
7008 types::BidirectionalPair<types::AudioContexts> contexts = {
7009 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
7010 .source = types::AudioContexts()};
7011 EXPECT_CALL(
7012 mock_state_machine_,
7013 ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA,
7014 contexts, ccids))
7015 .Times(1);
7016 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id,
7017 AUDIO_SOURCE_INVALID, true);
7018
7019 SyncOnMainLoop();
7020 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7021 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7022 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7023 }
7024
TEST_F(UnicastTest,TwoEarbudsVoipStreamingVerifyMetadataUpdate)7025 TEST_F(UnicastTest, TwoEarbudsVoipStreamingVerifyMetadataUpdate) {
7026 uint8_t group_size = 2;
7027 int group_id = 2;
7028
7029 /*
7030 * Scenario
7031 * 1. Configure stream for the VOIP
7032 * 2. Verify CONVERSATIONAL metadata and context is used.
7033 * 3. Resume LocalSink
7034 * 4. Make sure there is no change of the metadata and context
7035 */
7036
7037 // Report working CSIS
7038 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7039 .WillByDefault(Return(true));
7040
7041 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7042 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7043
7044 // First earbud
7045 const RawAddress test_address0 = GetTestAddress(0);
7046 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
7047 .Times(1);
7048 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7049 codec_spec_conf::kLeAudioLocationFrontLeft,
7050 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7051 group_id, 1 /* rank*/);
7052
7053 // Second earbud
7054 const RawAddress test_address1 = GetTestAddress(1);
7055 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
7056 .Times(1);
7057 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7058 codec_spec_conf::kLeAudioLocationFrontRight,
7059 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7060 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7061
7062 constexpr int gtbs_ccid = 2;
7063
7064 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
7065 LeAudioClient::Get()->GroupSetActive(group_id);
7066 SyncOnMainLoop();
7067
7068 // VOIP not using Telecom API has no ccids.
7069 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {},
7070 .source = {}};
7071 EXPECT_CALL(
7072 mock_state_machine_,
7073 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
7074 .Times(AtLeast(1));
7075
7076 UpdateLocalSourceMetadata(AUDIO_USAGE_VOICE_COMMUNICATION,
7077 AUDIO_CONTENT_TYPE_SPEECH);
7078 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
7079
7080 LocalAudioSourceResume();
7081 SyncOnMainLoop();
7082 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7083
7084 SyncOnMainLoop();
7085 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7086 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7087
7088 // Verify Data transfer are sending. The LocalSink is not yet resumed.
7089 uint8_t cis_count_out = 2;
7090 uint8_t cis_count_in = 0;
7091 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 0);
7092
7093 types::BidirectionalPair<types::AudioContexts> contexts = {
7094 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
7095 .source =
7096 types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
7097 EXPECT_CALL(mock_state_machine_,
7098 StartStream(_, types::LeAudioContextType::CONVERSATIONAL,
7099 contexts, ccids))
7100 .Times(AtLeast(1));
7101
7102 LocalAudioSinkResume();
7103 SyncOnMainLoop();
7104 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7105 }
7106
TEST_F(UnicastTest,TwoReconfigureAndVerifyEnableContextType)7107 TEST_F(UnicastTest, TwoReconfigureAndVerifyEnableContextType) {
7108 uint8_t group_size = 2;
7109 int group_id = 2;
7110
7111 /* Scenario
7112 * 1. Earbuds streaming MEDIA
7113 * 2. Reconfigure to VOIP
7114 * 3. Check if Metadata in Enable command are set to CONVERSATIONAL
7115 */
7116
7117 // Report working CSIS
7118 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7119 .WillByDefault(Return(true));
7120
7121 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7122 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7123
7124 // First earbud
7125 const RawAddress test_address0 = GetTestAddress(0);
7126 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
7127 .Times(1);
7128 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7129 codec_spec_conf::kLeAudioLocationFrontLeft,
7130 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7131 group_id, 1 /* rank*/);
7132
7133 // Second earbud
7134 const RawAddress test_address1 = GetTestAddress(1);
7135 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
7136 .Times(1);
7137 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7138 codec_spec_conf::kLeAudioLocationFrontRight,
7139 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7140 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7141
7142 constexpr int gmcs_ccid = 1;
7143 constexpr int gtbs_ccid = 2;
7144
7145 // Start streaming MEDIA
7146 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7147 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7148 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
7149 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
7150 LeAudioClient::Get()->GroupSetActive(group_id);
7151 SyncOnMainLoop();
7152
7153 // Update metadata on local audio sink
7154 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
7155
7156 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
7157 .source = {}};
7158 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
7159 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7160
7161 SyncOnMainLoop();
7162 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7163 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7164 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7165
7166 // Verify Data transfer on two peer sinks
7167 uint8_t cis_count_out = 2;
7168 uint8_t cis_count_in = 0;
7169 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7170
7171 // Conversational is a bidirectional scenario so expect GTBS CCID
7172 // in the metadata for both directions. Can be called twice when one
7173 // direction resume after the other and metadata is updated.
7174 ccids = {.sink = {gtbs_ccid}, .source = {gtbs_ccid}};
7175 types::BidirectionalPair<types::AudioContexts> conversiational_contexts = {
7176 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
7177 .source =
7178 types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
7179
7180 EXPECT_CALL(
7181 mock_state_machine_,
7182 ConfigureStream(_, types::LeAudioContextType::CONVERSATIONAL, _, _))
7183 .Times(AtLeast(1));
7184
7185 // Update metadata and resume
7186 UpdateLocalSourceMetadata(AUDIO_USAGE_VOICE_COMMUNICATION,
7187 AUDIO_CONTENT_TYPE_SPEECH, true);
7188 SyncOnMainLoop();
7189
7190 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7191 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7192 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7193
7194 EXPECT_CALL(mock_state_machine_,
7195 StartStream(_, types::LeAudioContextType::CONVERSATIONAL,
7196 conversiational_contexts, ccids))
7197 .Times(AtLeast(1));
7198
7199 LeAudioClient::Get()->SetInCall(true);
7200
7201 LocalAudioSourceResume(true);
7202 SyncOnMainLoop();
7203
7204 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7205 }
7206
TEST_F(UnicastTest,TwoEarbuds2ndLateConnect)7207 TEST_F(UnicastTest, TwoEarbuds2ndLateConnect) {
7208 uint8_t group_size = 2;
7209 int group_id = 2;
7210
7211 // Report working CSIS
7212 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7213 .WillByDefault(Return(true));
7214
7215 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7216 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7217
7218 const RawAddress test_address0 = GetTestAddress(0);
7219 const RawAddress test_address1 = GetTestAddress(1);
7220
7221 // First earbud
7222 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7223 codec_spec_conf::kLeAudioLocationFrontLeft,
7224 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7225 group_id, 1 /* rank*/);
7226
7227 // Start streaming
7228 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7229 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7230 LeAudioClient::Get()->GroupSetActive(group_id);
7231 SyncOnMainLoop();
7232
7233 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7234
7235 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7236 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7237 SyncOnMainLoop();
7238
7239 // Expect one iso channel to be fed with data
7240 uint8_t cis_count_out = 1;
7241 uint8_t cis_count_in = 0;
7242 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7243
7244 // Second earbud connects during stream
7245 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7246 codec_spec_conf::kLeAudioLocationFrontRight,
7247 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7248 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7249
7250 cis_count_out = 2;
7251 cis_count_in = 0;
7252
7253 /* The above will trigger reconfiguration. After that Audio Hal action
7254 * is needed to restart the stream */
7255 LocalAudioSourceResume();
7256
7257 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7258 }
7259
TEST_F(UnicastTest,LateStreamConnectBasedOnContextType)7260 TEST_F(UnicastTest, LateStreamConnectBasedOnContextType) {
7261 uint8_t group_size = 2;
7262 int group_id = 2;
7263
7264 /* Scenario
7265 * 1. Two devices A and B are connect. Device A has all available context
7266 * types, Device B has no available context types.
7267 * 2. Stream creation to Device A has been started
7268 * 3. Device B notified us with new available Context Types - while A is not
7269 * yet streaming
7270 * 4. Make sure AttachToStream was called for Device B
7271 */
7272
7273 // Report working CSIS
7274 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7275 .WillByDefault(Return(true));
7276
7277 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7278 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7279
7280 const RawAddress test_address0 = GetTestAddress(0);
7281 const RawAddress test_address1 = GetTestAddress(1);
7282
7283 // First earbud connects
7284 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7285 codec_spec_conf::kLeAudioLocationFrontLeft,
7286 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7287 group_id, 1 /* rank*/);
7288
7289 // Second earbud connects
7290 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7291 codec_spec_conf::kLeAudioLocationFrontRight,
7292 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7293 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7294
7295 // Start streaming
7296 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7297 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7298 LeAudioClient::Get()->GroupSetActive(group_id);
7299 SyncOnMainLoop();
7300
7301 /* Simulate available context type being cleared */
7302 InjectAvailableContextTypes(test_address1, 2, types::AudioContexts(0),
7303 types::AudioContexts(0));
7304
7305 // Block streaming state
7306 block_streaming_state_callback = true;
7307
7308 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
7309 LocalAudioSourceResume(false);
7310
7311 SyncOnMainLoop();
7312 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7313
7314 InjectAvailableContextTypes(test_address1, 2,
7315 types::kLeAudioContextAllRemoteSinkOnly,
7316 types::AudioContexts(0), false);
7317
7318 // Now simulate group is finally streaming
7319 auto group = streaming_groups.at(group_id);
7320 do_in_main_thread(
7321 FROM_HERE,
7322 base::BindOnce(
7323 [](int group_id,
7324 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
7325 state_machine_callbacks,
7326 LeAudioDeviceGroup* group) {
7327 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
7328
7329 state_machine_callbacks->StatusReportCb(
7330 group_id, GroupStreamStatus::STREAMING);
7331 },
7332 group_id, base::Unretained(this->state_machine_callbacks_),
7333 std::move(group)));
7334
7335 SyncOnMainLoop();
7336
7337 /* verify AttachToStream was called while stream was not yet created. */
7338 ASSERT_TRUE(attach_to_stream_scheduled);
7339
7340 // Expect two iso channel to be fed with data
7341 uint8_t cis_count_out = 2;
7342 uint8_t cis_count_in = 0;
7343 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7344 SyncOnMainLoop();
7345 }
7346
TEST_F(UnicastTest,CheckDeviceIsNotAttachedToStreamWhenNotNeeded)7347 TEST_F(UnicastTest, CheckDeviceIsNotAttachedToStreamWhenNotNeeded) {
7348 uint8_t group_size = 2;
7349 int group_id = 2;
7350
7351 /* Scenario
7352 * 1. Two devices A and B are connect. Both Devices have all available
7353 * contexts types
7354 * 2. Stream creation to Device A and B has been started
7355 * 3. Device B notified us with new available Context Types - while Group is
7356 * not yet streaming
7357 * 4. Make sure AttachToStream was not called for Device B since it is taking
7358 * part in Stream creation already
7359 */
7360
7361 // Report working CSIS
7362 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7363 .WillByDefault(Return(true));
7364
7365 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7366 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7367
7368 const RawAddress test_address0 = GetTestAddress(0);
7369 const RawAddress test_address1 = GetTestAddress(1);
7370
7371 // First earbud connects
7372 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7373 codec_spec_conf::kLeAudioLocationFrontLeft,
7374 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7375 group_id, 1 /* rank*/);
7376
7377 // Second earbud connects
7378 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7379 codec_spec_conf::kLeAudioLocationFrontRight,
7380 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7381 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7382
7383 // Start streaming
7384 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7385 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7386 LeAudioClient::Get()->GroupSetActive(group_id);
7387 SyncOnMainLoop();
7388
7389 // Block streaming state
7390 block_streaming_state_callback = true;
7391
7392 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
7393 LocalAudioSourceResume(false);
7394
7395 SyncOnMainLoop();
7396 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7397
7398 InjectAvailableContextTypes(test_address1, 2,
7399 types::kLeAudioContextAllRemoteSinkOnly,
7400 types::AudioContexts(0), false);
7401
7402 // Now simulate group is finally streaming
7403 auto group = streaming_groups.at(group_id);
7404 do_in_main_thread(
7405 FROM_HERE,
7406 base::BindOnce(
7407 [](int group_id,
7408 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
7409 state_machine_callbacks,
7410 LeAudioDeviceGroup* group) {
7411 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
7412
7413 state_machine_callbacks->StatusReportCb(
7414 group_id, GroupStreamStatus::STREAMING);
7415 },
7416 group_id, base::Unretained(this->state_machine_callbacks_),
7417 std::move(group)));
7418
7419 SyncOnMainLoop();
7420
7421 /* verify AttachToStream was NOT called while stream was not yet created. */
7422 ASSERT_FALSE(attach_to_stream_scheduled);
7423
7424 // Expect two iso channel to be fed with data
7425 uint8_t cis_count_out = 2;
7426 uint8_t cis_count_in = 0;
7427 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7428 SyncOnMainLoop();
7429 }
7430
TEST_F(UnicastTest,ReconnectedDeviceNotAttachedToStreamBecauseOfNotAvailableContext)7431 TEST_F(UnicastTest,
7432 ReconnectedDeviceNotAttachedToStreamBecauseOfNotAvailableContext) {
7433 uint8_t group_size = 2;
7434 int group_id = 2;
7435
7436 /* Scenario
7437 * 1. Two devices A and B are streaming
7438 * 2. Device A Release ASE and removes all available context types
7439 * 3. Device B keeps streaming
7440 * 4. Device A disconnectes
7441 * 5. Device A reconnect and should not be attached to the stream
7442 */
7443
7444 // Report working CSIS
7445 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7446 .WillByDefault(Return(true));
7447
7448 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7449 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7450
7451 const RawAddress test_address0 = GetTestAddress(0);
7452 const RawAddress test_address1 = GetTestAddress(1);
7453
7454 // First earbud connects
7455 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7456 codec_spec_conf::kLeAudioLocationFrontLeft,
7457 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7458 group_id, 1 /* rank*/);
7459
7460 // Second earbud connects
7461 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7462 codec_spec_conf::kLeAudioLocationFrontRight,
7463 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7464 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7465
7466 // Start streaming
7467 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7468 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7469 LeAudioClient::Get()->GroupSetActive(group_id);
7470 SyncOnMainLoop();
7471
7472 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7473
7474 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7475 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7476 SyncOnMainLoop();
7477
7478 // Expect two iso channel to be fed with data
7479 uint8_t cis_count_out = 2;
7480 uint8_t cis_count_in = 0;
7481 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7482
7483 /* Get group and Device A */
7484 ASSERT_NE(0lu, streaming_groups.count(group_id));
7485 auto group = streaming_groups.at(group_id);
7486 ASSERT_NE(group, nullptr);
7487 auto device = group->GetFirstDevice();
7488
7489 /* Simulate available context type being cleared */
7490 InjectAvailableContextTypes(device->address_, device->conn_id_,
7491 types::AudioContexts(0), types::AudioContexts(0));
7492
7493 /* Simulate ASE releasing and CIS Disconnection */
7494 for (auto& ase : device->ases_) {
7495 /* Releasing state */
7496 if (!ase.active) {
7497 continue;
7498 }
7499
7500 std::vector<uint8_t> releasing_state = {
7501 ase.id, static_cast<uint8_t>(
7502 types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
7503 InjectNotificationEvent(device->address_, device->conn_id_,
7504 ase.hdls.val_hdl, releasing_state);
7505 SyncOnMainLoop();
7506 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
7507 SyncOnMainLoop();
7508 }
7509
7510 cis_count_out = 1;
7511 cis_count_in = 0;
7512 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7513
7514 /* Device A will disconnect, and do not reconnect automatically */
7515 ON_CALL(mock_gatt_interface_,
7516 Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, _))
7517 .WillByDefault(Return());
7518
7519 /* Disconnect first device */
7520 auto conn_id = device->conn_id_;
7521 InjectDisconnectedEvent(conn_id, GATT_CONN_TERMINATE_PEER_USER);
7522 SyncOnMainLoop();
7523
7524 /* For background connect, test needs to Inject Connected Event */
7525 InjectConnectedEvent(device->address_, conn_id);
7526 SyncOnMainLoop();
7527
7528 /* Check single device is streaming */
7529 cis_count_out = 1;
7530 cis_count_in = 0;
7531 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7532 }
7533
TEST_F(UnicastTest,TwoEarbuds2ndReleaseAseRemoveAvailableContextAndBack)7534 TEST_F(UnicastTest, TwoEarbuds2ndReleaseAseRemoveAvailableContextAndBack) {
7535 uint8_t group_size = 2;
7536 int group_id = 2;
7537
7538 /* Scenario
7539 * 1. Two devices A and B are streaming
7540 * 2. Device A Release ASE and removes all available context types
7541 * 3. Device B keeps streaming
7542 * 4. Device A sets available context types
7543 * 5. Device A should be attached to the stream
7544 */
7545
7546 // Report working CSIS
7547 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7548 .WillByDefault(Return(true));
7549
7550 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7551 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7552
7553 const RawAddress test_address0 = GetTestAddress(0);
7554 const RawAddress test_address1 = GetTestAddress(1);
7555
7556 // First earbud connects
7557 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7558 codec_spec_conf::kLeAudioLocationFrontLeft,
7559 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7560 group_id, 1 /* rank*/);
7561
7562 // Second earbud connects
7563 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7564 codec_spec_conf::kLeAudioLocationFrontRight,
7565 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7566 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7567
7568 // Start streaming
7569 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7570 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7571 LeAudioClient::Get()->GroupSetActive(group_id);
7572 SyncOnMainLoop();
7573
7574 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7575
7576 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7577 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7578 SyncOnMainLoop();
7579
7580 // Expect two iso channel to be fed with data
7581 uint8_t cis_count_out = 2;
7582 uint8_t cis_count_in = 0;
7583 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7584
7585 /* Get group and Device A */
7586 ASSERT_NE(0lu, streaming_groups.count(group_id));
7587 auto group = streaming_groups.at(group_id);
7588 ASSERT_NE(group, nullptr);
7589 auto device = group->GetFirstDevice();
7590
7591 /* Simulate available context type being cleared */
7592 InjectAvailableContextTypes(device->address_, device->conn_id_,
7593 types::AudioContexts(0), types::AudioContexts(0));
7594
7595 /* Simulate ASE releasing and CIS Disconnection */
7596 for (auto& ase : device->ases_) {
7597 /* Releasing state */
7598 if (!ase.active) {
7599 continue;
7600 }
7601
7602 std::vector<uint8_t> releasing_state = {
7603 ase.id, static_cast<uint8_t>(
7604 types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
7605 InjectNotificationEvent(device->address_, device->conn_id_,
7606 ase.hdls.val_hdl, releasing_state);
7607 SyncOnMainLoop();
7608 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
7609 SyncOnMainLoop();
7610 }
7611
7612 cis_count_out = 1;
7613 cis_count_in = 0;
7614 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7615
7616 /* Bring back available context types */
7617 InjectAvailableContextTypes(device->address_, device->conn_id_,
7618 types::kLeAudioContextAllTypes,
7619 types::kLeAudioContextAllTypes);
7620
7621 /* Check both devices are streaming */
7622 cis_count_out = 2;
7623 cis_count_in = 0;
7624 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7625 }
7626
TEST_F(UnicastTest,StartStream_AvailableContextTypeNotifiedLater)7627 TEST_F(UnicastTest, StartStream_AvailableContextTypeNotifiedLater) {
7628 uint8_t group_size = 2;
7629 int group_id = 2;
7630
7631 available_snk_context_types_ = 0;
7632
7633 /* Scenario (Devices A and B called "Remote")
7634 * 1. Remote does supports all the context types, but has NO available
7635 * contexts at the beginning
7636 * 2. After connection Remote add Available context types
7637 * 3. Android start stream with MEDIA
7638 * 4. Make sure stream will be started
7639 */
7640
7641 // Report working CSIS
7642 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7643 .WillByDefault(Return(true));
7644
7645 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7646 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7647
7648 const RawAddress test_address0 = GetTestAddress(0);
7649 const RawAddress test_address1 = GetTestAddress(1);
7650
7651 // First earbud connects
7652 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7653 codec_spec_conf::kLeAudioLocationFrontLeft,
7654 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7655 group_id, 1 /* rank*/);
7656
7657 // Second earbud connects
7658 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7659 codec_spec_conf::kLeAudioLocationFrontRight,
7660 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7661 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7662
7663 // Inject Supported and available context types
7664 auto sink_available_contexts = types::kLeAudioContextAllRemoteSinkOnly;
7665 auto source_available_contexts = types::kLeAudioContextAllRemoteSource;
7666
7667 InjectAvailableContextTypes(test_address0, 1, sink_available_contexts,
7668 source_available_contexts);
7669 InjectAvailableContextTypes(test_address1, 2, sink_available_contexts,
7670 source_available_contexts);
7671 // Start streaming
7672 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7673 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7674 LeAudioClient::Get()->GroupSetActive(group_id);
7675 SyncOnMainLoop();
7676
7677 BidirectionalPair<AudioContexts> contexts = {
7678 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
7679 .source = types::AudioContexts()};
7680
7681 EXPECT_CALL(
7682 mock_state_machine_,
7683 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA,
7684 contexts, _))
7685 .Times(1);
7686
7687 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7688 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7689 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7690
7691 // Expect two iso channel to be fed with data
7692 uint8_t cis_count_out = 2;
7693 uint8_t cis_count_in = 0;
7694 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7695 }
7696
TEST_F(UnicastTest,ModifyContextTypeOnDeviceA_WhileDeviceB_IsDisconnected)7697 TEST_F(UnicastTest, ModifyContextTypeOnDeviceA_WhileDeviceB_IsDisconnected) {
7698 uint8_t group_size = 2;
7699 int group_id = 2;
7700
7701 /* Scenario (Device A and B called Remote)
7702 * 1. Remote set does supports all the context types and make them available
7703 * 2. Android start stream with MEDIA, verify it works.
7704 * 3. Android stops the stream
7705 * 4. Device B disconnects
7706 * 5. Device A removes Media from Available Contexts
7707 * 6. Android start stream with MEDIA, verify it will not be started
7708 */
7709
7710 // Report working CSIS
7711 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7712 .WillByDefault(Return(true));
7713
7714 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7715 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7716
7717 const RawAddress test_address0 = GetTestAddress(0);
7718 const RawAddress test_address1 = GetTestAddress(1);
7719
7720 // First earbud connects
7721 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7722 codec_spec_conf::kLeAudioLocationFrontLeft,
7723 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7724 group_id, 1 /* rank*/);
7725
7726 // Second earbud connects
7727 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7728 codec_spec_conf::kLeAudioLocationFrontRight,
7729 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7730 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7731
7732 // Start streaming
7733 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7734 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7735 LeAudioClient::Get()->GroupSetActive(group_id);
7736 SyncOnMainLoop();
7737
7738 BidirectionalPair<AudioContexts> contexts = {
7739 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
7740 .source = types::AudioContexts()};
7741
7742 EXPECT_CALL(
7743 mock_state_machine_,
7744 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA,
7745 contexts, _))
7746 .Times(1);
7747
7748 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7749
7750 SyncOnMainLoop();
7751 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7752 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7753 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7754
7755 // Expect two iso channel to be fed with data
7756 uint8_t cis_count_out = 2;
7757 uint8_t cis_count_in = 0;
7758 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7759
7760 // Stop
7761 StopStreaming(group_id);
7762 // simulate suspend timeout passed, alarm executing
7763 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7764 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7765
7766 // Device B got disconnected and will not reconnect.
7767 ON_CALL(mock_gatt_interface_,
7768 Open(_, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
7769 .WillByDefault(Return());
7770 InjectDisconnectedEvent(2, GATT_CONN_TERMINATE_PEER_USER);
7771 SyncOnMainLoop();
7772
7773 // Device A changes available context type
7774 // Inject Supported and available context types
7775 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
7776 sink_supported_context.unset(LeAudioContextType::MEDIA);
7777 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
7778
7779 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
7780 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
7781
7782 InjectSupportedContextTypes(test_address0, 1, sink_supported_context,
7783 source_supported_context);
7784 InjectAvailableContextTypes(test_address0, 1, sink_supported_context,
7785 source_supported_context);
7786
7787 /* Android starts stream. */
7788 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
7789
7790 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id,
7791 AUDIO_SOURCE_INVALID, false, false);
7792 SyncOnMainLoop();
7793
7794 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7795 }
7796
TEST_F(UnicastTest,StartStreamToUnsupportedContextTypeUsingUnspecified)7797 TEST_F(UnicastTest, StartStreamToUnsupportedContextTypeUsingUnspecified) {
7798 uint8_t group_size = 2;
7799 int group_id = 2;
7800
7801 /* Scenario (Devices A and B called "Remote")
7802 * 1. Remote does supports all the context types and make them available
7803 * 2. Remote removes SoundEffect from the supported and available context
7804 * types
7805 * 3. Android start stream with SoundEffects
7806 * 4. Make sure stream will be started with Unspecified context type
7807 */
7808
7809 // Report working CSIS
7810 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7811 .WillByDefault(Return(true));
7812
7813 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7814 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7815
7816 const RawAddress test_address0 = GetTestAddress(0);
7817 const RawAddress test_address1 = GetTestAddress(1);
7818
7819 // First earbud connects
7820 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7821 codec_spec_conf::kLeAudioLocationFrontLeft,
7822 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7823 group_id, 1 /* rank*/);
7824
7825 // Second earbud connects
7826 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7827 codec_spec_conf::kLeAudioLocationFrontRight,
7828 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7829 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7830
7831 // Inject Supported and available context types
7832 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
7833 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
7834 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
7835
7836 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
7837 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
7838
7839 InjectSupportedContextTypes(test_address0, 1, sink_supported_context,
7840 source_supported_context);
7841 InjectAvailableContextTypes(test_address0, 1, sink_supported_context,
7842 source_supported_context);
7843 InjectSupportedContextTypes(test_address1, 2, sink_supported_context,
7844 source_supported_context);
7845 InjectAvailableContextTypes(test_address1, 2, sink_supported_context,
7846 source_supported_context);
7847 // Start streaming
7848 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7849 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7850 LeAudioClient::Get()->GroupSetActive(group_id);
7851 SyncOnMainLoop();
7852
7853 BidirectionalPair<AudioContexts> contexts = {
7854 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
7855 .source = types::AudioContexts(0)};
7856
7857 EXPECT_CALL(
7858 mock_state_machine_,
7859 StartStream(_,
7860 bluetooth::le_audio::types::LeAudioContextType::SOUNDEFFECTS,
7861 contexts, _))
7862 .Times(1);
7863
7864 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION,
7865 AUDIO_CONTENT_TYPE_SONIFICATION, group_id);
7866
7867 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7868 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7869 SyncOnMainLoop();
7870
7871 // Expect two iso channel to be fed with data
7872 uint8_t cis_count_out = 2;
7873 uint8_t cis_count_in = 0;
7874 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
7875 }
7876
TEST_F(UnicastTest,StartStreamToUnsupportedContextTypeUnspecifiedNotAvailable)7877 TEST_F(UnicastTest,
7878 StartStreamToUnsupportedContextTypeUnspecifiedNotAvailable) {
7879 uint8_t group_size = 2;
7880 int group_id = 2;
7881
7882 /* Scenario (Device A and B called Remote)
7883 * 1. Remote does supports all the context types and make them available
7884 * 2. Remote removes SoundEffect from the Available Context Types
7885 * 3. Remote also removes UNSPECIFIED from the Available Context Types.
7886 * 4. Android start stream with SoundEffects
7887 * 5. Make sure stream will be NOT be started
7888 */
7889
7890 // Report working CSIS
7891 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7892 .WillByDefault(Return(true));
7893
7894 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7895 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7896
7897 const RawAddress test_address0 = GetTestAddress(0);
7898 const RawAddress test_address1 = GetTestAddress(1);
7899
7900 // First earbud connects
7901 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7902 codec_spec_conf::kLeAudioLocationFrontLeft,
7903 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7904 group_id, 1 /* rank*/);
7905
7906 // Second earbud connects
7907 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7908 codec_spec_conf::kLeAudioLocationFrontRight,
7909 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
7910 group_id, 2 /* rank*/, true /*connect_through_csis*/);
7911
7912 // Inject Supported and available context types
7913 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
7914 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
7915 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
7916
7917 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
7918 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
7919
7920 InjectSupportedContextTypes(test_address0, 1, sink_supported_context,
7921 source_supported_context);
7922 InjectSupportedContextTypes(test_address1, 2, sink_supported_context,
7923 source_supported_context);
7924
7925 auto sink_available_context = sink_supported_context;
7926 sink_available_context.unset(LeAudioContextType::UNSPECIFIED);
7927
7928 auto source_available_context = source_supported_context;
7929 source_available_context.unset(LeAudioContextType::UNSPECIFIED);
7930
7931 InjectAvailableContextTypes(test_address0, 1, sink_available_context,
7932 source_available_context);
7933 InjectAvailableContextTypes(test_address1, 2, sink_available_context,
7934 source_available_context);
7935 // Start streaming
7936 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
7937 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
7938 LeAudioClient::Get()->GroupSetActive(group_id);
7939 SyncOnMainLoop();
7940
7941 BidirectionalPair<AudioContexts> contexts = {
7942 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
7943 .source = types::AudioContexts()};
7944
7945 EXPECT_CALL(
7946 mock_state_machine_,
7947 StartStream(_,
7948 bluetooth::le_audio::types::LeAudioContextType::SOUNDEFFECTS,
7949 contexts, _))
7950 .Times(0);
7951
7952 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION,
7953 AUDIO_CONTENT_TYPE_SONIFICATION, group_id,
7954 AUDIO_SOURCE_INVALID, false, false);
7955
7956 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7957 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7958 SyncOnMainLoop();
7959 }
7960
TEST_F(UnicastTest,StartStreamToSupportedContextTypeThenMixUnavailable)7961 TEST_F(UnicastTest, StartStreamToSupportedContextTypeThenMixUnavailable) {
7962 uint8_t group_size = 2;
7963 int group_id = 2;
7964
7965 /* Scenario (Device A and B called Remote)
7966 * 1. Remote set does supports all the context types and make them available
7967 * 2. Abdriud start stream with MEDIA, verify it works.
7968 * 3. Stream becomes to be mixed with Soundeffect and Media - verify metadata
7969 * update
7970 * 4. Android Stop stream.
7971 * 5. Remote removes SoundEffect from the supported and available context
7972 * types
7973 * 6. Android start stream with MEDIA, verify it works.
7974 * 7. Stream becomes to be mixed with Soundeffect and Media
7975 * 8. Make sure metadata updated does not contain unavailable context
7976 * note: eventually, Audio framework should not give us unwanted context
7977 * types
7978 */
7979
7980 // Report working CSIS
7981 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
7982 .WillByDefault(Return(true));
7983
7984 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
7985 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
7986
7987 const RawAddress test_address0 = GetTestAddress(0);
7988 const RawAddress test_address1 = GetTestAddress(1);
7989
7990 // First earbud connects
7991 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
7992 codec_spec_conf::kLeAudioLocationFrontLeft,
7993 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
7994 group_id, 1 /* rank*/);
7995
7996 // Second earbud connects
7997 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
7998 codec_spec_conf::kLeAudioLocationFrontRight,
7999 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
8000 group_id, 2 /* rank*/, true /*connect_through_csis*/);
8001
8002 // Start streaming
8003 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8004 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8005 LeAudioClient::Get()->GroupSetActive(group_id);
8006 SyncOnMainLoop();
8007
8008 BidirectionalPair<AudioContexts> contexts = {
8009 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
8010 .source = types::AudioContexts()};
8011
8012 EXPECT_CALL(
8013 mock_state_machine_,
8014 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA,
8015 contexts, _))
8016 .Times(1);
8017
8018 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8019
8020 SyncOnMainLoop();
8021 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8022 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8023 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8024
8025 ASSERT_NE(0lu, streaming_groups.count(group_id));
8026 auto group = streaming_groups.at(group_id);
8027
8028 // Expect two iso channel to be fed with data
8029 uint8_t cis_count_out = 2;
8030 uint8_t cis_count_in = 0;
8031 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8032
8033 contexts.sink = types::AudioContexts(types::LeAudioContextType::MEDIA |
8034 types::LeAudioContextType::SOUNDEFFECTS);
8035 EXPECT_CALL(
8036 mock_state_machine_,
8037 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA,
8038 contexts, _))
8039 .Times(1);
8040
8041 /* Simulate metadata update, expect upadate , metadata */
8042 std::vector<struct playback_track_metadata> tracks = {
8043 {{AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, 0},
8044 {AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION,
8045 0}}};
8046 UpdateLocalSourceMetadata(tracks);
8047 SyncOnMainLoop();
8048
8049 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8050
8051 /* Stop stream */
8052 StopStreaming(group_id);
8053 // simulate suspend timeout passed, alarm executing
8054 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8055 SyncOnMainLoop();
8056
8057 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8058
8059 // Inject Supported and available context types
8060 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
8061 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
8062 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
8063
8064 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
8065 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
8066
8067 InjectSupportedContextTypes(test_address0, 1, sink_supported_context,
8068 source_supported_context);
8069 InjectAvailableContextTypes(test_address0, 1, sink_supported_context,
8070 source_supported_context);
8071 InjectSupportedContextTypes(test_address1, 2, sink_supported_context,
8072 source_supported_context);
8073 InjectAvailableContextTypes(test_address1, 2, sink_supported_context,
8074 source_supported_context);
8075
8076 // Verify cache has been removed due to available context change
8077 ASSERT_EQ(nullptr,
8078 group->GetCachedConfiguration(types::LeAudioContextType::MEDIA));
8079 /* Start Media again */
8080 contexts.sink = types::AudioContexts(types::LeAudioContextType::MEDIA);
8081 EXPECT_CALL(
8082 mock_state_machine_,
8083 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA,
8084 contexts, _))
8085 .Times(1);
8086
8087 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8088
8089 SyncOnMainLoop();
8090
8091 // Verify cache has been rebuilt
8092 ASSERT_NE(nullptr,
8093 group->GetCachedConfiguration(types::LeAudioContextType::MEDIA));
8094 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::MEDIA)
8095 ->confs.get(le_audio::types::kLeAudioDirectionSink)
8096 .size());
8097
8098 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8099 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8100 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8101
8102 // Expect two iso channel to be fed with data
8103 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8104
8105 /* Update metadata, and do not expect new context type*/
8106 EXPECT_CALL(
8107 mock_state_machine_,
8108 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA,
8109 contexts, _))
8110 .Times(1);
8111
8112 /* Simulate metadata update */
8113 UpdateLocalSourceMetadata(tracks);
8114 SyncOnMainLoop();
8115 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8116 }
8117
TEST_F(UnicastTest,TwoEarbuds2ndDisconnected)8118 TEST_F(UnicastTest, TwoEarbuds2ndDisconnected) {
8119 uint8_t group_size = 2;
8120 int group_id = 2;
8121
8122 // Report working CSIS
8123 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
8124 .WillByDefault(Return(true));
8125
8126 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8127 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
8128
8129 // First earbud
8130 const RawAddress test_address0 = GetTestAddress(0);
8131 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
8132 codec_spec_conf::kLeAudioLocationFrontLeft,
8133 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
8134 group_id, 1 /* rank*/);
8135
8136 // Second earbud
8137 const RawAddress test_address1 = GetTestAddress(1);
8138 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
8139 codec_spec_conf::kLeAudioLocationFrontRight,
8140 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
8141 group_id, 2 /* rank*/, true /*connect_through_csis*/);
8142
8143 // Audio sessions are started only when device gets active
8144 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8145 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8146 LeAudioClient::Get()->GroupSetActive(group_id);
8147 SyncOnMainLoop();
8148
8149 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8150 ASSERT_NE(0lu, streaming_groups.count(group_id));
8151 auto group = streaming_groups.at(group_id);
8152
8153 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8154 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8155 SyncOnMainLoop();
8156 ASSERT_EQ(2, group->NumOfConnected());
8157
8158 // Expect two iso channels to be fed with data
8159 uint8_t cis_count_out = 2;
8160 uint8_t cis_count_in = 0;
8161 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8162
8163 // Disconnect one device and expect the group to keep on streaming
8164 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
8165 auto device = group->GetFirstDevice();
8166 for (auto& ase : device->ases_) {
8167 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
8168 }
8169
8170 /* Disconnect ACL and do not reconnect. */
8171 ON_CALL(mock_gatt_interface_,
8172 Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, _))
8173 .WillByDefault(Return());
8174 EXPECT_CALL(mock_gatt_interface_,
8175 Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, false))
8176 .Times(1);
8177
8178 // Record NumOfConnected when groupStateMachine_ gets notified about the
8179 // disconnection
8180 int num_of_connected = 0;
8181 ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
8182 .WillByDefault([&num_of_connected](LeAudioDeviceGroup* group,
8183 LeAudioDevice* leAudioDevice) {
8184 num_of_connected = group->NumOfConnected();
8185 });
8186
8187 auto conn_id = device->conn_id_;
8188 InjectDisconnectedEvent(device->conn_id_, GATT_CONN_TERMINATE_PEER_USER);
8189 SyncOnMainLoop();
8190
8191 // Make sure the state machine knows about the disconnected device
8192 ASSERT_EQ(1, num_of_connected);
8193
8194 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
8195 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8196
8197 // Expect one channel ISO Data to be sent
8198 cis_count_out = 1;
8199 cis_count_in = 0;
8200 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8201
8202 InjectConnectedEvent(device->address_, conn_id);
8203 SyncOnMainLoop();
8204
8205 // Expect two iso channels to be fed with data
8206 cis_count_out = 2;
8207 cis_count_in = 0;
8208 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8209 }
8210
TEST_F(UnicastTest,TwoEarbudsStreamingProfileDisconnect)8211 TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnect) {
8212 uint8_t group_size = 2;
8213 int group_id = 2;
8214
8215 // Report working CSIS
8216 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
8217 .WillByDefault(Return(true));
8218
8219 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8220 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
8221
8222 // First earbud
8223 const RawAddress test_address0 = GetTestAddress(0);
8224 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
8225 codec_spec_conf::kLeAudioLocationFrontLeft,
8226 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
8227 group_id, 1 /* rank*/);
8228
8229 // Second earbud
8230 const RawAddress test_address1 = GetTestAddress(1);
8231 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
8232 codec_spec_conf::kLeAudioLocationFrontRight,
8233 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
8234 group_id, 2 /* rank*/, true /*connect_through_csis*/);
8235
8236 // Audio sessions are started only when device gets active
8237 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8238 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8239 LeAudioClient::Get()->GroupSetActive(group_id);
8240 SyncOnMainLoop();
8241
8242 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8243
8244 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8245 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8246 SyncOnMainLoop();
8247
8248 // Expect two iso channels to be fed with data
8249 uint8_t cis_count_out = 2;
8250 uint8_t cis_count_in = 0;
8251 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8252
8253 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
8254
8255 /* Do not inject OPEN_EVENT by default */
8256 ON_CALL(mock_gatt_interface_, Open(_, _, _, _))
8257 .WillByDefault(DoAll(Return()));
8258 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
8259 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
8260 .WillByDefault(DoAll(Return()));
8261
8262 DisconnectLeAudioNoDisconnectedEvtExpected(test_address0, 1);
8263 DisconnectLeAudioNoDisconnectedEvtExpected(test_address1, 2);
8264
8265 EXPECT_CALL(mock_gatt_interface_,
8266 Open(_, _, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
8267 .Times(2);
8268
8269 InjectDisconnectedEvent(1);
8270 InjectDisconnectedEvent(2);
8271
8272 SyncOnMainLoop();
8273 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8274 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
8275 }
8276
TEST_F(UnicastTest,TwoEarbudsStreamingProfileDisconnectStreamStopTimeout)8277 TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnectStreamStopTimeout) {
8278 uint8_t group_size = 2;
8279 int group_id = 2;
8280
8281 // Report working CSIS
8282 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
8283 .WillByDefault(Return(true));
8284
8285 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8286 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
8287
8288 // First earbud
8289 const RawAddress test_address0 = GetTestAddress(0);
8290 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
8291 codec_spec_conf::kLeAudioLocationFrontLeft,
8292 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
8293 group_id, 1 /* rank*/);
8294
8295 // Second earbud
8296 const RawAddress test_address1 = GetTestAddress(1);
8297 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
8298 codec_spec_conf::kLeAudioLocationFrontRight,
8299 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
8300 group_id, 2 /* rank*/, true /*connect_through_csis*/);
8301
8302 // Audio sessions are started only when device gets active
8303 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8304 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8305 LeAudioClient::Get()->GroupSetActive(group_id);
8306 SyncOnMainLoop();
8307
8308 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8309
8310 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8311 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8312 SyncOnMainLoop();
8313
8314 // Expect two iso channels to be fed with data
8315 uint8_t cis_count_out = 2;
8316 uint8_t cis_count_in = 0;
8317 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8318
8319 // Expect StopStream to be called before Close or ACL Disconnect is called.
8320 ON_CALL(mock_state_machine_, StopStream(_))
8321 .WillByDefault([](LeAudioDeviceGroup* group) {
8322 /* Stub the process of stopping stream, just set the target state.
8323 * this simulates issue with stopping the stream
8324 */
8325 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
8326 });
8327
8328 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(2);
8329 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
8330 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).Times(0);
8331
8332 do_in_main_thread(
8333 FROM_HERE,
8334 base::Bind(&LeAudioClient::Disconnect,
8335 base::Unretained(LeAudioClient::Get()), test_address0));
8336 do_in_main_thread(
8337 FROM_HERE,
8338 base::Bind(&LeAudioClient::Disconnect,
8339 base::Unretained(LeAudioClient::Get()), test_address1));
8340
8341 SyncOnMainLoop();
8342 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
8343 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
8344 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8345
8346 /* Now stream is trying to be stopped and devices are about to be
8347 * disconnected. Simulate stop stream failure and timeout fired. Make sure
8348 * code will not try to do recovery connect
8349 */
8350 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
8351 .WillByDefault(DoAll(Return()));
8352 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
8353 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).Times(2);
8354
8355 ASSERT_NE(0lu, streaming_groups.count(group_id));
8356 auto group = streaming_groups.at(group_id);
8357 ASSERT_TRUE(group != nullptr);
8358 ASSERT_TRUE(group->NumOfConnected() > 0);
8359
8360 state_machine_callbacks_->OnStateTransitionTimeout(group_id);
8361 SyncOnMainLoop();
8362
8363 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
8364 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
8365
8366 auto device = group->GetFirstDevice();
8367 ASSERT_TRUE(device != nullptr);
8368 ASSERT_NE(device->GetConnectionState(),
8369 DeviceConnectState::DISCONNECTING_AND_RECOVER);
8370 device = group->GetNextDevice(device);
8371 ASSERT_TRUE(device != nullptr);
8372 ASSERT_NE(device->GetConnectionState(),
8373 DeviceConnectState::DISCONNECTING_AND_RECOVER);
8374 }
8375
TEST_F(UnicastTest,EarbudsWithStereoSinkMonoSourceSupporting32kHz)8376 TEST_F(UnicastTest, EarbudsWithStereoSinkMonoSourceSupporting32kHz) {
8377 const RawAddress test_address0 = GetTestAddress(0);
8378 int group_id = 0;
8379 SetSampleDatabaseEarbudsValid(
8380 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
8381 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
8382 default_channel_cnt, 0x0024,
8383 /* source sample freq 32/16khz */ true, /*add_csis*/
8384 true, /*add_cas*/
8385 true, /*add_pacs*/
8386 default_ase_cnt /*add_ascs_cnt*/);
8387 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8388 OnConnectionState(ConnectionState::CONNECTED, test_address0))
8389 .Times(1);
8390 ConnectLeAudio(test_address0);
8391
8392 // LeAudioCodecConfiguration received_af_sink_config;
8393 const LeAudioCodecConfiguration expected_af_sink_config = {
8394 .num_channels = 2,
8395 .sample_rate = bluetooth::audio::le_audio::kSampleRate32000,
8396 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
8397 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
8398 };
8399
8400 // Audio sessions are started only when device gets active
8401 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8402 EXPECT_CALL(*mock_le_audio_sink_hal_client_,
8403 Start(expected_af_sink_config, _, _))
8404 .Times(1);
8405 LeAudioClient::Get()->GroupSetActive(group_id);
8406 SyncOnMainLoop();
8407 }
8408
TEST_F(UnicastTest,TwoEarbudsWithSourceSupporting32kHz)8409 TEST_F(UnicastTest, TwoEarbudsWithSourceSupporting32kHz) {
8410 const RawAddress test_address0 = GetTestAddress(0);
8411 int group_id = 0;
8412 SetSampleDatabaseEarbudsValid(
8413 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
8414 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
8415 default_channel_cnt, 0x0024,
8416 /* source sample freq 32/16khz */ true, /*add_csis*/
8417 true, /*add_cas*/
8418 true, /*add_pacs*/
8419 default_ase_cnt /*add_ascs_cnt*/);
8420 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8421 OnConnectionState(ConnectionState::CONNECTED, test_address0))
8422 .Times(1);
8423 ConnectLeAudio(test_address0);
8424
8425 // LeAudioCodecConfiguration received_af_sink_config;
8426 const LeAudioCodecConfiguration expected_af_sink_config = {
8427 .num_channels = 2,
8428 .sample_rate = bluetooth::audio::le_audio::kSampleRate32000,
8429 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
8430 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
8431 };
8432
8433 // Audio sessions are started only when device gets active
8434 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8435 EXPECT_CALL(*mock_le_audio_sink_hal_client_,
8436 Start(expected_af_sink_config, _, _))
8437 .Times(1);
8438 LeAudioClient::Get()->GroupSetActive(group_id);
8439 SyncOnMainLoop();
8440 }
8441
TEST_F(UnicastTest,MicrophoneAttachToCurrentMediaScenario)8442 TEST_F(UnicastTest, MicrophoneAttachToCurrentMediaScenario) {
8443 const RawAddress test_address0 = GetTestAddress(0);
8444 int group_id = bluetooth::groups::kGroupUnknown;
8445
8446 SetSampleDatabaseEarbudsValid(
8447 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
8448 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
8449 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
8450 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
8451 0 /*rank*/);
8452 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8453 OnConnectionState(ConnectionState::CONNECTED, test_address0))
8454 .Times(1);
8455 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8456 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
8457 .WillOnce(DoAll(SaveArg<1>(&group_id)));
8458
8459 ConnectLeAudio(test_address0);
8460 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
8461
8462 // Audio sessions are started only when device gets active
8463 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8464 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8465 LeAudioClient::Get()->GroupSetActive(group_id);
8466 SyncOnMainLoop();
8467
8468 // When the local audio source resumes we have no knowledge of recording
8469 EXPECT_CALL(
8470 mock_state_machine_,
8471 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, _,
8472 _))
8473 .Times(1);
8474
8475 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id,
8476 AUDIO_SOURCE_INVALID);
8477 SyncOnMainLoop();
8478
8479 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8480 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8481
8482 // Verify Data transfer on one audio source cis
8483 uint8_t cis_count_out = 1;
8484 uint8_t cis_count_in = 0;
8485 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8486
8487 // When the local audio sink resumes we should reconfigure
8488 EXPECT_CALL(
8489 mock_state_machine_,
8490 ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE,
8491 _, _))
8492 .Times(1);
8493 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
8494 .Times(1);
8495
8496 // Update metadata on local audio sink
8497 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
8498
8499 // Resume on local audio sink
8500 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
8501 do_in_main_thread(
8502 FROM_HERE,
8503 base::BindOnce(
8504 [](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
8505 unicast_sink_hal_cb_));
8506
8507 /* The above will trigger reconfiguration. After that Audio Hal action
8508 * is needed to restart the stream */
8509 SyncOnMainLoop();
8510
8511 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8512 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8513
8514 LocalAudioSourceResume();
8515 do_in_main_thread(
8516 FROM_HERE,
8517 base::BindOnce(
8518 [](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
8519 unicast_sink_hal_cb_));
8520 SyncOnMainLoop();
8521
8522 // Verify Data transfer on one audio source and sink cis
8523 cis_count_out = 1;
8524 cis_count_in = 1;
8525 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
8526
8527 // Stop
8528 StopStreaming(group_id);
8529 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8530
8531 // Release
8532 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
8533 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
8534 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
8535 do_in_main_thread(
8536 FROM_HERE, base::BindOnce(
8537 [](LeAudioClient* client) {
8538 client->GroupSetActive(bluetooth::groups::kGroupUnknown);
8539 },
8540 LeAudioClient::Get()));
8541 SyncOnMainLoop();
8542
8543 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8544 }
8545
8546 /* When a certain context is unavailable and not supported we should stream
8547 * as UNSPECIFIED for the backwards compatibility.
8548 * Since UNSPECIFIED is available, put the UNSPECIFIED into the metadata instead
8549 * What we can do now is to keep streaming (and reconfigure if needed for the
8550 * use case).
8551 */
TEST_F(UnicastTest,UpdateNotSupportedContextTypeUnspecifiedAvailable)8552 TEST_F(UnicastTest, UpdateNotSupportedContextTypeUnspecifiedAvailable) {
8553 const RawAddress test_address0 = GetTestAddress(0);
8554 int group_id = bluetooth::groups::kGroupUnknown;
8555
8556 available_snk_context_types_ = (types::LeAudioContextType::RINGTONE |
8557 types::LeAudioContextType::CONVERSATIONAL |
8558 types::LeAudioContextType::UNSPECIFIED |
8559 types::LeAudioContextType::MEDIA)
8560 .value();
8561 supported_snk_context_types_ = available_snk_context_types_;
8562 available_src_context_types_ = available_snk_context_types_;
8563 supported_src_context_types_ = available_src_context_types_;
8564
8565 SetSampleDatabaseEarbudsValid(
8566 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
8567 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
8568 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
8569 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
8570 0 /*rank*/);
8571 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8572 OnConnectionState(ConnectionState::CONNECTED, test_address0))
8573 .Times(1);
8574 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8575 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
8576 .WillOnce(DoAll(SaveArg<1>(&group_id)));
8577
8578 ConnectLeAudio(test_address0);
8579 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
8580
8581 // Start streaming
8582 uint8_t cis_count_out = 1;
8583 uint8_t cis_count_in = 0;
8584
8585 LeAudioClient::Get()->SetInCall(true);
8586
8587 // Audio sessions are started only when device gets active
8588 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8589 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8590 LeAudioClient::Get()->GroupSetActive(group_id);
8591 SyncOnMainLoop();
8592
8593 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
8594 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8595 LocalAudioSourceResume();
8596 LocalAudioSinkResume();
8597
8598 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8599 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8600 SyncOnMainLoop();
8601
8602 // Verify Data transfer on one audio source cis
8603 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8604
8605 LeAudioClient::Get()->SetInCall(false);
8606 LocalAudioSinkSuspend();
8607
8608 /* We should use GAME configuration, but do not send the GAME context type, as
8609 * it is not available on the remote device.
8610 */
8611 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
8612 types::BidirectionalPair<types::AudioContexts> contexts = {
8613 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
8614 .source = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED)};
8615 EXPECT_CALL(mock_state_machine_,
8616 StartStream(_, types::LeAudioContextType::GAME, contexts, _))
8617 .Times(1);
8618 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN,
8619 false);
8620 SyncOnMainLoop();
8621 }
8622
8623 /* Some bidirectional scenarios are triggered by the local sink, local source
8624 * metadata or the In Call preference callback call. Since each call invalidates
8625 * previous context source, make sure that getting all of these in a sequence,
8626 * always results with one bidirectional context, so that the remote device
8627 * is not confused about our intentions.
8628 */
TEST_F(UnicastTest,UpdateMultipleBidirContextTypes)8629 TEST_F(UnicastTest, UpdateMultipleBidirContextTypes) {
8630 const RawAddress test_address0 = GetTestAddress(0);
8631 int group_id = bluetooth::groups::kGroupUnknown;
8632
8633 available_snk_context_types_ =
8634 (types::LeAudioContextType::CONVERSATIONAL |
8635 types::LeAudioContextType::GAME | types::LeAudioContextType::LIVE)
8636 .value();
8637 supported_snk_context_types_ =
8638 available_snk_context_types_ |
8639 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
8640 available_src_context_types_ = available_snk_context_types_;
8641 supported_src_context_types_ =
8642 available_src_context_types_ |
8643 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
8644
8645 SetSampleDatabaseEarbudsValid(
8646 1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
8647 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
8648 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
8649 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
8650 0 /*rank*/);
8651 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8652 OnConnectionState(ConnectionState::CONNECTED, test_address0))
8653 .Times(1);
8654 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8655 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
8656 .WillOnce(DoAll(SaveArg<1>(&group_id)));
8657
8658 ConnectLeAudio(test_address0);
8659 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
8660
8661 // Audio sessions are started only when device gets active
8662 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8663 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8664 LeAudioClient::Get()->GroupSetActive(group_id);
8665 SyncOnMainLoop();
8666
8667 // When the local audio sink resumes expect only LIVE context
8668 types::BidirectionalPair<types::AudioContexts> contexts = {
8669 .sink = types::AudioContexts(types::LeAudioContextType::LIVE),
8670 .source = types::AudioContexts(types::LeAudioContextType::LIVE)};
8671 EXPECT_CALL(
8672 mock_state_machine_,
8673 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE,
8674 contexts, _))
8675 .Times(1);
8676
8677 // 1) Start the recording. Sink resume will trigger the reconfiguration
8678 // ---------------------------------------------------------------------
8679 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
8680 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
8681 LocalAudioSinkResume();
8682
8683 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8684 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8685 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8686
8687 /* After the reconfiguration the local Audio Sink HAL has to resume again */
8688 LocalAudioSourceResume();
8689 LocalAudioSinkResume();
8690
8691 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8692 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8693 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8694
8695 // Verify Data transfer on one audio source and sink cis
8696 uint8_t cis_count_out = 1;
8697 uint8_t cis_count_in = 1;
8698 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8699
8700 // Stop
8701 StopStreaming(group_id);
8702 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8703
8704 // 2) Now set in call preference to get CONVERSATIONAL into the mix
8705 // -----------------------------------------------------------------
8706 LeAudioClient::Get()->SetInCall(true);
8707
8708 // Verify that we only got CONVERSATIONAL context and no LIVE
8709 contexts = {
8710 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
8711 .source =
8712 types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
8713 EXPECT_CALL(
8714 mock_state_machine_,
8715 StartStream(
8716 _, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
8717 contexts, _))
8718 .Times(1);
8719
8720 // Start with ringtone on local source
8721 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
8722 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
8723 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8724
8725 // Resume both directions
8726 LocalAudioSourceResume();
8727 LocalAudioSinkResume();
8728
8729 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8730 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8731 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8732
8733 // Verify Data transfer on one audio source cis
8734 cis_count_out = 1;
8735 cis_count_in = 1;
8736 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8737
8738 // 3) Disable call so we could go to GAME
8739 // ---------------------------------------
8740 LeAudioClient::Get()->SetInCall(false);
8741
8742 /* Start the game on local source - expect no previous sink (LIVE) metadata */
8743 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
8744 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::GAME),
8745 .source = types::AudioContexts(types::LeAudioContextType::GAME)};
8746 EXPECT_CALL(mock_state_machine_,
8747 StartStream(_, types::LeAudioContextType::GAME, contexts, _))
8748 .Times(1);
8749 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN,
8750 false);
8751
8752 /* If the above triggers reconfiguration, Audio Hal action is needed to
8753 * restart the stream.
8754 */
8755 LocalAudioSourceResume();
8756 LocalAudioSinkResume();
8757 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8758
8759 // 4) Stop streaming
8760 // ------------------
8761 StopStreaming(group_id);
8762 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8763
8764 // Release
8765 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
8766 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
8767 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
8768 do_in_main_thread(
8769 FROM_HERE, base::BindOnce(
8770 [](LeAudioClient* client) {
8771 client->GroupSetActive(bluetooth::groups::kGroupUnknown);
8772 },
8773 LeAudioClient::Get()));
8774 SyncOnMainLoop();
8775 }
8776
TEST_F(UnicastTest,UpdateDisableLocalAudioSinkOnGame)8777 TEST_F(UnicastTest, UpdateDisableLocalAudioSinkOnGame) {
8778 const RawAddress test_address0 = GetTestAddress(0);
8779 int group_id = bluetooth::groups::kGroupUnknown;
8780
8781 available_snk_context_types_ =
8782 (types::LeAudioContextType::CONVERSATIONAL |
8783 types::LeAudioContextType::GAME | types::LeAudioContextType::LIVE)
8784 .value();
8785 supported_snk_context_types_ =
8786 available_snk_context_types_ |
8787 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
8788 available_src_context_types_ = available_snk_context_types_;
8789 supported_src_context_types_ =
8790 available_src_context_types_ |
8791 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
8792
8793 SetSampleDatabaseEarbudsValid(
8794 1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
8795 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
8796 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
8797 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
8798 0 /*rank*/);
8799 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8800 OnConnectionState(ConnectionState::CONNECTED, test_address0))
8801 .Times(1);
8802 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8803 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
8804 .WillOnce(DoAll(SaveArg<1>(&group_id)));
8805
8806 ConnectLeAudio(test_address0);
8807 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
8808
8809 // Audio sessions are started only when device gets active
8810 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8811 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8812 LeAudioClient::Get()->GroupSetActive(group_id);
8813 SyncOnMainLoop();
8814
8815 // Start GAME stream
8816 types::BidirectionalPair<types::AudioContexts> contexts = {
8817 .sink = types::AudioContexts(types::LeAudioContextType::GAME),
8818 .source = types::AudioContexts(types::LeAudioContextType::GAME)};
8819 EXPECT_CALL(
8820 mock_state_machine_,
8821 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::GAME,
8822 contexts, _))
8823 .Times(1);
8824
8825 // 1) Start the recording. Sink resume will trigger the reconfiguration
8826 // ---------------------------------------------------------------------
8827 StartStreaming(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_MUSIC, group_id,
8828 AUDIO_SOURCE_MIC);
8829
8830 SyncOnMainLoop();
8831
8832 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8833 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8834 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8835
8836 // Verify Data transfer on one audio source and sink cis
8837 uint8_t cis_count_out = 1;
8838 uint8_t cis_count_in = 1;
8839 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8840
8841 SyncOnMainLoop();
8842
8843 // 2) Now Lets suspend MIC and do not expect reconfiguration
8844 // -----------------------------------------------------------------
8845
8846 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
8847 LocalAudioSinkSuspend();
8848 // simulate suspend timeout passed, alarm executing
8849 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8850 SyncOnMainLoop();
8851 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8852 }
8853
8854 /* Start music when in a call, end the call, continue with music only */
TEST_F(UnicastTest,MusicDuringCallContextTypes)8855 TEST_F(UnicastTest, MusicDuringCallContextTypes) {
8856 const RawAddress test_address0 = GetTestAddress(0);
8857 int group_id = bluetooth::groups::kGroupUnknown;
8858
8859 available_snk_context_types_ =
8860 (types::LeAudioContextType::CONVERSATIONAL |
8861 types::LeAudioContextType::RINGTONE | types::LeAudioContextType::GAME |
8862 types::LeAudioContextType::MEDIA | types::LeAudioContextType::LIVE)
8863 .value();
8864 supported_snk_context_types_ =
8865 available_snk_context_types_ |
8866 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
8867 available_src_context_types_ = available_snk_context_types_;
8868 supported_src_context_types_ =
8869 available_src_context_types_ |
8870 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
8871
8872 SetSampleDatabaseEarbudsValid(
8873 1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
8874 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
8875 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
8876 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
8877 0 /*rank*/);
8878 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8879 OnConnectionState(ConnectionState::CONNECTED, test_address0))
8880 .Times(1);
8881 EXPECT_CALL(mock_audio_hal_client_callbacks_,
8882 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
8883 .WillOnce(DoAll(SaveArg<1>(&group_id)));
8884
8885 ConnectLeAudio(test_address0);
8886 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
8887
8888 // Audio sessions are started only when device gets active
8889 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8890 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8891 LeAudioClient::Get()->GroupSetActive(group_id);
8892 SyncOnMainLoop();
8893
8894 // 1) Start with the call first
8895 // -----------------------------
8896 // CONVERSATIONAL is from In Call preference, and RINGTONE is from metadata
8897 LeAudioClient::Get()->SetInCall(true);
8898 types::BidirectionalPair<types::AudioContexts> contexts = {
8899 .sink = types::AudioContexts(types::LeAudioContextType::RINGTONE |
8900 types::LeAudioContextType::CONVERSATIONAL),
8901 .source =
8902 types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
8903 EXPECT_CALL(
8904 mock_state_machine_,
8905 StartStream(
8906 _, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
8907 contexts, _))
8908 .Times(1);
8909 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
8910 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8911 LocalAudioSourceResume();
8912 LocalAudioSinkResume();
8913
8914 // Verify
8915 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8916 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8917 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8918
8919 // Verify Data transfer
8920 uint8_t cis_count_out = 1;
8921 uint8_t cis_count_in = 1;
8922 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8923
8924 // 2) Start MEDIA during the call, expect MEDIA only on the remote sink
8925 contexts = {
8926 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL |
8927 types::LeAudioContextType::MEDIA),
8928 .source =
8929 types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
8930 EXPECT_CALL(
8931 mock_state_machine_,
8932 StartStream(
8933 _, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
8934 contexts, _))
8935 .Times(1);
8936 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, false);
8937 SyncOnMainLoop();
8938
8939 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8940 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8941 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8942
8943 // 2) Disable In Call preference but do not suspend the local sink
8944 // We should stay in CONVERSATIONAL until the local sink suspends
8945 // ---------------------------------------
8946 LeAudioClient::Get()->SetInCall(false);
8947
8948 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
8949 contexts = {
8950 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA |
8951 types::LeAudioContextType::CONVERSATIONAL),
8952 .source =
8953 types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
8954 EXPECT_CALL(
8955 mock_state_machine_,
8956 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, contexts, _))
8957 .Times(1);
8958 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC,
8959 /*reconfigure=*/false);
8960 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8961 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8962 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8963
8964 // 3) Disable call so we could go back to MEDIA
8965 // ---------------------------------------
8966 // Suspend should stop the stream
8967 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
8968 LocalAudioSourceSuspend();
8969 LocalAudioSinkSuspend();
8970 // simulate suspend timeout passed, alarm executing
8971 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8972 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8973
8974 // Restart the stream with MEDIA
8975 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
8976 .source = types::AudioContexts()};
8977 EXPECT_CALL(mock_state_machine_,
8978 StartStream(_, types::LeAudioContextType::MEDIA, contexts, _))
8979 .Times(1);
8980 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC,
8981 /*reconfigure=*/false);
8982 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8983 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8984
8985 /* The source needs to resume to reconfigure to MEDIA */
8986 LocalAudioSourceResume(/*expect_confirm=*/false);
8987 LocalAudioSourceResume(/*expect_confirm=*/true);
8988 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8989 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8990 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8991
8992 // 4) Stop streaming
8993 // ------------------
8994 StopStreaming(group_id);
8995 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8996
8997 // Release
8998 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
8999 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
9000 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
9001 do_in_main_thread(
9002 FROM_HERE, base::BindOnce(
9003 [](LeAudioClient* client) {
9004 client->GroupSetActive(bluetooth::groups::kGroupUnknown);
9005 },
9006 LeAudioClient::Get()));
9007 SyncOnMainLoop();
9008 }
9009
9010 /* When a certain context is unavailable but supported we should not stream that
9011 * context - either stop the stream or eliminate this strim from the mix
9012 * This could be na IOP issue so continue streaming (and reconfigure if needed
9013 * for that use case).
9014 * Since the unavailable context is supported, do not put this context into
9015 * the metadata, and do not replace it with UNSPECIFIED.
9016 */
TEST_F(UnicastTest,StartNotAvailableSupportedContextType)9017 TEST_F(UnicastTest, StartNotAvailableSupportedContextType) {
9018 const RawAddress test_address0 = GetTestAddress(0);
9019 int group_id = bluetooth::groups::kGroupUnknown;
9020
9021 // EMERGENCYALARM is not available, but supported
9022 available_snk_context_types_ = (types::LeAudioContextType::RINGTONE |
9023 types::LeAudioContextType::CONVERSATIONAL |
9024 types::LeAudioContextType::UNSPECIFIED |
9025 types::LeAudioContextType::MEDIA)
9026 .value();
9027 available_src_context_types_ = available_snk_context_types_;
9028 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
9029 supported_src_context_types_ = (types::kLeAudioContextAllRemoteSource |
9030 types::LeAudioContextType::UNSPECIFIED)
9031 .value();
9032
9033 SetSampleDatabaseEarbudsValid(
9034 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9035 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9036 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
9037 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9038 0 /*rank*/);
9039 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9040 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9041 .Times(1);
9042 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9043 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9044 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9045
9046 ConnectLeAudio(test_address0);
9047 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9048
9049 // Expect configuring to (or staying with) the right configuration but the
9050 // metadata should not get the EMERGENCYALARM context, nor the UNSPECIFIED
9051 // Since the initial config is UNSPECIFIED, then even for sonification events
9052 // we should reconfigure to less generic EMERGENCYALARM scenario
9053 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9054 types::BidirectionalPair<types::AudioContexts> metadata = {
9055 .sink = types::AudioContexts(), .source = types::AudioContexts()};
9056 EXPECT_CALL(
9057 mock_state_machine_,
9058 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
9059 .Times(0);
9060
9061 LeAudioClient::Get()->GroupSetActive(group_id);
9062 SyncOnMainLoop();
9063
9064 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id,
9065 AUDIO_SOURCE_INVALID, false, false);
9066
9067 SyncOnMainLoop();
9068 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9069 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9070 }
9071
9072 /* When a certain context is unavailable and not supported and the UNSPECIFIED
9073 * is not available we should stop the stream.
9074 * For now, stream will not be started in such a case.
9075 * In future we should be able to eliminate this context from the track mix.
9076 */
TEST_F(UnicastTest,StartNotAvailableUnsupportedContextTypeUnspecifiedUnavail)9077 TEST_F(UnicastTest, StartNotAvailableUnsupportedContextTypeUnspecifiedUnavail) {
9078 const RawAddress test_address0 = GetTestAddress(0);
9079 int group_id = bluetooth::groups::kGroupUnknown;
9080
9081 // EMERGENCYALARM is not available, nor supported
9082 available_snk_context_types_ = (types::LeAudioContextType::RINGTONE |
9083 types::LeAudioContextType::CONVERSATIONAL |
9084 types::LeAudioContextType::MEDIA)
9085 .value();
9086 available_src_context_types_ = available_snk_context_types_;
9087 supported_snk_context_types_ =
9088 (available_snk_context_types_ | types::LeAudioContextType::UNSPECIFIED)
9089 .value();
9090 supported_src_context_types_ =
9091 (available_src_context_types_ | types::LeAudioContextType::UNSPECIFIED)
9092 .value();
9093
9094 SetSampleDatabaseEarbudsValid(
9095 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9096 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9097 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
9098 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9099 0 /*rank*/);
9100 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9101 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9102 .Times(1);
9103 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9104 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9105 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9106
9107 ConnectLeAudio(test_address0);
9108 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9109
9110 // Expect configuring to the default config since the EMERGENCYALARM is
9111 // not on the list of supported contexts and UNSPECIFIED should not be
9112 // in the metadata as it is unavailable.
9113 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9114 types::BidirectionalPair<types::AudioContexts> metadata = {
9115 .sink = types::AudioContexts(), .source = types::AudioContexts()};
9116 EXPECT_CALL(
9117 mock_state_machine_,
9118 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
9119 .Times(0);
9120
9121 LeAudioClient::Get()->GroupSetActive(group_id);
9122 SyncOnMainLoop();
9123
9124 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id,
9125 AUDIO_SOURCE_INVALID, false, false);
9126
9127 SyncOnMainLoop();
9128 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9129 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9130 }
9131
9132 /* This test verifies if we use UNSPCIFIED context when another context is
9133 * unavailable and not supported but UNSPCIFIED is in available audio contexts.
9134 */
TEST_F(UnicastTest,StartNotAvailableUnsupportedContextTypeUnspecifiedAvail)9135 TEST_F(UnicastTest, StartNotAvailableUnsupportedContextTypeUnspecifiedAvail) {
9136 const RawAddress test_address0 = GetTestAddress(0);
9137 int group_id = bluetooth::groups::kGroupUnknown;
9138
9139 // EMERGENCYALARM is not available, nor supported
9140 available_snk_context_types_ = (types::LeAudioContextType::RINGTONE |
9141 types::LeAudioContextType::CONVERSATIONAL |
9142 types::LeAudioContextType::UNSPECIFIED |
9143 types::LeAudioContextType::MEDIA)
9144 .value();
9145 available_src_context_types_ = available_snk_context_types_;
9146 supported_snk_context_types_ = available_snk_context_types_;
9147 supported_src_context_types_ = available_src_context_types_;
9148
9149 SetSampleDatabaseEarbudsValid(
9150 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9151 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9152 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
9153 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9154 0 /*rank*/);
9155 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9156 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9157 .Times(1);
9158 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9159 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9160 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9161
9162 ConnectLeAudio(test_address0);
9163 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9164
9165 // Expect configuring to the default config since the EMERGENCYALARM is
9166 // not on the list of supported contexts and UNSPECIFIED will be used in
9167 // the metadata.
9168 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9169 types::BidirectionalPair<types::AudioContexts> metadata = {
9170 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
9171 .source = types::AudioContexts()};
9172 EXPECT_CALL(
9173 mock_state_machine_,
9174 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
9175 .Times(1);
9176
9177 LeAudioClient::Get()->GroupSetActive(group_id);
9178 SyncOnMainLoop();
9179
9180 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
9181
9182 SyncOnMainLoop();
9183 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9184 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9185
9186 // Verify Data transfer on one audio source cis
9187 uint8_t cis_count_out = 1;
9188 uint8_t cis_count_in = 0;
9189 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9190 }
9191
TEST_F(UnicastTest,NotifyAboutGroupTunrnedIdleEnabled)9192 TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleEnabled) {
9193 const RawAddress test_address0 = GetTestAddress(0);
9194 int group_id = bluetooth::groups::kGroupUnknown;
9195
9196 osi_property_set_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall, true);
9197
9198 SetSampleDatabaseEarbudsValid(
9199 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9200 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9201 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
9202 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9203 0 /*rank*/);
9204 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9205 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9206 .Times(1);
9207 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9208 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9209 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9210
9211 ConnectLeAudio(test_address0);
9212 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9213
9214 // Start streaming
9215 uint8_t cis_count_out = 1;
9216 uint8_t cis_count_in = 0;
9217
9218 LeAudioClient::Get()->SetInCall(true);
9219
9220 // Audio sessions are started only when device gets active
9221 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9222 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9223 LeAudioClient::Get()->GroupSetActive(group_id);
9224 SyncOnMainLoop();
9225
9226 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
9227 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
9228
9229 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9230 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9231 SyncOnMainLoop();
9232
9233 // Verify Data transfer on one audio source cis
9234 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9235
9236 // Release
9237
9238 /* To be called twice
9239 * 1. GroupStatus::INACTIVE
9240 * 2. GroupStatus::TURNED_IDLE_DURING_CALL
9241 */
9242 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, _))
9243 .Times(2);
9244
9245 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
9246 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
9247 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
9248
9249 do_in_main_thread(
9250 FROM_HERE, base::BindOnce(
9251 [](LeAudioClient* client) {
9252 client->GroupSetActive(bluetooth::groups::kGroupUnknown);
9253 },
9254 LeAudioClient::Get()));
9255
9256 SyncOnMainLoop();
9257 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9258
9259 LeAudioClient::Get()->SetInCall(false);
9260 osi_property_set_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall,
9261 false);
9262 }
9263
TEST_F(UnicastTest,NotifyAboutGroupTunrnedIdleDisabled)9264 TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleDisabled) {
9265 const RawAddress test_address0 = GetTestAddress(0);
9266 int group_id = bluetooth::groups::kGroupUnknown;
9267
9268 SetSampleDatabaseEarbudsValid(
9269 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9270 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9271 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
9272 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9273 0 /*rank*/);
9274 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9275 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9276 .Times(1);
9277 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9278 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9279 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9280
9281 ConnectLeAudio(test_address0);
9282 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9283
9284 // Start streaming
9285 uint8_t cis_count_out = 1;
9286 uint8_t cis_count_in = 0;
9287
9288 LeAudioClient::Get()->SetInCall(true);
9289
9290 // Audio sessions are started only when device gets active
9291 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9292 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9293 LeAudioClient::Get()->GroupSetActive(group_id);
9294 SyncOnMainLoop();
9295
9296 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
9297 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
9298
9299 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9300 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9301 SyncOnMainLoop();
9302
9303 // Verify Data transfer on one audio source cis
9304 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9305
9306 // Release
9307
9308 /* To be called once only
9309 * 1. GroupStatus::INACTIVE
9310 */
9311 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, _))
9312 .Times(1);
9313
9314 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
9315 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
9316 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
9317
9318 do_in_main_thread(
9319 FROM_HERE, base::BindOnce(
9320 [](LeAudioClient* client) {
9321 client->GroupSetActive(bluetooth::groups::kGroupUnknown);
9322 },
9323 LeAudioClient::Get()));
9324
9325 SyncOnMainLoop();
9326 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9327
9328 LeAudioClient::Get()->SetInCall(false);
9329 }
9330
TEST_F(UnicastTest,HandleDatabaseOutOfSync)9331 TEST_F(UnicastTest, HandleDatabaseOutOfSync) {
9332 const RawAddress test_address0 = GetTestAddress(0);
9333 int group_id = bluetooth::groups::kGroupUnknown;
9334
9335 SetSampleDatabaseEarbudsValid(
9336 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9337 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9338 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
9339 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9340 0 /*rank*/);
9341 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9342 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9343 .Times(1);
9344 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9345 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9346 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9347
9348 ConnectLeAudio(test_address0);
9349 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9350
9351 SyncOnMainLoop();
9352 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9353
9354 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9355 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
9356 .Times(1);
9357 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
9358 SyncOnMainLoop();
9359 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9360 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9361
9362 /* Simulate DATABASE OUT OF SYNC */
9363 ccc_stored_byte_val_ = 0x01;
9364 gatt_read_ctp_ccc_status_ = GATT_DATABASE_OUT_OF_SYNC;
9365
9366 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)).Times(0);
9367 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
9368 .WillByDefault(Return());
9369 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _));
9370
9371 InjectConnectedEvent(test_address0, 1);
9372 SyncOnMainLoop();
9373 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9374 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
9375 }
9376
TEST_F(UnicastTest,TestRemoteDeviceKeepCccValues)9377 TEST_F(UnicastTest, TestRemoteDeviceKeepCccValues) {
9378 const RawAddress test_address0 = GetTestAddress(0);
9379 int group_id = bluetooth::groups::kGroupUnknown;
9380
9381 SetSampleDatabaseEarbudsValid(
9382 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9383 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9384 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
9385 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9386 0 /*rank*/);
9387 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9388 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9389 .Times(1);
9390 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9391 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9392 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9393
9394 ConnectLeAudio(test_address0);
9395 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9396
9397 SyncOnMainLoop();
9398 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9399
9400 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9401 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
9402 .Times(1);
9403 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
9404 SyncOnMainLoop();
9405 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9406 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
9407
9408 /* Simulate remote cache is good */
9409 ccc_stored_byte_val_ = 0x01;
9410
9411 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)).Times(0);
9412 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9413 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9414 .Times(1);
9415
9416 InjectConnectedEvent(test_address0, 1);
9417 SyncOnMainLoop();
9418 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
9419 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9420 }
9421
TEST_F(UnicastTest,TestRemoteDeviceForgetsCccValues)9422 TEST_F(UnicastTest, TestRemoteDeviceForgetsCccValues) {
9423 const RawAddress test_address0 = GetTestAddress(0);
9424 int group_id = bluetooth::groups::kGroupUnknown;
9425
9426 SetSampleDatabaseEarbudsValid(
9427 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9428 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9429 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
9430 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9431 0 /*rank*/);
9432 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9433 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9434 .Times(1);
9435 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9436 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9437 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9438
9439 ConnectLeAudio(test_address0);
9440 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9441
9442 SyncOnMainLoop();
9443 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9444
9445 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9446 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
9447 .Times(1);
9448 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
9449 SyncOnMainLoop();
9450 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9451 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
9452
9453 /* Simulate remote cache is broken */
9454 ccc_stored_byte_val_ = 0;
9455 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _))
9456 .Times(AtLeast(1));
9457 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9458 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9459 .Times(1);
9460
9461 InjectConnectedEvent(test_address0, 1);
9462 SyncOnMainLoop();
9463 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
9464 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9465 }
9466
TEST_F(UnicastTest,SpeakerStreamingTimeout)9467 TEST_F(UnicastTest, SpeakerStreamingTimeout) {
9468 const RawAddress test_address0 = GetTestAddress(0);
9469 int group_id = bluetooth::groups::kGroupUnknown;
9470
9471 SetSampleDatabaseEarbudsValid(
9472 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
9473 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
9474 default_channel_cnt, 0x0004,
9475 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
9476 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
9477 0 /*rank*/);
9478 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9479 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9480 .Times(1);
9481 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9482 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
9483 .WillOnce(DoAll(SaveArg<1>(&group_id)));
9484
9485 ConnectLeAudio(test_address0);
9486 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
9487
9488 // Start streaming
9489 uint8_t cis_count_out = 1;
9490 uint8_t cis_count_in = 0;
9491
9492 // Audio sessions are started only when device gets active
9493 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9494 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9495 LeAudioClient::Get()->GroupSetActive(group_id);
9496 SyncOnMainLoop();
9497
9498 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9499
9500 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9501 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9502 SyncOnMainLoop();
9503
9504 // Verify Data transfer on one audio source cis
9505 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9506
9507 // Do not accept direct connect, but expect it to arrive.
9508 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
9509 .WillByDefault(Return());
9510
9511 state_machine_callbacks_->OnStateTransitionTimeout(group_id);
9512 SyncOnMainLoop();
9513
9514 /* No assigned cises should remain when transition remains in IDLE state */
9515 ASSERT_NE(0lu, streaming_groups.count(group_id));
9516 auto group = streaming_groups.at(group_id);
9517 ASSERT_EQ(0, static_cast<int>(group->cig.cises.size()));
9518 }
9519
TEST_F(UnicastTest,AddMemberToAllowListWhenOneDeviceConnected)9520 TEST_F(UnicastTest, AddMemberToAllowListWhenOneDeviceConnected) {
9521 uint8_t group_size = 2;
9522 int group_id = 2;
9523 int conn_id_dev_0 = 1;
9524 int conn_id_dev_1 = 2;
9525
9526 /*Scenario to test
9527 * 1. Connect Device A and disconnect
9528 * 2. Connect Device B
9529 * 3. verify Device B is in the allow list with direct connect.
9530 */
9531 // Report working CSIS
9532 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
9533 .WillByDefault(Return(true));
9534
9535 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9536 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
9537
9538 // First earbud
9539 const RawAddress test_address0 = GetTestAddress(0);
9540 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
9541 .Times(1);
9542
9543 ConnectCsisDevice(test_address0, conn_id_dev_0,
9544 codec_spec_conf::kLeAudioLocationFrontLeft,
9545 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
9546 group_id, 1 /* rank*/);
9547
9548 SyncOnMainLoop();
9549
9550 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _))
9551 .Times(1);
9552 EXPECT_CALL(mock_gatt_interface_,
9553 Open(gatt_if, test_address0,
9554 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
9555 .Times(1);
9556
9557 InjectDisconnectedEvent(conn_id_dev_0);
9558
9559 SyncOnMainLoop();
9560 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9561
9562 // Second earbud
9563 const RawAddress test_address1 = GetTestAddress(1);
9564 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
9565 .Times(1);
9566
9567 /* Do not connect first device but expect Open will arrive.*/
9568 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
9569 .Times(1);
9570 EXPECT_CALL(mock_gatt_interface_,
9571 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
9572 .Times(1);
9573 ON_CALL(mock_gatt_interface_,
9574 Open(_, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
9575 .WillByDefault(Return());
9576
9577 ConnectCsisDevice(test_address1, conn_id_dev_1,
9578 codec_spec_conf::kLeAudioLocationFrontRight,
9579 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
9580 group_id, 2 /* rank*/, true /*connect_through_csis*/);
9581
9582 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9583 }
9584
TEST_F(UnicastTest,ResetToDefaultReconnectionMode)9585 TEST_F(UnicastTest, ResetToDefaultReconnectionMode) {
9586 uint8_t group_size = 2;
9587 int group_id = 2;
9588 int conn_id_dev_0 = 1;
9589 int conn_id_dev_1 = 2;
9590
9591 /*Scenario to test
9592 * 1. Connect Device A and disconnect
9593 * 2. Connect Device B
9594 * 3. verify Device B is in the allow list.
9595 * 4. Disconnect B device
9596 * 5, Verify A and B device are back in targeted announcement reconnection
9597 * mode
9598 */
9599 // Report working CSIS
9600 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
9601 .WillByDefault(Return(true));
9602
9603 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9604 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
9605
9606 // First earbud
9607 const RawAddress test_address0 = GetTestAddress(0);
9608 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
9609 .Times(1);
9610
9611 ConnectCsisDevice(test_address0, conn_id_dev_0,
9612 codec_spec_conf::kLeAudioLocationFrontLeft,
9613 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
9614 group_id, 1 /* rank*/);
9615
9616 SyncOnMainLoop();
9617
9618 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _))
9619 .Times(1);
9620 EXPECT_CALL(mock_gatt_interface_,
9621 Open(gatt_if, test_address0,
9622 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
9623 .Times(1);
9624
9625 InjectDisconnectedEvent(conn_id_dev_0);
9626
9627 SyncOnMainLoop();
9628 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9629
9630 // Second earbud
9631 const RawAddress test_address1 = GetTestAddress(1);
9632 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
9633 .Times(1);
9634
9635 /* Verify first earbud will start doing direct connect first */
9636 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
9637 .Times(1);
9638 ON_CALL(mock_gatt_interface_,
9639 Open(_, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
9640 .WillByDefault(Return());
9641 EXPECT_CALL(mock_gatt_interface_,
9642 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
9643 .Times(1);
9644
9645 ConnectCsisDevice(test_address1, conn_id_dev_1,
9646 codec_spec_conf::kLeAudioLocationFrontRight,
9647 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
9648 group_id, 2 /* rank*/, true /*connect_through_csis*/);
9649
9650 SyncOnMainLoop();
9651 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9652
9653 // Disconnect Device B, expect default reconnection mode for Device A.
9654 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
9655 .Times(1);
9656 EXPECT_CALL(mock_gatt_interface_,
9657 Open(gatt_if, test_address0,
9658 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
9659 .Times(1);
9660 EXPECT_CALL(mock_gatt_interface_,
9661 Open(gatt_if, test_address1,
9662 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
9663 .Times(1);
9664 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address1, false))
9665 .Times(1);
9666
9667 InjectDisconnectedEvent(conn_id_dev_1, GATT_CONN_TERMINATE_PEER_USER);
9668 SyncOnMainLoop();
9669
9670 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9671 }
9672
TEST_F(UnicastTest,DisconnectAclBeforeGettingReadResponses)9673 TEST_F(UnicastTest, DisconnectAclBeforeGettingReadResponses) {
9674 uint8_t group_size = 2;
9675 int group_id = 2;
9676
9677 // Report working CSIS
9678 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
9679 .WillByDefault(Return(true));
9680
9681 const RawAddress test_address0 = GetTestAddress(0);
9682 const RawAddress test_address1 = GetTestAddress(1);
9683
9684 /* Due to imitated problems with GATT read operations (status != GATT_SUCCESS)
9685 * a CONNECTED state should not be propagated together with audio location
9686 */
9687 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9688 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9689 .Times(0);
9690 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9691 OnSinkAudioLocationAvailable(
9692 test_address0, codec_spec_conf::kLeAudioLocationFrontLeft))
9693 .Times(0);
9694
9695 // First earbud initial connection
9696 SetSampleDatabaseEarbudsValid(1 /* conn_id */, test_address0,
9697 codec_spec_conf::kLeAudioLocationFrontLeft,
9698 codec_spec_conf::kLeAudioLocationFrontLeft,
9699 default_channel_cnt, default_channel_cnt,
9700 0x0004, /* source sample freq 16khz */
9701 true, /*add_csis*/
9702 true, /*add_cas*/
9703 true, /*add_pacs*/
9704 true, /*add_ascs*/
9705 group_size, 1 /* rank */, GATT_INTERNAL_ERROR);
9706 groups[test_address0] = group_id;
9707 // by default indicate link as encrypted
9708 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
9709 .WillByDefault(DoAll(Return(true)));
9710
9711 EXPECT_CALL(mock_gatt_interface_,
9712 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
9713 .Times(1);
9714 /* When connected it will got to TA */
9715 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _))
9716 .Times(1);
9717 EXPECT_CALL(mock_gatt_interface_,
9718 Open(gatt_if, test_address0,
9719 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
9720 .Times(1);
9721
9722 do_in_main_thread(
9723 FROM_HERE,
9724 base::BindOnce(&LeAudioClient::Connect,
9725 base::Unretained(LeAudioClient::Get()), test_address0));
9726
9727 SyncOnMainLoop();
9728 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
9729 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9730 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9731 InjectGroupDeviceAdded(test_address0, group_id);
9732
9733 // Second earbud initial connection
9734 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9735 OnSinkAudioLocationAvailable(
9736 test_address1, codec_spec_conf::kLeAudioLocationFrontRight))
9737 .Times(1);
9738
9739 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
9740 .Times(1);
9741 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
9742 codec_spec_conf::kLeAudioLocationFrontRight,
9743 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
9744 group_id, 2 /* rank*/, true /*connect_through_csis*/);
9745
9746 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
9747
9748 /* for Target announcements AutoConnect is always there, until
9749 * device is removed
9750 */
9751 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false))
9752 .Times(0);
9753 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
9754 .Times(0);
9755
9756 // Verify grouping information
9757 std::vector<RawAddress> devs =
9758 LeAudioClient::Get()->GetGroupDevices(group_id);
9759 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
9760 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
9761
9762 /* Remove default action on the direct connect */
9763 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
9764 .WillByDefault(Return());
9765
9766 /* Initiate disconnection with timeout reason, the possible reason why GATT
9767 * read attribute operation may be not handled
9768 */
9769 InjectDisconnectedEvent(1, GATT_CONN_TIMEOUT);
9770 SyncOnMainLoop();
9771
9772 /* After reconnection a sink audio location callback with connection state
9773 * should be propagated.
9774 */
9775 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9776 OnConnectionState(ConnectionState::CONNECTED, test_address0))
9777 .Times(1);
9778 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9779 OnSinkAudioLocationAvailable(
9780 test_address0, codec_spec_conf::kLeAudioLocationFrontLeft))
9781 .Times(1);
9782
9783 /* Prepare valid GATT status responsing attributes */
9784 SetSampleDatabaseEarbudsValid(1 /* conn_id */, test_address0,
9785 codec_spec_conf::kLeAudioLocationFrontLeft,
9786 codec_spec_conf::kLeAudioLocationFrontLeft,
9787 default_channel_cnt, default_channel_cnt,
9788 0x0004, /* source sample freq 16khz */
9789 true, /*add_csis*/
9790 true, /*add_cas*/
9791 true, /*add_pacs*/
9792 true, /*add_ascs*/
9793 group_size, 1 /* rank */);
9794
9795 /* For background connect, test needs to Inject Connected Event */
9796 InjectConnectedEvent(test_address0, 1);
9797 SyncOnMainLoop();
9798 }
9799
TEST_F_WITH_FLAGS(UnicastTest,GroupStreamStatus,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_callback_on_group_stream_status)))9800 TEST_F_WITH_FLAGS(UnicastTest, GroupStreamStatus,
9801 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
9802 TEST_BT, leaudio_callback_on_group_stream_status))) {
9803 int group_id = bluetooth::groups::kGroupUnknown;
9804
9805 InSequence s;
9806
9807 /* Check if all states are properly notified */
9808 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9809 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
9810 .Times(1);
9811 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
9812
9813 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9814 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
9815 .Times(1);
9816 state_machine_callbacks_->StatusReportCb(group_id,
9817 GroupStreamStatus::STREAMING);
9818
9819 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9820 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
9821 .Times(1);
9822 state_machine_callbacks_->StatusReportCb(group_id,
9823 GroupStreamStatus::RELEASING);
9824
9825 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9826 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
9827 .Times(1);
9828 state_machine_callbacks_->StatusReportCb(group_id,
9829 GroupStreamStatus::STREAMING);
9830
9831 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9832 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
9833 .Times(1);
9834 state_machine_callbacks_->StatusReportCb(group_id,
9835 GroupStreamStatus::SUSPENDING);
9836
9837 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9838 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
9839 .Times(1);
9840 state_machine_callbacks_->StatusReportCb(group_id,
9841 GroupStreamStatus::STREAMING);
9842
9843 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9844 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
9845 .Times(1);
9846 state_machine_callbacks_->StatusReportCb(group_id,
9847 GroupStreamStatus::SUSPENDED);
9848
9849 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9850 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
9851 .Times(1);
9852 state_machine_callbacks_->StatusReportCb(group_id,
9853 GroupStreamStatus::STREAMING);
9854
9855 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9856 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
9857 .Times(1);
9858 state_machine_callbacks_->StatusReportCb(
9859 group_id, GroupStreamStatus::CONFIGURED_AUTONOMOUS);
9860
9861 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9862 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
9863 .Times(1);
9864 state_machine_callbacks_->StatusReportCb(group_id,
9865 GroupStreamStatus::STREAMING);
9866
9867 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9868 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
9869 .Times(1);
9870 state_machine_callbacks_->StatusReportCb(
9871 group_id, GroupStreamStatus::CONFIGURED_BY_USER);
9872
9873 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9874 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
9875 .Times(1);
9876 state_machine_callbacks_->StatusReportCb(group_id,
9877 GroupStreamStatus::STREAMING);
9878
9879 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9880 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
9881 .Times(1);
9882 state_machine_callbacks_->StatusReportCb(group_id,
9883 GroupStreamStatus::DESTROYED);
9884
9885 /* Check if there are no resending of the same state */
9886 state_machine_callbacks_->StatusReportCb(group_id,
9887 GroupStreamStatus::RELEASING);
9888 state_machine_callbacks_->StatusReportCb(group_id,
9889 GroupStreamStatus::SUSPENDING);
9890 state_machine_callbacks_->StatusReportCb(group_id,
9891 GroupStreamStatus::SUSPENDED);
9892 state_machine_callbacks_->StatusReportCb(
9893 group_id, GroupStreamStatus::CONFIGURED_AUTONOMOUS);
9894 state_machine_callbacks_->StatusReportCb(
9895 group_id, GroupStreamStatus::CONFIGURED_BY_USER);
9896 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
9897
9898 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9899 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
9900 .Times(1);
9901 state_machine_callbacks_->StatusReportCb(group_id,
9902 GroupStreamStatus::STREAMING);
9903 state_machine_callbacks_->StatusReportCb(group_id,
9904 GroupStreamStatus::STREAMING);
9905 }
9906
TEST_F_WITH_FLAGS(UnicastTest,GroupStreamStatusManyGroups,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_callback_on_group_stream_status)))9907 TEST_F_WITH_FLAGS(UnicastTest, GroupStreamStatusManyGroups,
9908 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
9909 TEST_BT, leaudio_callback_on_group_stream_status))) {
9910 uint8_t group_size = 2;
9911 int group_id_1 = 1;
9912 int group_id_2 = 2;
9913
9914 // Report working CSIS
9915 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
9916 .WillByDefault(Return(true));
9917
9918 ON_CALL(mock_csis_client_module_, GetDesiredSize(_))
9919 .WillByDefault(Return(group_size));
9920
9921 // First group - First earbud
9922 const RawAddress test_address0 = GetTestAddress(0);
9923 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
9924 .Times(1);
9925 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
9926 codec_spec_conf::kLeAudioLocationFrontLeft,
9927 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
9928 group_id_1, 1 /* rank*/);
9929
9930 // First group - Second earbud
9931 const RawAddress test_address1 = GetTestAddress(1);
9932 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
9933 .Times(1);
9934 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
9935 codec_spec_conf::kLeAudioLocationFrontRight,
9936 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
9937 group_id_1, 2 /* rank*/, true /*connect_through_csis*/);
9938
9939 // Second group - First earbud
9940 const RawAddress test_address2 = GetTestAddress(2);
9941 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address2, true))
9942 .Times(1);
9943 ConnectCsisDevice(test_address2, 3 /*conn_id*/,
9944 codec_spec_conf::kLeAudioLocationFrontLeft,
9945 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
9946 group_id_2, 1 /* rank*/);
9947
9948 // Second group - Second earbud
9949 const RawAddress test_address3 = GetTestAddress(3);
9950 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address3, true))
9951 .Times(1);
9952 ConnectCsisDevice(test_address3, 4 /*conn_id*/,
9953 codec_spec_conf::kLeAudioLocationFrontRight,
9954 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
9955 group_id_2, 2 /* rank*/, true /*connect_through_csis*/);
9956
9957 InSequence s;
9958
9959 // Group 1 IDLE
9960 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9961 OnGroupStreamStatus(group_id_1, GroupStreamStatus::IDLE))
9962 .Times(1);
9963 state_machine_callbacks_->StatusReportCb(group_id_1, GroupStreamStatus::IDLE);
9964
9965 // Group 2 IDLE
9966 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9967 OnGroupStreamStatus(group_id_2, GroupStreamStatus::IDLE))
9968 .Times(1);
9969 state_machine_callbacks_->StatusReportCb(group_id_2, GroupStreamStatus::IDLE);
9970
9971 // Group 1 active and start streaming
9972 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9973 OnGroupStreamStatus(group_id_1, GroupStreamStatus::STREAMING))
9974 .Times(1);
9975 LeAudioClient::Get()->GroupSetActive(group_id_1);
9976 SyncOnMainLoop();
9977 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_1);
9978 SyncOnMainLoop();
9979 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9980
9981 // Group 2 active
9982 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9983 OnGroupStreamStatus(group_id_1, GroupStreamStatus::IDLE))
9984 .Times(1);
9985 LeAudioClient::Get()->GroupSetActive(group_id_2);
9986 SyncOnMainLoop();
9987 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9988
9989 // Group 2 start streaming
9990 EXPECT_CALL(mock_audio_hal_client_callbacks_,
9991 OnGroupStreamStatus(group_id_2, GroupStreamStatus::STREAMING))
9992 .Times(1);
9993 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_2);
9994 SyncOnMainLoop();
9995 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9996 }
9997
TEST_F_WITH_FLAGS(UnicastTest,GroupStreamStatusResendAfterRemove,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_callback_on_group_stream_status)))9998 TEST_F_WITH_FLAGS(UnicastTest, GroupStreamStatusResendAfterRemove,
9999 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10000 TEST_BT, leaudio_callback_on_group_stream_status))) {
10001 uint8_t group_size = 2;
10002 int group_id = 1;
10003
10004 // Report working CSIS
10005 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
10006 .WillByDefault(Return(true));
10007
10008 ON_CALL(mock_csis_client_module_, GetDesiredSize(_))
10009 .WillByDefault(Return(group_size));
10010
10011 // First earbud
10012 const RawAddress test_address0 = GetTestAddress(0);
10013 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
10014 .Times(1);
10015 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
10016 codec_spec_conf::kLeAudioLocationFrontLeft,
10017 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
10018 group_id, 1 /* rank*/);
10019
10020 // Second earbud
10021 const RawAddress test_address1 = GetTestAddress(1);
10022 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
10023 .Times(1);
10024 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
10025 codec_spec_conf::kLeAudioLocationFrontRight,
10026 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
10027 group_id, 2 /* rank*/, true /*connect_through_csis*/);
10028
10029 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
10030
10031 InSequence s;
10032
10033 // Activate group, start streaming and immediately stop
10034 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10035 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
10036 .Times(1);
10037 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10038 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
10039 .Times(1);
10040 LeAudioClient::Get()->GroupSetActive(group_id);
10041 SyncOnMainLoop();
10042 state_machine_callbacks_->StatusReportCb(group_id,
10043 GroupStreamStatus::STREAMING);
10044 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10045
10046 // No resend
10047 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10048 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
10049 .Times(0);
10050 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
10051
10052 // No resend after removing only one device
10053 /*
10054 * StopStream will put calls on main_loop so to keep the correct order
10055 * of operations and to avoid races we put the test command on main_loop as
10056 * well.
10057 */
10058 do_in_main_thread(FROM_HERE, base::BindOnce(
10059 [](LeAudioClient* client,
10060 const RawAddress& test_address0) {
10061 client->RemoveDevice(test_address0);
10062 },
10063 LeAudioClient::Get(), test_address0));
10064 SyncOnMainLoop();
10065 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10066 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
10067 .Times(0);
10068 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
10069 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10070
10071 // Resend after removing last device
10072 /*
10073 * StopStream will put calls on main_loop so to keep the correct order
10074 * of operations and to avoid races we put the test command on main_loop as
10075 * well.
10076 */
10077 do_in_main_thread(FROM_HERE, base::BindOnce(
10078 [](LeAudioClient* client,
10079 const RawAddress& test_address1) {
10080 client->RemoveDevice(test_address1);
10081 },
10082 LeAudioClient::Get(), test_address1));
10083 SyncOnMainLoop();
10084 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10085 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
10086 .Times(1);
10087 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
10088 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10089 }
10090
TEST_F_WITH_FLAGS(UnicastTestHandoverMode,SetSinkMonitorModeWhileUnicastIsActive,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_audio_handover_policies)))10091 TEST_F_WITH_FLAGS(UnicastTestHandoverMode,
10092 SetSinkMonitorModeWhileUnicastIsActive,
10093 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10094 TEST_BT, leaudio_broadcast_audio_handover_policies))) {
10095 uint8_t group_size = 2;
10096 int group_id = 2;
10097
10098 // Report working CSIS
10099 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
10100 .WillByDefault(Return(true));
10101
10102 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10103 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
10104
10105 // First earbud
10106 const RawAddress test_address0 = GetTestAddress(0);
10107 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
10108 .Times(1);
10109 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
10110 codec_spec_conf::kLeAudioLocationFrontLeft,
10111 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
10112 group_id, 1 /* rank*/);
10113
10114 // Second earbud
10115 const RawAddress test_address1 = GetTestAddress(1);
10116 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
10117 .Times(1);
10118 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
10119 codec_spec_conf::kLeAudioLocationFrontRight,
10120 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
10121 group_id, 2 /* rank*/, true /*connect_through_csis*/);
10122
10123 // Start streaming
10124 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10125 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10126 LeAudioClient::Get()->GroupSetActive(group_id);
10127 SyncOnMainLoop();
10128
10129 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10130
10131 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
10132 group_id);
10133
10134 SyncOnMainLoop();
10135 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10136 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10137
10138 // Verify Data transfer on two peer sinks and one source
10139 uint8_t cis_count_out = 2;
10140 uint8_t cis_count_in = 2;
10141 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10142
10143 // Imitate activation of monitor mode
10144 do_in_main_thread(
10145 FROM_HERE,
10146 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10147 base::Unretained(LeAudioClient::Get()),
10148 bluetooth::le_audio::types::kLeAudioDirectionSink,
10149 true /* enable */));
10150
10151 ASSERT_NE(0lu, streaming_groups.count(group_id));
10152 auto group = streaming_groups.at(group_id);
10153
10154 // Stop streaming and expect Service to be informed about straming suspension
10155 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10156 OnUnicastMonitorModeStatus(
10157 bluetooth::le_audio::types::kLeAudioDirectionSink,
10158 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
10159 .Times(1);
10160
10161 // Stop
10162 StopStreaming(group_id, true);
10163
10164 // Check if cache configuration is still present
10165 ASSERT_TRUE(
10166 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10167 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10168 .size());
10169 ASSERT_TRUE(
10170 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10171 ->confs.get(le_audio::types::kLeAudioDirectionSource)
10172 .size());
10173
10174 // Release, Sink HAL client should remain in monitor mode
10175 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10176 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10177 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
10178 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
10179 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
10180 SyncOnMainLoop();
10181
10182 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10183 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10184 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10185
10186 // Re-initialize mock for destroyed hal client
10187 RegisterSourceHalClientMock();
10188
10189 // Setting group inactive, shall not change cached configuration
10190 ASSERT_TRUE(
10191 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10192 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10193 .size());
10194 ASSERT_TRUE(
10195 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10196 ->confs.get(le_audio::types::kLeAudioDirectionSource)
10197 .size());
10198
10199 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10200 OnUnicastMonitorModeStatus(
10201 bluetooth::le_audio::types::kLeAudioDirectionSink,
10202 UnicastMonitorModeStatus::STREAMING_REQUESTED))
10203 .Times(1);
10204
10205 // Start streaming to trigger next group going to IDLE state
10206 LocalAudioSinkResume();
10207
10208 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10209 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10210 LeAudioClient::Get()->GroupSetActive(group_id);
10211 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10212 SyncOnMainLoop();
10213
10214 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10215
10216 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
10217 group_id);
10218 SyncOnMainLoop();
10219 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10220
10221 // Stop streaming and expect Service to be informed about straming suspension
10222 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10223 OnUnicastMonitorModeStatus(
10224 bluetooth::le_audio::types::kLeAudioDirectionSink,
10225 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
10226 .Times(1);
10227
10228 // Stop
10229 StopStreaming(group_id, true);
10230
10231 // Release, Sink HAL client should remain in monitor mode
10232 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10233 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10234 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
10235 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
10236 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
10237 SyncOnMainLoop();
10238
10239 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10240 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10241 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10242
10243 // De-activate monitoring mode
10244 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
10245 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10246 do_in_main_thread(
10247 FROM_HERE,
10248 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10249 base::Unretained(LeAudioClient::Get()),
10250 bluetooth::le_audio::types::kLeAudioDirectionSink,
10251 false /* enable */));
10252 SyncOnMainLoop();
10253 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10254 }
10255
TEST_F_WITH_FLAGS(UnicastTestHandoverMode,SetSinkMonitorModeWhileUnicastIsInactive,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_audio_handover_policies)))10256 TEST_F_WITH_FLAGS(UnicastTestHandoverMode,
10257 SetSinkMonitorModeWhileUnicastIsInactive,
10258 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10259 TEST_BT, leaudio_broadcast_audio_handover_policies))) {
10260 uint8_t group_size = 2;
10261 int group_id = 2;
10262
10263 // Imitate activation of monitor mode
10264 do_in_main_thread(
10265 FROM_HERE,
10266 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10267 base::Unretained(LeAudioClient::Get()),
10268 bluetooth::le_audio::types::kLeAudioDirectionSink,
10269 true /* enable */));
10270
10271 // Report working CSIS
10272 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
10273 .WillByDefault(Return(true));
10274
10275 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10276 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
10277
10278 // First earbud
10279 const RawAddress test_address0 = GetTestAddress(0);
10280 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
10281 .Times(1);
10282 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
10283 codec_spec_conf::kLeAudioLocationFrontLeft,
10284 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
10285 group_id, 1 /* rank*/);
10286
10287 // Second earbud
10288 const RawAddress test_address1 = GetTestAddress(1);
10289 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
10290 .Times(1);
10291 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
10292 codec_spec_conf::kLeAudioLocationFrontRight,
10293 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
10294 group_id, 2 /* rank*/, true /*connect_through_csis*/);
10295
10296 // Start streaming
10297 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10298 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10299 LeAudioClient::Get()->GroupSetActive(group_id);
10300 SyncOnMainLoop();
10301
10302 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10303
10304 // Expect no streaming request on stream resume when group is already active
10305 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10306 OnUnicastMonitorModeStatus(
10307 bluetooth::le_audio::types::kLeAudioDirectionSink,
10308 UnicastMonitorModeStatus::STREAMING_REQUESTED))
10309 .Times(0);
10310
10311 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
10312 group_id);
10313
10314 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10315 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10316 SyncOnMainLoop();
10317
10318 // Verify Data transfer on two peer sinks and one source
10319 uint8_t cis_count_out = 2;
10320 uint8_t cis_count_in = 2;
10321 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10322
10323 ASSERT_NE(0lu, streaming_groups.count(group_id));
10324 auto group = streaming_groups.at(group_id);
10325
10326 // Stop streaming and expect Service to be informed about straming suspension
10327 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10328 OnUnicastMonitorModeStatus(
10329 bluetooth::le_audio::types::kLeAudioDirectionSink,
10330 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
10331 .Times(1);
10332
10333 // Stop
10334 StopStreaming(group_id, true);
10335
10336 // Check if cache configuration is still present
10337 ASSERT_TRUE(
10338 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10339 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10340 .size());
10341 ASSERT_TRUE(
10342 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10343 ->confs.get(le_audio::types::kLeAudioDirectionSource)
10344 .size());
10345
10346 // Release, Sink HAL client should remain in monitor mode
10347 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10348 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10349 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
10350 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
10351 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
10352 SyncOnMainLoop();
10353
10354 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10355 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10356 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10357
10358 // Setting group inactive, shall not change cached configuration
10359 ASSERT_TRUE(
10360 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10361 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10362 .size());
10363 ASSERT_TRUE(
10364 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10365 ->confs.get(le_audio::types::kLeAudioDirectionSource)
10366 .size());
10367 }
10368
TEST_F_WITH_FLAGS(UnicastTestHandoverMode,ClearSinkMonitorModeWhileUnicastIsActive,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_audio_handover_policies)))10369 TEST_F_WITH_FLAGS(UnicastTestHandoverMode,
10370 ClearSinkMonitorModeWhileUnicastIsActive,
10371 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10372 TEST_BT, leaudio_broadcast_audio_handover_policies))) {
10373 uint8_t group_size = 2;
10374 int group_id = 2;
10375
10376 // Imitate activation of monitor mode
10377 do_in_main_thread(
10378 FROM_HERE,
10379 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10380 base::Unretained(LeAudioClient::Get()),
10381 bluetooth::le_audio::types::kLeAudioDirectionSink,
10382 true /* enable */));
10383
10384 // Report working CSIS
10385 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
10386 .WillByDefault(Return(true));
10387
10388 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10389 .WillByDefault(Invoke([&](int group_id) { return group_size; }));
10390
10391 // First earbud
10392 const RawAddress test_address0 = GetTestAddress(0);
10393 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
10394 .Times(1);
10395 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
10396 codec_spec_conf::kLeAudioLocationFrontLeft,
10397 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
10398 group_id, 1 /* rank*/);
10399
10400 // Second earbud
10401 const RawAddress test_address1 = GetTestAddress(1);
10402 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
10403 .Times(1);
10404 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
10405 codec_spec_conf::kLeAudioLocationFrontRight,
10406 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
10407 group_id, 2 /* rank*/, true /*connect_through_csis*/);
10408
10409 // Start streaming
10410 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10411 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10412 LeAudioClient::Get()->GroupSetActive(group_id);
10413 SyncOnMainLoop();
10414
10415 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10416
10417 // Expect no streaming request on stream resume when group is already active
10418 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10419 OnUnicastMonitorModeStatus(
10420 bluetooth::le_audio::types::kLeAudioDirectionSink,
10421 UnicastMonitorModeStatus::STREAMING_REQUESTED))
10422 .Times(0);
10423
10424 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
10425 group_id);
10426
10427 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10428 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10429 SyncOnMainLoop();
10430
10431 // Verify Data transfer on two peer sinks and one source
10432 uint8_t cis_count_out = 2;
10433 uint8_t cis_count_in = 2;
10434 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10435
10436 ASSERT_NE(0lu, streaming_groups.count(group_id));
10437 auto group = streaming_groups.at(group_id);
10438
10439 // De-activate monitoring mode
10440 do_in_main_thread(
10441 FROM_HERE,
10442 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10443 base::Unretained(LeAudioClient::Get()),
10444 bluetooth::le_audio::types::kLeAudioDirectionSink,
10445 false /* enable */));
10446
10447 // Stop
10448 StopStreaming(group_id, true);
10449 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10450
10451 // Check if cache configuration is still present
10452 ASSERT_TRUE(
10453 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10454 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10455 .size());
10456 ASSERT_TRUE(
10457 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10458 ->confs.get(le_audio::types::kLeAudioDirectionSource)
10459 .size());
10460
10461 // Release of sink and source hals due to de-activating monitor mode
10462 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10463 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10464 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
10465 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10466 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
10467 SyncOnMainLoop();
10468
10469 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10470 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10471
10472 // Setting group inactive, shall not change cached configuration
10473 ASSERT_TRUE(
10474 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10475 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10476 .size());
10477 ASSERT_TRUE(
10478 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10479 ->confs.get(le_audio::types::kLeAudioDirectionSource)
10480 .size());
10481 }
10482
TEST_F_WITH_FLAGS(UnicastTestHandoverMode,SetAndClearSinkMonitorModeWhileUnicastIsInactive,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_audio_handover_policies)))10483 TEST_F_WITH_FLAGS(UnicastTestHandoverMode,
10484 SetAndClearSinkMonitorModeWhileUnicastIsInactive,
10485 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10486 TEST_BT, leaudio_broadcast_audio_handover_policies))) {
10487 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(0);
10488 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(0);
10489 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
10490 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(0);
10491 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
10492 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
10493
10494 // Imitate activation of monitor mode
10495 do_in_main_thread(
10496 FROM_HERE,
10497 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10498 base::Unretained(LeAudioClient::Get()),
10499 bluetooth::le_audio::types::kLeAudioDirectionSink,
10500 true /* enable */));
10501 do_in_main_thread(
10502 FROM_HERE,
10503 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10504 base::Unretained(LeAudioClient::Get()),
10505 bluetooth::le_audio::types::kLeAudioDirectionSink,
10506 false /* enable */));
10507
10508 SyncOnMainLoop();
10509
10510 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10511 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10512 }
10513
TEST_F_WITH_FLAGS(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsInactive,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_audio_handover_policies)))10514 TEST_F_WITH_FLAGS(UnicastTestHandoverMode,
10515 SetSourceMonitorModeWhileUnicastIsInactive,
10516 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10517 TEST_BT, leaudio_broadcast_audio_handover_policies))) {
10518 /* Enabling monitor mode for source while group is not active should result in
10519 * sending STREAMING_SUSPENDED notification.
10520 */
10521 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10522 OnUnicastMonitorModeStatus(
10523 bluetooth::le_audio::types::kLeAudioDirectionSource,
10524 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
10525 .Times(1);
10526
10527 // Imitate activation of monitor mode
10528 do_in_main_thread(
10529 FROM_HERE,
10530 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10531 base::Unretained(LeAudioClient::Get()),
10532 bluetooth::le_audio::types::kLeAudioDirectionSource,
10533 true /* enable */));
10534 SyncOnMainLoop();
10535 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10536 }
10537
TEST_F_WITH_FLAGS(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsNotStreaming,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_audio_handover_policies)))10538 TEST_F_WITH_FLAGS(UnicastTestHandoverMode,
10539 SetSourceMonitorModeWhileUnicastIsNotStreaming,
10540 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10541 TEST_BT, leaudio_broadcast_audio_handover_policies))) {
10542 int group_id = 2;
10543
10544 LeAudioClient::Get()->GroupSetActive(group_id);
10545
10546 /* Enabling monitor mode for source while group is not active should result in
10547 * sending STREAMING_SUSPENDED notification.
10548 */
10549 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10550 OnUnicastMonitorModeStatus(
10551 bluetooth::le_audio::types::kLeAudioDirectionSource,
10552 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
10553 .Times(1);
10554
10555 // Imitate activation of monitor mode
10556 do_in_main_thread(
10557 FROM_HERE,
10558 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10559 base::Unretained(LeAudioClient::Get()),
10560 bluetooth::le_audio::types::kLeAudioDirectionSource,
10561 true /* enable */));
10562 SyncOnMainLoop();
10563 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10564 }
10565
TEST_F_WITH_FLAGS(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsActive,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_audio_handover_policies)))10566 TEST_F_WITH_FLAGS(UnicastTestHandoverMode,
10567 SetSourceMonitorModeWhileUnicastIsActive,
10568 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10569 TEST_BT, leaudio_broadcast_audio_handover_policies))) {
10570 uint8_t group_size = 2;
10571 int group_id = 2;
10572
10573 // Report working CSIS
10574 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
10575 .WillByDefault(Return(true));
10576
10577 // First earbud
10578 const RawAddress test_address0 = GetTestAddress(0);
10579 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
10580 .Times(1);
10581 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
10582 codec_spec_conf::kLeAudioLocationFrontLeft,
10583 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
10584 group_id, 1 /* rank*/);
10585
10586 // Second earbud
10587 const RawAddress test_address1 = GetTestAddress(1);
10588 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
10589 .Times(1);
10590 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
10591 codec_spec_conf::kLeAudioLocationFrontRight,
10592 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
10593 group_id, 2 /* rank*/, true /*connect_through_csis*/);
10594
10595 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10596 .WillByDefault(Invoke([&](int group_id) { return 2; }));
10597
10598 // Start streaming
10599 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10600 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10601 LeAudioClient::Get()->GroupSetActive(group_id);
10602 SyncOnMainLoop();
10603
10604 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
10605 group_id);
10606
10607 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10608 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10609 SyncOnMainLoop();
10610
10611 // Verify Data transfer on two peer sinks and one source
10612 uint8_t cis_count_out = 2;
10613 uint8_t cis_count_in = 2;
10614 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10615
10616 /* Enabling monitor mode for source while stream is active should result in
10617 * sending STREAMING notification.
10618 */
10619 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10620 OnUnicastMonitorModeStatus(
10621 bluetooth::le_audio::types::kLeAudioDirectionSource,
10622 UnicastMonitorModeStatus::STREAMING))
10623 .Times(1);
10624
10625 // Imitate activation of monitor mode
10626 do_in_main_thread(
10627 FROM_HERE,
10628 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10629 base::Unretained(LeAudioClient::Get()),
10630 bluetooth::le_audio::types::kLeAudioDirectionSource,
10631 true /* enable */));
10632 SyncOnMainLoop();
10633 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10634
10635 ASSERT_NE(0lu, streaming_groups.count(group_id));
10636 auto group = streaming_groups.at(group_id);
10637
10638 // Stop streaming and expect Service to be informed about straming suspension
10639 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10640 OnUnicastMonitorModeStatus(
10641 bluetooth::le_audio::types::kLeAudioDirectionSource,
10642 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
10643 .Times(1);
10644
10645 // Stop
10646 StopStreaming(group_id, true);
10647
10648 // Check if cache configuration is still present
10649 ASSERT_TRUE(
10650 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10651 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10652 .size());
10653 ASSERT_TRUE(
10654 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10655 ->confs.get(le_audio::types::kLeAudioDirectionSource)
10656 .size());
10657
10658 // Both Sink and Source HAL clients should be stopped
10659 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10660 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10661 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
10662 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10663 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
10664 SyncOnMainLoop();
10665
10666 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10667 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10668 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10669
10670 // Re-initialize mock for destroyed hal client
10671 RegisterSourceHalClientMock();
10672 RegisterSinkHalClientMock();
10673
10674 // Setting group inactive, shall not change cached configuration
10675 ASSERT_TRUE(
10676 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10677 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10678 .size());
10679 ASSERT_TRUE(
10680 group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
10681 ->confs.get(le_audio::types::kLeAudioDirectionSource)
10682 .size());
10683
10684 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10685 OnUnicastMonitorModeStatus(
10686 bluetooth::le_audio::types::kLeAudioDirectionSource,
10687 UnicastMonitorModeStatus::STREAMING_REQUESTED))
10688 .Times(1);
10689
10690 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10691 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10692 LeAudioClient::Get()->GroupSetActive(group_id);
10693
10694 // Start streaming to trigger next group going to IDLE state
10695 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
10696 group_id);
10697 SyncOnMainLoop();
10698
10699 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10700 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10701 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10702
10703 // Stop streaming and expect Service to be informed about straming suspension
10704 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10705 OnUnicastMonitorModeStatus(
10706 bluetooth::le_audio::types::kLeAudioDirectionSource,
10707 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
10708 .Times(1);
10709
10710 // Stop
10711 StopStreaming(group_id, true);
10712
10713 // Both Sink and Source HAL clients should be stopped
10714 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10715 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10716 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
10717 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10718 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
10719 SyncOnMainLoop();
10720
10721 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10722 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10723 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10724
10725 // De-activate monitoring mode
10726 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10727 OnUnicastMonitorModeStatus(
10728 bluetooth::le_audio::types::kLeAudioDirectionSource,
10729 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
10730 .Times(0);
10731
10732 do_in_main_thread(
10733 FROM_HERE,
10734 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10735 base::Unretained(LeAudioClient::Get()),
10736 bluetooth::le_audio::types::kLeAudioDirectionSink,
10737 false /* enable */));
10738 }
10739
TEST_F(UnicastTestHandoverMode,SetAllowedContextMask)10740 TEST_F(UnicastTestHandoverMode, SetAllowedContextMask) {
10741 const RawAddress test_address0 = GetTestAddress(0);
10742 int group_id = bluetooth::groups::kGroupUnknown;
10743
10744 available_snk_context_types_ = (types::LeAudioContextType::RINGTONE |
10745 types::LeAudioContextType::CONVERSATIONAL |
10746 types::LeAudioContextType::UNSPECIFIED |
10747 types::LeAudioContextType::MEDIA |
10748 types::LeAudioContextType::SOUNDEFFECTS)
10749 .value();
10750 available_src_context_types_ = available_snk_context_types_;
10751 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
10752 supported_src_context_types_ = (types::kLeAudioContextAllRemoteSource |
10753 types::LeAudioContextType::UNSPECIFIED)
10754 .value();
10755 /* Don't allow SOUNDEFFECTS context type to be streamed */
10756 int allowed_context_types = (types::LeAudioContextType::RINGTONE |
10757 types::LeAudioContextType::CONVERSATIONAL |
10758 types::LeAudioContextType::UNSPECIFIED |
10759 types::LeAudioContextType::MEDIA)
10760 .value();
10761
10762 SetSampleDatabaseEarbudsValid(
10763 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10764 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10765 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
10766 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10767 0 /*rank*/);
10768 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10769 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10770 .Times(1);
10771 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10772 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10773 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10774
10775 ConnectLeAudio(test_address0);
10776 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10777
10778 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10779 types::BidirectionalPair<types::AudioContexts> metadata = {
10780 .sink = types::AudioContexts(), .source = types::AudioContexts()};
10781 EXPECT_CALL(
10782 mock_state_machine_,
10783 StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, metadata, _))
10784 .Times(0);
10785
10786 LeAudioClient::Get()->GroupSetActive(group_id);
10787 SyncOnMainLoop();
10788
10789 /* Set the same allowed context mask for sink and source */
10790 LeAudioClient::Get()->SetGroupAllowedContextMask(
10791 group_id, allowed_context_types, allowed_context_types);
10792
10793 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION,
10794 AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID,
10795 false, false);
10796
10797 SyncOnMainLoop();
10798 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10799 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10800 }
10801
TEST_F_WITH_FLAGS(UnicastTest,NoContextvalidateStreamingRequest,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_no_context_validate_streaming_request)))10802 TEST_F_WITH_FLAGS(UnicastTest, NoContextvalidateStreamingRequest,
10803 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
10804 TEST_BT,
10805 leaudio_no_context_validate_streaming_request))) {
10806 const RawAddress test_address0 = GetTestAddress(0);
10807 int group_id = bluetooth::groups::kGroupUnknown;
10808
10809 available_snk_context_types_ = (types::LeAudioContextType::RINGTONE |
10810 types::LeAudioContextType::CONVERSATIONAL |
10811 types::LeAudioContextType::UNSPECIFIED |
10812 types::LeAudioContextType::MEDIA)
10813 .value();
10814 available_src_context_types_ = available_snk_context_types_;
10815 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
10816 supported_src_context_types_ = (types::kLeAudioContextAllRemoteSource |
10817 types::LeAudioContextType::UNSPECIFIED)
10818 .value();
10819
10820 SetSampleDatabaseEarbudsValid(
10821 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10822 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10823 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
10824 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10825 0 /*rank*/);
10826 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10827 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10828 .Times(1);
10829 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10830 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10831 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10832
10833 ConnectLeAudio(test_address0);
10834 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10835
10836 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10837 types::BidirectionalPair<types::AudioContexts> metadata = {
10838 .sink = types::AudioContexts(), .source = types::AudioContexts()};
10839 EXPECT_CALL(
10840 mock_state_machine_,
10841 StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, metadata, _))
10842 .Times(0);
10843
10844 LeAudioClient::Get()->GroupSetActive(group_id);
10845
10846 // Imitate activation of monitor mode
10847 do_in_main_thread(
10848 FROM_HERE,
10849 base::BindOnce(&LeAudioClient::SetUnicastMonitorMode,
10850 base::Unretained(LeAudioClient::Get()),
10851 bluetooth::le_audio::types::kLeAudioDirectionSource,
10852 true /* enable */));
10853 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10854 SyncOnMainLoop();
10855
10856 // Stop streaming and expect Service to be informed about straming suspension
10857 EXPECT_CALL(
10858 mock_audio_hal_client_callbacks_,
10859 OnUnicastMonitorModeStatus(
10860 bluetooth::le_audio::types::kLeAudioDirectionSource,
10861 UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE))
10862 .Times(1);
10863
10864 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION,
10865 AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID,
10866 false, false);
10867
10868 SyncOnMainLoop();
10869 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10870 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10871 }
10872 } // namespace bluetooth::le_audio
10873