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 <gmock/gmock.h>
19 #include <gtest/gtest.h>
20
21 #include <chrono>
22
23 #include "bta/csis/csis_types.h"
24 #include "bta_gatt_api_mock.h"
25 #include "bta_gatt_queue_mock.h"
26 #include "bta_groups.h"
27 #include "bta_le_audio_api.h"
28 #include "btif_storage_mock.h"
29 #include "btm_api_mock.h"
30 #include "btm_iso_api.h"
31 #include "common/message_loop_thread.h"
32 #include "device/include/controller.h"
33 #include "fake_osi.h"
34 #include "gatt/database_builder.h"
35 #include "hardware/bt_gatt_types.h"
36 #include "internal_include/stack_config.h"
37 #include "le_audio_set_configuration_provider.h"
38 #include "le_audio_types.h"
39 #include "mock_controller.h"
40 #include "mock_csis_client.h"
41 #include "mock_device_groups.h"
42 #include "mock_iso_manager.h"
43 #include "mock_state_machine.h"
44 #include "osi/include/log.h"
45 #include "test/common/mock_functions.h"
46
47 using testing::_;
48 using testing::AnyNumber;
49 using testing::AtLeast;
50 using testing::AtMost;
51 using testing::DoAll;
52 using testing::Expectation;
53 using testing::Invoke;
54 using testing::Matcher;
55 using testing::Mock;
56 using testing::MockFunction;
57 using testing::NiceMock;
58 using testing::NotNull;
59 using testing::Return;
60 using testing::SaveArg;
61 using testing::SetArgPointee;
62 using testing::Test;
63 using testing::WithArg;
64
65 using bluetooth::Uuid;
66
67 using namespace bluetooth::le_audio;
68
69 using le_audio::LeAudioCodecConfiguration;
70 using le_audio::LeAudioSinkAudioHalClient;
71 using le_audio::LeAudioSourceAudioHalClient;
72
73 extern struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_;
74
75 constexpr int max_num_of_ases = 5;
76
77 static constexpr char kNotifyUpperLayerAboutGroupBeingInIdleDuringCall[] =
78 "persist.bluetooth.leaudio.notify.idle.during.call";
79 const char* test_flags[] = {
80 "INIT_logging_debug_enabled_for_all=true",
81 "INIT_leaudio_targeted_announcement_reconnection_mode=true",
82 nullptr,
83 };
84
85 void osi_property_set_bool(const char* key, bool value);
86
87 // Disables most likely false-positives from base::SplitString()
__asan_default_options()88 extern "C" const char* __asan_default_options() {
89 return "detect_container_overflow=0";
90 }
91
92 std::atomic<int> num_async_tasks;
93 bluetooth::common::MessageLoopThread message_loop_thread("test message loop");
get_main_thread()94 bluetooth::common::MessageLoopThread* get_main_thread() {
95 return &message_loop_thread;
96 }
do_in_main_thread(const base::Location & from_here,base::OnceClosure task)97 bt_status_t do_in_main_thread(const base::Location& from_here,
98 base::OnceClosure task) {
99 // Wrap the task with task counter so we could later know if there are
100 // any callbacks scheduled and we should wait before performing some actions
101 if (!message_loop_thread.DoInThread(
102 from_here,
103 base::BindOnce(
104 [](base::OnceClosure task, std::atomic<int>& num_async_tasks) {
105 std::move(task).Run();
106 num_async_tasks--;
107 },
108 std::move(task), std::ref(num_async_tasks)))) {
109 LOG(ERROR) << __func__ << ": failed from " << from_here.ToString();
110 return BT_STATUS_FAIL;
111 }
112 num_async_tasks++;
113 return BT_STATUS_SUCCESS;
114 }
115
do_in_main_thread_delayed(const base::Location & from_here,base::OnceClosure task,const base::TimeDelta & delay)116 bt_status_t do_in_main_thread_delayed(const base::Location& from_here,
117 base::OnceClosure task,
118 const base::TimeDelta& delay) {
119 /* For testing purpose it is ok to just skip delay */
120 return do_in_main_thread(from_here, std::move(task));
121 }
122
123 static base::MessageLoop* message_loop_;
get_main_message_loop()124 base::MessageLoop* get_main_message_loop() { return message_loop_; }
125
init_message_loop_thread()126 static void init_message_loop_thread() {
127 num_async_tasks = 0;
128 message_loop_thread.StartUp();
129 if (!message_loop_thread.IsRunning()) {
130 FAIL() << "unable to create message loop thread.";
131 }
132
133 if (!message_loop_thread.EnableRealTimeScheduling())
134 LOG(ERROR) << "Unable to set real time scheduling";
135
136 message_loop_ = message_loop_thread.message_loop();
137 if (message_loop_ == nullptr) FAIL() << "unable to get message loop.";
138 }
139
cleanup_message_loop_thread()140 static void cleanup_message_loop_thread() {
141 message_loop_ = nullptr;
142 message_loop_thread.ShutDown();
143 }
144
invoke_switch_codec_cb(bool is_low_latency_buffer_size)145 void invoke_switch_codec_cb(bool is_low_latency_buffer_size) {}
invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size)146 void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) {}
147
148 const std::string kSmpOptions("mock smp options");
get_trace_config_enabled(void)149 bool get_trace_config_enabled(void) { return false; }
get_pts_avrcp_test(void)150 bool get_pts_avrcp_test(void) { return false; }
get_pts_secure_only_mode(void)151 bool get_pts_secure_only_mode(void) { return false; }
get_pts_conn_updates_disabled(void)152 bool get_pts_conn_updates_disabled(void) { return false; }
get_pts_crosskey_sdp_disable(void)153 bool get_pts_crosskey_sdp_disable(void) { return false; }
get_pts_smp_options(void)154 const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
get_pts_smp_failure_case(void)155 int get_pts_smp_failure_case(void) { return 123; }
get_pts_force_eatt_for_notifications(void)156 bool get_pts_force_eatt_for_notifications(void) { return false; }
get_pts_connect_eatt_unconditionally(void)157 bool get_pts_connect_eatt_unconditionally(void) { return false; }
get_pts_connect_eatt_before_encryption(void)158 bool get_pts_connect_eatt_before_encryption(void) { return false; }
get_pts_unencrypt_broadcast(void)159 bool get_pts_unencrypt_broadcast(void) { return false; }
get_pts_eatt_peripheral_collision_support(void)160 bool get_pts_eatt_peripheral_collision_support(void) { return false; }
get_pts_force_le_audio_multiple_contexts_metadata(void)161 bool get_pts_force_le_audio_multiple_contexts_metadata(void) { return false; }
get_pts_le_audio_disable_ases_before_stopping(void)162 bool get_pts_le_audio_disable_ases_before_stopping(void) { return false; }
get_all(void)163 config_t* get_all(void) { return nullptr; }
164
165 stack_config_t mock_stack_config{
166 .get_trace_config_enabled = get_trace_config_enabled,
167 .get_pts_avrcp_test = get_pts_avrcp_test,
168 .get_pts_secure_only_mode = get_pts_secure_only_mode,
169 .get_pts_conn_updates_disabled = get_pts_conn_updates_disabled,
170 .get_pts_crosskey_sdp_disable = get_pts_crosskey_sdp_disable,
171 .get_pts_smp_options = get_pts_smp_options,
172 .get_pts_smp_failure_case = get_pts_smp_failure_case,
173 .get_pts_force_eatt_for_notifications =
174 get_pts_force_eatt_for_notifications,
175 .get_pts_connect_eatt_unconditionally =
176 get_pts_connect_eatt_unconditionally,
177 .get_pts_connect_eatt_before_encryption =
178 get_pts_connect_eatt_before_encryption,
179 .get_pts_unencrypt_broadcast = get_pts_unencrypt_broadcast,
180 .get_pts_eatt_peripheral_collision_support =
181 get_pts_eatt_peripheral_collision_support,
182 .get_pts_force_le_audio_multiple_contexts_metadata =
183 get_pts_force_le_audio_multiple_contexts_metadata,
184 .get_pts_le_audio_disable_ases_before_stopping =
185 get_pts_le_audio_disable_ases_before_stopping,
186 .get_all = get_all,
187 };
stack_config_get_interface(void)188 const stack_config_t* stack_config_get_interface(void) {
189 return &mock_stack_config;
190 }
191
192 namespace le_audio {
193 class MockLeAudioSourceHalClient;
194 MockLeAudioSourceHalClient* mock_le_audio_source_hal_client_;
195 std::unique_ptr<LeAudioSourceAudioHalClient>
196 owned_mock_le_audio_source_hal_client_;
197 bool is_audio_unicast_source_acquired;
198
199 std::unique_ptr<LeAudioSourceAudioHalClient>
AcquireUnicast()200 LeAudioSourceAudioHalClient::AcquireUnicast() {
201 if (is_audio_unicast_source_acquired) return nullptr;
202 is_audio_unicast_source_acquired = true;
203 return std::move(owned_mock_le_audio_source_hal_client_);
204 }
205
DebugDump(int fd)206 void LeAudioSourceAudioHalClient::DebugDump(int fd) {}
207
208 class MockLeAudioSinkHalClient;
209 MockLeAudioSinkHalClient* mock_le_audio_sink_hal_client_;
210 std::unique_ptr<LeAudioSinkAudioHalClient> owned_mock_le_audio_sink_hal_client_;
211 bool is_audio_unicast_sink_acquired;
212
213 std::unique_ptr<LeAudioSinkAudioHalClient>
AcquireUnicast()214 LeAudioSinkAudioHalClient::AcquireUnicast() {
215 if (is_audio_unicast_sink_acquired) return nullptr;
216 is_audio_unicast_sink_acquired = true;
217 return std::move(owned_mock_le_audio_sink_hal_client_);
218 }
219
DebugDump(int fd)220 void LeAudioSinkAudioHalClient::DebugDump(int fd) {}
221
222 class MockAudioHalClientCallbacks
223 : public bluetooth::le_audio::LeAudioClientCallbacks {
224 public:
225 MOCK_METHOD((void), OnInitialized, (), (override));
226 MOCK_METHOD((void), OnConnectionState,
227 (ConnectionState state, const RawAddress& address), (override));
228 MOCK_METHOD((void), OnGroupStatus, (int group_id, GroupStatus group_status),
229 (override));
230 MOCK_METHOD((void), OnGroupNodeStatus,
231 (const RawAddress& bd_addr, int group_id,
232 GroupNodeStatus node_status),
233 (override));
234 MOCK_METHOD((void), OnAudioConf,
235 (uint8_t direction, int group_id, uint32_t snk_audio_location,
236 uint32_t src_audio_location, uint16_t avail_cont),
237 (override));
238 MOCK_METHOD((void), OnSinkAudioLocationAvailable,
239 (const RawAddress& bd_addr, uint32_t snk_audio_location),
240 (override));
241 MOCK_METHOD(
242 (void), OnAudioLocalCodecCapabilities,
243 (std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
244 std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf),
245 (override));
246 MOCK_METHOD(
247 (void), OnAudioGroupCodecConf,
248 (int group_id, btle_audio_codec_config_t input_codec_conf,
249 btle_audio_codec_config_t output_codec_conf,
250 std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
251 std::vector<btle_audio_codec_config_t> output_selectable_codec_conf),
252 (override));
253 };
254
255 class MockLeAudioSinkHalClient : public LeAudioSinkAudioHalClient {
256 public:
257 MockLeAudioSinkHalClient() = default;
258 MOCK_METHOD((bool), Start,
259 (const LeAudioCodecConfiguration& codecConfiguration,
260 LeAudioSinkAudioHalClient::Callbacks* audioReceiver),
261 (override));
262 MOCK_METHOD((void), Stop, (), (override));
263 MOCK_METHOD((size_t), SendData, (uint8_t * data, uint16_t size), (override));
264 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
265 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
266 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
267 MOCK_METHOD((void), UpdateAudioConfigToHal,
268 (const ::le_audio::offload_config&), (override));
269 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
270 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
271
272 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSinkHalClient()273 virtual ~MockLeAudioSinkHalClient() override { OnDestroyed(); }
274 };
275
276 class MockLeAudioSourceHalClient : public LeAudioSourceAudioHalClient {
277 public:
278 MockLeAudioSourceHalClient() = default;
279 MOCK_METHOD((bool), Start,
280 (const LeAudioCodecConfiguration& codecConfiguration,
281 LeAudioSourceAudioHalClient::Callbacks* audioReceiver),
282 (override));
283 MOCK_METHOD((void), Stop, (), (override));
284 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
285 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
286 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
287 MOCK_METHOD((void), UpdateAudioConfigToHal,
288 (const ::le_audio::offload_config&), (override));
289 MOCK_METHOD((void), UpdateBroadcastAudioConfigToHal,
290 (const ::le_audio::broadcast_offload_config&), (override));
291 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
292 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
293
294 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSourceHalClient()295 virtual ~MockLeAudioSourceHalClient() override { OnDestroyed(); }
296 };
297
298 class UnicastTestNoInit : public Test {
299 protected:
SetUpMockAudioHal()300 void SetUpMockAudioHal() {
301 bluetooth::common::InitFlags::Load(test_flags);
302
303 /* Since these are returned by the Acquire() methods as unique_ptrs, we
304 * will not free them manually.
305 */
306
307 owned_mock_le_audio_sink_hal_client_.reset(new NiceMock<MockLeAudioSinkHalClient>());
308 mock_le_audio_sink_hal_client_ =
309 (MockLeAudioSinkHalClient*)owned_mock_le_audio_sink_hal_client_.get();
310
311 owned_mock_le_audio_source_hal_client_.reset(
312 new NiceMock<MockLeAudioSourceHalClient>());
313 mock_le_audio_source_hal_client_ =
314 (MockLeAudioSourceHalClient*)
315 owned_mock_le_audio_source_hal_client_.get();
316
317 is_audio_unicast_source_acquired = false;
318 ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _))
319 .WillByDefault(
320 [this](const LeAudioCodecConfiguration& codec_configuration,
321 LeAudioSourceAudioHalClient::Callbacks* audioReceiver) {
322 unicast_source_hal_cb_ = audioReceiver;
323 return true;
324 });
325 ON_CALL(*mock_le_audio_source_hal_client_, OnDestroyed).WillByDefault([]() {
326 mock_le_audio_source_hal_client_ = nullptr;
327 is_audio_unicast_source_acquired = false;
328 });
329
330 is_audio_unicast_sink_acquired = false;
331 ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _))
332 .WillByDefault(
333 [this](const LeAudioCodecConfiguration& codec_configuration,
334 LeAudioSinkAudioHalClient::Callbacks* audioReceiver) {
335 unicast_sink_hal_cb_ = audioReceiver;
336 return true;
337 });
338 ON_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed).WillByDefault([]() {
339 mock_le_audio_sink_hal_client_ = nullptr;
340 is_audio_unicast_sink_acquired = false;
341 });
342
343 ON_CALL(*mock_le_audio_sink_hal_client_, SendData)
344 .WillByDefault([](uint8_t* data, uint16_t size) { return size; });
345
346 // HAL
347 ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool {
348 return true;
349 });
350 }
351
InjectGroupDeviceRemoved(const RawAddress & address,int group_id)352 void InjectGroupDeviceRemoved(const RawAddress& address, int group_id) {
353 group_callbacks_->OnGroupMemberRemoved(address, group_id);
354 }
355
InjectGroupDeviceAdded(const RawAddress & address,int group_id)356 void InjectGroupDeviceAdded(const RawAddress& address, int group_id) {
357 bluetooth::Uuid uuid = le_audio::uuid::kCapServiceUuid;
358
359 int group_members_num = 0;
360 for (const auto& [addr, id] : groups) {
361 if (id == group_id) group_members_num++;
362 }
363
364 bool first_device = (group_members_num == 1);
365 do_in_main_thread(
366 FROM_HERE,
367 base::BindOnce(
368 [](const RawAddress& addr, int group_id, bluetooth::Uuid uuid,
369 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks,
370 bool first_device) {
371 if (first_device) {
372 group_callbacks->OnGroupAdded(addr, uuid, group_id);
373 } else {
374 group_callbacks->OnGroupMemberAdded(addr, group_id);
375 }
376 },
377 address, group_id, uuid, base::Unretained(this->group_callbacks_),
378 first_device));
379 }
380
InjectConnectedEvent(const RawAddress & address,uint16_t conn_id,tGATT_STATUS status=GATT_SUCCESS)381 void InjectConnectedEvent(const RawAddress& address, uint16_t conn_id,
382 tGATT_STATUS status = GATT_SUCCESS) {
383 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
384 tBTA_GATTC_OPEN event_data = {
385 .status = status,
386 .conn_id = conn_id,
387 .client_if = gatt_if,
388 .remote_bda = address,
389 .transport = GATT_TRANSPORT_LE,
390 .mtu = 240,
391 };
392
393 if (status == GATT_SUCCESS) {
394 ASSERT_NE(peer_devices.count(conn_id), 0u);
395 peer_devices.at(conn_id)->connected = true;
396 }
397
398 do_in_main_thread(
399 FROM_HERE,
400 base::BindOnce(
401 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_OPEN event_data) {
402 gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
403 },
404 base::Unretained(this->gatt_callback), event_data));
405 }
406
InjectDisconnectedEvent(uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST)407 void InjectDisconnectedEvent(
408 uint16_t conn_id,
409 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) {
410 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
411 ASSERT_NE(peer_devices.count(conn_id), 0u);
412
413 tBTA_GATTC_CLOSE event_data = {
414 .status = GATT_SUCCESS,
415 .conn_id = conn_id,
416 .client_if = gatt_if,
417 .remote_bda = peer_devices.at(conn_id)->addr,
418 .reason = reason,
419 };
420
421 peer_devices.at(conn_id)->connected = false;
422 do_in_main_thread(
423 FROM_HERE,
424 base::BindOnce(
425 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_CLOSE event_data) {
426 gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
427 },
428 base::Unretained(this->gatt_callback), event_data));
429 }
430
InjectSearchCompleteEvent(uint16_t conn_id)431 void InjectSearchCompleteEvent(uint16_t conn_id) {
432 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
433 tBTA_GATTC_SEARCH_CMPL event_data = {
434 .status = GATT_SUCCESS,
435 .conn_id = conn_id,
436 };
437
438 do_in_main_thread(FROM_HERE,
439 base::BindOnce(
440 [](tBTA_GATTC_CBACK* gatt_callback,
441 tBTA_GATTC_SEARCH_CMPL event_data) {
442 gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT,
443 (tBTA_GATTC*)&event_data);
444 },
445 base::Unretained(this->gatt_callback), event_data));
446 }
447
InjectNotificationEvent(const RawAddress & test_address,uint16_t conn_id,uint16_t handle,std::vector<uint8_t> value)448 void InjectNotificationEvent(const RawAddress& test_address, uint16_t conn_id,
449 uint16_t handle, std::vector<uint8_t> value) {
450 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
451 tBTA_GATTC_NOTIFY event_data = {
452 .conn_id = conn_id,
453 .bda = test_address,
454 .handle = handle,
455 .len = (uint8_t)value.size(),
456 .is_notify = true,
457 };
458
459 std::copy(value.begin(), value.end(), event_data.value);
460 do_in_main_thread(
461 FROM_HERE,
462 base::BindOnce(
463 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_NOTIFY event_data) {
464 gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
465 },
466 base::Unretained(this->gatt_callback), event_data));
467 }
468
SetUpMockGatt()469 void SetUpMockGatt() {
470 // default action for GetCharacteristic function call
471 ON_CALL(mock_gatt_interface_, GetCharacteristic(_, _))
472 .WillByDefault(
473 Invoke([&](uint16_t conn_id,
474 uint16_t handle) -> const gatt::Characteristic* {
475 std::list<gatt::Service>& services =
476 peer_devices.at(conn_id)->services;
477 for (auto const& service : services) {
478 for (auto const& characteristic : service.characteristics) {
479 if (characteristic.value_handle == handle) {
480 return &characteristic;
481 }
482 }
483 }
484
485 return nullptr;
486 }));
487
488 // default action for GetOwningService function call
489 ON_CALL(mock_gatt_interface_, GetOwningService(_, _))
490 .WillByDefault(Invoke(
491 [&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
492 std::list<gatt::Service>& services =
493 peer_devices.at(conn_id)->services;
494 for (auto const& service : services) {
495 if (service.handle <= handle && service.end_handle >= handle) {
496 return &service;
497 }
498 }
499
500 return nullptr;
501 }));
502
503 // default action for ServiceSearchRequest function call
504 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
505 .WillByDefault(WithArg<0>(Invoke(
506 [&](uint16_t conn_id) { InjectSearchCompleteEvent(conn_id); })));
507
508 // default action for GetServices function call
509 ON_CALL(mock_gatt_interface_, GetServices(_))
510 .WillByDefault(WithArg<0>(
511 Invoke([&](uint16_t conn_id) -> std::list<gatt::Service>* {
512 return &peer_devices.at(conn_id)->services;
513 })));
514
515 // default action for RegisterForNotifications function call
516 ON_CALL(mock_gatt_interface_, RegisterForNotifications(gatt_if, _, _))
517 .WillByDefault(Return(GATT_SUCCESS));
518
519 // default action for DeregisterForNotifications function call
520 ON_CALL(mock_gatt_interface_, DeregisterForNotifications(gatt_if, _, _))
521 .WillByDefault(Return(GATT_SUCCESS));
522
523 // default action for WriteDescriptor function call
524 ON_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _))
525 .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle,
526 std::vector<uint8_t> value,
527 tGATT_WRITE_TYPE write_type,
528 GATT_WRITE_OP_CB cb, void* cb_data) -> void {
529 if (cb)
530 do_in_main_thread(
531 FROM_HERE,
532 base::BindOnce(
533 [](GATT_WRITE_OP_CB cb, uint16_t conn_id, uint16_t handle,
534 uint16_t len, uint8_t* value, void* cb_data) {
535 cb(conn_id, GATT_SUCCESS, handle, len, value, cb_data);
536 },
537 cb, conn_id, handle, value.size(), value.data(), cb_data));
538 }));
539
540 global_conn_id = 1;
541 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
542 .WillByDefault(
543 Invoke([&](tGATT_IF client_if, const RawAddress& remote_bda,
544 bool is_direct, bool opportunistic) {
545 InjectConnectedEvent(remote_bda, global_conn_id++);
546 }));
547
548 ON_CALL(mock_gatt_interface_, Close(_))
549 .WillByDefault(Invoke(
550 [&](uint16_t conn_id) { InjectDisconnectedEvent(conn_id); }));
551
552 // default Characteristic read handler dispatches requests to service mocks
553 ON_CALL(mock_gatt_queue_, ReadCharacteristic(_, _, _, _))
554 .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle,
555 GATT_READ_OP_CB cb, void* cb_data) {
556 do_in_main_thread(
557 FROM_HERE,
558 base::BindOnce(
559 [](std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>>*
560 peer_devices,
561 uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
562 void* cb_data) -> void {
563 if (peer_devices->count(conn_id)) {
564 auto& device = peer_devices->at(conn_id);
565 auto svc = std::find_if(
566 device->services.begin(), device->services.end(),
567 [handle](const gatt::Service& svc) {
568 return (handle >= svc.handle) &&
569 (handle <= svc.end_handle);
570 });
571 if (svc == device->services.end()) return;
572
573 // Dispatch to mockable handler functions
574 if (svc->handle == device->csis->start) {
575 device->csis->OnReadCharacteristic(handle, cb, cb_data);
576 } else if (svc->handle == device->cas->start) {
577 device->cas->OnReadCharacteristic(handle, cb, cb_data);
578 } else if (svc->handle == device->ascs->start) {
579 device->ascs->OnReadCharacteristic(handle, cb, cb_data);
580 } else if (svc->handle == device->pacs->start) {
581 device->pacs->OnReadCharacteristic(handle, cb, cb_data);
582 }
583 }
584 },
585 &peer_devices, conn_id, handle, cb, cb_data));
586 }));
587 }
588
SetUpMockGroups()589 void SetUpMockGroups() {
590 MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
591 MockDeviceGroups::SetMockInstanceForTesting(&mock_groups_module_);
592 MockLeAudioGroupStateMachine::SetMockInstanceForTesting(
593 &mock_state_machine_);
594
595 ON_CALL(mock_csis_client_module_, Get())
596 .WillByDefault(Return(&mock_csis_client_module_));
597
598 // Store group callbacks so that we could inject grouping events
599 group_callbacks_ = nullptr;
600 ON_CALL(mock_groups_module_, Initialize(_))
601 .WillByDefault(SaveArg<0>(&group_callbacks_));
602
603 ON_CALL(mock_groups_module_, GetGroupId(_, _))
604 .WillByDefault([this](const RawAddress& addr, bluetooth::Uuid uuid) {
605 if (groups.find(addr) != groups.end()) return groups.at(addr);
606 return bluetooth::groups::kGroupUnknown;
607 });
608
609 ON_CALL(mock_groups_module_, RemoveDevice(_, _))
610 .WillByDefault([this](const RawAddress& addr, int group_id_) {
611 int group_id = -1;
612 if (groups.find(addr) != groups.end()) {
613 group_id = groups[addr];
614 groups.erase(addr);
615 }
616 if (group_id < 0) return;
617
618 do_in_main_thread(
619 FROM_HERE,
620 base::BindOnce(
621 [](const RawAddress& address, int group_id,
622 bluetooth::groups::DeviceGroupsCallbacks*
623 group_callbacks) {
624 group_callbacks->OnGroupMemberRemoved(address, group_id);
625 },
626 addr, group_id, base::Unretained(group_callbacks_)));
627 });
628
629 // Our test devices have unique LSB - use it for unique grouping when
630 // devices added with a non-CIS context and no grouping info
631 ON_CALL(mock_groups_module_,
632 AddDevice(_, le_audio::uuid::kCapServiceUuid, _))
633 .WillByDefault(
634 [this](const RawAddress& addr,
635 bluetooth::Uuid uuid = le_audio::uuid::kCapServiceUuid,
636 int group_id = bluetooth::groups::kGroupUnknown) -> int {
637 if (group_id == bluetooth::groups::kGroupUnknown) {
638 /* Generate group id from address */
639 groups[addr] = addr.address[RawAddress::kLength - 1];
640 group_id = groups[addr];
641 } else {
642 groups[addr] = group_id;
643 }
644
645 InjectGroupDeviceAdded(addr, groups[addr]);
646 return addr.address[RawAddress::kLength - 1];
647 });
648
649 ON_CALL(mock_state_machine_, Initialize(_))
650 .WillByDefault(SaveArg<0>(&state_machine_callbacks_));
651
652 ON_CALL(mock_state_machine_, ConfigureStream(_, _, _, _))
653 .WillByDefault(
654 [this](LeAudioDeviceGroup* group,
655 types::LeAudioContextType context_type,
656 types::BidirectionalPair<types::AudioContexts>
657 metadata_context_types,
658 types::BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
659 bool isReconfiguration = group->IsPendingConfiguration();
660
661 /* This shall be called only for user reconfiguration */
662 if (!isReconfiguration) return false;
663
664 /* Do what ReleaseCisIds(group) does: start */
665 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
666 while (leAudioDevice != nullptr) {
667 for (auto& ase : leAudioDevice->ases_) {
668 ase.cis_id = le_audio::kInvalidCisId;
669 }
670 leAudioDevice = group->GetNextDevice(leAudioDevice);
671 }
672 group->CigClearCis();
673 /* end */
674
675 if (!group->Configure(context_type, metadata_context_types,
676 ccid_lists)) {
677 LOG_ERROR(
678 "Could not configure ASEs for group %d content type %d",
679 group->group_id_, int(context_type));
680
681 return false;
682 }
683
684 group->CigGenerateCisIds(context_type);
685
686 for (LeAudioDevice* device = group->GetFirstDevice();
687 device != nullptr; device = group->GetNextDevice(device)) {
688 for (auto& ase : device->ases_) {
689 ase.data_path_state = types::AudioStreamDataPathState::IDLE;
690 ase.active = false;
691 ase.state =
692 types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
693 }
694 }
695
696 // Inject the state
697 group->SetTargetState(
698 types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
699 group->SetState(group->GetTargetState());
700 group->ClearPendingConfiguration();
701 do_in_main_thread(
702 FROM_HERE,
703 base::BindOnce(
704 [](int group_id,
705 le_audio::LeAudioGroupStateMachine::Callbacks*
706 state_machine_callbacks) {
707 state_machine_callbacks->StatusReportCb(
708 group_id, GroupStreamStatus::CONFIGURED_BY_USER);
709 },
710 group->group_id_,
711 base::Unretained(this->state_machine_callbacks_)));
712 return true;
713 });
714
715 ON_CALL(mock_state_machine_, AttachToStream(_, _))
716 .WillByDefault([](LeAudioDeviceGroup* group,
717 LeAudioDevice* leAudioDevice) {
718 if (group->GetState() !=
719 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
720 return false;
721 }
722
723 group->Configure(group->GetConfigurationContextType(),
724 group->GetMetadataContexts());
725 if (!group->CigAssignCisIds(leAudioDevice)) return false;
726 group->CigAssignCisConnHandlesToAses(leAudioDevice);
727
728 auto* stream_conf = &group->stream_conf;
729
730 for (auto& ase : leAudioDevice->ases_) {
731 if (!ase.active) continue;
732
733 // And also skip the ase establishment procedure which should
734 // be tested as part of the state machine unit tests
735 ase.data_path_state =
736 types::AudioStreamDataPathState::DATA_PATH_ESTABLISHED;
737 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
738
739 uint16_t cis_conn_hdl = ase.cis_conn_hdl;
740
741 /* Copied from state_machine.cc ProcessHciNotifSetupIsoDataPath */
742 if (ase.direction == le_audio::types::kLeAudioDirectionSource) {
743 auto iter = std::find_if(stream_conf->source_streams.begin(),
744 stream_conf->source_streams.end(),
745 [cis_conn_hdl](auto& pair) {
746 return cis_conn_hdl == pair.first;
747 });
748
749 if (iter == stream_conf->source_streams.end()) {
750 stream_conf->source_streams.emplace_back(
751 std::make_pair(ase.cis_conn_hdl,
752 *ase.codec_config.audio_channel_allocation));
753
754 stream_conf->source_num_of_devices++;
755 stream_conf->source_num_of_channels +=
756 ase.codec_config.channel_count;
757
758 LOG_INFO(
759 " Added Source Stream Configuration. CIS Connection "
760 "Handle: %d"
761 ", Audio Channel Allocation: %d"
762 ", Source Number Of Devices: %d"
763 ", Source Number Of Channels: %d",
764 +ase.cis_conn_hdl,
765 +(*ase.codec_config.audio_channel_allocation),
766 +stream_conf->source_num_of_devices,
767 +stream_conf->source_num_of_channels);
768 }
769 } else {
770 auto iter = std::find_if(stream_conf->sink_streams.begin(),
771 stream_conf->sink_streams.end(),
772 [cis_conn_hdl](auto& pair) {
773 return cis_conn_hdl == pair.first;
774 });
775
776 if (iter == stream_conf->sink_streams.end()) {
777 stream_conf->sink_streams.emplace_back(
778 std::make_pair(ase.cis_conn_hdl,
779 *ase.codec_config.audio_channel_allocation));
780
781 stream_conf->sink_num_of_devices++;
782 stream_conf->sink_num_of_channels +=
783 ase.codec_config.channel_count;
784
785 LOG_INFO(
786 " Added Sink Stream Configuration. CIS Connection Handle: "
787 "%d"
788 ", Audio Channel Allocation: %d"
789 ", Sink Number Of Devices: %d"
790 ", Sink Number Of Channels: %d",
791 +ase.cis_conn_hdl,
792 +(*ase.codec_config.audio_channel_allocation),
793 +stream_conf->sink_num_of_devices,
794 +stream_conf->sink_num_of_channels);
795 }
796 }
797 }
798
799 return true;
800 });
801
802 ON_CALL(mock_state_machine_, StartStream(_, _, _, _))
803 .WillByDefault([this](LeAudioDeviceGroup* group,
804 types::LeAudioContextType context_type,
805 types::BidirectionalPair<types::AudioContexts>
806 metadata_context_types,
807 types::BidirectionalPair<std::vector<uint8_t>>
808 ccid_lists) {
809 /* Do nothing if already streaming - the implementation would
810 * probably update the metadata.
811 */
812 if (group->GetState() ==
813 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
814 return true;
815 }
816
817 /* Do what ReleaseCisIds(group) does: start */
818 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
819 while (leAudioDevice != nullptr) {
820 for (auto& ase : leAudioDevice->ases_) {
821 ase.cis_id = le_audio::kInvalidCisId;
822 }
823 leAudioDevice = group->GetNextDevice(leAudioDevice);
824 }
825 group->CigClearCis();
826 /* end */
827
828 if (!group->Configure(context_type, metadata_context_types,
829 ccid_lists)) {
830 LOG(ERROR) << __func__ << ", failed to set ASE configuration";
831 return false;
832 }
833
834 if (group->GetState() ==
835 types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {
836 group->CigGenerateCisIds(context_type);
837
838 std::vector<uint16_t> conn_handles;
839 for (uint8_t i = 0; i < (uint8_t)(group->cises_.size()); i++) {
840 conn_handles.push_back(iso_con_counter_++);
841 }
842 group->CigAssignCisConnHandles(conn_handles);
843 for (LeAudioDevice* device = group->GetFirstActiveDevice();
844 device != nullptr;
845 device = group->GetNextActiveDevice(device)) {
846 if (!group->CigAssignCisIds(device)) return false;
847 group->CigAssignCisConnHandlesToAses(device);
848 }
849 }
850
851 auto* stream_conf = &group->stream_conf;
852
853 // Fake ASE configuration
854 for (LeAudioDevice* device = group->GetFirstActiveDevice();
855 device != nullptr; device = group->GetNextActiveDevice(device)) {
856 for (auto& ase : device->ases_) {
857 if (!ase.active) continue;
858
859 // And also skip the ase establishment procedure which should
860 // be tested as part of the state machine unit tests
861 ase.data_path_state =
862 types::AudioStreamDataPathState::DATA_PATH_ESTABLISHED;
863 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
864
865 uint16_t cis_conn_hdl = ase.cis_conn_hdl;
866
867 /* Copied from state_machine.cc ProcessHciNotifSetupIsoDataPath */
868 if (ase.direction == le_audio::types::kLeAudioDirectionSource) {
869 auto iter = std::find_if(stream_conf->source_streams.begin(),
870 stream_conf->source_streams.end(),
871 [cis_conn_hdl](auto& pair) {
872 return cis_conn_hdl == pair.first;
873 });
874
875 if (iter == stream_conf->source_streams.end()) {
876 stream_conf->source_streams.emplace_back(std::make_pair(
877 ase.cis_conn_hdl,
878 *ase.codec_config.audio_channel_allocation));
879
880 stream_conf->source_num_of_devices++;
881 stream_conf->source_num_of_channels +=
882 ase.codec_config.channel_count;
883 stream_conf->source_audio_channel_allocation |=
884 *ase.codec_config.audio_channel_allocation;
885
886 if (stream_conf->source_sample_frequency_hz == 0) {
887 stream_conf->source_sample_frequency_hz =
888 ase.codec_config.GetSamplingFrequencyHz();
889 } else {
890 ASSERT_LOG(stream_conf->source_sample_frequency_hz ==
891 ase.codec_config.GetSamplingFrequencyHz(),
892 "sample freq mismatch: %d!=%d",
893 stream_conf->source_sample_frequency_hz,
894 ase.codec_config.GetSamplingFrequencyHz());
895 }
896
897 if (stream_conf->source_octets_per_codec_frame == 0) {
898 stream_conf->source_octets_per_codec_frame =
899 *ase.codec_config.octets_per_codec_frame;
900 } else {
901 ASSERT_LOG(stream_conf->source_octets_per_codec_frame ==
902 *ase.codec_config.octets_per_codec_frame,
903 "octets per frame mismatch: %d!=%d",
904 stream_conf->source_octets_per_codec_frame,
905 *ase.codec_config.octets_per_codec_frame);
906 }
907
908 if (stream_conf->source_codec_frames_blocks_per_sdu == 0) {
909 stream_conf->source_codec_frames_blocks_per_sdu =
910 *ase.codec_config.codec_frames_blocks_per_sdu;
911 } else {
912 ASSERT_LOG(
913 stream_conf->source_codec_frames_blocks_per_sdu ==
914 *ase.codec_config.codec_frames_blocks_per_sdu,
915 "codec_frames_blocks_per_sdu: %d!=%d",
916 stream_conf->source_codec_frames_blocks_per_sdu,
917 *ase.codec_config.codec_frames_blocks_per_sdu);
918 }
919
920 LOG_INFO(
921 " Added Source Stream Configuration. CIS Connection "
922 "Handle: %d"
923 ", Audio Channel Allocation: %d"
924 ", Source Number Of Devices: %d"
925 ", Source Number Of Channels: %d",
926 +ase.cis_conn_hdl,
927 +(*ase.codec_config.audio_channel_allocation),
928 +stream_conf->source_num_of_devices,
929 +stream_conf->source_num_of_channels);
930 }
931 } else {
932 auto iter = std::find_if(stream_conf->sink_streams.begin(),
933 stream_conf->sink_streams.end(),
934 [cis_conn_hdl](auto& pair) {
935 return cis_conn_hdl == pair.first;
936 });
937
938 if (iter == stream_conf->sink_streams.end()) {
939 stream_conf->sink_streams.emplace_back(std::make_pair(
940 ase.cis_conn_hdl,
941 *ase.codec_config.audio_channel_allocation));
942
943 stream_conf->sink_num_of_devices++;
944 stream_conf->sink_num_of_channels +=
945 ase.codec_config.channel_count;
946
947 stream_conf->sink_audio_channel_allocation |=
948 *ase.codec_config.audio_channel_allocation;
949
950 if (stream_conf->sink_sample_frequency_hz == 0) {
951 stream_conf->sink_sample_frequency_hz =
952 ase.codec_config.GetSamplingFrequencyHz();
953 } else {
954 ASSERT_LOG(stream_conf->sink_sample_frequency_hz ==
955 ase.codec_config.GetSamplingFrequencyHz(),
956 "sample freq mismatch: %d!=%d",
957 stream_conf->sink_sample_frequency_hz,
958 ase.codec_config.GetSamplingFrequencyHz());
959 }
960
961 if (stream_conf->sink_octets_per_codec_frame == 0) {
962 stream_conf->sink_octets_per_codec_frame =
963 *ase.codec_config.octets_per_codec_frame;
964 } else {
965 ASSERT_LOG(stream_conf->sink_octets_per_codec_frame ==
966 *ase.codec_config.octets_per_codec_frame,
967 "octets per frame mismatch: %d!=%d",
968 stream_conf->sink_octets_per_codec_frame,
969 *ase.codec_config.octets_per_codec_frame);
970 }
971
972 if (stream_conf->sink_codec_frames_blocks_per_sdu == 0) {
973 stream_conf->sink_codec_frames_blocks_per_sdu =
974 *ase.codec_config.codec_frames_blocks_per_sdu;
975 } else {
976 ASSERT_LOG(
977 stream_conf->sink_codec_frames_blocks_per_sdu ==
978 *ase.codec_config.codec_frames_blocks_per_sdu,
979 "codec_frames_blocks_per_sdu: %d!=%d",
980 stream_conf->sink_codec_frames_blocks_per_sdu,
981 *ase.codec_config.codec_frames_blocks_per_sdu);
982 }
983
984 LOG_INFO(
985 " Added Sink Stream Configuration. CIS Connection "
986 "Handle: %d"
987 ", Audio Channel Allocation: %d"
988 ", Sink Number Of Devices: %d"
989 ", Sink Number Of Channels: %d",
990 +ase.cis_conn_hdl,
991 +(*ase.codec_config.audio_channel_allocation),
992 +stream_conf->sink_num_of_devices,
993 +stream_conf->sink_num_of_channels);
994 }
995 }
996 }
997 }
998
999 // Inject the state
1000 group->SetTargetState(
1001 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1002 group->SetState(group->GetTargetState());
1003 streaming_groups[group->group_id_] = group;
1004
1005 /* Assume CIG is created */
1006 group->cig_state_ = le_audio::types::CigState::CREATED;
1007
1008 do_in_main_thread(
1009 FROM_HERE, base::BindOnce(
1010 [](int group_id,
1011 le_audio::LeAudioGroupStateMachine::Callbacks*
1012 state_machine_callbacks) {
1013 state_machine_callbacks->StatusReportCb(
1014 group_id, GroupStreamStatus::STREAMING);
1015 },
1016 group->group_id_,
1017 base::Unretained(this->state_machine_callbacks_)));
1018 return true;
1019 });
1020
1021 ON_CALL(mock_state_machine_, SuspendStream(_))
1022 .WillByDefault([this](LeAudioDeviceGroup* group) {
1023 // Fake ASE state
1024 for (LeAudioDevice* device = group->GetFirstDevice();
1025 device != nullptr; device = group->GetNextDevice(device)) {
1026 for (auto& ase : device->ases_) {
1027 ase.data_path_state =
1028 types::AudioStreamDataPathState::CIS_ESTABLISHED;
1029 ase.active = false;
1030 ase.state =
1031 types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED;
1032 }
1033 }
1034
1035 // Inject the state
1036 group->SetTargetState(
1037 types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1038 group->SetState(group->GetTargetState());
1039 state_machine_callbacks_->StatusReportCb(
1040 group->group_id_, GroupStreamStatus::SUSPENDED);
1041 });
1042
1043 ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
1044 .WillByDefault([this](LeAudioDeviceGroup* group,
1045 LeAudioDevice* leAudioDevice) {
1046 if (!group) return;
1047 auto* stream_conf = &group->stream_conf;
1048 if (!stream_conf->sink_streams.empty() ||
1049 !stream_conf->source_streams.empty()) {
1050 stream_conf->sink_streams.erase(
1051 std::remove_if(stream_conf->sink_streams.begin(),
1052 stream_conf->sink_streams.end(),
1053 [leAudioDevice, &stream_conf](auto& pair) {
1054 auto ases = leAudioDevice->GetAsesByCisConnHdl(
1055 pair.first);
1056 if (ases.sink) {
1057 stream_conf->sink_num_of_devices--;
1058 stream_conf->sink_num_of_channels -=
1059 ases.sink->codec_config.channel_count;
1060
1061 LOG_INFO(
1062 ", Source Number Of Devices: %d"
1063 ", Source Number Of Channels: %d",
1064 +stream_conf->source_num_of_devices,
1065 +stream_conf->source_num_of_channels);
1066 }
1067 return ases.sink;
1068 }),
1069 stream_conf->sink_streams.end());
1070
1071 stream_conf->source_streams.erase(
1072 std::remove_if(stream_conf->source_streams.begin(),
1073 stream_conf->source_streams.end(),
1074 [leAudioDevice, &stream_conf](auto& pair) {
1075 auto ases = leAudioDevice->GetAsesByCisConnHdl(
1076 pair.first);
1077 if (ases.source) {
1078 stream_conf->source_num_of_devices--;
1079 stream_conf->source_num_of_channels -=
1080 ases.source->codec_config.channel_count;
1081
1082 LOG_INFO(
1083 ", Source Number Of Devices: %d"
1084 ", Source Number Of Channels: %d",
1085 +stream_conf->source_num_of_devices,
1086 +stream_conf->source_num_of_channels);
1087 }
1088 return ases.source;
1089 }),
1090 stream_conf->source_streams.end());
1091 }
1092
1093 group->CigUnassignCis(leAudioDevice);
1094
1095 if (group->IsEmpty()) {
1096 group->cig_state_ = le_audio::types::CigState::NONE;
1097 InjectCigRemoved(group->group_id_);
1098 }
1099 });
1100
1101 ON_CALL(mock_state_machine_, ProcessHciNotifCisDisconnected(_, _, _))
1102 .WillByDefault(
1103 [](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
1104 const bluetooth::hci::iso_manager::cis_disconnected_evt* event) {
1105 if (!group) return;
1106 auto ases_pair =
1107 leAudioDevice->GetAsesByCisConnHdl(event->cis_conn_hdl);
1108 if (ases_pair.sink) {
1109 ases_pair.sink->data_path_state =
1110 types::AudioStreamDataPathState::CIS_ASSIGNED;
1111 ases_pair.sink->active = false;
1112 }
1113 if (ases_pair.source) {
1114 ases_pair.source->active = false;
1115 ases_pair.source->data_path_state =
1116 types::AudioStreamDataPathState::CIS_ASSIGNED;
1117 }
1118 /* Invalidate stream configuration if needed */
1119 auto* stream_conf = &group->stream_conf;
1120 if (!stream_conf->sink_streams.empty() ||
1121 !stream_conf->source_streams.empty()) {
1122 stream_conf->sink_streams.erase(
1123 std::remove_if(
1124 stream_conf->sink_streams.begin(),
1125 stream_conf->sink_streams.end(),
1126 [leAudioDevice, &stream_conf](auto& pair) {
1127 auto ases =
1128 leAudioDevice->GetAsesByCisConnHdl(pair.first);
1129
1130 LOG_INFO(
1131 ", sink ase to delete. Cis handle: %d"
1132 ", ase pointer: %p",
1133 +(int)(pair.first), +ases.sink);
1134 if (ases.sink) {
1135 stream_conf->sink_num_of_devices--;
1136 stream_conf->sink_num_of_channels -=
1137 ases.sink->codec_config.channel_count;
1138
1139 LOG_INFO(
1140 " Sink Number Of Devices: %d"
1141 ", Sink Number Of Channels: %d",
1142 +stream_conf->sink_num_of_devices,
1143 +stream_conf->sink_num_of_channels);
1144 }
1145 return ases.sink;
1146 }),
1147 stream_conf->sink_streams.end());
1148
1149 stream_conf->source_streams.erase(
1150 std::remove_if(
1151 stream_conf->source_streams.begin(),
1152 stream_conf->source_streams.end(),
1153 [leAudioDevice, &stream_conf](auto& pair) {
1154 auto ases =
1155 leAudioDevice->GetAsesByCisConnHdl(pair.first);
1156
1157 LOG_INFO(
1158 ", source to delete. Cis handle: %d"
1159 ", ase pointer: %p",
1160 +(int)(pair.first), ases.source);
1161 if (ases.source) {
1162 stream_conf->source_num_of_devices--;
1163 stream_conf->source_num_of_channels -=
1164 ases.source->codec_config.channel_count;
1165
1166 LOG_INFO(
1167 ", Source Number Of Devices: %d"
1168 ", Source Number Of Channels: %d",
1169 +stream_conf->source_num_of_devices,
1170 +stream_conf->source_num_of_channels);
1171 }
1172 return ases.source;
1173 }),
1174 stream_conf->source_streams.end());
1175 }
1176
1177 group->CigUnassignCis(leAudioDevice);
1178 });
1179
1180 ON_CALL(mock_state_machine_, StopStream(_))
1181 .WillByDefault([this](LeAudioDeviceGroup* group) {
1182 for (LeAudioDevice* device = group->GetFirstDevice();
1183 device != nullptr; device = group->GetNextDevice(device)) {
1184 /* Invalidate stream configuration if needed */
1185 auto* stream_conf = &group->stream_conf;
1186 if (!stream_conf->sink_streams.empty() ||
1187 !stream_conf->source_streams.empty()) {
1188 stream_conf->sink_streams.erase(
1189 std::remove_if(stream_conf->sink_streams.begin(),
1190 stream_conf->sink_streams.end(),
1191 [device, &stream_conf](auto& pair) {
1192 auto ases =
1193 device->GetAsesByCisConnHdl(pair.first);
1194
1195 LOG_INFO(
1196 ", sink ase to delete. Cis handle: %d"
1197 ", ase pointer: %p",
1198 +(int)(pair.first), +ases.sink);
1199 if (ases.sink) {
1200 stream_conf->sink_num_of_devices--;
1201 stream_conf->sink_num_of_channels -=
1202 ases.sink->codec_config.channel_count;
1203
1204 LOG_INFO(
1205 " Sink Number Of Devices: %d"
1206 ", Sink Number Of Channels: %d",
1207 +stream_conf->sink_num_of_devices,
1208 +stream_conf->sink_num_of_channels);
1209 }
1210 return ases.sink;
1211 }),
1212 stream_conf->sink_streams.end());
1213
1214 stream_conf->source_streams.erase(
1215 std::remove_if(
1216 stream_conf->source_streams.begin(),
1217 stream_conf->source_streams.end(),
1218 [device, &stream_conf](auto& pair) {
1219 auto ases = device->GetAsesByCisConnHdl(pair.first);
1220
1221 LOG_INFO(
1222 ", source to delete. Cis handle: %d"
1223 ", ase pointer: %p",
1224 +(int)(pair.first), +ases.source);
1225 if (ases.source) {
1226 stream_conf->source_num_of_devices--;
1227 stream_conf->source_num_of_channels -=
1228 ases.source->codec_config.channel_count;
1229
1230 LOG_INFO(
1231 ", Source Number Of Devices: %d"
1232 ", Source Number Of Channels: %d",
1233 +stream_conf->source_num_of_devices,
1234 +stream_conf->source_num_of_channels);
1235 }
1236 return ases.source;
1237 }),
1238 stream_conf->source_streams.end());
1239 }
1240
1241 group->CigUnassignCis(device);
1242
1243 for (auto& ase : device->ases_) {
1244 ase.data_path_state = types::AudioStreamDataPathState::IDLE;
1245 ase.active = false;
1246 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
1247 ase.cis_id = 0;
1248 ase.cis_conn_hdl = 0;
1249 }
1250 }
1251
1252 // Inject the state
1253 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
1254 group->SetState(group->GetTargetState());
1255 state_machine_callbacks_->StatusReportCb(
1256 group->group_id_, GroupStreamStatus::RELEASING);
1257
1258 do_in_main_thread(
1259 FROM_HERE,
1260 base::BindOnce(
1261 [](le_audio::LeAudioGroupStateMachine::Callbacks* cb,
1262 int group_id) {
1263 cb->StatusReportCb(group_id, GroupStreamStatus::IDLE);
1264 },
1265 state_machine_callbacks_, group->group_id_));
1266 });
1267 }
1268
SetUp()1269 void SetUp() override {
1270 init_message_loop_thread();
1271 ON_CALL(controller_interface_, SupportsBleConnectedIsochronousStreamCentral)
1272 .WillByDefault(Return(true));
1273 ON_CALL(controller_interface_,
1274 SupportsBleConnectedIsochronousStreamPeripheral)
1275 .WillByDefault(Return(true));
1276
1277 controller::SetMockControllerInterface(&controller_interface_);
1278 bluetooth::manager::SetMockBtmInterface(&mock_btm_interface_);
1279 gatt::SetMockBtaGattInterface(&mock_gatt_interface_);
1280 gatt::SetMockBtaGattQueue(&mock_gatt_queue_);
1281 bluetooth::storage::SetMockBtifStorageInterface(&mock_btif_storage_);
1282
1283 iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
1284 ASSERT_NE(iso_manager_, nullptr);
1285 iso_manager_->Start();
1286
1287 mock_iso_manager_ = MockIsoManager::GetInstance();
1288 ON_CALL(*mock_iso_manager_, RegisterCigCallbacks(_))
1289 .WillByDefault(SaveArg<0>(&cig_callbacks_));
1290
1291 SetUpMockAudioHal();
1292 SetUpMockGroups();
1293 SetUpMockGatt();
1294
1295 supported_snk_context_types_ = 0xffff;
1296 supported_src_context_types_ = 0xffff;
1297 le_audio::AudioSetConfigurationProvider::Initialize();
1298 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
1299 }
1300
TearDown()1301 void TearDown() override {
1302 if (is_audio_unicast_source_acquired) {
1303 if (unicast_source_hal_cb_ != nullptr) {
1304 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(1);
1305 }
1306 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
1307 }
1308
1309 if (is_audio_unicast_sink_acquired) {
1310 if (unicast_sink_hal_cb_ != nullptr) {
1311 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop).Times(1);
1312 }
1313 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
1314 }
1315
1316 // Message loop cleanup should wait for all the 'till now' scheduled calls
1317 // so it should be called right at the very begginning of teardown.
1318 cleanup_message_loop_thread();
1319
1320 // This is required since Stop() and Cleanup() may trigger some callbacks or
1321 // drop unique pointers to mocks we have raw pointer for and we want to
1322 // verify them all.
1323 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1324
1325 if (LeAudioClient::IsLeAudioClientRunning()) {
1326 EXPECT_CALL(mock_gatt_interface_, AppDeregister(gatt_if)).Times(1);
1327 LeAudioClient::Cleanup(base::DoNothing());
1328 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
1329 }
1330
1331 owned_mock_le_audio_sink_hal_client_.reset();
1332 owned_mock_le_audio_source_hal_client_.reset();
1333
1334 if (le_audio::AudioSetConfigurationProvider::Get())
1335 le_audio::AudioSetConfigurationProvider::Cleanup();
1336
1337 iso_manager_->Stop();
1338 }
1339
1340 protected:
1341 class MockDeviceWrapper {
1342 class IGattHandlers {
1343 public:
1344 // IGattHandlers() = default;
1345 virtual ~IGattHandlers() = default;
1346 virtual void OnReadCharacteristic(uint16_t handle, GATT_READ_OP_CB cb,
1347 void* cb_data) = 0;
1348 virtual void OnWriteCharacteristic(uint16_t handle,
1349 std::vector<uint8_t> value,
1350 tGATT_WRITE_TYPE write_type,
1351 GATT_WRITE_OP_CB cb,
1352 void* cb_data) = 0;
1353 };
1354
1355 public:
1356 struct csis_mock : public IGattHandlers {
1357 uint16_t start = 0;
1358 uint16_t end = 0;
1359 uint16_t sirk_char = 0;
1360 uint16_t sirk_ccc = 0;
1361 uint16_t size_char = 0;
1362 uint16_t size_ccc = 0;
1363 uint16_t lock_char = 0;
1364 uint16_t lock_ccc = 0;
1365 uint16_t rank_char = 0;
1366
1367 int rank = 0;
1368 int size = 0;
1369
1370 MOCK_METHOD((void), OnReadCharacteristic,
1371 (uint16_t handle, GATT_READ_OP_CB cb, void* cb_data),
1372 (override));
1373 MOCK_METHOD((void), OnWriteCharacteristic,
1374 (uint16_t handle, std::vector<uint8_t> value,
1375 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1376 void* cb_data),
1377 (override));
1378 };
1379
1380 struct cas_mock : public IGattHandlers {
1381 uint16_t start = 0;
1382 uint16_t end = 0;
1383 uint16_t csis_include = 0;
1384
1385 MOCK_METHOD((void), OnReadCharacteristic,
1386 (uint16_t handle, GATT_READ_OP_CB cb, void* cb_data),
1387 (override));
1388 MOCK_METHOD((void), OnWriteCharacteristic,
1389 (uint16_t handle, std::vector<uint8_t> value,
1390 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1391 void* cb_data),
1392 (override));
1393 };
1394
1395 struct pacs_mock : public IGattHandlers {
1396 uint16_t start = 0;
1397 uint16_t sink_pac_char = 0;
1398 uint16_t sink_pac_ccc = 0;
1399 uint16_t sink_audio_loc_char = 0;
1400 uint16_t sink_audio_loc_ccc = 0;
1401 uint16_t source_pac_char = 0;
1402 uint16_t source_pac_ccc = 0;
1403 uint16_t source_audio_loc_char = 0;
1404 uint16_t source_audio_loc_ccc = 0;
1405 uint16_t avail_contexts_char = 0;
1406 uint16_t avail_contexts_ccc = 0;
1407 uint16_t supp_contexts_char = 0;
1408 uint16_t supp_contexts_ccc = 0;
1409 uint16_t end = 0;
1410
1411 MOCK_METHOD((void), OnReadCharacteristic,
1412 (uint16_t handle, GATT_READ_OP_CB cb, void* cb_data),
1413 (override));
1414 MOCK_METHOD((void), OnWriteCharacteristic,
1415 (uint16_t handle, std::vector<uint8_t> value,
1416 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1417 void* cb_data),
1418 (override));
1419 };
1420
1421 struct ascs_mock : public IGattHandlers {
1422 uint16_t start = 0;
1423 uint16_t sink_ase_char[max_num_of_ases] = {0};
1424 uint16_t sink_ase_ccc[max_num_of_ases] = {0};
1425 uint16_t source_ase_char[max_num_of_ases] = {0};
1426 uint16_t source_ase_ccc[max_num_of_ases] = {0};
1427 uint16_t ctp_char = 0;
1428 uint16_t ctp_ccc = 0;
1429 uint16_t end = 0;
1430
1431 MOCK_METHOD((void), OnReadCharacteristic,
1432 (uint16_t handle, GATT_READ_OP_CB cb, void* cb_data),
1433 (override));
1434 MOCK_METHOD((void), OnWriteCharacteristic,
1435 (uint16_t handle, std::vector<uint8_t> value,
1436 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1437 void* cb_data),
1438 (override));
1439 };
1440
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)1441 MockDeviceWrapper(RawAddress addr, const std::list<gatt::Service>& services,
1442 std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,
1443 std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,
1444 std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,
1445 std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs)
1446 : addr(addr) {
1447 this->services = services;
1448 this->csis = std::move(csis);
1449 this->cas = std::move(cas);
1450 this->ascs = std::move(ascs);
1451 this->pacs = std::move(pacs);
1452 }
1453
~MockDeviceWrapper()1454 ~MockDeviceWrapper() {
1455 Mock::VerifyAndClearExpectations(csis.get());
1456 Mock::VerifyAndClearExpectations(cas.get());
1457 Mock::VerifyAndClearExpectations(ascs.get());
1458 Mock::VerifyAndClearExpectations(pacs.get());
1459 }
1460
1461 RawAddress addr;
1462 bool connected = false;
1463
1464 // A list of services and their useful params
1465 std::list<gatt::Service> services;
1466 std::unique_ptr<csis_mock> csis;
1467 std::unique_ptr<cas_mock> cas;
1468 std::unique_ptr<ascs_mock> ascs;
1469 std::unique_ptr<pacs_mock> pacs;
1470 };
1471
SyncOnMainLoop()1472 void SyncOnMainLoop() {
1473 // Wait for the main loop to flush
1474 // WARNING: Not tested with Timers pushing periodic tasks to the main loop
1475 while (num_async_tasks > 0)
1476 ;
1477 }
1478
ConnectLeAudio(const RawAddress & address,bool isEncrypted=true)1479 void ConnectLeAudio(const RawAddress& address, bool isEncrypted = true) {
1480 // by default indicate link as encrypted
1481 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(address, _))
1482 .WillByDefault(DoAll(Return(isEncrypted)));
1483
1484 EXPECT_CALL(mock_gatt_interface_,
1485 Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, _))
1486 .Times(1);
1487
1488 do_in_main_thread(
1489 FROM_HERE, base::Bind(&LeAudioClient::Connect,
1490 base::Unretained(LeAudioClient::Get()), address));
1491
1492 SyncOnMainLoop();
1493 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1494 }
1495
DisconnectLeAudio(const RawAddress & address,uint16_t conn_id)1496 void DisconnectLeAudio(const RawAddress& address, uint16_t conn_id) {
1497 SyncOnMainLoop();
1498 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
1499 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1500 OnConnectionState(ConnectionState::DISCONNECTED, address))
1501 .Times(1);
1502 do_in_main_thread(
1503 FROM_HERE, base::Bind(&LeAudioClient::Disconnect,
1504 base::Unretained(LeAudioClient::Get()), address));
1505 }
1506
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)1507 void ConnectCsisDevice(const RawAddress& addr, uint16_t conn_id,
1508 uint32_t sink_audio_allocation,
1509 uint32_t source_audio_allocation, uint8_t group_size,
1510 int group_id, uint8_t rank,
1511 bool connect_through_csis = false,
1512 bool new_device = true) {
1513 SetSampleDatabaseEarbudsValid(conn_id, addr, sink_audio_allocation,
1514 source_audio_allocation, default_channel_cnt,
1515 default_channel_cnt,
1516 0x0004, /* source sample freq 16khz */
1517 true, /*add_csis*/
1518 true, /*add_cas*/
1519 true, /*add_pacs*/
1520 true, /*add_ascs*/
1521 group_size, rank);
1522 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1523 OnConnectionState(ConnectionState::CONNECTED, addr))
1524 .Times(1);
1525
1526 if (new_device) {
1527 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1528 OnGroupNodeStatus(addr, group_id, GroupNodeStatus::ADDED))
1529 .Times(1);
1530 }
1531
1532 if (connect_through_csis) {
1533 // Add it the way CSIS would do: add to group and then connect
1534 do_in_main_thread(
1535 FROM_HERE,
1536 base::Bind(&LeAudioClient::GroupAddNode,
1537 base::Unretained(LeAudioClient::Get()), group_id, addr));
1538 ConnectLeAudio(addr);
1539 } else {
1540 // The usual connect
1541 // Since device has CSIS, lets add it here to groups already now
1542 groups[addr] = group_id;
1543 ConnectLeAudio(addr);
1544 InjectGroupDeviceAdded(addr, group_id);
1545 }
1546 }
1547
ConnectNonCsisDevice(const RawAddress & addr,uint16_t conn_id,uint32_t sink_audio_allocation,uint32_t source_audio_allocation)1548 void ConnectNonCsisDevice(const RawAddress& addr, uint16_t conn_id,
1549 uint32_t sink_audio_allocation,
1550 uint32_t source_audio_allocation) {
1551 SetSampleDatabaseEarbudsValid(
1552 conn_id, addr, sink_audio_allocation, source_audio_allocation,
1553 default_channel_cnt, default_channel_cnt, 0x0004,
1554 /* source sample freq 16khz */ false, /*add_csis*/
1555 true, /*add_cas*/
1556 true, /*add_pacs*/
1557 true, /*add_ascs*/
1558 0, 0);
1559 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1560 OnConnectionState(ConnectionState::CONNECTED, addr))
1561 .Times(1);
1562
1563 ConnectLeAudio(addr);
1564 }
1565
UpdateMetadata(audio_usage_t usage,audio_content_type_t content_type,bool reconfigure_existing_stream=false)1566 void UpdateMetadata(audio_usage_t usage, audio_content_type_t content_type,
1567 bool reconfigure_existing_stream = false) {
1568 std::vector<struct playback_track_metadata> source_metadata = {
1569 {{AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0},
1570 {AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0}}};
1571
1572 source_metadata[0].usage = usage;
1573 source_metadata[0].content_type = content_type;
1574
1575 if (reconfigure_existing_stream) {
1576 Expectation reconfigure = EXPECT_CALL(*mock_le_audio_source_hal_client_,
1577 SuspendedForReconfiguration())
1578 .Times(1);
1579 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest())
1580 .Times(1);
1581 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
1582 .Times(1)
1583 .After(reconfigure);
1584 } else {
1585 EXPECT_CALL(*mock_le_audio_source_hal_client_,
1586 SuspendedForReconfiguration())
1587 .Times(0);
1588 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
1589 .Times(0);
1590 }
1591
1592 ASSERT_NE(unicast_source_hal_cb_, nullptr);
1593 unicast_source_hal_cb_->OnAudioMetadataUpdate(source_metadata);
1594 }
1595
UpdateSourceMetadata(audio_source_t audio_source)1596 void UpdateSourceMetadata(audio_source_t audio_source) {
1597 std::vector<struct record_track_metadata> sink_metadata = {
1598 {{AUDIO_SOURCE_INVALID, 0.5, AUDIO_DEVICE_NONE, "00:11:22:33:44:55"},
1599 {AUDIO_SOURCE_MIC, 0.7, AUDIO_DEVICE_OUT_BLE_HEADSET,
1600 "AA:BB:CC:DD:EE:FF"}}};
1601
1602 sink_metadata[1].source = audio_source;
1603 unicast_sink_hal_cb_->OnAudioMetadataUpdate(sink_metadata);
1604 }
1605
SinkAudioResume(void)1606 void SinkAudioResume(void) {
1607 EXPECT_CALL(*mock_le_audio_source_hal_client_, ConfirmStreamingRequest())
1608 .Times(1);
1609 do_in_main_thread(FROM_HERE,
1610 base::BindOnce(
1611 [](LeAudioSourceAudioHalClient::Callbacks* cb) {
1612 cb->OnAudioResume();
1613 },
1614 unicast_source_hal_cb_));
1615
1616 SyncOnMainLoop();
1617 Mock::VerifyAndClearExpectations(&*mock_le_audio_source_hal_client_);
1618 }
1619
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)1620 void StartStreaming(audio_usage_t usage, audio_content_type_t content_type,
1621 int group_id,
1622 audio_source_t audio_source = AUDIO_SOURCE_INVALID,
1623 bool reconfigure_existing_stream = false) {
1624 ASSERT_NE(unicast_source_hal_cb_, nullptr);
1625
1626 UpdateMetadata(usage, content_type, reconfigure_existing_stream);
1627 if (audio_source != AUDIO_SOURCE_INVALID) {
1628 UpdateSourceMetadata(audio_source);
1629 }
1630
1631 /* Stream has been automatically restarted on UpdateMetadata */
1632 if (reconfigure_existing_stream) return;
1633
1634 SinkAudioResume();
1635 SyncOnMainLoop();
1636 Mock::VerifyAndClearExpectations(&mock_state_machine_);
1637
1638 if (usage == AUDIO_USAGE_VOICE_COMMUNICATION ||
1639 audio_source != AUDIO_SOURCE_INVALID) {
1640 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
1641 do_in_main_thread(FROM_HERE,
1642 base::BindOnce(
1643 [](LeAudioSinkAudioHalClient::Callbacks* cb) {
1644 cb->OnAudioResume();
1645 },
1646 unicast_sink_hal_cb_));
1647 }
1648 }
1649
StopStreaming(int group_id,bool suspend_source=false)1650 void StopStreaming(int group_id, bool suspend_source = false) {
1651 ASSERT_NE(unicast_source_hal_cb_, nullptr);
1652
1653 /* TODO We should have a way to confirm Stop() otherwise, audio framework
1654 * might have different state that it is in the le_audio code - as tearing
1655 * down CISes might take some time
1656 */
1657 std::promise<void> do_suspend_sink_promise;
1658 auto do_suspend_sink_future = do_suspend_sink_promise.get_future();
1659 /* It's enough to call only one resume even if it'll be bi-directional
1660 * streaming. First suspend will trigger GroupStop.
1661 *
1662 * There is no - 'only source receiver' scenario (e.g. single microphone).
1663 * If there will be such test oriented scenario, such resume choose logic
1664 * should be applied.
1665 */
1666 unicast_source_hal_cb_->OnAudioSuspend(std::move(do_suspend_sink_promise));
1667 do_suspend_sink_future.wait();
1668
1669 if (suspend_source) {
1670 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
1671 std::promise<void> do_suspend_source_promise;
1672 auto do_suspend_source_future = do_suspend_source_promise.get_future();
1673 unicast_sink_hal_cb_->OnAudioSuspend(
1674 std::move(do_suspend_source_promise));
1675 do_suspend_source_future.wait();
1676 }
1677 }
1678
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)1679 void set_sample_database(uint16_t conn_id, RawAddress addr,
1680 std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,
1681 std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,
1682 std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,
1683 std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs) {
1684 gatt::DatabaseBuilder bob;
1685
1686 /* Generic Access Service */
1687 bob.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
1688 /* Device Name Char. */
1689 bob.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00),
1690 GATT_CHAR_PROP_BIT_READ);
1691
1692 if (csis->start) {
1693 bool is_primary = true;
1694 bob.AddService(csis->start, csis->end, bluetooth::csis::kCsisServiceUuid,
1695 is_primary);
1696 if (csis->sirk_char) {
1697 bob.AddCharacteristic(
1698 csis->sirk_char, csis->sirk_char + 1,
1699 bluetooth::csis::kCsisSirkUuid,
1700 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
1701 if (csis->sirk_ccc)
1702 bob.AddDescriptor(csis->sirk_ccc,
1703 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1704 }
1705
1706 if (csis->size_char) {
1707 bob.AddCharacteristic(
1708 csis->size_char, csis->size_char + 1,
1709 bluetooth::csis::kCsisSizeUuid,
1710 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
1711 if (csis->size_ccc)
1712 bob.AddDescriptor(csis->size_ccc,
1713 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1714 }
1715
1716 if (csis->lock_char) {
1717 bob.AddCharacteristic(csis->lock_char, csis->lock_char + 1,
1718 bluetooth::csis::kCsisLockUuid,
1719 GATT_CHAR_PROP_BIT_READ |
1720 GATT_CHAR_PROP_BIT_NOTIFY |
1721 GATT_CHAR_PROP_BIT_WRITE);
1722 if (csis->lock_ccc)
1723 bob.AddDescriptor(csis->lock_ccc,
1724 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1725 }
1726
1727 if (csis->rank_char)
1728 bob.AddCharacteristic(csis->rank_char, csis->rank_char + 1,
1729 bluetooth::csis::kCsisRankUuid,
1730 GATT_CHAR_PROP_BIT_READ);
1731 }
1732
1733 if (cas->start) {
1734 bool is_primary = true;
1735 bob.AddService(cas->start, cas->end, le_audio::uuid::kCapServiceUuid,
1736 is_primary);
1737 // Include CSIS service inside
1738 if (cas->csis_include)
1739 bob.AddIncludedService(cas->csis_include,
1740 bluetooth::csis::kCsisServiceUuid, csis->start,
1741 csis->end);
1742 }
1743
1744 if (pacs->start) {
1745 bool is_primary = true;
1746 bob.AddService(pacs->start, pacs->end,
1747 le_audio::uuid::kPublishedAudioCapabilityServiceUuid,
1748 is_primary);
1749
1750 if (pacs->sink_pac_char) {
1751 bob.AddCharacteristic(
1752 pacs->sink_pac_char, pacs->sink_pac_char + 1,
1753 le_audio::uuid::kSinkPublishedAudioCapabilityCharacteristicUuid,
1754 GATT_CHAR_PROP_BIT_READ);
1755 if (pacs->sink_pac_ccc)
1756 bob.AddDescriptor(pacs->sink_pac_ccc,
1757 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1758 }
1759
1760 if (pacs->sink_audio_loc_char) {
1761 bob.AddCharacteristic(
1762 pacs->sink_audio_loc_char, pacs->sink_audio_loc_char + 1,
1763 le_audio::uuid::kSinkAudioLocationCharacteristicUuid,
1764 GATT_CHAR_PROP_BIT_READ);
1765 if (pacs->sink_audio_loc_ccc)
1766 bob.AddDescriptor(pacs->sink_audio_loc_ccc,
1767 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1768 }
1769
1770 if (pacs->source_pac_char) {
1771 bob.AddCharacteristic(
1772 pacs->source_pac_char, pacs->source_pac_char + 1,
1773 le_audio::uuid::kSourcePublishedAudioCapabilityCharacteristicUuid,
1774 GATT_CHAR_PROP_BIT_READ);
1775 if (pacs->source_pac_ccc)
1776 bob.AddDescriptor(pacs->source_pac_ccc,
1777 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1778 }
1779
1780 if (pacs->source_audio_loc_char) {
1781 bob.AddCharacteristic(
1782 pacs->source_audio_loc_char, pacs->source_audio_loc_char + 1,
1783 le_audio::uuid::kSourceAudioLocationCharacteristicUuid,
1784 GATT_CHAR_PROP_BIT_READ);
1785 if (pacs->source_audio_loc_ccc)
1786 bob.AddDescriptor(pacs->source_audio_loc_ccc,
1787 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1788 }
1789
1790 if (pacs->avail_contexts_char) {
1791 bob.AddCharacteristic(
1792 pacs->avail_contexts_char, pacs->avail_contexts_char + 1,
1793 le_audio::uuid::kAudioContextAvailabilityCharacteristicUuid,
1794 GATT_CHAR_PROP_BIT_READ);
1795 if (pacs->avail_contexts_ccc)
1796 bob.AddDescriptor(pacs->avail_contexts_ccc,
1797 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1798 }
1799
1800 if (pacs->supp_contexts_char) {
1801 bob.AddCharacteristic(
1802 pacs->supp_contexts_char, pacs->supp_contexts_char + 1,
1803 le_audio::uuid::kAudioSupportedContextCharacteristicUuid,
1804 GATT_CHAR_PROP_BIT_READ);
1805 if (pacs->supp_contexts_ccc)
1806 bob.AddDescriptor(pacs->supp_contexts_ccc,
1807 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1808 }
1809 }
1810
1811 if (ascs->start) {
1812 bool is_primary = true;
1813 bob.AddService(ascs->start, ascs->end,
1814 le_audio::uuid::kAudioStreamControlServiceUuid,
1815 is_primary);
1816 for (int i = 0; i < max_num_of_ases; i++) {
1817 if (ascs->sink_ase_char[i]) {
1818 bob.AddCharacteristic(ascs->sink_ase_char[i],
1819 ascs->sink_ase_char[i] + 1,
1820 le_audio::uuid::kSinkAudioStreamEndpointUuid,
1821 GATT_CHAR_PROP_BIT_READ);
1822 if (ascs->sink_ase_ccc[i])
1823 bob.AddDescriptor(ascs->sink_ase_ccc[i],
1824 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1825 }
1826 if (ascs->source_ase_char[i]) {
1827 bob.AddCharacteristic(ascs->source_ase_char[i],
1828 ascs->source_ase_char[i] + 1,
1829 le_audio::uuid::kSourceAudioStreamEndpointUuid,
1830 GATT_CHAR_PROP_BIT_READ);
1831 if (ascs->source_ase_ccc[i])
1832 bob.AddDescriptor(ascs->source_ase_ccc[i],
1833 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1834 }
1835 }
1836 if (ascs->ctp_char) {
1837 bob.AddCharacteristic(
1838 ascs->ctp_char, ascs->ctp_char + 1,
1839 le_audio::uuid::kAudioStreamEndpointControlPointCharacteristicUuid,
1840 GATT_CHAR_PROP_BIT_READ);
1841 if (ascs->ctp_ccc)
1842 bob.AddDescriptor(ascs->ctp_ccc,
1843 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
1844 }
1845 }
1846
1847 // Assign conn_id to a certain device - this does not mean it is connected
1848 auto dev_wrapper = std::make_unique<NiceMock<MockDeviceWrapper>>(
1849 addr, bob.Build().Services(), std::move(csis), std::move(cas),
1850 std::move(ascs), std::move(pacs));
1851 peer_devices.emplace(conn_id, std::move(dev_wrapper));
1852 }
1853
SetSampleDatabaseEmpty(uint16_t conn_id,RawAddress addr)1854 void SetSampleDatabaseEmpty(uint16_t conn_id, RawAddress addr) {
1855 auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
1856 auto cas = std::make_unique<NiceMock<MockDeviceWrapper::cas_mock>>();
1857 auto pacs = std::make_unique<NiceMock<MockDeviceWrapper::pacs_mock>>();
1858 auto ascs = std::make_unique<NiceMock<MockDeviceWrapper::ascs_mock>>();
1859 set_sample_database(conn_id, addr, std::move(csis), std::move(cas),
1860 std::move(ascs), std::move(pacs));
1861 }
1862
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)1863 void SetSampleDatabaseEarbudsValid(
1864 uint16_t conn_id, RawAddress addr, uint32_t sink_audio_allocation,
1865 uint32_t source_audio_allocation, uint8_t sink_channel_cnt = 0x03,
1866 uint8_t source_channel_cnt = 0x03, uint16_t sample_freq_mask = 0x0004,
1867 bool add_csis = true, bool add_cas = true, bool add_pacs = true,
1868 int add_ascs_cnt = 1, uint8_t set_size = 2, uint8_t rank = 1) {
1869 auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
1870 if (add_csis) {
1871 // attribute handles
1872 csis->start = 0x0010;
1873 csis->sirk_char = 0x0020;
1874 csis->sirk_ccc = 0x0022;
1875 csis->size_char = 0x0023;
1876 csis->size_ccc = 0x0025;
1877 csis->lock_char = 0x0026;
1878 csis->lock_ccc = 0x0028;
1879 csis->rank_char = 0x0029;
1880 csis->end = 0x0030;
1881 // other params
1882 csis->size = set_size;
1883 csis->rank = rank;
1884 }
1885
1886 auto cas = std::make_unique<NiceMock<MockDeviceWrapper::cas_mock>>();
1887 if (add_cas) {
1888 // attribute handles
1889 cas->start = 0x0040;
1890 if (add_csis) cas->csis_include = 0x0041;
1891 cas->end = 0x0050;
1892 // other params
1893 }
1894
1895 auto pacs = std::make_unique<NiceMock<MockDeviceWrapper::pacs_mock>>();
1896 if (add_pacs) {
1897 // attribute handles
1898 pacs->start = 0x0060;
1899 pacs->sink_pac_char = 0x0061;
1900 pacs->sink_pac_ccc = 0x0063;
1901 pacs->sink_audio_loc_char = 0x0064;
1902 pacs->sink_audio_loc_ccc = 0x0066;
1903 pacs->source_pac_char = 0x0067;
1904 pacs->source_pac_ccc = 0x0069;
1905 pacs->source_audio_loc_char = 0x0070;
1906 pacs->source_audio_loc_ccc = 0x0072;
1907 pacs->avail_contexts_char = 0x0073;
1908 pacs->avail_contexts_ccc = 0x0075;
1909 pacs->supp_contexts_char = 0x0076;
1910 pacs->supp_contexts_ccc = 0x0078;
1911 pacs->end = 0x0080;
1912 // other params
1913 }
1914
1915 auto ascs = std::make_unique<NiceMock<MockDeviceWrapper::ascs_mock>>();
1916 if (add_ascs_cnt > 0) {
1917 // attribute handles
1918 ascs->start = 0x0090;
1919 uint16_t handle = 0x0091;
1920 for (int i = 0; i < add_ascs_cnt; i++) {
1921 if (sink_audio_allocation != 0) {
1922 ascs->sink_ase_char[i] = handle;
1923 handle += 2;
1924 ascs->sink_ase_ccc[i] = handle;
1925 handle++;
1926 }
1927
1928 if (source_audio_allocation != 0) {
1929 ascs->source_ase_char[i] = handle;
1930 handle += 2;
1931 ascs->source_ase_ccc[i] = handle;
1932 handle++;
1933 }
1934 }
1935 ascs->ctp_char = handle;
1936 handle += 2;
1937 ascs->ctp_ccc = handle;
1938 handle++;
1939 ascs->end = handle;
1940 // other params
1941 }
1942
1943 set_sample_database(conn_id, addr, std::move(csis), std::move(cas),
1944 std::move(ascs), std::move(pacs));
1945
1946 if (add_pacs) {
1947 uint8_t snk_allocation[4];
1948 uint8_t src_allocation[4];
1949
1950 snk_allocation[0] = (uint8_t)(sink_audio_allocation);
1951 snk_allocation[1] = (uint8_t)(sink_audio_allocation >> 8);
1952 snk_allocation[2] = (uint8_t)(sink_audio_allocation >> 16);
1953 snk_allocation[3] = (uint8_t)(sink_audio_allocation >> 24);
1954
1955 src_allocation[0] = (uint8_t)(source_audio_allocation);
1956 src_allocation[1] = (uint8_t)(source_audio_allocation >> 8);
1957 src_allocation[2] = (uint8_t)(source_audio_allocation >> 16);
1958 src_allocation[3] = (uint8_t)(source_audio_allocation >> 24);
1959
1960 uint8_t sample_freq[2];
1961 sample_freq[0] = (uint8_t)(sample_freq_mask);
1962 sample_freq[1] = (uint8_t)(sample_freq_mask >> 8);
1963
1964 // Set pacs default read values
1965 ON_CALL(*peer_devices.at(conn_id)->pacs, OnReadCharacteristic(_, _, _))
1966 .WillByDefault(
1967 [this, conn_id, snk_allocation, src_allocation, sample_freq,
1968 sink_channel_cnt, source_channel_cnt](
1969 uint16_t handle, GATT_READ_OP_CB cb, void* cb_data) {
1970 auto& pacs = peer_devices.at(conn_id)->pacs;
1971 std::vector<uint8_t> value;
1972 if (handle == pacs->sink_pac_char + 1) {
1973 value = {
1974 // Num records
1975 0x02,
1976 // Codec_ID
1977 0x06,
1978 0x00,
1979 0x00,
1980 0x00,
1981 0x00,
1982 // Codec Spec. Caps. Len
1983 0x10,
1984 0x03, /* sample freq */
1985 0x01,
1986 sample_freq[0],
1987 sample_freq[1],
1988 0x02,
1989 0x02, /* frame duration */
1990 0x03,
1991 0x02, /* channel count */
1992 0x03,
1993 sink_channel_cnt,
1994 0x05,
1995 0x04,
1996 0x1E,
1997 0x00,
1998 0x78,
1999 0x00,
2000 // Metadata Length
2001 0x00,
2002 // Codec_ID
2003 0x06,
2004 0x00,
2005 0x00,
2006 0x00,
2007 0x00,
2008 // Codec Spec. Caps. Len
2009 0x10,
2010 0x03, /* sample freq */
2011 0x01,
2012 0x80, /* 48kHz */
2013 0x00,
2014 0x02, /* frame duration */
2015 0x02,
2016 0x03,
2017 0x02, /* channel count */
2018 0x03,
2019 sink_channel_cnt,
2020 0x05, /* octects per frame */
2021 0x04,
2022 0x78,
2023 0x00,
2024 0x78,
2025 0x00,
2026 // Metadata Length
2027 0x00,
2028 };
2029 } else if (handle == pacs->sink_audio_loc_char + 1) {
2030 value = {
2031 // Audio Locations
2032 snk_allocation[0],
2033 snk_allocation[1],
2034 snk_allocation[2],
2035 snk_allocation[3],
2036 };
2037 } else if (handle == pacs->source_pac_char + 1) {
2038 value = {
2039 // Num records
2040 0x02,
2041 // Codec_ID
2042 0x06,
2043 0x00,
2044 0x00,
2045 0x00,
2046 0x00,
2047 // Codec Spec. Caps. Len
2048 0x10,
2049 0x03,
2050 0x01,
2051 sample_freq[0],
2052 sample_freq[1],
2053 0x02,
2054 0x02,
2055 0x03,
2056 0x02,
2057 0x03,
2058 source_channel_cnt,
2059 0x05,
2060 0x04,
2061 0x1E,
2062 0x00,
2063 0x78,
2064 0x00,
2065 // Metadata Length
2066 0x00,
2067 // Codec_ID
2068 0x06,
2069 0x00,
2070 0x00,
2071 0x00,
2072 0x00,
2073 // Codec Spec. Caps. Len
2074 0x10,
2075 0x03,
2076 0x01,
2077 0x24,
2078 0x00,
2079 0x02,
2080 0x02,
2081 0x03,
2082 0x02,
2083 0x03,
2084 source_channel_cnt,
2085 0x05,
2086 0x04,
2087 0x1E,
2088 0x00,
2089 0x50,
2090 0x00,
2091 // Metadata Length
2092 0x00,
2093 };
2094 } else if (handle == pacs->source_audio_loc_char + 1) {
2095 value = {
2096 // Audio Locations
2097 src_allocation[0],
2098 src_allocation[1],
2099 src_allocation[2],
2100 src_allocation[3],
2101 };
2102 } else if (handle == pacs->avail_contexts_char + 1) {
2103 value = {
2104 // Sink Avail Contexts
2105 (uint8_t)(supported_snk_context_types_),
2106 (uint8_t)(supported_snk_context_types_ >> 8),
2107 // Source Avail Contexts
2108 (uint8_t)(supported_src_context_types_),
2109 (uint8_t)(supported_src_context_types_ >> 8),
2110 };
2111 } else if (handle == pacs->supp_contexts_char + 1) {
2112 value = {
2113 // Sink Avail Contexts
2114 (uint8_t)(supported_snk_context_types_),
2115 (uint8_t)(supported_snk_context_types_ >> 8),
2116 // Source Avail Contexts
2117 (uint8_t)(supported_src_context_types_),
2118 (uint8_t)(supported_src_context_types_ >> 8),
2119 };
2120 }
2121 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
2122 cb_data);
2123 });
2124 }
2125
2126 if (add_ascs_cnt > 0) {
2127 // Set ascs default read values
2128 ON_CALL(*peer_devices.at(conn_id)->ascs, OnReadCharacteristic(_, _, _))
2129 .WillByDefault([this, conn_id](uint16_t handle, GATT_READ_OP_CB cb,
2130 void* cb_data) {
2131 auto& ascs = peer_devices.at(conn_id)->ascs;
2132 std::vector<uint8_t> value;
2133 bool is_ase_sink_request = false;
2134 bool is_ase_src_request = false;
2135 uint8_t idx;
2136 for (idx = 0; idx < max_num_of_ases; idx++) {
2137 if (handle == ascs->sink_ase_char[idx] + 1) {
2138 is_ase_sink_request = true;
2139 break;
2140 }
2141 if (handle == ascs->source_ase_char[idx] + 1) {
2142 is_ase_src_request = true;
2143 break;
2144 }
2145 }
2146
2147 if (is_ase_sink_request) {
2148 value = {
2149 // ASE ID
2150 static_cast<uint8_t>(idx + 1),
2151 // State
2152 static_cast<uint8_t>(
2153 le_audio::types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE),
2154 // No Additional ASE params for IDLE state
2155 };
2156 } else if (is_ase_src_request) {
2157 value = {
2158 // ASE ID
2159 static_cast<uint8_t>(idx + 6),
2160 // State
2161 static_cast<uint8_t>(
2162 le_audio::types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE),
2163 // No Additional ASE params for IDLE state
2164 };
2165 }
2166 cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(),
2167 cb_data);
2168 });
2169 }
2170 }
2171
TestAudioDataTransfer(int group_id,uint8_t cis_count_out,uint8_t cis_count_in,int data_len,int in_data_len=40)2172 void TestAudioDataTransfer(int group_id, uint8_t cis_count_out,
2173 uint8_t cis_count_in, int data_len,
2174 int in_data_len = 40) {
2175 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2176
2177 // Expect two channels ISO Data to be sent
2178 std::vector<uint16_t> handles;
2179 EXPECT_CALL(*mock_iso_manager_, SendIsoData(_, _, _))
2180 .Times(cis_count_out)
2181 .WillRepeatedly(
2182 [&handles](uint16_t iso_handle, const uint8_t* data,
2183 uint16_t data_len) { handles.push_back(iso_handle); });
2184 std::vector<uint8_t> data(data_len);
2185 unicast_source_hal_cb_->OnAudioDataReady(data);
2186
2187 // Inject microphone data from group
2188 EXPECT_CALL(*mock_le_audio_sink_hal_client_, SendData(_, _))
2189 .Times(cis_count_in > 0 ? 1 : 0);
2190 ASSERT_EQ(streaming_groups.count(group_id), 1u);
2191
2192 if (cis_count_in) {
2193 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2194
2195 auto group = streaming_groups.at(group_id);
2196 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
2197 device = group->GetNextDevice(device)) {
2198 for (auto& ase : device->ases_) {
2199 if (ase.direction == le_audio::types::kLeAudioDirectionSource) {
2200 InjectIncomingIsoData(group_id, ase.cis_conn_hdl, in_data_len);
2201 --cis_count_in;
2202 if (!cis_count_in) break;
2203 }
2204 }
2205 if (!cis_count_in) break;
2206 }
2207 }
2208
2209 SyncOnMainLoop();
2210 std::sort(handles.begin(), handles.end());
2211 ASSERT_EQ(cis_count_in, 0);
2212 handles.clear();
2213
2214 Mock::VerifyAndClearExpectations(mock_iso_manager_);
2215 }
2216
InjectIncomingIsoData(uint16_t cig_id,uint16_t cis_con_hdl,size_t payload_size)2217 void InjectIncomingIsoData(uint16_t cig_id, uint16_t cis_con_hdl,
2218 size_t payload_size) {
2219 BT_HDR* bt_hdr = (BT_HDR*)malloc(sizeof(BT_HDR) + payload_size);
2220
2221 bt_hdr->offset = 0;
2222 bt_hdr->len = payload_size;
2223
2224 bluetooth::hci::iso_manager::cis_data_evt cis_evt;
2225 cis_evt.cig_id = cig_id;
2226 cis_evt.cis_conn_hdl = cis_con_hdl;
2227 cis_evt.ts = 0;
2228 cis_evt.evt_lost = 0;
2229 cis_evt.p_msg = bt_hdr;
2230
2231 ASSERT_NE(cig_callbacks_, nullptr);
2232 cig_callbacks_->OnCisEvent(
2233 bluetooth::hci::iso_manager::kIsoEventCisDataAvailable, &cis_evt);
2234 free(bt_hdr);
2235 }
2236
InjectCisDisconnected(uint16_t cig_id,uint16_t cis_con_hdl,uint8_t reason=0)2237 void InjectCisDisconnected(uint16_t cig_id, uint16_t cis_con_hdl,
2238 uint8_t reason = 0) {
2239 bluetooth::hci::iso_manager::cis_disconnected_evt cis_evt;
2240 cis_evt.cig_id = cig_id;
2241 cis_evt.cis_conn_hdl = cis_con_hdl;
2242 cis_evt.reason = reason;
2243
2244 ASSERT_NE(cig_callbacks_, nullptr);
2245 cig_callbacks_->OnCisEvent(
2246 bluetooth::hci::iso_manager::kIsoEventCisDisconnected, &cis_evt);
2247 }
2248
InjectCigRemoved(uint8_t cig_id)2249 void InjectCigRemoved(uint8_t cig_id) {
2250 bluetooth::hci::iso_manager::cig_remove_cmpl_evt evt;
2251 evt.status = 0;
2252 evt.cig_id = cig_id;
2253
2254 ASSERT_NE(cig_callbacks_, nullptr);
2255 cig_callbacks_->OnCisEvent(
2256 bluetooth::hci::iso_manager::kIsoEventCigOnRemoveCmpl, &evt);
2257 }
2258
2259 NiceMock<MockAudioHalClientCallbacks> mock_audio_hal_client_callbacks_;
2260 LeAudioSourceAudioHalClient::Callbacks* unicast_source_hal_cb_ = nullptr;
2261 LeAudioSinkAudioHalClient::Callbacks* unicast_sink_hal_cb_ = nullptr;
2262
2263 uint8_t default_channel_cnt = 0x03;
2264 uint8_t default_ase_cnt = 1;
2265
2266 NiceMock<MockCsisClient> mock_csis_client_module_;
2267 NiceMock<MockDeviceGroups> mock_groups_module_;
2268 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks_;
2269 NiceMock<MockLeAudioGroupStateMachine> mock_state_machine_;
2270
2271 NiceMock<MockFunction<void()>> mock_storage_load;
2272 NiceMock<MockFunction<bool()>> mock_hal_2_1_verifier;
2273
2274 NiceMock<controller::MockControllerInterface> controller_interface_;
2275 NiceMock<bluetooth::manager::MockBtmInterface> mock_btm_interface_;
2276 NiceMock<gatt::MockBtaGattInterface> mock_gatt_interface_;
2277 NiceMock<gatt::MockBtaGattQueue> mock_gatt_queue_;
2278 tBTA_GATTC_CBACK* gatt_callback;
2279 const uint8_t gatt_if = 0xfe;
2280 uint16_t global_conn_id = 1;
2281 le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks_;
2282 std::map<int, LeAudioDeviceGroup*> streaming_groups;
2283
2284 bluetooth::hci::IsoManager* iso_manager_;
2285 MockIsoManager* mock_iso_manager_;
2286 bluetooth::hci::iso_manager::CigCallbacks* cig_callbacks_ = nullptr;
2287 uint16_t iso_con_counter_ = 1;
2288
2289 uint16_t supported_snk_context_types_ = 0xffff;
2290 uint16_t supported_src_context_types_ = 0xffff;
2291
2292 NiceMock<bluetooth::storage::MockBtifStorageInterface> mock_btif_storage_;
2293
2294 std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>> peer_devices;
2295 std::list<int> group_locks;
2296 std::map<RawAddress, int> groups;
2297 };
2298
2299 class UnicastTest : public UnicastTestNoInit {
2300 protected:
SetUp()2301 void SetUp() override {
2302 UnicastTestNoInit::SetUp();
2303
2304 EXPECT_CALL(mock_hal_2_1_verifier, Call()).Times(1);
2305 EXPECT_CALL(mock_storage_load, Call()).Times(1);
2306
2307 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
2308 framework_encode_preference;
2309 BtaAppRegisterCallback app_register_callback;
2310 EXPECT_CALL(mock_gatt_interface_, AppRegister(_, _, _))
2311 .WillOnce(DoAll(SaveArg<0>(&gatt_callback),
2312 SaveArg<1>(&app_register_callback)));
2313 LeAudioClient::Initialize(
2314 &mock_audio_hal_client_callbacks_,
2315 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
2316 &mock_storage_load),
2317 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2318 &mock_hal_2_1_verifier),
2319 framework_encode_preference);
2320
2321 SyncOnMainLoop();
2322 ASSERT_TRUE(gatt_callback);
2323 ASSERT_TRUE(group_callbacks_);
2324 ASSERT_TRUE(app_register_callback);
2325 app_register_callback.Run(gatt_if, GATT_SUCCESS);
2326 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
2327 }
2328
TearDown()2329 void TearDown() override {
2330 groups.clear();
2331 UnicastTestNoInit::TearDown();
2332 }
2333 };
2334
GetTestAddress(uint8_t index)2335 RawAddress GetTestAddress(uint8_t index) {
2336 CHECK_LT(index, UINT8_MAX);
2337 RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}};
2338 return result;
2339 }
2340
TEST_F(UnicastTest,Initialize)2341 TEST_F(UnicastTest, Initialize) {
2342 ASSERT_NE(LeAudioClient::Get(), nullptr);
2343 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
2344 }
2345
TEST_F(UnicastTestNoInit,InitializeNoHal_2_1)2346 TEST_F(UnicastTestNoInit, InitializeNoHal_2_1) {
2347 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
2348
2349 // Report False when asked for Audio HAL 2.1 support
2350 ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool {
2351 return false;
2352 });
2353
2354 BtaAppRegisterCallback app_register_callback;
2355 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
2356 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
2357 SaveArg<1>(&app_register_callback)));
2358 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
2359 framework_encode_preference;
2360
2361 EXPECT_DEATH(
2362 LeAudioClient::Initialize(
2363 &mock_audio_hal_client_callbacks_,
2364 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
2365 &mock_storage_load),
2366 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2367 &mock_hal_2_1_verifier),
2368 framework_encode_preference),
2369 ", LE Audio Client requires Bluetooth Audio HAL V2.1 at least. Either "
2370 "disable LE Audio Profile, or update your HAL");
2371 }
2372
TEST_F(UnicastTest,ConnectOneEarbudEmpty)2373 TEST_F(UnicastTest, ConnectOneEarbudEmpty) {
2374 const RawAddress test_address0 = GetTestAddress(0);
2375 SetSampleDatabaseEmpty(1, test_address0);
2376 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2377 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
2378 .Times(1);
2379 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
2380 ConnectLeAudio(test_address0);
2381 }
2382
TEST_F(UnicastTest,ConnectOneEarbudNoPacs)2383 TEST_F(UnicastTest, ConnectOneEarbudNoPacs) {
2384 const RawAddress test_address0 = GetTestAddress(0);
2385 SetSampleDatabaseEarbudsValid(
2386 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
2387 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
2388 default_channel_cnt, 0x0004,
2389 /* source sample freq 16khz */ true, /*add_csis*/
2390 true, /*add_cas*/
2391 false, /*add_pacs*/
2392 default_ase_cnt /*add_ascs*/);
2393 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2394 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
2395 .Times(1);
2396 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
2397 ConnectLeAudio(test_address0);
2398 }
2399
TEST_F(UnicastTest,ConnectOneEarbudNoAscs)2400 TEST_F(UnicastTest, ConnectOneEarbudNoAscs) {
2401 const RawAddress test_address0 = GetTestAddress(0);
2402 SetSampleDatabaseEarbudsValid(
2403 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
2404 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
2405 default_channel_cnt, 0x0004,
2406 /* source sample freq 16khz */ true, /*add_csis*/
2407 true, /*add_cas*/
2408 true, /*add_pacs*/
2409 0 /*add_ascs*/);
2410 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2411 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
2412 .Times(1);
2413 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
2414 ConnectLeAudio(test_address0);
2415 }
2416
TEST_F(UnicastTest,ConnectOneEarbudNoCas)2417 TEST_F(UnicastTest, ConnectOneEarbudNoCas) {
2418 const RawAddress test_address0 = GetTestAddress(0);
2419 uint16_t conn_id = 1;
2420 SetSampleDatabaseEarbudsValid(
2421 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
2422 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
2423 default_channel_cnt, 0x0004,
2424 /* source sample freq 16khz */ true, /*add_csis*/
2425 false, /*add_cas*/
2426 true, /*add_pacs*/
2427 default_ase_cnt /*add_ascs*/);
2428
2429 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2430 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2431 .Times(1);
2432 ConnectLeAudio(test_address0);
2433 }
2434
TEST_F(UnicastTest,ConnectOneEarbudNoCsis)2435 TEST_F(UnicastTest, ConnectOneEarbudNoCsis) {
2436 const RawAddress test_address0 = GetTestAddress(0);
2437 SetSampleDatabaseEarbudsValid(
2438 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
2439 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
2440 default_channel_cnt, 0x0004,
2441 /* source sample freq 16khz */ false, /*add_csis*/
2442 true, /*add_cas*/
2443 true, /*add_pacs*/
2444 default_ase_cnt /*add_ascs*/);
2445 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2446 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2447 .Times(1);
2448 ConnectLeAudio(test_address0);
2449 }
2450
TEST_F(UnicastTest,ConnectDisconnectOneEarbud)2451 TEST_F(UnicastTest, ConnectDisconnectOneEarbud) {
2452 const RawAddress test_address0 = GetTestAddress(0);
2453 SetSampleDatabaseEarbudsValid(1, test_address0,
2454 codec_spec_conf::kLeAudioLocationStereo,
2455 codec_spec_conf::kLeAudioLocationStereo);
2456 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2457 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2458 .Times(1);
2459 ConnectLeAudio(test_address0);
2460 DisconnectLeAudio(test_address0, 1);
2461 }
2462
2463 /* same as above case except the disconnect is initiated by remote */
TEST_F(UnicastTest,ConnectRemoteDisconnectOneEarbud)2464 TEST_F(UnicastTest, ConnectRemoteDisconnectOneEarbud) {
2465 const RawAddress test_address0 = GetTestAddress(0);
2466 SetSampleDatabaseEarbudsValid(1, test_address0,
2467 codec_spec_conf::kLeAudioLocationStereo,
2468 codec_spec_conf::kLeAudioLocationStereo);
2469 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2470 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2471 .Times(1);
2472 ConnectLeAudio(test_address0);
2473 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2474 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
2475 .Times(1);
2476 /* For remote disconnection, expect stack to try background re-connect */
2477 EXPECT_CALL(mock_gatt_interface_,
2478 Open(gatt_if, test_address0,
2479 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
2480 .Times(1);
2481
2482 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2483 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2484 .Times(1);
2485 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
2486 SyncOnMainLoop();
2487
2488 /* For background connect, test needs to Inject Connected Event */
2489 InjectConnectedEvent(test_address0, 1);
2490 SyncOnMainLoop();
2491 }
2492
2493 /* same as above case except the disconnect is initiated by remote */
TEST_F(UnicastTest,ConnectRemoteDisconnectOnTimeoutOneEarbud)2494 TEST_F(UnicastTest, ConnectRemoteDisconnectOnTimeoutOneEarbud) {
2495 const RawAddress test_address0 = GetTestAddress(0);
2496 SetSampleDatabaseEarbudsValid(1, test_address0,
2497 codec_spec_conf::kLeAudioLocationStereo,
2498 codec_spec_conf::kLeAudioLocationStereo);
2499 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2500 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2501 .Times(1);
2502 ConnectLeAudio(test_address0);
2503 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2504 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
2505 .Times(1);
2506
2507 /* Remove default action on the direct connect */
2508 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
2509 .WillByDefault(Return());
2510
2511 /* For remote disconnection, expect stack to try background re-connect */
2512 EXPECT_CALL(mock_gatt_interface_,
2513 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
2514 .Times(1);
2515
2516 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2517 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2518 .Times(1);
2519 InjectDisconnectedEvent(1, GATT_CONN_TIMEOUT);
2520 SyncOnMainLoop();
2521
2522 /* For background connect, test needs to Inject Connected Event */
2523 InjectConnectedEvent(test_address0, 1);
2524 SyncOnMainLoop();
2525 }
2526
TEST_F(UnicastTest,ConnectTwoEarbudsCsisGrouped)2527 TEST_F(UnicastTest, ConnectTwoEarbudsCsisGrouped) {
2528 uint8_t group_size = 2;
2529 int group_id = 2;
2530
2531 // Report working CSIS
2532 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
2533 .WillByDefault(Return(true));
2534
2535 // First earbud
2536 const RawAddress test_address0 = GetTestAddress(0);
2537 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
2538 .Times(1);
2539 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
2540 codec_spec_conf::kLeAudioLocationFrontLeft,
2541 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
2542 group_id, 1 /* rank*/);
2543
2544 // Second earbud
2545 const RawAddress test_address1 = GetTestAddress(1);
2546 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
2547 .Times(1);
2548 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
2549 codec_spec_conf::kLeAudioLocationFrontRight,
2550 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
2551 group_id, 2 /* rank*/, true /*connect_through_csis*/);
2552
2553 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
2554
2555 /* for Target announcements AutoConnect is always there, until
2556 * device is removed
2557 */
2558 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false))
2559 .Times(0);
2560 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
2561 .Times(0);
2562
2563 // Verify grouping information
2564 std::vector<RawAddress> devs =
2565 LeAudioClient::Get()->GetGroupDevices(group_id);
2566 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
2567 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
2568
2569 DisconnectLeAudio(test_address0, 1);
2570 DisconnectLeAudio(test_address1, 2);
2571 }
2572
TEST_F(UnicastTest,ConnectTwoEarbudsCsisGroupUnknownAtConnect)2573 TEST_F(UnicastTest, ConnectTwoEarbudsCsisGroupUnknownAtConnect) {
2574 uint8_t group_size = 2;
2575 uint8_t group_id = 2;
2576
2577 // Report working CSIS
2578 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
2579 .WillByDefault(Return(true));
2580
2581 // First earbud connects without known grouping
2582 const RawAddress test_address0 = GetTestAddress(0);
2583 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
2584 .Times(1);
2585 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
2586 codec_spec_conf::kLeAudioLocationFrontLeft,
2587 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
2588 group_id, 1 /* rank*/);
2589
2590 // Second earbud
2591 const RawAddress test_address1 = GetTestAddress(1);
2592 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
2593 .Times(1);
2594 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
2595 codec_spec_conf::kLeAudioLocationFrontRight,
2596 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
2597 group_id, 2 /* rank*/, true /*connect_through_csis*/);
2598
2599 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
2600
2601 // Verify grouping information
2602 std::vector<RawAddress> devs =
2603 LeAudioClient::Get()->GetGroupDevices(group_id);
2604 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
2605 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
2606
2607 /* for Target announcements AutoConnect is always there, until
2608 * device is removed
2609 */
2610 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false))
2611 .Times(0);
2612 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
2613 .Times(0);
2614 DisconnectLeAudio(test_address0, 1);
2615 DisconnectLeAudio(test_address1, 2);
2616 }
2617
TEST_F(UnicastTestNoInit,LoadStoredEarbudsCsisGrouped)2618 TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) {
2619 // Prepare two devices
2620 uint8_t group_size = 2;
2621 uint8_t group_id = 2;
2622
2623 /* Prepare mock to not inject connect event so the device can stay in
2624 * CONNECTING state*/
2625 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
2626 .WillByDefault(DoAll(Return()));
2627
2628 const RawAddress test_address0 = GetTestAddress(0);
2629 SetSampleDatabaseEarbudsValid(
2630 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
2631 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
2632 default_channel_cnt, 0x0004,
2633 /* source sample freq 16khz */ true, /*add_csis*/
2634 true, /*add_cas*/
2635 true, /*add_pacs*/
2636 default_ase_cnt, /*add_ascs_cnt*/
2637 group_size, 1);
2638
2639 const RawAddress test_address1 = GetTestAddress(1);
2640 SetSampleDatabaseEarbudsValid(
2641 2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
2642 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
2643 default_channel_cnt, 0x0004,
2644 /* source sample freq 16khz */ true, /*add_csis*/
2645 true, /*add_cas*/
2646 true, /*add_pacs*/
2647 default_ase_cnt, /*add_ascs_cnt*/
2648 group_size, 2);
2649
2650 // Load devices from the storage when storage API is called
2651 bool autoconnect = true;
2652
2653 /* Common storage values */
2654 std::vector<uint8_t> handles;
2655 LeAudioClient::GetHandlesForStorage(test_address0, handles);
2656
2657 std::vector<uint8_t> ases;
2658 LeAudioClient::GetAsesForStorage(test_address0, ases);
2659
2660 std::vector<uint8_t> src_pacs;
2661 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
2662
2663 std::vector<uint8_t> snk_pacs;
2664 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
2665
2666 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
2667 do_in_main_thread(
2668 FROM_HERE,
2669 base::Bind(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
2670 codec_spec_conf::kLeAudioLocationFrontLeft,
2671 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
2672 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
2673 std::move(ases)));
2674 do_in_main_thread(
2675 FROM_HERE,
2676 base::Bind(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
2677 codec_spec_conf::kLeAudioLocationFrontRight,
2678 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
2679 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
2680 std::move(ases)));
2681 });
2682
2683 // Expect stored device0 to connect automatically (first directed connection )
2684 EXPECT_CALL(mock_gatt_interface_,
2685 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
2686 .Times(1);
2687
2688 // Expect stored device1 to connect automatically (first direct connection)
2689 EXPECT_CALL(mock_gatt_interface_,
2690 Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
2691 .Times(1);
2692
2693 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
2694 .WillByDefault(DoAll(Return(true)));
2695 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
2696 .WillByDefault(DoAll(Return(true)));
2697
2698 ON_CALL(mock_groups_module_, GetGroupId(_, _))
2699 .WillByDefault(DoAll(Return(group_id)));
2700
2701 ON_CALL(mock_btm_interface_,
2702 GetSecurityFlagsByTransport(test_address0, NotNull(), _))
2703 .WillByDefault(
2704 DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
2705
2706 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
2707 framework_encode_preference;
2708
2709 // Initialize
2710 BtaAppRegisterCallback app_register_callback;
2711 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
2712 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
2713 SaveArg<1>(&app_register_callback)));
2714 LeAudioClient::Initialize(
2715 &mock_audio_hal_client_callbacks_,
2716 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
2717 &mock_storage_load),
2718 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2719 &mock_hal_2_1_verifier),
2720 framework_encode_preference);
2721 if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS);
2722
2723 // We need to wait for the storage callback before verifying stuff
2724 SyncOnMainLoop();
2725 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
2726 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
2727
2728 // Simulate devices are not there and phone fallbacks to targeted
2729 // announcements
2730 EXPECT_CALL(mock_gatt_interface_,
2731 Open(gatt_if, test_address0,
2732 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
2733 .Times(1);
2734
2735 EXPECT_CALL(mock_gatt_interface_,
2736 Open(gatt_if, test_address1,
2737 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
2738 .Times(1);
2739
2740 // Devices not found
2741 InjectConnectedEvent(test_address0, 0, GATT_ERROR);
2742 InjectConnectedEvent(test_address1, 0, GATT_ERROR);
2743
2744 SyncOnMainLoop();
2745 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
2746
2747 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2748 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2749 .Times(1);
2750
2751 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2752 OnConnectionState(ConnectionState::CONNECTED, test_address1))
2753 .Times(1);
2754
2755 /* For background connect, test needs to Inject Connected Event */
2756 InjectConnectedEvent(test_address0, 1);
2757 InjectConnectedEvent(test_address1, 2);
2758
2759 // Verify if all went well and we got the proper group
2760 std::vector<RawAddress> devs =
2761 LeAudioClient::Get()->GetGroupDevices(group_id);
2762 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
2763 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
2764
2765 DisconnectLeAudio(test_address0, 1);
2766 DisconnectLeAudio(test_address1, 2);
2767 }
2768
TEST_F(UnicastTestNoInit,LoadStoredEarbudsCsisGroupedDifferently)2769 TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGroupedDifferently) {
2770 // Prepare two devices
2771 uint8_t group_size = 1;
2772
2773 // Device 0
2774 uint8_t group_id0 = 2;
2775 bool autoconnect0 = true;
2776 const RawAddress test_address0 = GetTestAddress(0);
2777 SetSampleDatabaseEarbudsValid(
2778 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
2779 codec_spec_conf::kLeAudioLocationFrontLeft, 0x0004,
2780 /* source sample freq 16khz */ true, /*add_csis*/
2781 true, /*add_cas*/
2782 true, /*add_pacs*/
2783 true, /*add_ascs*/
2784 group_size, 1);
2785
2786 ON_CALL(mock_groups_module_, GetGroupId(test_address0, _))
2787 .WillByDefault(DoAll(Return(group_id0)));
2788
2789 // Device 1
2790 uint8_t group_id1 = 3;
2791 bool autoconnect1 = false;
2792 const RawAddress test_address1 = GetTestAddress(1);
2793 SetSampleDatabaseEarbudsValid(
2794 2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
2795 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
2796 default_channel_cnt, 0x0004,
2797 /* source sample freq 16khz */ true, /*add_csis*/
2798 true, /*add_cas*/
2799 true, /*add_pacs*/
2800 default_ase_cnt, /*add_ascs_cnt*/
2801 group_size, 2);
2802
2803 ON_CALL(mock_groups_module_, GetGroupId(test_address1, _))
2804 .WillByDefault(DoAll(Return(group_id1)));
2805
2806 /* Commont storage values */
2807 std::vector<uint8_t> handles;
2808 LeAudioClient::GetHandlesForStorage(test_address0, handles);
2809
2810 std::vector<uint8_t> ases;
2811 LeAudioClient::GetAsesForStorage(test_address0, ases);
2812
2813 std::vector<uint8_t> src_pacs;
2814 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
2815
2816 std::vector<uint8_t> snk_pacs;
2817 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
2818
2819 // Load devices from the storage when storage API is called
2820 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
2821 do_in_main_thread(
2822 FROM_HERE,
2823 base::Bind(&LeAudioClient::AddFromStorage, test_address0, autoconnect0,
2824 codec_spec_conf::kLeAudioLocationFrontLeft,
2825 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
2826 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
2827 std::move(ases)));
2828 do_in_main_thread(
2829 FROM_HERE,
2830 base::Bind(&LeAudioClient::AddFromStorage, test_address1, autoconnect1,
2831 codec_spec_conf::kLeAudioLocationFrontRight,
2832 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
2833 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
2834 std::move(ases)));
2835 });
2836
2837 // Expect stored device0 to connect automatically
2838 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2839 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2840 .Times(1);
2841 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
2842 .WillByDefault(DoAll(Return(true)));
2843 EXPECT_CALL(mock_gatt_interface_,
2844 Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
2845 .Times(1);
2846
2847 // Expect stored device1 to NOT connect automatically
2848 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2849 OnConnectionState(ConnectionState::CONNECTED, test_address1))
2850 .Times(0);
2851 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
2852 .WillByDefault(DoAll(Return(true)));
2853 EXPECT_CALL(mock_gatt_interface_,
2854 Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
2855 .Times(0);
2856
2857 // Initialize
2858 BtaAppRegisterCallback app_register_callback;
2859 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
2860 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback),
2861 SaveArg<1>(&app_register_callback)));
2862 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t>
2863 framework_encode_preference;
2864 LeAudioClient::Initialize(
2865 &mock_audio_hal_client_callbacks_,
2866 base::Bind([](MockFunction<void()>* foo) { foo->Call(); },
2867 &mock_storage_load),
2868 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2869 &mock_hal_2_1_verifier),
2870 framework_encode_preference);
2871 if (app_register_callback) app_register_callback.Run(gatt_if, GATT_SUCCESS);
2872
2873 // We need to wait for the storage callback before verifying stuff
2874 SyncOnMainLoop();
2875 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
2876 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
2877
2878 // Simulate device is not there and phone fallbacks to targeted announcements
2879 EXPECT_CALL(mock_gatt_interface_,
2880 Open(gatt_if, test_address0,
2881 BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
2882 .Times(1);
2883
2884 // Devices not found
2885 InjectConnectedEvent(test_address0, 0, GATT_ERROR);
2886
2887 SyncOnMainLoop();
2888 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
2889
2890 /* For background connect, test needs to Inject Connected Event */
2891 InjectConnectedEvent(test_address0, 1);
2892
2893 // We need to wait for the storage callback before verifying stuff
2894 SyncOnMainLoop();
2895 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
2896
2897 std::vector<RawAddress> devs =
2898 LeAudioClient::Get()->GetGroupDevices(group_id0);
2899 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
2900 ASSERT_EQ(std::find(devs.begin(), devs.end(), test_address1), devs.end());
2901
2902 devs = LeAudioClient::Get()->GetGroupDevices(group_id1);
2903 ASSERT_EQ(std::find(devs.begin(), devs.end(), test_address0), devs.end());
2904 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
2905
2906 DisconnectLeAudio(test_address0, 1);
2907 }
2908
TEST_F(UnicastTest,GroupingAddRemove)2909 TEST_F(UnicastTest, GroupingAddRemove) {
2910 // Earbud connects without known grouping
2911 uint8_t group_id0 = bluetooth::groups::kGroupUnknown;
2912 const RawAddress test_address0 = GetTestAddress(0);
2913
2914 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
2915 .Times(1);
2916 ConnectNonCsisDevice(test_address0, 1 /*conn_id*/,
2917 codec_spec_conf::kLeAudioLocationFrontLeft,
2918 codec_spec_conf::kLeAudioLocationFrontLeft);
2919
2920 group_id0 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
2921
2922 // Earbud connects without known grouping
2923 uint8_t group_id1 = bluetooth::groups::kGroupUnknown;
2924 const RawAddress test_address1 = GetTestAddress(1);
2925 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
2926 .Times(1);
2927 ConnectNonCsisDevice(test_address1, 2 /*conn_id*/,
2928 codec_spec_conf::kLeAudioLocationFrontRight,
2929 codec_spec_conf::kLeAudioLocationFrontRight);
2930
2931 group_id1 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
2932
2933 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
2934
2935 // Verify individual groups
2936 ASSERT_NE(group_id0, bluetooth::groups::kGroupUnknown);
2937 ASSERT_NE(group_id1, bluetooth::groups::kGroupUnknown);
2938 ASSERT_NE(group_id0, group_id1);
2939 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 1u);
2940 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 1u);
2941
2942 // Expectations on reassigning second earbud to the first group
2943 int dev1_storage_group = bluetooth::groups::kGroupUnknown;
2944 int dev1_new_group = bluetooth::groups::kGroupUnknown;
2945
2946 EXPECT_CALL(
2947 mock_audio_hal_client_callbacks_,
2948 OnGroupNodeStatus(test_address1, group_id1, GroupNodeStatus::REMOVED))
2949 .Times(AtLeast(1));
2950 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2951 OnGroupNodeStatus(test_address1, _, GroupNodeStatus::ADDED))
2952 .WillRepeatedly(SaveArg<1>(&dev1_new_group));
2953 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id1))
2954 .Times(AtLeast(1));
2955 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, _))
2956 .Times(AnyNumber());
2957
2958 LeAudioClient::Get()->GroupRemoveNode(group_id1, test_address1);
2959 SyncOnMainLoop();
2960
2961 Mock::VerifyAndClearExpectations(&mock_groups_module_);
2962 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
2963
2964 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, group_id0))
2965 .Times(1);
2966
2967 LeAudioClient::Get()->GroupAddNode(group_id0, test_address1);
2968 SyncOnMainLoop();
2969 Mock::VerifyAndClearExpectations(&mock_groups_module_);
2970
2971 dev1_storage_group =
2972 MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
2973
2974 // Verify regrouping results
2975 EXPECT_EQ(dev1_new_group, group_id0);
2976 EXPECT_EQ(dev1_new_group, dev1_storage_group);
2977 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 0u);
2978 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 2u);
2979 std::vector<RawAddress> devs =
2980 LeAudioClient::Get()->GetGroupDevices(group_id0);
2981 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
2982 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
2983 }
2984
TEST_F(UnicastTest,RemoveNodeWhileStreaming)2985 TEST_F(UnicastTest, RemoveNodeWhileStreaming) {
2986 const RawAddress test_address0 = GetTestAddress(0);
2987 int group_id = bluetooth::groups::kGroupUnknown;
2988
2989 SetSampleDatabaseEarbudsValid(
2990 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
2991 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
2992 default_channel_cnt, 0x0004,
2993 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
2994 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
2995 0 /*rank*/);
2996 EXPECT_CALL(mock_audio_hal_client_callbacks_,
2997 OnConnectionState(ConnectionState::CONNECTED, test_address0))
2998 .Times(1);
2999 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3000 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
3001 .WillOnce(DoAll(SaveArg<1>(&group_id)));
3002
3003 ConnectLeAudio(test_address0);
3004 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
3005
3006 // Start streaming
3007 constexpr uint8_t cis_count_out = 1;
3008 constexpr uint8_t cis_count_in = 0;
3009
3010 constexpr int gmcs_ccid = 1;
3011 constexpr int gtbs_ccid = 2;
3012
3013 // Audio sessions are started only when device gets active
3014 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
3015 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
3016 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
3017 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
3018 LeAudioClient::Get()->GroupSetActive(group_id);
3019
3020 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
3021 .source = {}};
3022 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
3023
3024 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
3025
3026 SyncOnMainLoop();
3027 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3028 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3029 Mock::VerifyAndClearExpectations(&mock_state_machine_);
3030 SyncOnMainLoop();
3031
3032 // Verify Data transfer on one audio source cis
3033 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
3034
3035 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id))
3036 .Times(1);
3037 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
3038 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
3039 .Times(0);
3040 EXPECT_CALL(
3041 mock_audio_hal_client_callbacks_,
3042 OnGroupNodeStatus(test_address0, group_id, GroupNodeStatus::REMOVED));
3043 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3044 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3045 .Times(0);
3046
3047 LeAudioClient::Get()->GroupRemoveNode(group_id, test_address0);
3048
3049 SyncOnMainLoop();
3050 Mock::VerifyAndClearExpectations(&mock_groups_module_);
3051 Mock::VerifyAndClearExpectations(&mock_state_machine_);
3052 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3053 }
3054
TEST_F(UnicastTest,GroupingAddTwiceNoRemove)3055 TEST_F(UnicastTest, GroupingAddTwiceNoRemove) {
3056 // Earbud connects without known grouping
3057 uint8_t group_id0 = bluetooth::groups::kGroupUnknown;
3058 const RawAddress test_address0 = GetTestAddress(0);
3059 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3060 .WillOnce(Return())
3061 .RetiresOnSaturation();
3062 ConnectNonCsisDevice(test_address0, 1 /*conn_id*/,
3063 codec_spec_conf::kLeAudioLocationFrontLeft,
3064 codec_spec_conf::kLeAudioLocationFrontLeft);
3065
3066 group_id0 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
3067
3068 // Earbud connects without known grouping
3069 uint8_t group_id1 = bluetooth::groups::kGroupUnknown;
3070 const RawAddress test_address1 = GetTestAddress(1);
3071 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
3072 .WillOnce(Return())
3073 .RetiresOnSaturation();
3074 ConnectNonCsisDevice(test_address1, 2 /*conn_id*/,
3075 codec_spec_conf::kLeAudioLocationFrontRight,
3076 codec_spec_conf::kLeAudioLocationFrontRight);
3077
3078 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3079
3080 group_id1 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
3081 // Verify individual groups
3082 ASSERT_NE(group_id0, bluetooth::groups::kGroupUnknown);
3083 ASSERT_NE(group_id1, bluetooth::groups::kGroupUnknown);
3084 ASSERT_NE(group_id0, group_id1);
3085 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 1u);
3086 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 1u);
3087
3088 // Expectations on reassigning second earbud to the first group
3089 int dev1_storage_group = bluetooth::groups::kGroupUnknown;
3090 int dev1_new_group = bluetooth::groups::kGroupUnknown;
3091
3092 EXPECT_CALL(
3093 mock_audio_hal_client_callbacks_,
3094 OnGroupNodeStatus(test_address1, group_id1, GroupNodeStatus::REMOVED))
3095 .Times(AtLeast(1));
3096 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3097 OnGroupNodeStatus(test_address1, _, GroupNodeStatus::ADDED))
3098 .WillRepeatedly(SaveArg<1>(&dev1_new_group));
3099
3100 // FIXME: We should expect removal with group_id context. No such API exists.
3101 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id1))
3102 .Times(AtLeast(1));
3103 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, _))
3104 .Times(AnyNumber());
3105 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, group_id0))
3106 .Times(1);
3107
3108 // Regroup device: assign new group without removing it from the first one
3109 LeAudioClient::Get()->GroupAddNode(group_id0, test_address1);
3110 SyncOnMainLoop();
3111 Mock::VerifyAndClearExpectations(&mock_groups_module_);
3112
3113 dev1_storage_group =
3114 MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
3115
3116 // Verify regrouping results
3117 EXPECT_EQ(dev1_new_group, group_id0);
3118 EXPECT_EQ(dev1_new_group, dev1_storage_group);
3119 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 0u);
3120 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 2u);
3121 std::vector<RawAddress> devs =
3122 LeAudioClient::Get()->GetGroupDevices(group_id0);
3123 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3124 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3125 }
3126
TEST_F(UnicastTest,RemoveTwoEarbudsCsisGrouped)3127 TEST_F(UnicastTest, RemoveTwoEarbudsCsisGrouped) {
3128 uint8_t group_size = 2;
3129 int group_id0 = 2;
3130 int group_id1 = 3;
3131
3132 // Report working CSIS
3133 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
3134 .WillByDefault(Return(true));
3135
3136 // First group - First earbud
3137 const RawAddress test_address0 = GetTestAddress(0);
3138 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3139 .Times(1);
3140 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
3141 codec_spec_conf::kLeAudioLocationFrontLeft,
3142 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
3143 group_id0, 1 /* rank*/);
3144
3145 // First group - Second earbud
3146 const RawAddress test_address1 = GetTestAddress(1);
3147 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
3148 .Times(1);
3149 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
3150 codec_spec_conf::kLeAudioLocationFrontRight,
3151 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
3152 group_id0, 2 /* rank*/, true /*connect_through_csis*/);
3153
3154 // Second group - First earbud
3155 const RawAddress test_address2 = GetTestAddress(2);
3156 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address2, true))
3157 .Times(1);
3158 ConnectCsisDevice(test_address2, 3 /*conn_id*/,
3159 codec_spec_conf::kLeAudioLocationFrontLeft,
3160 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
3161 group_id1, 1 /* rank*/);
3162
3163 // Second group - Second earbud
3164 const RawAddress test_address3 = GetTestAddress(3);
3165 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address3, true))
3166 .Times(1);
3167 ConnectCsisDevice(test_address3, 4 /*conn_id*/,
3168 codec_spec_conf::kLeAudioLocationFrontRight,
3169 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
3170 group_id1, 2 /* rank*/, true /*connect_through_csis*/);
3171
3172 // First group - verify grouping information
3173 std::vector<RawAddress> group0_devs =
3174 LeAudioClient::Get()->GetGroupDevices(group_id0);
3175 ASSERT_NE(std::find(group0_devs.begin(), group0_devs.end(), test_address0),
3176 group0_devs.end());
3177 ASSERT_NE(std::find(group0_devs.begin(), group0_devs.end(), test_address1),
3178 group0_devs.end());
3179
3180 // Second group - verify grouping information
3181 std::vector<RawAddress> group1_devs =
3182 LeAudioClient::Get()->GetGroupDevices(group_id1);
3183 ASSERT_NE(std::find(group1_devs.begin(), group1_devs.end(), test_address2),
3184 group1_devs.end());
3185 ASSERT_NE(std::find(group1_devs.begin(), group1_devs.end(), test_address3),
3186 group1_devs.end());
3187 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3188
3189 // Expect one of the groups to be dropped and devices to be disconnected
3190 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id0))
3191 .Times(1);
3192 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id0))
3193 .Times(1);
3194 EXPECT_CALL(
3195 mock_audio_hal_client_callbacks_,
3196 OnGroupNodeStatus(test_address0, group_id0, GroupNodeStatus::REMOVED));
3197 EXPECT_CALL(
3198 mock_audio_hal_client_callbacks_,
3199 OnGroupNodeStatus(test_address1, group_id0, GroupNodeStatus::REMOVED));
3200 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3201 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3202 .Times(1);
3203 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3204 OnConnectionState(ConnectionState::DISCONNECTED, test_address1))
3205 .Times(1);
3206
3207 // Expect the other groups to be left as is
3208 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id1, _))
3209 .Times(0);
3210 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3211 OnConnectionState(ConnectionState::DISCONNECTED, test_address2))
3212 .Times(0);
3213 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3214 OnConnectionState(ConnectionState::DISCONNECTED, test_address3))
3215 .Times(0);
3216
3217 do_in_main_thread(
3218 FROM_HERE, base::Bind(&LeAudioClient::GroupDestroy,
3219 base::Unretained(LeAudioClient::Get()), group_id0));
3220
3221 SyncOnMainLoop();
3222 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3223 }
3224
TEST_F(UnicastTest,RemoveDeviceWhenConnected)3225 TEST_F(UnicastTest, RemoveDeviceWhenConnected) {
3226 const RawAddress test_address0 = GetTestAddress(0);
3227 int group_id = bluetooth::groups::kGroupUnknown;
3228 uint16_t conn_id = 1;
3229
3230 SetSampleDatabaseEarbudsValid(
3231 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3232 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3233 default_channel_cnt, 0x0004,
3234 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3235 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3236 0 /*rank*/);
3237 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3238 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3239 .Times(1);
3240 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3241 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
3242 .WillOnce(DoAll(SaveArg<1>(&group_id)));
3243 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3244 .Times(1);
3245 ConnectLeAudio(test_address0);
3246 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
3247
3248 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3249 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3250
3251 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
3252 .Times(1);
3253 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
3254 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3255
3256 /*
3257 * StopStream will put calls on main_loop so to keep the correct order
3258 * of operations and to avoid races we put the test command on main_loop as
3259 * well.
3260 */
3261 do_in_main_thread(FROM_HERE, base::BindOnce(
3262 [](LeAudioClient* client,
3263 const RawAddress& test_address0) {
3264 client->RemoveDevice(test_address0);
3265 },
3266 LeAudioClient::Get(), test_address0));
3267 SyncOnMainLoop();
3268
3269 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3270 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
3271 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3272 }
3273
TEST_F(UnicastTest,RemoveDeviceWhenConnecting)3274 TEST_F(UnicastTest, RemoveDeviceWhenConnecting) {
3275 const RawAddress test_address0 = GetTestAddress(0);
3276 uint16_t conn_id = 1;
3277
3278 /* Prepare mock to not inject connect event so the device can stay in
3279 * CONNECTING state*/
3280 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
3281 .WillByDefault(DoAll(Return()));
3282
3283 SetSampleDatabaseEarbudsValid(
3284 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3285 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3286 default_channel_cnt, 0x0004,
3287 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3288 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3289 0 /*rank*/);
3290 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3291 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3292 .Times(0);
3293 ConnectLeAudio(test_address0);
3294
3295 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3296
3297 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true))
3298 .Times(1);
3299 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
3300 .Times(1);
3301
3302 /*
3303 * StopStream will put calls on main_loop so to keep the correct order
3304 * of operations and to avoid races we put the test command on main_loop as
3305 * well.
3306 */
3307 do_in_main_thread(FROM_HERE, base::BindOnce(
3308 [](LeAudioClient* client,
3309 const RawAddress& test_address0) {
3310 client->RemoveDevice(test_address0);
3311 },
3312 LeAudioClient::Get(), test_address0));
3313
3314 SyncOnMainLoop();
3315
3316 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3317 }
3318
TEST_F(UnicastTest,RemoveDeviceWhenGettingConnectionReady)3319 TEST_F(UnicastTest, RemoveDeviceWhenGettingConnectionReady) {
3320 const RawAddress test_address0 = GetTestAddress(0);
3321 uint16_t conn_id = 1;
3322
3323 /* Prepare mock to not inject Service Search Complete*/
3324 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
3325 .WillByDefault(DoAll(Return()));
3326
3327 SetSampleDatabaseEarbudsValid(
3328 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3329 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3330 default_channel_cnt, 0x0004,
3331 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3332 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3333 0 /*rank*/);
3334 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3335 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3336 .Times(0);
3337 ConnectLeAudio(test_address0);
3338
3339 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3340
3341 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
3342 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3343 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
3344 .Times(1);
3345
3346 /*
3347 * StopStream will put calls on main_loop so to keep the correct order
3348 * of operations and to avoid races we put the test command on main_loop as
3349 * well.
3350 */
3351 do_in_main_thread(FROM_HERE, base::BindOnce(
3352 [](LeAudioClient* client,
3353 const RawAddress& test_address0) {
3354 client->RemoveDevice(test_address0);
3355 },
3356 LeAudioClient::Get(), test_address0));
3357
3358 SyncOnMainLoop();
3359
3360 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3361 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3362 }
3363
TEST_F(UnicastTest,DisconnectDeviceWhenConnected)3364 TEST_F(UnicastTest, DisconnectDeviceWhenConnected) {
3365 const RawAddress test_address0 = GetTestAddress(0);
3366 int group_id = bluetooth::groups::kGroupUnknown;
3367 uint16_t conn_id = 1;
3368
3369 SetSampleDatabaseEarbudsValid(
3370 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3371 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3372 default_channel_cnt, 0x0004,
3373 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3374 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3375 0 /*rank*/);
3376 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3377 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3378 .Times(1);
3379 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3380 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
3381 .WillOnce(DoAll(SaveArg<1>(&group_id)));
3382 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3383 .Times(1);
3384 ConnectLeAudio(test_address0);
3385 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
3386
3387 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3388 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3389
3390 /* for Target announcements AutoConnect is always there, until
3391 * device is removed
3392 */
3393 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false))
3394 .Times(0);
3395 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
3396 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3397
3398 LeAudioClient::Get()->Disconnect(test_address0);
3399 SyncOnMainLoop();
3400
3401 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3402 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
3403 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3404 }
3405
TEST_F(UnicastTest,DisconnectDeviceWhenConnecting)3406 TEST_F(UnicastTest, DisconnectDeviceWhenConnecting) {
3407 const RawAddress test_address0 = GetTestAddress(0);
3408 uint16_t conn_id = 1;
3409
3410 /* Prepare mock to not inject connect event so the device can stay in
3411 * CONNECTING state*/
3412 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
3413 .WillByDefault(DoAll(Return()));
3414
3415 SetSampleDatabaseEarbudsValid(
3416 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3417 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3418 default_channel_cnt, 0x0004,
3419 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3420 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3421 0 /*rank*/);
3422 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3423 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3424 .Times(0);
3425 ConnectLeAudio(test_address0);
3426
3427 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3428
3429 /* Prepare on call mock on Close - to not trigger Inject Disconnection, as it
3430 * is done in default mock.
3431 */
3432 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
3433 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true))
3434 .Times(1);
3435
3436 LeAudioClient::Get()->Disconnect(test_address0);
3437
3438 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3439 }
3440
TEST_F(UnicastTest,DisconnectDeviceWhenGettingConnectionReady)3441 TEST_F(UnicastTest, DisconnectDeviceWhenGettingConnectionReady) {
3442 const RawAddress test_address0 = GetTestAddress(0);
3443 uint16_t conn_id = global_conn_id;
3444
3445 /* Prepare mock to not inject Service Search Complete*/
3446 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
3447 .WillByDefault(DoAll(Return()));
3448
3449 SetSampleDatabaseEarbudsValid(
3450 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3451 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3452 default_channel_cnt, 0x0004,
3453 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3454 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3455 0 /*rank*/);
3456 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3457 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3458 .Times(0);
3459 ConnectLeAudio(test_address0);
3460
3461 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3462
3463 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
3464 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3465 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false))
3466 .Times(0);
3467
3468 LeAudioClient::Get()->Disconnect(test_address0);
3469 SyncOnMainLoop();
3470
3471 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
3472 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3473 }
3474
TEST_F(UnicastTest,RemoveWhileStreaming)3475 TEST_F(UnicastTest, RemoveWhileStreaming) {
3476 const RawAddress test_address0 = GetTestAddress(0);
3477 int group_id = bluetooth::groups::kGroupUnknown;
3478
3479 SetSampleDatabaseEarbudsValid(
3480 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3481 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3482 default_channel_cnt, 0x0004,
3483 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3484 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3485 0 /*rank*/);
3486 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3487 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3488 .Times(1);
3489 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3490 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
3491 .WillOnce(DoAll(SaveArg<1>(&group_id)));
3492
3493 ConnectLeAudio(test_address0);
3494 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
3495
3496 // Start streaming
3497 constexpr uint8_t cis_count_out = 1;
3498 constexpr uint8_t cis_count_in = 0;
3499
3500 constexpr int gmcs_ccid = 1;
3501 constexpr int gtbs_ccid = 2;
3502
3503 // Audio sessions are started only when device gets active
3504 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
3505 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
3506 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
3507 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
3508 LeAudioClient::Get()->GroupSetActive(group_id);
3509
3510 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
3511 .source = {}};
3512 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
3513
3514 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
3515
3516 SyncOnMainLoop();
3517 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3518 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3519 Mock::VerifyAndClearExpectations(&mock_state_machine_);
3520 SyncOnMainLoop();
3521
3522 // Verify Data transfer on one audio source cis
3523 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
3524
3525 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id))
3526 .Times(1);
3527
3528 LeAudioDeviceGroup* group = nullptr;
3529 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
3530 .WillOnce(DoAll(SaveArg<0>(&group)));
3531 EXPECT_CALL(
3532 mock_audio_hal_client_callbacks_,
3533 OnGroupNodeStatus(test_address0, group_id, GroupNodeStatus::REMOVED));
3534
3535 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3536 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3537 .Times(1);
3538
3539 /*
3540 * StopStream will put calls on main_loop so to keep the correct order
3541 * of operations and to avoid races we put the test command on main_loop as
3542 * well.
3543 */
3544 do_in_main_thread(FROM_HERE, base::BindOnce(
3545 [](LeAudioClient* client,
3546 const RawAddress& test_address0) {
3547 client->RemoveDevice(test_address0);
3548 },
3549 LeAudioClient::Get(), test_address0));
3550
3551 SyncOnMainLoop();
3552 Mock::VerifyAndClearExpectations(&mock_groups_module_);
3553 Mock::VerifyAndClearExpectations(&mock_state_machine_);
3554 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3555
3556 ASSERT_NE(group, nullptr);
3557 }
3558
TEST_F(UnicastTest,EarbudsTwsStyleStreaming)3559 TEST_F(UnicastTest, EarbudsTwsStyleStreaming) {
3560 const RawAddress test_address0 = GetTestAddress(0);
3561 int group_id = bluetooth::groups::kGroupUnknown;
3562
3563 SetSampleDatabaseEarbudsValid(
3564 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3565 codec_spec_conf::kLeAudioLocationStereo, 0x01, 0x01, 0x0004,
3566 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3567 true /*add_pacs*/, 2 /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
3568 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3569 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3570 .Times(1);
3571 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3572 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
3573 .WillOnce(DoAll(SaveArg<1>(&group_id)));
3574
3575 ConnectLeAudio(test_address0);
3576 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
3577
3578 // Start streaming
3579 uint8_t cis_count_out = 2;
3580 uint8_t cis_count_in = 0;
3581
3582 // Audio sessions are started only when device gets active
3583 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
3584 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
3585 LeAudioClient::Get()->GroupSetActive(group_id);
3586
3587 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
3588
3589 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3590 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3591 SyncOnMainLoop();
3592
3593 // Verify Data transfer on one audio source cis
3594 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
3595
3596 // Suspend
3597 /*TODO Need a way to verify STOP */
3598 LeAudioClient::Get()->GroupSuspend(group_id);
3599 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3600 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3601
3602 // Resume
3603 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
3604 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3605 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3606
3607 // Stop
3608 StopStreaming(group_id);
3609 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3610
3611 // Release
3612 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
3613 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
3614 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
3615 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
3616 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3617 }
3618
TEST_F(UnicastTest,SpeakerFailedConversationalStreaming)3619 TEST_F(UnicastTest, SpeakerFailedConversationalStreaming) {
3620 const RawAddress test_address0 = GetTestAddress(0);
3621 int group_id = bluetooth::groups::kGroupUnknown;
3622
3623 supported_src_context_types_ = 0;
3624 supported_snk_context_types_ = 0x0004;
3625
3626 SetSampleDatabaseEarbudsValid(
3627 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3628 0, default_channel_cnt,
3629 default_channel_cnt, 0x0004,
3630 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3631 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3632 0 /*rank*/);
3633 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3634 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3635 .Times(1);
3636 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3637 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
3638 .WillOnce(DoAll(SaveArg<1>(&group_id)));
3639
3640 ConnectLeAudio(test_address0);
3641 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
3642
3643 // Audio sessions are started only when device gets active
3644 LeAudioClient::Get()->GroupSetActive(group_id);
3645
3646 /* Nothing to do - expect no crash */
3647 }
3648
TEST_F(UnicastTest,SpeakerStreaming)3649 TEST_F(UnicastTest, SpeakerStreaming) {
3650 const RawAddress test_address0 = GetTestAddress(0);
3651 int group_id = bluetooth::groups::kGroupUnknown;
3652
3653 SetSampleDatabaseEarbudsValid(
3654 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3655 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3656 default_channel_cnt, 0x0004,
3657 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3658 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3659 0 /*rank*/);
3660 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3661 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3662 .Times(1);
3663 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3664 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
3665 .WillOnce(DoAll(SaveArg<1>(&group_id)));
3666
3667 ConnectLeAudio(test_address0);
3668 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
3669
3670 // Start streaming
3671 uint8_t cis_count_out = 1;
3672 uint8_t cis_count_in = 0;
3673
3674 // Audio sessions are started only when device gets active
3675 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
3676 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
3677 LeAudioClient::Get()->GroupSetActive(group_id);
3678
3679 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
3680
3681 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3682 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3683 SyncOnMainLoop();
3684
3685 // Verify Data transfer on one audio source cis
3686 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
3687
3688 // Suspend
3689 /*TODO Need a way to verify STOP */
3690 LeAudioClient::Get()->GroupSuspend(group_id);
3691 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3692 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3693
3694 // Resume
3695 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
3696 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3697 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3698
3699 // Stop
3700 StopStreaming(group_id);
3701 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3702
3703 // Release
3704 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
3705 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
3706 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
3707 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
3708 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3709 }
3710
TEST_F(UnicastTest,SpeakerStreamingAutonomousRelease)3711 TEST_F(UnicastTest, SpeakerStreamingAutonomousRelease) {
3712 const RawAddress test_address0 = GetTestAddress(0);
3713 int group_id = bluetooth::groups::kGroupUnknown;
3714
3715 SetSampleDatabaseEarbudsValid(
3716 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3717 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3718 default_channel_cnt, 0x0004,
3719 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
3720 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
3721 0 /*rank*/);
3722 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3723 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3724 .Times(1);
3725 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3726 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
3727 .WillOnce(DoAll(SaveArg<1>(&group_id)));
3728
3729 ConnectLeAudio(test_address0);
3730 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
3731
3732 // Start streaming
3733 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
3734 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
3735 LeAudioClient::Get()->GroupSetActive(group_id);
3736
3737 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
3738
3739 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3740 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3741 SyncOnMainLoop();
3742
3743 // Verify Data transfer on one audio source cis
3744 TestAudioDataTransfer(group_id, 1 /* cis_count_out */, 0 /* cis_count_in */,
3745 1920);
3746
3747 // Inject the IDLE state as if an autonomous release happened
3748 auto group = streaming_groups.at(group_id);
3749 ASSERT_NE(group, nullptr);
3750 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
3751 device = group->GetNextDevice(device)) {
3752 for (auto& ase : device->ases_) {
3753 ase.data_path_state = types::AudioStreamDataPathState::IDLE;
3754 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
3755 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
3756 }
3757 }
3758
3759 // Verify no Data transfer after the autonomous release
3760 TestAudioDataTransfer(group_id, 0 /* cis_count_out */, 0 /* cis_count_in */,
3761 1920);
3762 }
3763
TEST_F(UnicastTest,TwoEarbudsStreaming)3764 TEST_F(UnicastTest, TwoEarbudsStreaming) {
3765 uint8_t group_size = 2;
3766 int group_id = 2;
3767
3768 // Report working CSIS
3769 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
3770 .WillByDefault(Return(true));
3771
3772 // First earbud
3773 const RawAddress test_address0 = GetTestAddress(0);
3774 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3775 .Times(1);
3776 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
3777 codec_spec_conf::kLeAudioLocationFrontLeft,
3778 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
3779 group_id, 1 /* rank*/);
3780
3781 // Second earbud
3782 const RawAddress test_address1 = GetTestAddress(1);
3783 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
3784 .Times(1);
3785 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
3786 codec_spec_conf::kLeAudioLocationFrontRight,
3787 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
3788 group_id, 2 /* rank*/, true /*connect_through_csis*/);
3789
3790 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
3791 .WillByDefault(Invoke([&](int group_id) { return 2; }));
3792
3793 // Start streaming
3794 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
3795 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
3796 LeAudioClient::Get()->GroupSetActive(group_id);
3797 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3798
3799 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
3800 group_id);
3801
3802 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3803 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3804 SyncOnMainLoop();
3805
3806 // Verify Data transfer on two peer sinks and one source
3807 uint8_t cis_count_out = 2;
3808 uint8_t cis_count_in = 2;
3809 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
3810
3811 // Suspend
3812 LeAudioClient::Get()->GroupSuspend(group_id);
3813 SyncOnMainLoop();
3814
3815 // Resume
3816 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
3817 group_id);
3818 SyncOnMainLoop();
3819 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3820
3821 // Verify Data transfer still works
3822 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
3823
3824 // Stop
3825 StopStreaming(group_id, true);
3826 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3827
3828 // Release
3829 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
3830 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
3831 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
3832 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
3833 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
3834 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3835 }
3836
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchNoReconfigure)3837 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) {
3838 uint8_t group_size = 2;
3839 int group_id = 2;
3840
3841 // Report working CSIS
3842 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
3843 .WillByDefault(Return(true));
3844
3845 // First earbud
3846 const RawAddress test_address0 = GetTestAddress(0);
3847 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3848 .Times(1);
3849 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
3850 codec_spec_conf::kLeAudioLocationFrontLeft,
3851 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
3852 group_id, 1 /* rank*/);
3853
3854 // Second earbud
3855 const RawAddress test_address1 = GetTestAddress(1);
3856 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
3857 .Times(1);
3858 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
3859 codec_spec_conf::kLeAudioLocationFrontRight,
3860 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
3861 group_id, 2 /* rank*/, true /*connect_through_csis*/);
3862
3863 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
3864 .WillByDefault(Invoke([&](int group_id) { return 2; }));
3865
3866 // Start streaming
3867 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
3868 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
3869 LeAudioClient::Get()->GroupSetActive(group_id);
3870 SyncOnMainLoop();
3871 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3872
3873 // Start streaming with new metadata, but use the existing configuration
3874 types::BidirectionalPair<types::AudioContexts> contexts = {
3875 .sink = types::AudioContexts(types::LeAudioContextType::NOTIFICATIONS),
3876 .source = types::AudioContexts()};
3877 EXPECT_CALL(mock_state_machine_,
3878 StartStream(_, types::LeAudioContextType::MEDIA, contexts, _))
3879 .Times(1);
3880
3881 StartStreaming(AUDIO_USAGE_NOTIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN,
3882 group_id);
3883
3884 SyncOnMainLoop();
3885 Mock::VerifyAndClearExpectations(&mock_state_machine_);
3886 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3887 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3888
3889 // Do a metadata content switch to ALERTS but stay on MEDIA configuration
3890 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
3891 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
3892 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
3893 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::ALERTS),
3894 .source = types::AudioContexts()};
3895 EXPECT_CALL(
3896 mock_state_machine_,
3897 StartStream(_, le_audio::types::LeAudioContextType::MEDIA, contexts, _))
3898 .Times(1);
3899 UpdateMetadata(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN);
3900
3901 SyncOnMainLoop();
3902 Mock::VerifyAndClearExpectations(&mock_state_machine_);
3903 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3904 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3905
3906 // Do a metadata content switch to EMERGENCY but stay on MEDIA configuration
3907 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
3908 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
3909 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
3910
3911 contexts = {
3912 .sink = types::AudioContexts(types::LeAudioContextType::EMERGENCYALARM),
3913 .source = types::AudioContexts()};
3914 EXPECT_CALL(
3915 mock_state_machine_,
3916 StartStream(_, le_audio::types::LeAudioContextType::MEDIA, contexts, _))
3917 .Times(1);
3918 UpdateMetadata(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN);
3919
3920 SyncOnMainLoop();
3921 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3922 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3923
3924 // Do a metadata content switch to INSTRUCTIONAL but stay on MEDIA
3925 // configuration
3926 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
3927 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
3928 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
3929 contexts = {
3930 .sink = types::AudioContexts(types::LeAudioContextType::INSTRUCTIONAL),
3931 .source = types::AudioContexts()};
3932 EXPECT_CALL(
3933 mock_state_machine_,
3934 StartStream(_, le_audio::types::LeAudioContextType::MEDIA, contexts, _))
3935 .Times(1);
3936 UpdateMetadata(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
3937 AUDIO_CONTENT_TYPE_UNKNOWN);
3938
3939 SyncOnMainLoop();
3940 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3941 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3942 }
3943
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchReconfigure)3944 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) {
3945 uint8_t group_size = 2;
3946 int group_id = 2;
3947
3948 // Report working CSIS
3949 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
3950 .WillByDefault(Return(true));
3951
3952 // First earbud
3953 const RawAddress test_address0 = GetTestAddress(0);
3954 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
3955 .Times(1);
3956 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
3957 codec_spec_conf::kLeAudioLocationFrontLeft,
3958 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
3959 group_id, 1 /* rank*/);
3960
3961 // Second earbud
3962 const RawAddress test_address1 = GetTestAddress(1);
3963 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
3964 .Times(1);
3965 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
3966 codec_spec_conf::kLeAudioLocationFrontRight,
3967 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
3968 group_id, 2 /* rank*/, true /*connect_through_csis*/);
3969
3970 constexpr int gmcs_ccid = 1;
3971 constexpr int gtbs_ccid = 2;
3972
3973 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
3974 .WillByDefault(Invoke([&](int group_id) { return 2; }));
3975
3976 // Start streaming MEDIA
3977 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
3978 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
3979 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
3980 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
3981 LeAudioClient::Get()->GroupSetActive(group_id);
3982
3983 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
3984 .source = {}};
3985 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
3986 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
3987
3988 SyncOnMainLoop();
3989 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3990 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
3991
3992 // Verify Data transfer on two peer sinks
3993 uint8_t cis_count_out = 2;
3994 uint8_t cis_count_in = 0;
3995 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
3996
3997 // Stop
3998 StopStreaming(group_id);
3999 // simulate suspend timeout passed, alarm executing
4000 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
4001 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4002
4003 // Conversational is a bidirectional scenario so expect GTBS CCID
4004 // in the metadata for both directions. Can be called twice when one
4005 // direction resume after the other and metadata is updated.
4006 ccids = {.sink = {gtbs_ccid}, .source = {gtbs_ccid}};
4007 EXPECT_CALL(
4008 mock_state_machine_,
4009 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
4010 .Times(AtLeast(1));
4011 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
4012 group_id);
4013
4014 SyncOnMainLoop();
4015 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4016 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4017
4018 // Verify Data transfer on two peer sinks and one source
4019 cis_count_out = 2;
4020 cis_count_in = 2;
4021 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
4022 }
4023
TEST_F(UnicastTest,TwoEarbuds2ndLateConnect)4024 TEST_F(UnicastTest, TwoEarbuds2ndLateConnect) {
4025 uint8_t group_size = 2;
4026 int group_id = 2;
4027
4028 // Report working CSIS
4029 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
4030 .WillByDefault(Return(true));
4031
4032 const RawAddress test_address0 = GetTestAddress(0);
4033 const RawAddress test_address1 = GetTestAddress(1);
4034
4035 // First earbud
4036 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
4037 codec_spec_conf::kLeAudioLocationFrontLeft,
4038 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
4039 group_id, 1 /* rank*/);
4040
4041 // Start streaming
4042 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4043 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
4044 LeAudioClient::Get()->GroupSetActive(group_id);
4045
4046 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
4047 .WillByDefault(Invoke([&](int group_id) { return 2; }));
4048
4049 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
4050
4051 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4052 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4053 SyncOnMainLoop();
4054
4055 // Expect one iso channel to be fed with data
4056 uint8_t cis_count_out = 1;
4057 uint8_t cis_count_in = 0;
4058 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4059
4060 // Second earbud connects during stream
4061 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
4062 codec_spec_conf::kLeAudioLocationFrontRight,
4063 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
4064 group_id, 2 /* rank*/, true /*connect_through_csis*/);
4065
4066 cis_count_out = 2;
4067 cis_count_in = 0;
4068
4069 /* The above will trigger reconfiguration. After that Audio Hal action
4070 * is needed to restart the stream */
4071 SinkAudioResume();
4072
4073 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4074 }
4075
TEST_F(UnicastTest,TwoEarbuds2ndDisconnected)4076 TEST_F(UnicastTest, TwoEarbuds2ndDisconnected) {
4077 uint8_t group_size = 2;
4078 int group_id = 2;
4079
4080 // Report working CSIS
4081 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
4082 .WillByDefault(Return(true));
4083
4084 // First earbud
4085 const RawAddress test_address0 = GetTestAddress(0);
4086 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
4087 codec_spec_conf::kLeAudioLocationFrontLeft,
4088 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
4089 group_id, 1 /* rank*/);
4090
4091 // Second earbud
4092 const RawAddress test_address1 = GetTestAddress(1);
4093 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
4094 codec_spec_conf::kLeAudioLocationFrontRight,
4095 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
4096 group_id, 2 /* rank*/, true /*connect_through_csis*/);
4097
4098 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
4099 .WillByDefault(Invoke([&](int group_id) { return 2; }));
4100
4101 // Audio sessions are started only when device gets active
4102 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4103 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
4104 LeAudioClient::Get()->GroupSetActive(group_id);
4105
4106 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
4107 auto group = streaming_groups.at(group_id);
4108
4109 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4110 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4111 SyncOnMainLoop();
4112 ASSERT_EQ(2, group->NumOfConnected());
4113
4114 // Expect two iso channels to be fed with data
4115 uint8_t cis_count_out = 2;
4116 uint8_t cis_count_in = 0;
4117 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4118
4119 // Disconnect one device and expect the group to keep on streaming
4120 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
4121 auto device = group->GetFirstDevice();
4122 for (auto& ase : device->ases_) {
4123 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
4124 }
4125
4126 /* It is called twice. Once with BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS,
4127 * and then after delay with BTM_BLE_BKG_CONNECT_ALLOW_LIST
4128 */
4129 EXPECT_CALL(mock_gatt_interface_, Open(_, device->address_, _, false))
4130 .Times(2);
4131
4132 // Record NumOfConnected when groupStateMachine_ gets notified about the
4133 // disconnection
4134 int num_of_connected = 0;
4135 ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
4136 .WillByDefault([&num_of_connected](LeAudioDeviceGroup* group,
4137 LeAudioDevice* leAudioDevice) {
4138 num_of_connected = group->NumOfConnected();
4139 });
4140
4141 auto conn_id = device->conn_id_;
4142 InjectDisconnectedEvent(device->conn_id_, GATT_CONN_TERMINATE_PEER_USER);
4143 SyncOnMainLoop();
4144
4145 // Make sure the state machine knows about the disconnected device
4146 ASSERT_EQ(1, num_of_connected);
4147
4148 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4149
4150 // Expect one channel ISO Data to be sent
4151 cis_count_out = 1;
4152 cis_count_in = 0;
4153 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4154
4155 InjectConnectedEvent(device->address_, conn_id);
4156 SyncOnMainLoop();
4157
4158 // Expect two iso channels to be fed with data
4159 cis_count_out = 2;
4160 cis_count_in = 0;
4161 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4162 }
4163
TEST_F(UnicastTest,TwoEarbudsStreamingProfileDisconnect)4164 TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnect) {
4165 uint8_t group_size = 2;
4166 int group_id = 2;
4167
4168 // Report working CSIS
4169 ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
4170 .WillByDefault(Return(true));
4171
4172 // First earbud
4173 const RawAddress test_address0 = GetTestAddress(0);
4174 ConnectCsisDevice(test_address0, 1 /*conn_id*/,
4175 codec_spec_conf::kLeAudioLocationFrontLeft,
4176 codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
4177 group_id, 1 /* rank*/);
4178
4179 // Second earbud
4180 const RawAddress test_address1 = GetTestAddress(1);
4181 ConnectCsisDevice(test_address1, 2 /*conn_id*/,
4182 codec_spec_conf::kLeAudioLocationFrontRight,
4183 codec_spec_conf::kLeAudioLocationFrontRight, group_size,
4184 group_id, 2 /* rank*/, true /*connect_through_csis*/);
4185
4186 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
4187 .WillByDefault(Invoke([&](int group_id) { return 2; }));
4188
4189 // Audio sessions are started only when device gets active
4190 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4191 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
4192 LeAudioClient::Get()->GroupSetActive(group_id);
4193
4194 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
4195
4196 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4197 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4198 SyncOnMainLoop();
4199
4200 // Expect two iso channels to be fed with data
4201 uint8_t cis_count_out = 2;
4202 uint8_t cis_count_in = 0;
4203 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4204
4205 EXPECT_CALL(mock_gatt_interface_,
4206 Open(_, _, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4207 .Times(1);
4208 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
4209
4210 DisconnectLeAudio(test_address0, 1);
4211 SyncOnMainLoop();
4212 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4213 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4214
4215 EXPECT_CALL(mock_gatt_interface_,
4216 Open(_, _, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4217 .Times(1);
4218
4219 DisconnectLeAudio(test_address1, 2);
4220
4221 SyncOnMainLoop();
4222 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4223 }
4224
TEST_F(UnicastTest,EarbudsWithStereoSinkMonoSourceSupporting32kHz)4225 TEST_F(UnicastTest, EarbudsWithStereoSinkMonoSourceSupporting32kHz) {
4226 const RawAddress test_address0 = GetTestAddress(0);
4227 int group_id = 0;
4228 SetSampleDatabaseEarbudsValid(
4229 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4230 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
4231 default_channel_cnt, 0x0024,
4232 /* source sample freq 32/16khz */ true, /*add_csis*/
4233 true, /*add_cas*/
4234 true, /*add_pacs*/
4235 default_ase_cnt /*add_ascs_cnt*/);
4236 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4237 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4238 .Times(1);
4239 ConnectLeAudio(test_address0);
4240
4241 // LeAudioCodecConfiguration received_af_sink_config;
4242 const LeAudioCodecConfiguration expected_af_sink_config = {
4243 .num_channels = 2,
4244 .sample_rate = bluetooth::audio::le_audio::kSampleRate32000,
4245 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
4246 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
4247 };
4248
4249 // Audio sessions are started only when device gets active
4250 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4251 EXPECT_CALL(*mock_le_audio_sink_hal_client_,
4252 Start(expected_af_sink_config, _))
4253 .Times(1);
4254 LeAudioClient::Get()->GroupSetActive(group_id);
4255 SyncOnMainLoop();
4256 }
4257
TEST_F(UnicastTest,MicrophoneAttachToCurrentMediaScenario)4258 TEST_F(UnicastTest, MicrophoneAttachToCurrentMediaScenario) {
4259 const RawAddress test_address0 = GetTestAddress(0);
4260 int group_id = bluetooth::groups::kGroupUnknown;
4261
4262 SetSampleDatabaseEarbudsValid(
4263 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4264 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4265 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
4266 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4267 0 /*rank*/);
4268 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4269 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4270 .Times(1);
4271 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4272 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4273 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4274
4275 ConnectLeAudio(test_address0);
4276 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4277
4278 // Audio sessions are started only when device gets active
4279 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4280 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
4281 LeAudioClient::Get()->GroupSetActive(group_id);
4282
4283 // When the local audio source resumes we have no knowledge of recording
4284 EXPECT_CALL(mock_state_machine_,
4285 StartStream(_, le_audio::types::LeAudioContextType::MEDIA, _, _))
4286 .Times(1);
4287
4288 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id,
4289 AUDIO_SOURCE_INVALID);
4290 SyncOnMainLoop();
4291
4292 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4293 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4294
4295 // Verify Data transfer on one audio source cis
4296 uint8_t cis_count_out = 1;
4297 uint8_t cis_count_in = 0;
4298 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4299
4300 // When the local audio sink resumes we should reconfigure
4301 EXPECT_CALL(
4302 mock_state_machine_,
4303 ConfigureStream(_, le_audio::types::LeAudioContextType::LIVE, _, _))
4304 .Times(1);
4305 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
4306 .Times(1);
4307
4308 // Update metadata on local audio sink
4309 UpdateSourceMetadata(AUDIO_SOURCE_MIC);
4310
4311 // Resume on local audio sink
4312 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
4313 do_in_main_thread(
4314 FROM_HERE,
4315 base::BindOnce(
4316 [](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
4317 unicast_sink_hal_cb_));
4318
4319 /* The above will trigger reconfiguration. After that Audio Hal action
4320 * is needed to restart the stream */
4321 SyncOnMainLoop();
4322
4323 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4324 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4325
4326 SinkAudioResume();
4327 do_in_main_thread(
4328 FROM_HERE,
4329 base::BindOnce(
4330 [](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
4331 unicast_sink_hal_cb_));
4332 SyncOnMainLoop();
4333
4334 // Verify Data transfer on one audio source and sink cis
4335 cis_count_out = 1;
4336 cis_count_in = 1;
4337 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
4338
4339 // Stop
4340 StopStreaming(group_id);
4341 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4342
4343 // Release
4344 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
4345 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
4346 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
4347 do_in_main_thread(
4348 FROM_HERE, base::BindOnce(
4349 [](LeAudioClient* client) {
4350 client->GroupSetActive(bluetooth::groups::kGroupUnknown);
4351 },
4352 LeAudioClient::Get()));
4353 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4354
4355 SyncOnMainLoop();
4356 }
4357
TEST_F(UnicastTest,UpdateNotSupportedContextType)4358 TEST_F(UnicastTest, UpdateNotSupportedContextType) {
4359 const RawAddress test_address0 = GetTestAddress(0);
4360 int group_id = bluetooth::groups::kGroupUnknown;
4361
4362 supported_snk_context_types_ = (types::LeAudioContextType::RINGTONE |
4363 types::LeAudioContextType::CONVERSATIONAL |
4364 types::LeAudioContextType::UNSPECIFIED |
4365 types::LeAudioContextType::MEDIA)
4366 .value();
4367 supported_src_context_types_ = supported_snk_context_types_;
4368
4369 SetSampleDatabaseEarbudsValid(
4370 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4371 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4372 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
4373 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4374 0 /*rank*/);
4375 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4376 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4377 .Times(1);
4378 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4379 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4380 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4381
4382 ConnectLeAudio(test_address0);
4383 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4384
4385 // Start streaming
4386 uint8_t cis_count_out = 1;
4387 uint8_t cis_count_in = 0;
4388
4389 LeAudioClient::Get()->SetInCall(true);
4390
4391 // Audio sessions are started only when device gets active
4392 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4393 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
4394 LeAudioClient::Get()->GroupSetActive(group_id);
4395
4396 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
4397 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
4398
4399 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4400 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4401 SyncOnMainLoop();
4402
4403 // Verify Data transfer on one audio source cis
4404 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4405
4406 LeAudioClient::Get()->SetInCall(false);
4407
4408 /* We should stay on the existing configuration as there is no GAME
4409 * context available on the remote device.
4410 */
4411 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
4412 types::BidirectionalPair<types::AudioContexts> contexts = {
4413 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
4414 .source = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED)};
4415 EXPECT_CALL(
4416 mock_state_machine_,
4417 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, contexts, _))
4418 .Times(1);
4419 UpdateMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false);
4420
4421 /* If the above triggers reconfiguration, Audio Hal action is needed to
4422 * restart the stream.
4423 */
4424 SinkAudioResume();
4425 }
4426
TEST_F(UnicastTest,StartNotSupportedContextType)4427 TEST_F(UnicastTest, StartNotSupportedContextType) {
4428 const RawAddress test_address0 = GetTestAddress(0);
4429 int group_id = bluetooth::groups::kGroupUnknown;
4430
4431 supported_snk_context_types_ = (types::LeAudioContextType::RINGTONE |
4432 types::LeAudioContextType::CONVERSATIONAL |
4433 types::LeAudioContextType::UNSPECIFIED |
4434 types::LeAudioContextType::MEDIA)
4435 .value();
4436 supported_src_context_types_ = supported_snk_context_types_;
4437
4438 SetSampleDatabaseEarbudsValid(
4439 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4440 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4441 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
4442 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4443 0 /*rank*/);
4444 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4445 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4446 .Times(1);
4447 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4448 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4449 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4450
4451 ConnectLeAudio(test_address0);
4452 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4453
4454 // Expect configuring to the default config since the EMERGENCYALARM is
4455 // not on the list of supported contexts and UNSPECIFIED will be used in
4456 // the metadata.
4457 auto default_config = types::LeAudioContextType::MEDIA;
4458 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4459 types::BidirectionalPair<types::AudioContexts> metadata = {
4460 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
4461 .source = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED)};
4462 EXPECT_CALL(mock_state_machine_, StartStream(_, default_config, metadata, _))
4463 .Times(1);
4464
4465 LeAudioClient::Get()->GroupSetActive(group_id);
4466
4467 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
4468
4469 SyncOnMainLoop();
4470 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4471 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4472
4473 // Verify Data transfer on one audio source cis
4474 uint8_t cis_count_out = 1;
4475 uint8_t cis_count_in = 0;
4476 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4477 }
4478
TEST_F(UnicastTest,NotifyAboutGroupTunrnedIdleEnabled)4479 TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleEnabled) {
4480 const RawAddress test_address0 = GetTestAddress(0);
4481 int group_id = bluetooth::groups::kGroupUnknown;
4482
4483 osi_property_set_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall, true);
4484
4485 SetSampleDatabaseEarbudsValid(
4486 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4487 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4488 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
4489 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4490 0 /*rank*/);
4491 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4492 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4493 .Times(1);
4494 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4495 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4496 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4497
4498 ConnectLeAudio(test_address0);
4499 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4500
4501 // Start streaming
4502 uint8_t cis_count_out = 1;
4503 uint8_t cis_count_in = 0;
4504
4505 LeAudioClient::Get()->SetInCall(true);
4506
4507 // Audio sessions are started only when device gets active
4508 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4509 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
4510 LeAudioClient::Get()->GroupSetActive(group_id);
4511
4512 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
4513 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
4514
4515 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4516 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4517 SyncOnMainLoop();
4518
4519 // Verify Data transfer on one audio source cis
4520 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4521
4522 // Release
4523
4524 /* To be called twice
4525 * 1. GroupStatus::INACTIVE
4526 * 2. GroupStatus::TURNED_IDLE_DURING_CALL
4527 */
4528 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, _))
4529 .Times(2);
4530
4531 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
4532 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
4533 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
4534
4535 do_in_main_thread(
4536 FROM_HERE, base::BindOnce(
4537 [](LeAudioClient* client) {
4538 client->GroupSetActive(bluetooth::groups::kGroupUnknown);
4539 },
4540 LeAudioClient::Get()));
4541
4542 SyncOnMainLoop();
4543 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4544
4545 LeAudioClient::Get()->SetInCall(false);
4546 osi_property_set_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall,
4547 false);
4548 }
4549
TEST_F(UnicastTest,NotifyAboutGroupTunrnedIdleDisabled)4550 TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleDisabled) {
4551 const RawAddress test_address0 = GetTestAddress(0);
4552 int group_id = bluetooth::groups::kGroupUnknown;
4553
4554 SetSampleDatabaseEarbudsValid(
4555 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4556 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4557 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
4558 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4559 0 /*rank*/);
4560 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4561 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4562 .Times(1);
4563 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4564 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4565 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4566
4567 ConnectLeAudio(test_address0);
4568 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4569
4570 // Start streaming
4571 uint8_t cis_count_out = 1;
4572 uint8_t cis_count_in = 0;
4573
4574 LeAudioClient::Get()->SetInCall(true);
4575
4576 // Audio sessions are started only when device gets active
4577 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4578 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
4579 LeAudioClient::Get()->GroupSetActive(group_id);
4580
4581 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
4582 AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
4583
4584 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4585 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4586 SyncOnMainLoop();
4587
4588 // Verify Data transfer on one audio source cis
4589 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4590
4591 // Release
4592
4593 /* To be called once only
4594 * 1. GroupStatus::INACTIVE
4595 */
4596 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, _))
4597 .Times(1);
4598
4599 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
4600 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
4601 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
4602
4603 do_in_main_thread(
4604 FROM_HERE, base::BindOnce(
4605 [](LeAudioClient* client) {
4606 client->GroupSetActive(bluetooth::groups::kGroupUnknown);
4607 },
4608 LeAudioClient::Get()));
4609
4610 SyncOnMainLoop();
4611 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4612
4613 LeAudioClient::Get()->SetInCall(false);
4614 }
4615
TEST_F(UnicastTest,HandleDatabaseOutOfSync)4616 TEST_F(UnicastTest, HandleDatabaseOutOfSync) {
4617 const RawAddress test_address0 = GetTestAddress(0);
4618 int group_id = bluetooth::groups::kGroupUnknown;
4619
4620 SetSampleDatabaseEarbudsValid(
4621 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4622 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4623 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
4624 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4625 0 /*rank*/);
4626 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4627 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4628 .Times(1);
4629 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4630 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4631 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4632
4633 ConnectLeAudio(test_address0);
4634 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4635
4636 SyncOnMainLoop();
4637 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4638
4639 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4640 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
4641 .Times(1);
4642 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
4643 SyncOnMainLoop();
4644 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4645
4646 // default action for WriteDescriptor function call
4647 ON_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _))
4648 .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle,
4649 std::vector<uint8_t> value,
4650 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
4651 void* cb_data) -> void {
4652 if (cb)
4653 do_in_main_thread(
4654 FROM_HERE,
4655 base::BindOnce(
4656 [](GATT_WRITE_OP_CB cb, uint16_t conn_id, uint16_t handle,
4657 uint16_t len, uint8_t* value, void* cb_data) {
4658 cb(conn_id, GATT_DATABASE_OUT_OF_SYNC, handle, len, value,
4659 cb_data);
4660 },
4661 cb, conn_id, handle, value.size(), value.data(), cb_data));
4662 }));
4663
4664 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
4665 .WillByDefault(Return());
4666 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _));
4667
4668 InjectConnectedEvent(test_address0, 1);
4669 SyncOnMainLoop();
4670 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4671 }
4672
TEST_F(UnicastTest,SpeakerStreamingTimeout)4673 TEST_F(UnicastTest, SpeakerStreamingTimeout) {
4674 const RawAddress test_address0 = GetTestAddress(0);
4675 int group_id = bluetooth::groups::kGroupUnknown;
4676
4677 SetSampleDatabaseEarbudsValid(
4678 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4679 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
4680 default_channel_cnt, 0x0004,
4681 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
4682 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
4683 0 /*rank*/);
4684 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4685 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4686 .Times(1);
4687 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4688 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4689 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4690
4691 ConnectLeAudio(test_address0);
4692 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4693
4694 // Start streaming
4695 uint8_t cis_count_out = 1;
4696 uint8_t cis_count_in = 0;
4697
4698 // Audio sessions are started only when device gets active
4699 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _)).Times(1);
4700 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
4701 LeAudioClient::Get()->GroupSetActive(group_id);
4702
4703 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
4704
4705 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4706 Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
4707 SyncOnMainLoop();
4708
4709 // Verify Data transfer on one audio source cis
4710 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4711
4712 // Do not accept direct connect, but expect it to arrive.
4713 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
4714 .WillByDefault(Return());
4715
4716 state_machine_callbacks_->OnStateTransitionTimeout(group_id);
4717 SyncOnMainLoop();
4718
4719 /* No assigned cises should remain when transition remains in IDLE state */
4720 auto group = streaming_groups.at(group_id);
4721 ASSERT_EQ(0, static_cast<int>(group->cises_.size()));
4722 }
4723 } // namespace le_audio
4724