1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <bluetooth/log.h>
19 #include <com_android_bluetooth_flags.h>
20 #include <flag_macros.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24
25 #include <chrono>
26
27 #include "bta/csis/csis_types.h"
28 #include "bta_gatt_api_mock.h"
29 #include "bta_gatt_queue_mock.h"
30 #include "bta_groups.h"
31 #include "bta_le_audio_api.h"
32 #include "bta_le_audio_broadcaster_api.h"
33 #include "btif/include/btif_common.h"
34 #include "btif/include/mock_core_callbacks.h"
35 #include "btif_storage_mock.h"
36 #include "btm_api_mock.h"
37 #include "btm_iso_api.h"
38 #include "common/message_loop_thread.h"
39 #include "fake_osi.h"
40 #include "gatt/database_builder.h"
41 #include "hardware/bt_gatt_types.h"
42 #include "hardware/bt_le_audio.h"
43 #include "hci/controller_interface_mock.h"
44 #include "internal_include/stack_config.h"
45 #include "le_audio/codec_manager.h"
46 #include "le_audio/mock_codec_interface.h"
47 #include "le_audio_health_status.h"
48 #include "le_audio_set_configuration_provider.h"
49 #include "le_audio_types.h"
50 #include "mock_codec_manager.h"
51 #include "mock_csis_client.h"
52 #include "mock_device_groups.h"
53 #include "mock_state_machine.h"
54 #include "osi/include/properties.h"
55 #include "stack/include/btm_status.h"
56 #include "stack/include/main_thread.h"
57 #include "test/common/mock_functions.h"
58 #include "test/mock/mock_main_shim_entry.h"
59 #include "test/mock/mock_stack_btm_iso.h"
60
61 #define TEST_BT com::android::bluetooth::flags
62
63 using testing::_;
64 using testing::AnyNumber;
65 using testing::AtLeast;
66 using testing::AtMost;
67 using testing::DoAll;
68 using testing::Expectation;
69 using testing::InSequence;
70 using testing::Invoke;
71 using testing::Matcher;
72 using testing::Mock;
73 using testing::MockFunction;
74 using testing::NiceMock;
75 using testing::NotNull;
76 using testing::Return;
77 using testing::SaveArg;
78 using testing::SetArgPointee;
79 using testing::Test;
80 using testing::WithArg;
81
82 using bluetooth::Uuid;
83
84 using namespace bluetooth::le_audio;
85
86 using bluetooth::le_audio::LeAudioCodecConfiguration;
87 using bluetooth::le_audio::LeAudioDeviceGroup;
88 using bluetooth::le_audio::LeAudioHealthStatus;
89 using bluetooth::le_audio::LeAudioSinkAudioHalClient;
90 using bluetooth::le_audio::LeAudioSourceAudioHalClient;
91
92 using bluetooth::le_audio::DsaMode;
93 using bluetooth::le_audio::DsaModes;
94 using bluetooth::le_audio::types::AudioContexts;
95 using bluetooth::le_audio::types::BidirectionalPair;
96 using bluetooth::le_audio::types::LeAudioContextType;
97
98 extern struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_;
99
100 constexpr int max_num_of_ases = 5;
101 constexpr bluetooth::le_audio::types::LeAudioContextType kLeAudioDefaultConfigurationContext =
102 bluetooth::le_audio::types::LeAudioContextType::UNSPECIFIED;
103
104 static constexpr char kNotifyUpperLayerAboutGroupBeingInIdleDuringCall[] =
105 "persist.bluetooth.leaudio.notify.idle.during.call";
106
107 // Disables most likely false-positives from base::SplitString()
108 extern "C" const char* __asan_default_options();
__asan_default_options()109 extern "C" const char* __asan_default_options() { return "detect_container_overflow=0"; }
110
111 std::atomic<int> num_async_tasks;
112 bluetooth::common::MessageLoopThread message_loop_thread("test message loop");
get_main_thread()113 bluetooth::common::MessageLoopThread* get_main_thread() { return &message_loop_thread; }
114
do_in_main_thread(base::OnceClosure task)115 bt_status_t do_in_main_thread(base::OnceClosure task) {
116 // Wrap the task with task counter so we could later know if there are
117 // any callbacks scheduled and we should wait before performing some actions
118 if (!message_loop_thread.DoInThread(base::BindOnce(
119 [](base::OnceClosure task, std::atomic<int>& num_async_tasks) {
120 std::move(task).Run();
121 num_async_tasks--;
122 },
123 std::move(task), std::ref(num_async_tasks)))) {
124 bluetooth::log::error("failed to post task to task runner!");
125 return BT_STATUS_FAIL;
126 }
127 num_async_tasks++;
128 return BT_STATUS_SUCCESS;
129 }
130
do_in_main_thread_delayed(base::OnceClosure task,std::chrono::microseconds)131 bt_status_t do_in_main_thread_delayed(base::OnceClosure task, std::chrono::microseconds /*delay*/) {
132 /* For testing purpose it is ok to just skip delay */
133 return do_in_main_thread(std::move(task));
134 }
135
init_message_loop_thread()136 static void init_message_loop_thread() {
137 num_async_tasks = 0;
138 message_loop_thread.StartUp();
139 if (!message_loop_thread.IsRunning()) {
140 FAIL() << "unable to create message loop thread.";
141 }
142
143 if (!message_loop_thread.EnableRealTimeScheduling()) {
144 bluetooth::log::error("Unable to set real time scheduling");
145 }
146 }
147
cleanup_message_loop_thread()148 static void cleanup_message_loop_thread() { message_loop_thread.ShutDown(); }
149
BTM_Sec_GetAddressWithType(const RawAddress & bd_addr)150 const tBLE_BD_ADDR BTM_Sec_GetAddressWithType(const RawAddress& bd_addr) {
151 return tBLE_BD_ADDR{.type = BLE_ADDR_PUBLIC, .bda = bd_addr};
152 }
153
invoke_switch_codec_cb(bool)154 void invoke_switch_codec_cb(bool /*is_low_latency_buffer_size*/) {}
invoke_switch_buffer_size_cb(bool)155 void invoke_switch_buffer_size_cb(bool /*is_low_latency_buffer_size*/) {}
156
157 const std::string kSmpOptions("mock smp options");
get_pts_avrcp_test(void)158 static bool get_pts_avrcp_test(void) { return false; }
get_pts_secure_only_mode(void)159 static bool get_pts_secure_only_mode(void) { return false; }
get_pts_conn_updates_disabled(void)160 static bool get_pts_conn_updates_disabled(void) { return false; }
get_pts_crosskey_sdp_disable(void)161 static bool get_pts_crosskey_sdp_disable(void) { return false; }
get_pts_smp_options(void)162 static const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
get_pts_smp_failure_case(void)163 static int get_pts_smp_failure_case(void) { return 123; }
get_pts_force_eatt_for_notifications(void)164 static bool get_pts_force_eatt_for_notifications(void) { return false; }
get_pts_connect_eatt_unconditionally(void)165 static bool get_pts_connect_eatt_unconditionally(void) { return false; }
get_pts_connect_eatt_before_encryption(void)166 static bool get_pts_connect_eatt_before_encryption(void) { return false; }
get_pts_unencrypt_broadcast(void)167 static bool get_pts_unencrypt_broadcast(void) { return false; }
get_pts_eatt_peripheral_collision_support(void)168 static bool get_pts_eatt_peripheral_collision_support(void) { return false; }
get_pts_force_le_audio_multiple_contexts_metadata(void)169 static bool get_pts_force_le_audio_multiple_contexts_metadata(void) { return false; }
get_pts_le_audio_disable_ases_before_stopping(void)170 static bool get_pts_le_audio_disable_ases_before_stopping(void) { return false; }
get_all(void)171 static config_t* get_all(void) { return nullptr; }
172
173 stack_config_t mock_stack_config{
174 .get_pts_avrcp_test = get_pts_avrcp_test,
175 .get_pts_secure_only_mode = get_pts_secure_only_mode,
176 .get_pts_conn_updates_disabled = get_pts_conn_updates_disabled,
177 .get_pts_crosskey_sdp_disable = get_pts_crosskey_sdp_disable,
178 .get_pts_smp_options = get_pts_smp_options,
179 .get_pts_smp_failure_case = get_pts_smp_failure_case,
180 .get_pts_force_eatt_for_notifications = get_pts_force_eatt_for_notifications,
181 .get_pts_connect_eatt_unconditionally = get_pts_connect_eatt_unconditionally,
182 .get_pts_connect_eatt_before_encryption = get_pts_connect_eatt_before_encryption,
183 .get_pts_unencrypt_broadcast = get_pts_unencrypt_broadcast,
184 .get_pts_eatt_peripheral_collision_support = get_pts_eatt_peripheral_collision_support,
185 .get_pts_force_le_audio_multiple_contexts_metadata =
186 get_pts_force_le_audio_multiple_contexts_metadata,
187 .get_pts_le_audio_disable_ases_before_stopping =
188 get_pts_le_audio_disable_ases_before_stopping,
189 .get_all = get_all,
190 };
stack_config_get_interface(void)191 const stack_config_t* stack_config_get_interface(void) { return &mock_stack_config; }
192
IsLeAudioBroadcasterRunning()193 bool LeAudioBroadcaster::IsLeAudioBroadcasterRunning() { return false; }
194
195 namespace bluetooth::le_audio {
196 class MockLeAudioSourceHalClient;
197 MockLeAudioSourceHalClient* mock_le_audio_source_hal_client_;
198 std::unique_ptr<LeAudioSourceAudioHalClient> owned_mock_le_audio_source_hal_client_;
199 bool is_audio_unicast_source_acquired;
200
AcquireUnicast()201 std::unique_ptr<LeAudioSourceAudioHalClient> LeAudioSourceAudioHalClient::AcquireUnicast() {
202 if (is_audio_unicast_source_acquired) {
203 return nullptr;
204 }
205 is_audio_unicast_source_acquired = true;
206 return std::move(owned_mock_le_audio_source_hal_client_);
207 }
208
DebugDump(int)209 void LeAudioSourceAudioHalClient::DebugDump(int /*fd*/) {}
210
211 class MockLeAudioSinkHalClient;
212 MockLeAudioSinkHalClient* mock_le_audio_sink_hal_client_;
213 std::unique_ptr<LeAudioSinkAudioHalClient> owned_mock_le_audio_sink_hal_client_;
214 bool is_audio_unicast_sink_acquired;
215
AcquireUnicast()216 std::unique_ptr<LeAudioSinkAudioHalClient> LeAudioSinkAudioHalClient::AcquireUnicast() {
217 if (is_audio_unicast_sink_acquired) {
218 return nullptr;
219 }
220 is_audio_unicast_sink_acquired = true;
221 return std::move(owned_mock_le_audio_sink_hal_client_);
222 }
223
DebugDump(int)224 void LeAudioSinkAudioHalClient::DebugDump(int /*fd*/) {}
225
GetTestAddress(uint8_t index)226 static RawAddress GetTestAddress(uint8_t index) {
227 EXPECT_LT(index, UINT8_MAX);
228 RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}};
229 return result;
230 }
231
232 class MockAudioHalClientCallbacks : public bluetooth::le_audio::LeAudioClientCallbacks {
233 public:
234 MOCK_METHOD((void), OnInitialized, (), (override));
235 MOCK_METHOD((void), OnConnectionState, (ConnectionState state, const RawAddress& address),
236 (override));
237 MOCK_METHOD((void), OnGroupStatus, (int group_id, GroupStatus group_status), (override));
238 MOCK_METHOD((void), OnGroupStreamStatus, (int group_id, GroupStreamStatus group_stream_status),
239 (override));
240 MOCK_METHOD((void), OnGroupNodeStatus,
241 (const RawAddress& bd_addr, int group_id, GroupNodeStatus node_status), (override));
242 MOCK_METHOD((void), OnAudioConf,
243 (uint8_t direction, int group_id, std::optional<std::bitset<32>> snk_audio_location,
244 std::optional<std::bitset<32>> src_audio_location, uint16_t avail_cont),
245 (override));
246 MOCK_METHOD(void, OnSinkAudioLocationAvailable,
247 (const RawAddress& bd_addr, std::optional<std::bitset<32>> snk_audio_location),
248 (override));
249 MOCK_METHOD((void), OnAudioLocalCodecCapabilities,
250 (std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
251 std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf),
252 (override));
253 MOCK_METHOD((void), OnAudioGroupCurrentCodecConf,
254 (int group_id, btle_audio_codec_config_t input_codec_conf,
255 btle_audio_codec_config_t output_codec_conf),
256 (override));
257 MOCK_METHOD((void), OnAudioGroupSelectableCodecConf,
258 (int group_id, std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
259 std::vector<btle_audio_codec_config_t> output_selectable_codec_conf),
260 (override));
261 MOCK_METHOD((void), OnHealthBasedRecommendationAction,
262 (const RawAddress& address, LeAudioHealthBasedAction action), (override));
263 MOCK_METHOD((void), OnHealthBasedGroupRecommendationAction,
264 (int group_id, LeAudioHealthBasedAction action), (override));
265 MOCK_METHOD((void), OnUnicastMonitorModeStatus,
266 (uint8_t direction, UnicastMonitorModeStatus status));
267 };
268
269 class MockLeAudioSinkHalClient : public LeAudioSinkAudioHalClient {
270 public:
271 MockLeAudioSinkHalClient() = default;
272 MOCK_METHOD((bool), Start,
273 (const LeAudioCodecConfiguration& codecConfiguration,
274 LeAudioSinkAudioHalClient::Callbacks* audioReceiver, DsaModes dsa_modes),
275 (override));
276 MOCK_METHOD((void), Stop, (), (override));
277 MOCK_METHOD((size_t), SendData, (uint8_t* data, uint16_t size), (override));
278 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
279 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
280 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
281 MOCK_METHOD((void), UpdateAudioConfigToHal, (const ::bluetooth::le_audio::stream_config&),
282 (override));
283 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
284 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
285
286 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSinkHalClient()287 virtual ~MockLeAudioSinkHalClient() override { OnDestroyed(); }
288 };
289
290 class MockLeAudioSourceHalClient : public LeAudioSourceAudioHalClient {
291 public:
292 MockLeAudioSourceHalClient() = default;
293 MOCK_METHOD((bool), Start,
294 (const LeAudioCodecConfiguration& codecConfiguration,
295 LeAudioSourceAudioHalClient::Callbacks* audioReceiver, DsaModes dsa_modes),
296 (override));
297 MOCK_METHOD((void), Stop, (), (override));
298 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
299 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
300 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
301 MOCK_METHOD((void), UpdateAudioConfigToHal, (const ::bluetooth::le_audio::stream_config&),
302 (override));
303 MOCK_METHOD((std::optional<broadcaster::BroadcastConfiguration>), GetBroadcastConfig,
304 ((const std::vector<std::pair<types::LeAudioContextType, uint8_t>>&),
305 (const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>>&)),
306 (const override));
307 MOCK_METHOD((std::optional<::bluetooth::le_audio::types::AudioSetConfiguration>),
308 GetUnicastConfig, (const CodecManager::UnicastConfigurationRequirements&),
309 (const override));
310 MOCK_METHOD((void), UpdateBroadcastAudioConfigToHal,
311 (const ::bluetooth::le_audio::broadcast_offload_config&), (override));
312 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
313 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
314
315 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSourceHalClient()316 virtual ~MockLeAudioSourceHalClient() override { OnDestroyed(); }
317 };
318
319 class UnicastTestNoInit : public Test {
320 public:
321 bool use_handover_mode = false;
322
323 protected:
RegisterSourceHalClientMock()324 void RegisterSourceHalClientMock() {
325 owned_mock_le_audio_source_hal_client_.reset(new NiceMock<MockLeAudioSourceHalClient>());
326 mock_le_audio_source_hal_client_ =
327 (MockLeAudioSourceHalClient*)owned_mock_le_audio_source_hal_client_.get();
328
329 is_audio_unicast_source_acquired = false;
330 ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _))
331 .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/,
332 LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
333 DsaModes /*dsa_modes*/) {
334 unicast_source_hal_cb_ = audioReceiver;
335 return true;
336 });
337 ON_CALL(*mock_le_audio_source_hal_client_, OnDestroyed).WillByDefault([]() {
338 mock_le_audio_source_hal_client_ = nullptr;
339 is_audio_unicast_source_acquired = false;
340 });
341 }
342
RegisterSinkHalClientMock()343 void RegisterSinkHalClientMock() {
344 owned_mock_le_audio_sink_hal_client_.reset(new NiceMock<MockLeAudioSinkHalClient>());
345 mock_le_audio_sink_hal_client_ =
346 (MockLeAudioSinkHalClient*)owned_mock_le_audio_sink_hal_client_.get();
347
348 is_audio_unicast_sink_acquired = false;
349 ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _))
350 .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/,
351 LeAudioSinkAudioHalClient::Callbacks* audioReceiver,
352 DsaModes /*dsa_modes*/) {
353 unicast_sink_hal_cb_ = audioReceiver;
354 return true;
355 });
356 ON_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed).WillByDefault([]() {
357 mock_le_audio_sink_hal_client_ = nullptr;
358 is_audio_unicast_sink_acquired = false;
359 });
360 }
361
SetUpMockAudioHal()362 void SetUpMockAudioHal() {
363 /* Since these are returned by the Acquire() methods as unique_ptrs, we
364 * will not free them manually.
365 */
366 RegisterSourceHalClientMock();
367
368 owned_mock_le_audio_sink_hal_client_.reset(new NiceMock<MockLeAudioSinkHalClient>());
369 mock_le_audio_sink_hal_client_ =
370 (MockLeAudioSinkHalClient*)owned_mock_le_audio_sink_hal_client_.get();
371
372 owned_mock_le_audio_source_hal_client_.reset(new NiceMock<MockLeAudioSourceHalClient>());
373 mock_le_audio_source_hal_client_ =
374 (MockLeAudioSourceHalClient*)owned_mock_le_audio_source_hal_client_.get();
375
376 is_audio_unicast_source_acquired = false;
377 ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _))
378 .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/,
379 LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
380 DsaModes /*dsa_modes*/) {
381 unicast_source_hal_cb_ = audioReceiver;
382 return true;
383 });
384 ON_CALL(*mock_le_audio_source_hal_client_, OnDestroyed).WillByDefault([]() {
385 mock_le_audio_source_hal_client_ = nullptr;
386 is_audio_unicast_source_acquired = false;
387 });
388
389 is_audio_unicast_sink_acquired = false;
390 ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _))
391 .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/,
392 LeAudioSinkAudioHalClient::Callbacks* audioReceiver,
393 DsaModes /*dsa_modes*/) {
394 unicast_sink_hal_cb_ = audioReceiver;
395 return true;
396 });
397 ON_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed).WillByDefault([]() {
398 mock_le_audio_sink_hal_client_ = nullptr;
399 is_audio_unicast_sink_acquired = false;
400 });
401
402 ON_CALL(*mock_le_audio_sink_hal_client_, SendData)
403 .WillByDefault([](uint8_t* /*data*/, uint16_t size) { return size; });
404
405 // HAL
406 ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool { return true; });
407 }
408
InjectGroupDeviceRemoved(const RawAddress & address,int group_id)409 void InjectGroupDeviceRemoved(const RawAddress& address, int group_id) {
410 group_callbacks_->OnGroupMemberRemoved(address, group_id);
411 }
412
InjectGroupDeviceAdded(const RawAddress & address,int group_id)413 void InjectGroupDeviceAdded(const RawAddress& address, int group_id) {
414 bluetooth::Uuid uuid = bluetooth::le_audio::uuid::kCapServiceUuid;
415
416 int group_members_num = 0;
417 for (const auto& [addr, id] : groups) {
418 if (id == group_id) {
419 group_members_num++;
420 }
421 }
422
423 bool first_device = (group_members_num == 1);
424 do_in_main_thread(base::BindOnce(
425 [](const RawAddress& addr, int group_id, bluetooth::Uuid uuid,
426 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks, bool first_device) {
427 if (first_device) {
428 group_callbacks->OnGroupAdded(addr, uuid, group_id);
429 } else {
430 group_callbacks->OnGroupMemberAdded(addr, group_id);
431 }
432 },
433 address, group_id, uuid, base::Unretained(this->group_callbacks_), first_device));
434 }
435
InjectServiceChangedEvent(const RawAddress & address,uint16_t conn_id)436 void InjectServiceChangedEvent(const RawAddress& address, uint16_t conn_id) {
437 tBTA_GATTC_SERVICE_CHANGED event_data = {.remote_bda = address, .conn_id = conn_id};
438
439 do_in_main_thread(base::BindOnce(
440 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_SERVICE_CHANGED event_data) {
441 gatt_callback(BTA_GATTC_SRVC_CHG_EVT, (tBTA_GATTC*)&event_data);
442 },
443 base::Unretained(this->gatt_callback), event_data));
444 }
445
InjectConnectedEvent(const RawAddress & address,uint16_t conn_id,tGATT_STATUS status=GATT_SUCCESS)446 void InjectConnectedEvent(const RawAddress& address, uint16_t conn_id,
447 tGATT_STATUS status = GATT_SUCCESS) {
448 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
449 tBTA_GATTC_OPEN event_data = {
450 .status = status,
451 .conn_id = conn_id,
452 .client_if = gatt_if,
453 .remote_bda = address,
454 .transport = BT_TRANSPORT_LE,
455 .mtu = 240,
456 };
457
458 if (status == GATT_SUCCESS) {
459 ASSERT_NE(peer_devices.count(conn_id), 0u);
460 peer_devices.at(conn_id)->connected = true;
461 }
462
463 do_in_main_thread(base::BindOnce(
464 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_OPEN event_data) {
465 gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
466 },
467 base::Unretained(this->gatt_callback), event_data));
468 }
469
InjectEncryptionChangedEvent(const RawAddress & address)470 void InjectEncryptionChangedEvent(const RawAddress& address) {
471 tBTA_GATTC_ENC_CMPL_CB event_data = {
472 .client_if = gatt_if,
473 .remote_bda = address,
474 };
475
476 do_in_main_thread(base::BindOnce(
477 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_ENC_CMPL_CB event_data) {
478 gatt_callback(BTA_GATTC_ENC_CMPL_CB_EVT, (tBTA_GATTC*)&event_data);
479 },
480 base::Unretained(this->gatt_callback), event_data));
481 }
482
TriggerDisconnectionFromApp(const RawAddress & address)483 void TriggerDisconnectionFromApp(const RawAddress& address) {
484 do_in_main_thread(base::BindOnce(
485 [](LeAudioClient* client, const RawAddress& address) { client->Disconnect(address); },
486 LeAudioClient::Get(), address));
487 }
488
InjectDisconnectedEvent(uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST)489 void InjectDisconnectedEvent(uint16_t conn_id,
490 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) {
491 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
492 ASSERT_NE(peer_devices.count(conn_id), 0u);
493
494 tBTA_GATTC_CLOSE event_data = {
495 .conn_id = conn_id,
496 .status = GATT_SUCCESS,
497 .client_if = gatt_if,
498 .remote_bda = peer_devices.at(conn_id)->addr,
499 .reason = reason,
500 };
501
502 peer_devices.at(conn_id)->connected = false;
503 do_in_main_thread(base::BindOnce(
504 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_CLOSE event_data) {
505 gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
506 },
507 base::Unretained(this->gatt_callback), event_data));
508 }
509
InjectPhyChangedEvent(uint16_t conn_id,uint8_t tx_phy,uint8_t rx_phy,tGATT_STATUS status)510 void InjectPhyChangedEvent(uint16_t conn_id, uint8_t tx_phy, uint8_t rx_phy,
511 tGATT_STATUS status) {
512 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
513 tBTA_GATTC_PHY_UPDATE event_data = {
514 .conn_id = conn_id,
515 .tx_phy = tx_phy,
516 .rx_phy = rx_phy,
517 .status = status,
518 };
519
520 do_in_main_thread(base::BindOnce(
521 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_PHY_UPDATE event_data) {
522 gatt_callback(BTA_GATTC_PHY_UPDATE_EVT, (tBTA_GATTC*)&event_data);
523 },
524 base::Unretained(this->gatt_callback), event_data));
525 }
526
InjectSearchCompleteEvent(uint16_t conn_id)527 void InjectSearchCompleteEvent(uint16_t conn_id) {
528 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
529 tBTA_GATTC_SEARCH_CMPL event_data = {
530 .conn_id = conn_id,
531 .status = GATT_SUCCESS,
532 };
533
534 do_in_main_thread(base::BindOnce(
535 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_SEARCH_CMPL event_data) {
536 gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT, (tBTA_GATTC*)&event_data);
537 },
538 base::Unretained(this->gatt_callback), event_data));
539 }
540
InjectNotificationEvent(const RawAddress & test_address,uint16_t conn_id,uint16_t handle,std::vector<uint8_t> value)541 void InjectNotificationEvent(const RawAddress& test_address, uint16_t conn_id, uint16_t handle,
542 std::vector<uint8_t> value) {
543 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
544 tBTA_GATTC_NOTIFY event_data = {
545 .conn_id = conn_id,
546 .bda = test_address,
547 .handle = handle,
548 .len = (uint8_t)value.size(),
549 .is_notify = true,
550 };
551
552 std::copy(value.begin(), value.end(), event_data.value);
553 do_in_main_thread(base::BindOnce(
554 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_NOTIFY event_data) {
555 gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
556 },
557 base::Unretained(this->gatt_callback), event_data));
558 }
559
InjectContextTypes(const RawAddress & test_address,uint16_t conn_id,uint16_t handle,AudioContexts sink_ctxs,AudioContexts source_ctxs)560 void InjectContextTypes(const RawAddress& test_address, uint16_t conn_id, uint16_t handle,
561 AudioContexts sink_ctxs, AudioContexts source_ctxs) {
562 std::vector<uint8_t> contexts = {
563 (uint8_t)(sink_ctxs.value()), (uint8_t)(sink_ctxs.value() >> 8),
564 (uint8_t)(source_ctxs.value()), (uint8_t)(source_ctxs.value() >> 8)};
565
566 InjectNotificationEvent(test_address, conn_id, handle, contexts);
567 }
568
InjectSupportedContextTypes(const RawAddress & test_address,uint16_t conn_id,AudioContexts sink_ctxs,AudioContexts source_ctxs)569 void InjectSupportedContextTypes(const RawAddress& test_address, uint16_t conn_id,
570 AudioContexts sink_ctxs, AudioContexts source_ctxs) {
571 /* 0x0077 pacs->supp_contexts_char + 1 */
572 InjectContextTypes(test_address, conn_id, 0x0077, sink_ctxs, source_ctxs);
573 SyncOnMainLoop();
574 }
575
InjectAvailableContextTypes(const RawAddress & test_address,uint16_t conn_id,AudioContexts sink_ctxs,AudioContexts source_ctxs,bool sync_on_mainloop=true)576 void InjectAvailableContextTypes(const RawAddress& test_address, uint16_t conn_id,
577 AudioContexts sink_ctxs, AudioContexts source_ctxs,
578 bool sync_on_mainloop = true) {
579 /* 0x0074 is pacs->avail_contexts_char + 1 */
580 InjectContextTypes(test_address, conn_id, 0x0074, sink_ctxs, source_ctxs);
581 if (sync_on_mainloop) {
582 SyncOnMainLoop();
583 }
584 }
585
SetUpMockGatt()586 void SetUpMockGatt() {
587 // default action for GetCharacteristic function call
588 ON_CALL(mock_gatt_interface_, GetCharacteristic(_, _))
589 .WillByDefault(
590 Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Characteristic* {
591 std::list<gatt::Service>& services = peer_devices.at(conn_id)->services;
592 for (auto const& service : services) {
593 for (auto const& characteristic : service.characteristics) {
594 if (characteristic.value_handle == handle) {
595 return &characteristic;
596 }
597 }
598 }
599
600 return nullptr;
601 }));
602
603 // default action for GetOwningService function call
604 ON_CALL(mock_gatt_interface_, GetOwningService(_, _))
605 .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
606 std::list<gatt::Service>& services = peer_devices.at(conn_id)->services;
607 for (auto const& service : services) {
608 if (service.handle <= handle && service.end_handle >= handle) {
609 return &service;
610 }
611 }
612
613 return nullptr;
614 }));
615
616 // default action for ServiceSearchRequest function call
617 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
618 .WillByDefault(WithArg<0>(
619 Invoke([&](uint16_t conn_id) { InjectSearchCompleteEvent(conn_id); })));
620
621 // default action for GetServices function call
622 ON_CALL(mock_gatt_interface_, GetServices(_))
623 .WillByDefault(WithArg<0>(Invoke([&](uint16_t conn_id) -> std::list<gatt::Service>* {
624 return &peer_devices.at(conn_id)->services;
625 })));
626
627 // default action for RegisterForNotifications function call
628 ON_CALL(mock_gatt_interface_, RegisterForNotifications(gatt_if, _, _))
629 .WillByDefault(Return(GATT_SUCCESS));
630
631 // default action for DeregisterForNotifications function call
632 ON_CALL(mock_gatt_interface_, DeregisterForNotifications(gatt_if, _, _))
633 .WillByDefault(Return(GATT_SUCCESS));
634
635 // default action for WriteDescriptor function call
636 ON_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _))
637 .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle,
638 std::vector<uint8_t> value,
639 tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb,
640 void* cb_data) -> void {
641 auto& ascs = peer_devices.at(conn_id)->ascs;
642 uint8_t idx;
643
644 if (handle == ascs->ctp_ccc) {
645 value = UINT16_TO_VEC_UINT8(ascs->ctp_ccc_val);
646 } else {
647 for (idx = 0; idx < max_num_of_ases; idx++) {
648 if (handle == ascs->sink_ase_ccc[idx] + 1) {
649 value = UINT16_TO_VEC_UINT8(ascs->sink_ase_ccc_val[idx]);
650 break;
651 }
652 if (handle == ascs->source_ase_char[idx] + 1) {
653 value = UINT16_TO_VEC_UINT8(ascs->source_ase_ccc_val[idx]);
654 break;
655 }
656 }
657 }
658
659 if (cb) {
660 do_in_main_thread(base::BindOnce(
661 [](GATT_WRITE_OP_CB cb, uint16_t conn_id, uint16_t handle, uint16_t len,
662 uint8_t* value, void* cb_data) {
663 cb(conn_id, GATT_SUCCESS, handle, len, value, cb_data);
664 },
665 cb, conn_id, handle, value.size(), value.data(), cb_data));
666 }
667 }));
668
669 global_conn_id = 1;
670 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
671 .WillByDefault(Invoke([&](tGATT_IF /*client_if*/, const RawAddress& remote_bda,
672 bool /*is_direct*/, bool /*opportunistic*/) {
673 InjectConnectedEvent(remote_bda, global_conn_id++);
674 }));
675
676 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(Invoke([&](uint16_t conn_id) {
677 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
678 InjectDisconnectedEvent(conn_id);
679 }));
680
681 // default Characteristic read handler dispatches requests to service mocks
682 ON_CALL(mock_gatt_queue_, ReadCharacteristic(_, _, _, _))
683 .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
684 void* cb_data) {
685 do_in_main_thread(base::BindOnce(
686 [](std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>>*
687 peer_devices,
688 uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
689 void* cb_data) -> void {
690 if (peer_devices->count(conn_id)) {
691 auto& device = peer_devices->at(conn_id);
692 auto svc = std::find_if(device->services.begin(), device->services.end(),
693 [handle](const gatt::Service& svc) {
694 return (handle >= svc.handle) &&
695 (handle <= svc.end_handle);
696 });
697 if (svc == device->services.end()) {
698 return;
699 }
700
701 GattStatus status;
702 std::vector<uint8_t> value;
703 // Dispatch to mockable handler functions
704 if (svc->handle == device->csis->start) {
705 std::tie(status, value) =
706 device->csis->OnGetCharacteristicValue(handle);
707 } else if (svc->handle == device->cas->start) {
708 std::tie(status, value) = device->cas->OnGetCharacteristicValue(handle);
709 } else if (svc->handle == device->ascs->start) {
710 std::tie(status, value) =
711 device->ascs->OnGetCharacteristicValue(handle);
712 } else if (svc->handle == device->pacs->start) {
713 std::tie(status, value) =
714 device->pacs->OnGetCharacteristicValue(handle);
715 } else {
716 return;
717 }
718
719 cb(conn_id, status, handle, value.size(), value.data(), cb_data);
720 }
721 },
722 &peer_devices, conn_id, handle, cb, cb_data));
723 }));
724
725 // default multiple Characteristic read handler dispatches requests to service mocks
726 ON_CALL(mock_gatt_queue_, ReadMultiCharacteristic(_, _, _, _))
727 .WillByDefault(Invoke([&](uint16_t conn_id, tBTA_GATTC_MULTI& handles,
728 GATT_READ_MULTI_OP_CB cb, void* cb_data) {
729 do_in_main_thread(base::BindOnce(
730 [](std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>>*
731 peer_devices,
732 uint16_t conn_id, tBTA_GATTC_MULTI handles, GATT_READ_MULTI_OP_CB cb,
733 void* cb_data) -> void {
734 if (!peer_devices->count(conn_id)) {
735 return;
736 }
737 auto& device = peer_devices->at(conn_id);
738
739 auto get_char_value_helper = [&](NiceMock<MockDeviceWrapper>& device,
740 uint16_t handle) {
741 auto svc = std::find_if(device.services.begin(), device.services.end(),
742 [handle](const gatt::Service& svc) {
743 return (handle >= svc.handle) &&
744 (handle <= svc.end_handle);
745 });
746 if (svc == device.services.end()) {
747 return std::make_pair(GATT_ERROR, std::vector<uint8_t>());
748 }
749
750 // Dispatch to mockable handler functions
751 if (svc->handle == device.csis->start) {
752 return device.csis->OnGetCharacteristicValue(handle);
753 } else if (svc->handle == device.cas->start) {
754 return device.cas->OnGetCharacteristicValue(handle);
755 } else if (svc->handle == device.ascs->start) {
756 return device.ascs->OnGetCharacteristicValue(handle);
757 } else if (svc->handle == device.pacs->start) {
758 return device.pacs->OnGetCharacteristicValue(handle);
759 } else {
760 return std::make_pair(GATT_ERROR, std::vector<uint8_t>());
761 };
762 };
763 std::array<uint8_t, GATT_MAX_ATTR_LEN> value;
764 uint16_t value_end = 0;
765 for (int i = 0; i < handles.num_attr; i++) {
766 GattStatus status;
767 std::vector<uint8_t> curr_val;
768 std::tie(status, curr_val) =
769 get_char_value_helper(*device, handles.handles[i]);
770
771 if (status != GATT_SUCCESS) {
772 cb(conn_id, status, handles, 0, value.data(), cb_data);
773 return;
774 }
775
776 value[value_end] = (curr_val.size() & 0x00ff);
777 value[value_end + 1] = (curr_val.size() & 0xff00) >> 8;
778 value_end += 2;
779
780 // concatenate all read values together
781 std::copy(curr_val.begin(), curr_val.end(), value.data() + value_end);
782 value_end += curr_val.size();
783 }
784 cb(conn_id, GATT_SUCCESS, handles, value_end, value.data(), cb_data);
785 },
786 &peer_devices, conn_id, handles, cb, cb_data));
787 }));
788 }
789
SetUpMockGroups()790 void SetUpMockGroups() {
791 MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
792 MockDeviceGroups::SetMockInstanceForTesting(&mock_groups_module_);
793 MockLeAudioGroupStateMachine::SetMockInstanceForTesting(&mock_state_machine_);
794
795 ON_CALL(mock_csis_client_module_, Get()).WillByDefault(Return(&mock_csis_client_module_));
796
797 // Store group callbacks so that we could inject grouping events
798 group_callbacks_ = nullptr;
799 ON_CALL(mock_groups_module_, Initialize(_)).WillByDefault(SaveArg<0>(&group_callbacks_));
800
801 ON_CALL(mock_groups_module_, GetGroupId(_, _))
802 .WillByDefault([this](const RawAddress& addr, bluetooth::Uuid /*uuid*/) {
803 if (groups.find(addr) != groups.end()) {
804 return groups.at(addr);
805 }
806 return bluetooth::groups::kGroupUnknown;
807 });
808
809 ON_CALL(mock_groups_module_, RemoveDevice(_, _))
810 .WillByDefault([this](const RawAddress& addr, int /*group_id*/) {
811 int group_id = -1;
812 if (groups.find(addr) != groups.end()) {
813 group_id = groups[addr];
814 groups.erase(addr);
815 }
816 if (group_id < 0) {
817 return;
818 }
819
820 do_in_main_thread(base::BindOnce(
821 [](const RawAddress& address, int group_id,
822 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks) {
823 group_callbacks->OnGroupMemberRemoved(address, group_id);
824 },
825 addr, group_id, base::Unretained(group_callbacks_)));
826 });
827
828 // Our test devices have unique LSB - use it for unique grouping when
829 // devices added with a non-CIS context and no grouping info
830 ON_CALL(mock_groups_module_, AddDevice(_, bluetooth::le_audio::uuid::kCapServiceUuid, _))
831 .WillByDefault(
832 [this](const RawAddress& addr,
833 bluetooth::Uuid /*uuid*/ = bluetooth::le_audio::uuid::kCapServiceUuid,
834 int group_id = bluetooth::groups::kGroupUnknown) -> int {
835 if (group_id == bluetooth::groups::kGroupUnknown) {
836 /* Generate group id from address */
837 groups[addr] = addr.address[RawAddress::kLength - 1];
838 group_id = groups[addr];
839 } else {
840 groups[addr] = group_id;
841 }
842
843 InjectGroupDeviceAdded(addr, groups[addr]);
844 return addr.address[RawAddress::kLength - 1];
845 });
846
847 ON_CALL(mock_state_machine_, Initialize(_))
848 .WillByDefault(SaveArg<0>(&state_machine_callbacks_));
849
850 ON_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _))
851 .WillByDefault([this](LeAudioDeviceGroup* group, types::LeAudioContextType context_type,
852 types::BidirectionalPair<types::AudioContexts>
853 metadata_context_types,
854 types::BidirectionalPair<std::vector<uint8_t>> ccid_lists,
855 bool configure_qos) {
856 auto group_state = group->GetState();
857 bool isReconfiguration = group->IsPendingConfiguration();
858
859 log::info(
860 "ConfigureStream: group {} state {}, context type {} sink metadata_ctx {}, "
861 "source metadata_ctx {}, ccid_sink size {}, ccid_source_size {}, "
862 "isReconfiguration {}",
863 group->group_id_, bluetooth::common::ToString(group_state),
864 bluetooth::common::ToString(context_type),
865 bluetooth::common::ToString(metadata_context_types.sink),
866 bluetooth::common::ToString(metadata_context_types.source),
867 ccid_lists.sink.size(), ccid_lists.source.size(), isReconfiguration);
868
869 /* Do what ReleaseCisIds(group) does: start */
870 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
871 while (leAudioDevice != nullptr) {
872 for (auto& ase : leAudioDevice->ases_) {
873 ase.cis_id = bluetooth::le_audio::kInvalidCisId;
874 }
875 leAudioDevice = group->GetNextDevice(leAudioDevice);
876 }
877 group->ClearAllCises();
878 /* end */
879
880 if (!group->Configure(context_type, metadata_context_types, ccid_lists)) {
881 log::error("ConfigureStream: Could not configure ASEs for group {} content type {}",
882 group->group_id_, int(context_type));
883
884 return false;
885 }
886
887 group->cig.GenerateCisIds(context_type);
888
889 types::AseState config_state =
890 types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
891
892 if (configure_qos) {
893 // Make sure CIG is created
894 config_state = types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED;
895 group->cig.SetState(types::CigState::CREATED);
896 }
897
898 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
899 device = group->GetNextDevice(device)) {
900 if (!group->cig.AssignCisIds(device)) {
901 continue;
902 }
903
904 if (group->cig.GetState() == types::CigState::CREATED) {
905 group->AssignCisConnHandlesToAses(device);
906 }
907
908 for (auto& ase : device->ases_) {
909 if (!ase.active) {
910 continue;
911 }
912
913 ase.cis_state = types::CisState::IDLE;
914 ase.data_path_state = types::DataPathState::IDLE;
915 ase.state = config_state;
916 }
917 }
918
919 // Inject the state
920 group->SetTargetState(config_state);
921 group->SetState(group->GetTargetState());
922 if (group->IsPendingConfiguration()) {
923 group->ClearPendingConfiguration();
924 do_in_main_thread(base::BindOnce(
925 [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
926 state_machine_callbacks) {
927 state_machine_callbacks->StatusReportCb(
928 group_id, GroupStreamStatus::CONFIGURED_BY_USER);
929 },
930 group->group_id_, base::Unretained(this->state_machine_callbacks_)));
931 }
932 return true;
933 });
934
935 ON_CALL(mock_state_machine_, AttachToStream(_, _, _))
936 .WillByDefault([this](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
937 types::BidirectionalPair<std::vector<uint8_t>> ccids) {
938 log::info(
939 "AttachToStream: group_id {}, address {}, current_state {}, target_state {}",
940 group->group_id_, leAudioDevice->address_,
941 bluetooth::common::ToString(group->GetState()),
942 bluetooth::common::ToString(group->GetTargetState()));
943
944 if (group->GetState() != types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
945 if (group->GetTargetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
946 attach_to_stream_scheduled = true;
947 }
948
949 return false;
950 }
951
952 group->Configure(group->GetConfigurationContextType(), group->GetMetadataContexts(),
953 ccids);
954 if (!group->cig.AssignCisIds(leAudioDevice)) {
955 return false;
956 }
957 group->AssignCisConnHandlesToAses(leAudioDevice);
958
959 auto* stream_conf = &group->stream_conf;
960
961 for (auto& ase : leAudioDevice->ases_) {
962 if (!ase.active) {
963 continue;
964 }
965
966 // And also skip the ase establishment procedure which should
967 // be tested as part of the state machine unit tests
968 ase.cis_state = types::CisState::CONNECTED;
969 ase.data_path_state = types::DataPathState::CONFIGURED;
970 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
971
972 uint16_t cis_conn_hdl = ase.cis_conn_hdl;
973 auto core_config = ase.codec_config.params.GetAsCoreCodecConfig();
974
975 /* Copied from state_machine.cc ProcessHciNotifSetupIsoDataPath */
976 if (ase.direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
977 auto iter = std::find_if(
978 stream_conf->stream_params.source.stream_config.stream_map.begin(),
979 stream_conf->stream_params.source.stream_config.stream_map.end(),
980 [cis_conn_hdl](auto& info) {
981 return cis_conn_hdl == info.stream_handle;
982 });
983
984 if (iter == stream_conf->stream_params.source.stream_config.stream_map.end()) {
985 stream_conf->stream_params.source.stream_config.stream_map.emplace_back(
986 stream_map_info(ase.cis_conn_hdl, *core_config.audio_channel_allocation,
987 true));
988
989 stream_conf->stream_params.source.num_of_devices++;
990 stream_conf->stream_params.source.num_of_channels +=
991 ase.codec_config.channel_count_per_iso_stream;
992
993 log::info(
994 "AttachToStream: Added Source Stream Configuration. CIS Connection "
995 "Handle: "
996 "{}, Audio Channel Allocation: {}, Source Number Of "
997 "Devices: {}, Source Number Of Channels: {}",
998 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
999 stream_conf->stream_params.source.num_of_devices,
1000 stream_conf->stream_params.source.num_of_channels);
1001 }
1002 } else {
1003 auto iter = std::find_if(
1004 stream_conf->stream_params.sink.stream_config.stream_map.begin(),
1005 stream_conf->stream_params.sink.stream_config.stream_map.end(),
1006 [cis_conn_hdl](auto& info) {
1007 return cis_conn_hdl == info.stream_handle;
1008 });
1009
1010 if (iter == stream_conf->stream_params.sink.stream_config.stream_map.end()) {
1011 stream_conf->stream_params.sink.stream_config.stream_map.emplace_back(
1012 stream_map_info(ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1013 true));
1014
1015 stream_conf->stream_params.sink.num_of_devices++;
1016 stream_conf->stream_params.sink.num_of_channels +=
1017 ase.codec_config.channel_count_per_iso_stream;
1018
1019 log::info(
1020 "AttachToStream: Added Sink Stream Configuration. CIS Connection "
1021 "Handle: "
1022 "{}, Audio Channel Allocation: {}, Sink Number Of Devices: "
1023 "{}, Sink Number Of Channels: {}",
1024 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1025 stream_conf->stream_params.sink.num_of_devices,
1026 stream_conf->stream_params.sink.num_of_channels);
1027 }
1028 }
1029 }
1030
1031 // When the device attaches to the stream we send again the state machine state to
1032 // stimulate the stream map update
1033 // see LeAudioGroupStateMachineImpl::SendStreamingStatusCbIfNeeded(group);
1034 if (!group->HaveAllCisesDisconnected() &&
1035 (group->GetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) &&
1036 (group->GetTargetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING)) {
1037 do_in_main_thread(base::BindOnce(
1038 [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
1039 state_machine_callbacks) {
1040 state_machine_callbacks->StatusReportCb(group_id,
1041 GroupStreamStatus::STREAMING);
1042 },
1043 group->group_id_, base::Unretained(this->state_machine_callbacks_)));
1044 }
1045
1046 return true;
1047 });
1048
1049 ON_CALL(mock_state_machine_, StartStream(_, _, _, _))
1050 .WillByDefault([this](LeAudioDeviceGroup* group, types::LeAudioContextType context_type,
1051 types::BidirectionalPair<types::AudioContexts>
1052 metadata_context_types,
1053 types::BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
1054 auto group_state = group->GetState();
1055 log::info(
1056 "StartStream: group {} state {}, context type {} sink metadata_ctx {}, "
1057 "source metadata_ctx {}, ccid_sink size {}, ccid_source_size {}",
1058 group->group_id_, bluetooth::common::ToString(group_state),
1059 bluetooth::common::ToString(context_type),
1060 bluetooth::common::ToString(metadata_context_types.sink),
1061 bluetooth::common::ToString(metadata_context_types.source),
1062 ccid_lists.sink.size(), ccid_lists.source.size());
1063
1064 /* Do nothing if already streaming - the implementation would
1065 * probably update the metadata.
1066 */
1067 if (group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
1068 return true;
1069 }
1070
1071 // Inject the state
1072 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1073
1074 if (group_state != types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) {
1075 /* Do what ReleaseCisIds(group) does: start */
1076 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
1077 while (leAudioDevice != nullptr) {
1078 for (auto& ase : leAudioDevice->ases_) {
1079 ase.cis_id = bluetooth::le_audio::kInvalidCisId;
1080 }
1081 leAudioDevice = group->GetNextDevice(leAudioDevice);
1082 }
1083 group->ClearAllCises();
1084 /* end */
1085
1086 if (!group->Configure(context_type, metadata_context_types, ccid_lists)) {
1087 log::error("StartStream: failed to set ASE configuration");
1088 return false;
1089 }
1090
1091 if (group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE ||
1092 group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) {
1093 group->cig.GenerateCisIds(context_type);
1094
1095 std::vector<uint16_t> conn_handles;
1096 for (uint8_t i = 0; i < (uint8_t)(group->cig.cises.size()); i++) {
1097 conn_handles.push_back(iso_con_counter_++);
1098 }
1099 group->cig.AssignCisConnHandles(conn_handles);
1100 for (LeAudioDevice* device = group->GetFirstActiveDevice(); device != nullptr;
1101 device = group->GetNextActiveDevice(device)) {
1102 if (!group->cig.AssignCisIds(device)) {
1103 return false;
1104 }
1105 group->AssignCisConnHandlesToAses(device);
1106 }
1107 }
1108 }
1109
1110 auto* stream_conf = &group->stream_conf;
1111
1112 // Fake ASE configuration
1113 for (LeAudioDevice* device = group->GetFirstActiveDevice(); device != nullptr;
1114 device = group->GetNextActiveDevice(device)) {
1115 for (auto& ase : device->ases_) {
1116 if (!ase.active) {
1117 continue;
1118 }
1119
1120 // And also skip the ase establishment procedure which should
1121 // be tested as part of the state machine unit tests
1122 ase.cis_state = types::CisState::CONNECTED;
1123 ase.data_path_state = types::DataPathState::CONFIGURED;
1124 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
1125 ase.qos_preferences.pres_delay_min = 2500;
1126 ase.qos_preferences.pres_delay_max = 2500;
1127 ase.qos_preferences.preferred_pres_delay_min = 2500;
1128 ase.qos_preferences.preferred_pres_delay_max = 2500;
1129 auto core_config = ase.codec_config.params.GetAsCoreCodecConfig();
1130
1131 uint16_t cis_conn_hdl = ase.cis_conn_hdl;
1132
1133 /* Copied from state_machine.cc AddCisToStreamConfiguration */
1134 if (ase.direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
1135 auto iter = std::find_if(
1136 stream_conf->stream_params.source.stream_config.stream_map.begin(),
1137 stream_conf->stream_params.source.stream_config.stream_map.end(),
1138 [cis_conn_hdl](auto& info) {
1139 return cis_conn_hdl == info.stream_handle;
1140 });
1141
1142 if (iter == stream_conf->stream_params.source.stream_config.stream_map.end()) {
1143 stream_conf->stream_params.source.stream_config.stream_map.emplace_back(
1144 stream_map_info(ase.cis_conn_hdl,
1145 *core_config.audio_channel_allocation, true));
1146
1147 stream_conf->stream_params.source.num_of_devices++;
1148 stream_conf->stream_params.source.num_of_channels +=
1149 ase.codec_config.channel_count_per_iso_stream;
1150 stream_conf->stream_params.source.audio_channel_allocation |=
1151 *core_config.audio_channel_allocation;
1152 stream_conf->stream_params.source.stream_config.peer_delay_ms = 44;
1153
1154 if (stream_conf->stream_params.source.stream_config.sampling_frequency_hz ==
1155 0) {
1156 stream_conf->stream_params.source.stream_config.sampling_frequency_hz =
1157 core_config.GetSamplingFrequencyHz();
1158 } else {
1159 log::assert_that(stream_conf->stream_params.source.stream_config
1160 .sampling_frequency_hz ==
1161 core_config.GetSamplingFrequencyHz(),
1162 "StartStream: sample freq mismatch: {}!={}",
1163 stream_conf->stream_params.source.stream_config
1164 .sampling_frequency_hz,
1165 core_config.GetSamplingFrequencyHz());
1166 }
1167
1168 if (stream_conf->stream_params.source.stream_config.octets_per_codec_frame ==
1169 0) {
1170 stream_conf->stream_params.source.stream_config.octets_per_codec_frame =
1171 *core_config.octets_per_codec_frame;
1172 } else {
1173 log::assert_that(stream_conf->stream_params.source.stream_config
1174 .octets_per_codec_frame ==
1175 *core_config.octets_per_codec_frame,
1176 "StartStream: octets per frame mismatch: {}!={}",
1177 stream_conf->stream_params.source.stream_config
1178 .octets_per_codec_frame,
1179 *core_config.octets_per_codec_frame);
1180 }
1181
1182 if (stream_conf->stream_params.source.stream_config
1183 .codec_frames_blocks_per_sdu == 0) {
1184 stream_conf->stream_params.source.stream_config
1185 .codec_frames_blocks_per_sdu =
1186 *core_config.codec_frames_blocks_per_sdu;
1187 stream_conf->stream_params.source.stream_config.frame_duration_us =
1188 core_config.GetFrameDurationUs();
1189 } else {
1190 log::assert_that(stream_conf->stream_params.source.stream_config
1191 .codec_frames_blocks_per_sdu ==
1192 *core_config.codec_frames_blocks_per_sdu,
1193 "StartStream: codec_frames_blocks_per_sdu: {}!={}",
1194 stream_conf->stream_params.source.stream_config
1195 .codec_frames_blocks_per_sdu,
1196 *core_config.codec_frames_blocks_per_sdu);
1197 }
1198
1199 log::info(
1200 "StartStream: Added Source Stream Configuration. CIS Connection "
1201 "Handle: {}, Audio Channel Allocation: {}, Source Number "
1202 "Of Devices: {}, Source Number Of Channels: {}",
1203 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1204 stream_conf->stream_params.source.num_of_devices,
1205 stream_conf->stream_params.source.num_of_channels);
1206 }
1207 } else {
1208 auto iter = std::find_if(
1209 stream_conf->stream_params.sink.stream_config.stream_map.begin(),
1210 stream_conf->stream_params.sink.stream_config.stream_map.end(),
1211 [cis_conn_hdl](auto& info) {
1212 return cis_conn_hdl == info.stream_handle;
1213 });
1214
1215 if (iter == stream_conf->stream_params.sink.stream_config.stream_map.end()) {
1216 stream_conf->stream_params.sink.stream_config.stream_map.emplace_back(
1217 stream_map_info(ase.cis_conn_hdl,
1218 *core_config.audio_channel_allocation, true));
1219
1220 stream_conf->stream_params.sink.num_of_devices++;
1221 stream_conf->stream_params.sink.num_of_channels +=
1222 ase.codec_config.channel_count_per_iso_stream;
1223 stream_conf->stream_params.sink.audio_channel_allocation |=
1224 *core_config.audio_channel_allocation;
1225 stream_conf->stream_params.sink.stream_config.peer_delay_ms = 44;
1226
1227 if (stream_conf->stream_params.sink.stream_config.sampling_frequency_hz ==
1228 0) {
1229 stream_conf->stream_params.sink.stream_config.sampling_frequency_hz =
1230 core_config.GetSamplingFrequencyHz();
1231 } else {
1232 log::assert_that(
1233 stream_conf->stream_params.sink.stream_config
1234 .sampling_frequency_hz ==
1235 core_config.GetSamplingFrequencyHz(),
1236 "StartStream: sample freq mismatch: {}!={}",
1237 stream_conf->stream_params.sink.stream_config.sampling_frequency_hz,
1238 core_config.GetSamplingFrequencyHz());
1239 }
1240
1241 if (stream_conf->stream_params.sink.stream_config.octets_per_codec_frame ==
1242 0) {
1243 stream_conf->stream_params.sink.stream_config.octets_per_codec_frame =
1244 *core_config.octets_per_codec_frame;
1245 } else {
1246 log::assert_that(stream_conf->stream_params.sink.stream_config
1247 .octets_per_codec_frame ==
1248 *core_config.octets_per_codec_frame,
1249 "StartStream: octets per frame mismatch: {}!={}",
1250 stream_conf->stream_params.sink.stream_config
1251 .octets_per_codec_frame,
1252 *core_config.octets_per_codec_frame);
1253 }
1254
1255 if (stream_conf->stream_params.sink.stream_config
1256 .codec_frames_blocks_per_sdu == 0) {
1257 stream_conf->stream_params.sink.stream_config.codec_frames_blocks_per_sdu =
1258 *core_config.codec_frames_blocks_per_sdu;
1259 stream_conf->stream_params.sink.stream_config.frame_duration_us =
1260 core_config.GetFrameDurationUs();
1261 } else {
1262 log::assert_that(stream_conf->stream_params.sink.stream_config
1263 .codec_frames_blocks_per_sdu ==
1264 *core_config.codec_frames_blocks_per_sdu,
1265 "StartStream: codec_frames_blocks_per_sdu: {}!={}",
1266 stream_conf->stream_params.sink.stream_config
1267 .codec_frames_blocks_per_sdu,
1268 *core_config.codec_frames_blocks_per_sdu);
1269 }
1270
1271 log::info(
1272 "StartStream: Added Sink Stream Configuration. CIS Connection "
1273 "Handle: "
1274 "{}, Audio Channel Allocation: {}, Sink Number Of "
1275 "Devices: {}, Sink Number Of Channels: {}",
1276 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1277 stream_conf->stream_params.sink.num_of_devices,
1278 stream_conf->stream_params.sink.num_of_channels);
1279 }
1280 }
1281 }
1282 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1283 /* Assume CIG is created */
1284 group->cig.SetState(bluetooth::le_audio::types::CigState::CREATED);
1285 }
1286
1287 streaming_groups[group->group_id_] = group;
1288
1289 if (stay_at_qos_config_in_start_stream) {
1290 return true;
1291 }
1292
1293 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1294 // Set streaming metadata
1295 for (LeAudioDevice* device = group->GetFirstActiveDevice(); device != nullptr;
1296 device = group->GetNextActiveDevice(device)) {
1297 for (auto& ase : device->ases_) {
1298 if (!ase.active) {
1299 continue;
1300 }
1301 group->SetStreamingMetadataContexts(metadata_context_types.get(ase.direction),
1302 ase.direction);
1303 }
1304 }
1305
1306 do_in_main_thread(base::BindOnce(
1307 [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
1308 state_machine_callbacks) {
1309 state_machine_callbacks->StatusReportCb(group_id,
1310 GroupStreamStatus::STREAMING);
1311 },
1312 group->group_id_, base::Unretained(this->state_machine_callbacks_)));
1313 return true;
1314 });
1315
1316 ON_CALL(mock_state_machine_, SuspendStream(_)).WillByDefault([this](LeAudioDeviceGroup* group) {
1317 // Fake ASE state
1318 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
1319 device = group->GetNextDevice(device)) {
1320 for (auto& ase : device->ases_) {
1321 ase.cis_state = types::CisState::CONNECTED;
1322 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED;
1323 }
1324 }
1325
1326 // Inject the state
1327 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1328 group->ClearStreamingMetadataContexts();
1329 group->SetState(group->GetTargetState());
1330 state_machine_callbacks_->StatusReportCb(group->group_id_, GroupStreamStatus::SUSPENDED);
1331 });
1332
1333 ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
1334 .WillByDefault([this](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) {
1335 if (!group) {
1336 return;
1337 }
1338
1339 for (auto& ase : leAudioDevice->ases_) {
1340 group->RemoveCisFromStreamIfNeeded(leAudioDevice, ase.cis_conn_hdl);
1341 }
1342
1343 if (group->IsEmpty()) {
1344 group->cig.SetState(bluetooth::le_audio::types::CigState::NONE);
1345 InjectCigRemoved(group->group_id_);
1346 }
1347 });
1348
1349 ON_CALL(mock_state_machine_, ProcessHciNotifCisDisconnected(_, _, _))
1350 .WillByDefault([this](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
1351 const bluetooth::hci::iso_manager::cis_disconnected_evt* event) {
1352 if (!group) {
1353 return;
1354 }
1355 auto ases_pair = leAudioDevice->GetAsesByCisConnHdl(event->cis_conn_hdl);
1356 if (ases_pair.sink) {
1357 ases_pair.sink->cis_state = types::CisState::ASSIGNED;
1358 ases_pair.sink->active = false;
1359 }
1360 if (ases_pair.source) {
1361 ases_pair.source->active = false;
1362 ases_pair.source->cis_state = types::CisState::ASSIGNED;
1363 }
1364
1365 group->RemoveCisFromStreamIfNeeded(leAudioDevice, event->cis_conn_hdl);
1366
1367 // When the device detaches from the stream we send again the state machine state to
1368 // stimulate the stream map update
1369 // see LeAudioGroupStateMachineImpl::SendStreamingStatusCbIfNeeded(group);
1370 if (!group->HaveAllCisesDisconnected() &&
1371 (group->GetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) &&
1372 (group->GetTargetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING)) {
1373 do_in_main_thread(base::BindOnce(
1374 [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
1375 state_machine_callbacks) {
1376 state_machine_callbacks->StatusReportCb(group_id,
1377 GroupStreamStatus::STREAMING);
1378 },
1379 group->group_id_, base::Unretained(this->state_machine_callbacks_)));
1380 }
1381 });
1382
1383 ON_CALL(mock_state_machine_, StopStream(_)).WillByDefault([this](LeAudioDeviceGroup* group) {
1384 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
1385 device = group->GetNextDevice(device)) {
1386 /* Invalidate stream configuration if needed */
1387 auto* stream_conf = &group->stream_conf;
1388 if (!stream_conf->stream_params.sink.stream_config.stream_map.empty() ||
1389 !stream_conf->stream_params.source.stream_config.stream_map.empty()) {
1390 stream_conf->stream_params.sink.stream_config.stream_map.erase(
1391 std::remove_if(stream_conf->stream_params.sink.stream_config.stream_map.begin(),
1392 stream_conf->stream_params.sink.stream_config.stream_map.end(),
1393 [device, &stream_conf](auto& info) {
1394 auto ases = device->GetAsesByCisConnHdl(info.stream_handle);
1395
1396 log::info(
1397 ", sink ase to delete. Cis handle: {}, ase "
1398 "pointer: {}",
1399 (int)(info.stream_handle), std::format_ptr(+ases.sink));
1400 if (ases.sink) {
1401 stream_conf->stream_params.sink.num_of_devices--;
1402 stream_conf->stream_params.sink.num_of_channels -=
1403 ases.sink->codec_config.channel_count_per_iso_stream;
1404
1405 log::info(
1406 "Sink Number Of Devices: {}, Sink Number Of "
1407 "Channels: {}",
1408 stream_conf->stream_params.sink.num_of_devices,
1409 stream_conf->stream_params.sink.num_of_channels);
1410 }
1411 return ases.sink;
1412 }),
1413 stream_conf->stream_params.sink.stream_config.stream_map.end());
1414
1415 stream_conf->stream_params.source.stream_config.stream_map.erase(
1416 std::remove_if(stream_conf->stream_params.source.stream_config.stream_map.begin(),
1417 stream_conf->stream_params.source.stream_config.stream_map.end(),
1418 [device, &stream_conf](auto& info) {
1419 auto ases = device->GetAsesByCisConnHdl(info.stream_handle);
1420
1421 log::info(
1422 ", source to delete. Cis handle: {}, ase pointer: "
1423 "{}",
1424 (int)(info.stream_handle),
1425 std::format_ptr(+ases.source));
1426 if (ases.source) {
1427 stream_conf->stream_params.source.num_of_devices--;
1428 stream_conf->stream_params.source.num_of_channels -=
1429 ases.source->codec_config.channel_count_per_iso_stream;
1430
1431 log::info(
1432 ", Source Number Of Devices: {}, Source Number "
1433 "Of Channels: {}",
1434 stream_conf->stream_params.source.num_of_devices,
1435 stream_conf->stream_params.source.num_of_channels);
1436 }
1437 return ases.source;
1438 }),
1439 stream_conf->stream_params.source.stream_config.stream_map.end());
1440 }
1441
1442 group->ClearStreamingMetadataContexts();
1443 for (auto& ase : device->ases_) {
1444 group->cig.UnassignCis(device, ase.cis_conn_hdl);
1445
1446 ase.cis_state = types::CisState::IDLE;
1447 ase.data_path_state = types::DataPathState::IDLE;
1448 ase.active = false;
1449 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
1450 ase.cis_id = 0;
1451 ase.cis_conn_hdl = bluetooth::le_audio::kInvalidCisConnHandle;
1452 }
1453 }
1454
1455 // Inject the state
1456 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
1457 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING);
1458 state_machine_callbacks_->StatusReportCb(group->group_id_, GroupStreamStatus::RELEASING);
1459
1460 if (stay_at_releasing_stop_stream) {
1461 log::info("StopStream {} -> stay in Releasing state", group->group_id_);
1462 return;
1463 }
1464 group->SetState(group->GetTargetState());
1465
1466 do_in_main_thread(base::BindOnce(
1467 [](bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* cb, int group_id) {
1468 cb->StatusReportCb(group_id, GroupStreamStatus::IDLE);
1469 },
1470 state_machine_callbacks_, group->group_id_));
1471 });
1472 }
1473
SetUp()1474 void SetUp() override {
1475 __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
1476 com::android::bluetooth::flags::provider_->reset_flags();
1477
1478 init_message_loop_thread();
1479 reset_mock_function_count_map();
1480 hci::testing::mock_controller_ =
1481 std::make_unique<NiceMock<bluetooth::hci::testing::MockControllerInterface>>();
1482 ON_CALL(*hci::testing::mock_controller_, SupportsBleConnectedIsochronousStreamCentral)
1483 .WillByDefault(Return(true));
1484 ON_CALL(*hci::testing::mock_controller_, SupportsBleConnectedIsochronousStreamPeripheral)
1485 .WillByDefault(Return(true));
1486 ON_CALL(*hci::testing::mock_controller_, SupportsBle2mPhy).WillByDefault(Return(true));
1487 bluetooth::manager::SetMockBtmInterface(&mock_btm_interface_);
1488 gatt::SetMockBtaGattInterface(&mock_gatt_interface_);
1489 gatt::SetMockBtaGattQueue(&mock_gatt_queue_);
1490 bluetooth::storage::SetMockBtifStorageInterface(&mock_btif_storage_);
1491
1492 iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
1493 ASSERT_NE(iso_manager_, nullptr);
1494 iso_manager_->Start();
1495
1496 mock_iso_manager_ = MockIsoManager::GetInstance();
1497 ON_CALL(*mock_iso_manager_, RegisterCigCallbacks(_)).WillByDefault(SaveArg<0>(&cig_callbacks_));
1498
1499 ON_CALL(mock_btm_interface_, IsDeviceBonded(_, _)).WillByDefault(DoAll(Return(true)));
1500
1501 // Required since we call OnAudioDataReady()
1502 const auto codec_location = ::bluetooth::le_audio::types::CodecLocation::HOST;
1503
1504 SetUpMockAudioHal();
1505 SetUpMockGroups();
1506 SetUpMockGatt();
1507 SetUpMockCodecManager(codec_location);
1508
1509 stay_at_qos_config_in_start_stream = false;
1510 stay_at_releasing_stop_stream = false;
1511
1512 available_snk_context_types_ = 0xffff;
1513 available_src_context_types_ = 0xffff;
1514 supported_snk_context_types_ = 0xffff;
1515 supported_src_context_types_ = 0xffff;
1516
1517 empty_source_pack_ = false;
1518 empty_sink_pack_ = false;
1519
1520 bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(codec_location);
1521 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
1522 }
1523
SetUpMockCodecManager(types::CodecLocation location)1524 void SetUpMockCodecManager(types::CodecLocation location) {
1525 codec_manager_ = bluetooth::le_audio::CodecManager::GetInstance();
1526 ASSERT_NE(codec_manager_, nullptr);
1527 std::vector<bluetooth::le_audio::btle_audio_codec_config_t> mock_offloading_preference(0);
1528 codec_manager_->Start(mock_offloading_preference);
1529 mock_codec_manager_ = MockCodecManager::GetInstance();
1530 ASSERT_NE((void*)mock_codec_manager_, (void*)codec_manager_);
1531 ASSERT_NE(mock_codec_manager_, nullptr);
1532 ON_CALL(*mock_codec_manager_, GetCodecLocation()).WillByDefault(Return(location));
1533 ON_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(_, _, _))
1534 .WillByDefault(Return(true));
1535 ON_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(_, _))
1536 .WillByDefault(Return(true));
1537 // Turn on the dual bidir SWB support
1538 ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(true));
1539 // Regardless of the codec location, return all the possible configurations
1540 ON_CALL(*mock_codec_manager_, GetCodecConfig)
1541 .WillByDefault(Invoke([](const CodecManager::UnicastConfigurationRequirements&
1542 requirements,
1543 CodecManager::UnicastConfigurationProvider provider) {
1544 auto filtered = *le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
1545 requirements.audio_context_type);
1546 // Filter out the dual bidir SWB configurations
1547 if (!bluetooth::le_audio::CodecManager::GetInstance()->IsDualBiDirSwbSupported()) {
1548 filtered.erase(std::remove_if(filtered.begin(), filtered.end(),
1549 [](auto const& el) {
1550 if (el->confs.source.empty()) {
1551 return false;
1552 }
1553 return AudioSetConfigurationProvider::Get()
1554 ->CheckConfigurationIsDualBiDirSwb(*el);
1555 }),
1556 filtered.end());
1557 }
1558 return provider(requirements, &filtered);
1559 }));
1560 }
1561
TearDown()1562 void TearDown() override {
1563 // WARNING: Message loop cleanup should wait for all the 'till now' scheduled calls
1564 // so it should be called right at the very begginning of teardown.
1565 cleanup_message_loop_thread();
1566
1567 if (is_audio_unicast_source_acquired) {
1568 if (unicast_source_hal_cb_ != nullptr) {
1569 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(1);
1570 }
1571 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
1572 }
1573
1574 if (is_audio_unicast_sink_acquired) {
1575 if (unicast_sink_hal_cb_ != nullptr) {
1576 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop).Times(1);
1577 }
1578 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
1579 }
1580
1581 // This is required since Stop() and Cleanup() may trigger some callbacks or
1582 // drop unique pointers to mocks we have raw pointer for and we want to
1583 // verify them all.
1584 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1585
1586 if (LeAudioClient::IsLeAudioClientRunning()) {
1587 EXPECT_CALL(mock_gatt_interface_, AppDeregister(gatt_if)).Times(1);
1588 LeAudioClient::Cleanup();
1589 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
1590 }
1591
1592 owned_mock_le_audio_sink_hal_client_.reset();
1593 owned_mock_le_audio_source_hal_client_.reset();
1594
1595 if (bluetooth::le_audio::AudioSetConfigurationProvider::Get()) {
1596 bluetooth::le_audio::AudioSetConfigurationProvider::Cleanup();
1597 }
1598
1599 iso_manager_->Stop();
1600 hci::testing::mock_controller_.reset();
1601 }
1602
1603 protected:
1604 class MockDeviceWrapper {
1605 class IGattHandlers {
1606 public:
1607 // IGattHandlers() = default;
1608 virtual ~IGattHandlers() = default;
1609 virtual std::pair<GattStatus, std::vector<uint8_t>> OnGetCharacteristicValue(
1610 uint16_t handle) = 0;
1611 virtual void OnWriteCharacteristic(uint16_t handle, std::vector<uint8_t> value,
1612 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1613 void* cb_data) = 0;
1614 };
1615
1616 public:
1617 struct csis_mock : public IGattHandlers {
1618 uint16_t start = 0;
1619 uint16_t end = 0;
1620 uint16_t sirk_char = 0;
1621 uint16_t sirk_ccc = 0;
1622 uint16_t size_char = 0;
1623 uint16_t size_ccc = 0;
1624 uint16_t lock_char = 0;
1625 uint16_t lock_ccc = 0;
1626 uint16_t rank_char = 0;
1627
1628 int rank = 0;
1629 int size = 0;
1630
1631 MOCK_METHOD((std::pair<GattStatus, std::vector<uint8_t>>), OnGetCharacteristicValue,
1632 (uint16_t handle), (override));
1633 MOCK_METHOD((void), OnWriteCharacteristic,
1634 (uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
1635 GATT_WRITE_OP_CB cb, void* cb_data),
1636 (override));
1637 };
1638
1639 struct cas_mock : public IGattHandlers {
1640 uint16_t start = 0;
1641 uint16_t end = 0;
1642 uint16_t csis_include = 0;
1643
1644 MOCK_METHOD((std::pair<GattStatus, std::vector<uint8_t>>), OnGetCharacteristicValue,
1645 (uint16_t handle), (override));
1646 MOCK_METHOD((void), OnWriteCharacteristic,
1647 (uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
1648 GATT_WRITE_OP_CB cb, void* cb_data),
1649 (override));
1650 };
1651
1652 struct pacs_mock : public IGattHandlers {
1653 uint16_t start = 0;
1654 uint16_t sink_pac_char = 0;
1655 uint16_t sink_pac_ccc = 0;
1656 uint16_t sink_audio_loc_char = 0;
1657 uint16_t sink_audio_loc_ccc = 0;
1658 uint16_t source_pac_char = 0;
1659 uint16_t source_pac_ccc = 0;
1660 uint16_t source_audio_loc_char = 0;
1661 uint16_t source_audio_loc_ccc = 0;
1662 uint16_t avail_contexts_char = 0;
1663 uint16_t avail_contexts_ccc = 0;
1664 uint16_t supp_contexts_char = 0;
1665 uint16_t supp_contexts_ccc = 0;
1666 uint16_t end = 0;
1667
1668 MOCK_METHOD((std::pair<GattStatus, std::vector<uint8_t>>), OnGetCharacteristicValue,
1669 (uint16_t handle), (override));
1670 MOCK_METHOD((void), OnWriteCharacteristic,
1671 (uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
1672 GATT_WRITE_OP_CB cb, void* cb_data),
1673 (override));
1674 };
1675
1676 struct ascs_mock : public IGattHandlers {
1677 uint16_t start = 0;
1678 uint16_t sink_ase_char[max_num_of_ases] = {0};
1679 uint16_t sink_ase_ccc[max_num_of_ases] = {0};
1680 uint16_t sink_ase_ccc_val[max_num_of_ases] = {0};
1681 uint16_t source_ase_char[max_num_of_ases] = {0};
1682 uint16_t source_ase_ccc[max_num_of_ases] = {0};
1683 uint16_t source_ase_ccc_val[max_num_of_ases] = {0};
1684 uint16_t ctp_char = 0;
1685 uint16_t ctp_ccc = 0;
1686 uint16_t ctp_ccc_val = 0;
1687 uint16_t end = 0;
1688
1689 MOCK_METHOD((std::pair<GattStatus, std::vector<uint8_t>>), OnGetCharacteristicValue,
1690 (uint16_t handle), (override));
1691 MOCK_METHOD((void), OnWriteCharacteristic,
1692 (uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
1693 GATT_WRITE_OP_CB cb, void* cb_data),
1694 (override));
1695 };
1696
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)1697 MockDeviceWrapper(RawAddress addr, const std::list<gatt::Service>& services,
1698 std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,
1699 std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,
1700 std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,
1701 std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs)
1702 : addr(addr) {
1703 this->services = services;
1704 this->csis = std::move(csis);
1705 this->cas = std::move(cas);
1706 this->ascs = std::move(ascs);
1707 this->pacs = std::move(pacs);
1708 }
1709
~MockDeviceWrapper()1710 ~MockDeviceWrapper() {
1711 Mock::VerifyAndClearExpectations(csis.get());
1712 Mock::VerifyAndClearExpectations(cas.get());
1713 Mock::VerifyAndClearExpectations(ascs.get());
1714 Mock::VerifyAndClearExpectations(pacs.get());
1715 }
1716
1717 RawAddress addr;
1718 bool connected = false;
1719
1720 // A list of services and their useful params
1721 std::list<gatt::Service> services;
1722 std::unique_ptr<csis_mock> csis;
1723 std::unique_ptr<cas_mock> cas;
1724 std::unique_ptr<ascs_mock> ascs;
1725 std::unique_ptr<pacs_mock> pacs;
1726 };
1727
SyncOnMainLoop()1728 void SyncOnMainLoop() {
1729 // Wait for the main loop to flush
1730 // WARNING: Not tested with Timers pushing periodic tasks to the main loop
1731 while (num_async_tasks > 0) {
1732 }
1733 }
1734
ConnectLeAudio(const RawAddress & address,bool isEncrypted=true,bool expect_connected_event=true)1735 void ConnectLeAudio(const RawAddress& address, bool isEncrypted = true,
1736 bool expect_connected_event = true) {
1737 // by default indicate link as encrypted
1738 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(address, _))
1739 .WillByDefault(DoAll(Return(isEncrypted)));
1740
1741 ON_CALL(mock_btm_interface_, IsDeviceBonded(address, _)).WillByDefault(DoAll(Return(true)));
1742
1743 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, _))
1744 .Times(1);
1745
1746 /* If connected event is not expected to arrive, don't test those two below
1747 */
1748 if (expect_connected_event) {
1749 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, address, false));
1750 EXPECT_CALL(mock_gatt_interface_,
1751 Open(gatt_if, address, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
1752 .Times(1);
1753 }
1754
1755 do_in_main_thread(base::BindOnce(&LeAudioClient::Connect,
1756 base::Unretained(LeAudioClient::Get()), address));
1757
1758 SyncOnMainLoop();
1759 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1760 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1761 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1762 }
1763
DisconnectLeAudioWithGattClose(const RawAddress & address,uint16_t conn_id,tGATT_DISCONN_REASON=GATT_CONN_TERMINATE_LOCAL_HOST)1764 void DisconnectLeAudioWithGattClose(
1765 const RawAddress& address, uint16_t conn_id,
1766 tGATT_DISCONN_REASON /*reason*/ = GATT_CONN_TERMINATE_LOCAL_HOST) {
1767 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1768 OnConnectionState(ConnectionState::DISCONNECTED, address))
1769 .Times(1);
1770
1771 // For test purpose use the acl handle same as conn_id
1772 ON_CALL(mock_btm_interface_, GetHCIConnHandle(address, _))
1773 .WillByDefault([conn_id](RawAddress const& /*bd_addr*/, tBT_TRANSPORT /*transport*/) {
1774 return conn_id;
1775 });
1776 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(0);
1777 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
1778
1779 do_in_main_thread(base::Bind(&LeAudioClient::Disconnect, base::Unretained(LeAudioClient::Get()),
1780 address));
1781 SyncOnMainLoop();
1782 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1783 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1784 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1785 }
1786
DisconnectLeAudioWithAclClose(const RawAddress & address,uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST)1787 void DisconnectLeAudioWithAclClose(const RawAddress& address, uint16_t conn_id,
1788 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) {
1789 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1790 OnConnectionState(ConnectionState::DISCONNECTED, address))
1791 .Times(1);
1792
1793 // For test purpose use the acl handle same as conn_id
1794 ON_CALL(mock_btm_interface_, GetHCIConnHandle(address, _))
1795 .WillByDefault([conn_id](RawAddress const& /*bd_addr*/, tBT_TRANSPORT /*transport*/) {
1796 return conn_id;
1797 });
1798 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _))
1799 .WillOnce([this, &reason](uint16_t handle, tHCI_STATUS /*rs*/) {
1800 InjectDisconnectedEvent(handle, reason);
1801 });
1802 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(0);
1803
1804 do_in_main_thread(base::Bind(&LeAudioClient::Disconnect, base::Unretained(LeAudioClient::Get()),
1805 address));
1806 SyncOnMainLoop();
1807 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1808 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1809 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1810 }
1811
DisconnectLeAudioNoDisconnectedEvtExpected(const RawAddress & address,uint16_t conn_id)1812 void DisconnectLeAudioNoDisconnectedEvtExpected(const RawAddress& address, uint16_t conn_id) {
1813 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(0);
1814 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(1);
1815 do_in_main_thread(base::BindOnce(&LeAudioClient::Disconnect,
1816 base::Unretained(LeAudioClient::Get()), address));
1817 SyncOnMainLoop();
1818 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1819 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1820 }
1821
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)1822 void ConnectCsisDevice(const RawAddress& addr, uint16_t conn_id, uint32_t sink_audio_allocation,
1823 uint32_t source_audio_allocation, uint8_t group_size, int group_id,
1824 uint8_t rank, bool connect_through_csis = false, bool new_device = true) {
1825 SetSampleDatabaseEarbudsValid(conn_id, addr, sink_audio_allocation, source_audio_allocation,
1826 default_channel_cnt, default_channel_cnt,
1827 0x0034, /* source sample freq 16/24k/32hz */
1828 true, /*add_csis*/
1829 true, /*add_cas*/
1830 true, /*add_pacs*/
1831 true, /*add_ascs*/
1832 group_size, rank);
1833 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1834 OnConnectionState(ConnectionState::CONNECTED, addr))
1835 .Times(1);
1836
1837 if (new_device) {
1838 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1839 OnGroupNodeStatus(addr, group_id, GroupNodeStatus::ADDED))
1840 .Times(1);
1841 }
1842
1843 if (connect_through_csis) {
1844 // Add it the way CSIS would do: add to group and then connect
1845 do_in_main_thread(base::BindOnce(&LeAudioClient::GroupAddNode,
1846 base::Unretained(LeAudioClient::Get()), group_id, addr));
1847 ConnectLeAudio(addr);
1848 } else {
1849 // The usual connect
1850 // Since device has CSIS, lets add it here to groups already now
1851 groups[addr] = group_id;
1852 ConnectLeAudio(addr);
1853 InjectGroupDeviceAdded(addr, group_id);
1854 }
1855 }
1856
ConnectNonCsisDevice(const RawAddress & addr,uint16_t conn_id,uint32_t sink_audio_allocation,uint32_t source_audio_allocation)1857 void ConnectNonCsisDevice(const RawAddress& addr, uint16_t conn_id,
1858 uint32_t sink_audio_allocation, uint32_t source_audio_allocation) {
1859 SetSampleDatabaseEarbudsValid(conn_id, addr, sink_audio_allocation, source_audio_allocation,
1860 default_channel_cnt, default_channel_cnt, 0x0004,
1861 /* source sample freq 16khz */ false, /*add_csis*/
1862 true, /*add_cas*/
1863 true, /*add_pacs*/
1864 true, /*add_ascs*/
1865 0, 0);
1866 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1867 OnConnectionState(ConnectionState::CONNECTED, addr))
1868 .Times(1);
1869
1870 ConnectLeAudio(addr);
1871 }
1872
UpdateLocalSourceMetadata(std::vector<struct playback_track_metadata> tracks,bool reconfigure_existing_stream=false)1873 void UpdateLocalSourceMetadata(std::vector<struct playback_track_metadata> tracks,
1874 bool reconfigure_existing_stream = false) {
1875 std::vector<playback_track_metadata_v7> tracks_vec;
1876 tracks_vec.reserve(tracks.size());
1877 for (const auto& track : tracks) {
1878 playback_track_metadata_v7 desc_track = {
1879 .base =
1880 {
1881 .usage = static_cast<audio_usage_t>(track.usage),
1882 .content_type = static_cast<audio_content_type_t>(track.content_type),
1883 .gain = track.gain,
1884 },
1885 };
1886 if (test_tags_ptr_) {
1887 memcpy(desc_track.tags, test_tags_ptr_, strlen(test_tags_ptr_));
1888 }
1889
1890 tracks_vec.push_back(desc_track);
1891 }
1892
1893 ASSERT_NE(nullptr, mock_le_audio_source_hal_client_);
1894 /* Local Source may reconfigure once the metadata is updated */
1895 if (reconfigure_existing_stream) {
1896 Expectation reconfigure =
1897 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration())
1898 .Times(1);
1899 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
1900 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
1901 .Times(1)
1902 .After(reconfigure);
1903 } else {
1904 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(0);
1905 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0);
1906 }
1907
1908 ASSERT_NE(unicast_source_hal_cb_, nullptr);
1909 unicast_source_hal_cb_->OnAudioMetadataUpdate(std::move(tracks_vec), DsaMode::DISABLED);
1910 }
1911
UpdateLocalSourceMetadata(audio_usage_t usage,audio_content_type_t content_type,bool reconfigure_existing_stream=false)1912 void UpdateLocalSourceMetadata(audio_usage_t usage, audio_content_type_t content_type,
1913 bool reconfigure_existing_stream = false) {
1914 std::vector<struct playback_track_metadata> tracks = {
1915 {{AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0},
1916 {AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0}}};
1917
1918 tracks[0].usage = usage;
1919 tracks[0].content_type = content_type;
1920 UpdateLocalSourceMetadata(tracks, reconfigure_existing_stream);
1921 }
1922
UpdateLocalSinkMetadata(std::optional<audio_source_t> audio_source,std::optional<audio_source_t> additional_audio_source=std::nullopt)1923 void UpdateLocalSinkMetadata(
1924 std::optional<audio_source_t> audio_source,
1925 std::optional<audio_source_t> additional_audio_source = std::nullopt) {
1926 std::vector<struct record_track_metadata> tracks = {
1927 {{AUDIO_SOURCE_INVALID, 0.5, AUDIO_DEVICE_NONE, "00:11:22:33:44:55"}}};
1928
1929 if (audio_source.has_value() && (audio_source.value() != AUDIO_SOURCE_INVALID)) {
1930 tracks.push_back(
1931 {audio_source.value(), 0.7, AUDIO_DEVICE_OUT_BLE_HEADSET, "AA:BB:CC:DD:EE:FF"});
1932 }
1933 if (additional_audio_source.has_value() &&
1934 (additional_audio_source.value() != AUDIO_SOURCE_INVALID)) {
1935 tracks.push_back({additional_audio_source.value(), 0.7, AUDIO_DEVICE_OUT_BLE_HEADSET,
1936 "AA:BB:CC:DD:EE:FF"});
1937 }
1938
1939 // Call the callback if we have added a valid track or we explicitly want to send no tracks
1940 if (!audio_source.has_value() || tracks.size() > 1) {
1941 std::vector<record_track_metadata_v7> tracks_vec;
1942 tracks_vec.reserve(tracks.size());
1943 for (const auto& track : tracks) {
1944 record_track_metadata_v7 desc_track = {
1945 .base =
1946 {
1947 .source = static_cast<audio_source_t>(track.source),
1948 .gain = track.gain,
1949 .dest_device = static_cast<audio_devices_t>(track.dest_device),
1950 },
1951 };
1952
1953 snprintf(desc_track.base.dest_device_address, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%s",
1954 track.dest_device_address);
1955 tracks_vec.push_back(desc_track);
1956 }
1957
1958 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
1959 unicast_sink_hal_cb_->OnAudioMetadataUpdate(std::move(tracks_vec));
1960 }
1961 }
1962
LocalAudioSourceSuspend(void)1963 void LocalAudioSourceSuspend(void) {
1964 ASSERT_NE(unicast_source_hal_cb_, nullptr);
1965 unicast_source_hal_cb_->OnAudioSuspend();
1966 SyncOnMainLoop();
1967 }
1968
LocalAudioSourceResume(bool expected_confirmation=true,bool expected_cancel=false)1969 void LocalAudioSourceResume(bool expected_confirmation = true, bool expected_cancel = false) {
1970 ASSERT_NE(nullptr, mock_le_audio_source_hal_client_);
1971 if (expected_confirmation) {
1972 EXPECT_CALL(*mock_le_audio_source_hal_client_, ConfirmStreamingRequest()).Times(1);
1973 }
1974
1975 if (expected_cancel) {
1976 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
1977 }
1978
1979 do_in_main_thread(base::BindOnce(
1980 [](LeAudioSourceAudioHalClient::Callbacks* cb) {
1981 if (cb) {
1982 cb->OnAudioResume();
1983 }
1984 },
1985 unicast_source_hal_cb_));
1986
1987 SyncOnMainLoop();
1988 if (expected_confirmation || expected_cancel) {
1989 Mock::VerifyAndClearExpectations(&*mock_le_audio_source_hal_client_);
1990 }
1991 }
1992
LocalAudioSinkSuspend(void)1993 void LocalAudioSinkSuspend(void) {
1994 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
1995 unicast_sink_hal_cb_->OnAudioSuspend();
1996 SyncOnMainLoop();
1997 }
1998
LocalAudioSinkResume(void)1999 void LocalAudioSinkResume(void) {
2000 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2001 do_in_main_thread(
2002 base::BindOnce([](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
2003 unicast_sink_hal_cb_));
2004
2005 SyncOnMainLoop();
2006 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
2007 }
2008
StartStreaming(audio_usage_t usage,audio_content_type_t content_type,int,audio_source_t audio_source=AUDIO_SOURCE_INVALID,bool reconfigure_existing_stream=false,bool expected_resume_confirmation=true)2009 void StartStreaming(audio_usage_t usage, audio_content_type_t content_type, int /*group_id*/,
2010 audio_source_t audio_source = AUDIO_SOURCE_INVALID,
2011 bool reconfigure_existing_stream = false,
2012 bool expected_resume_confirmation = true) {
2013 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2014
2015 UpdateLocalSourceMetadata(usage, content_type, reconfigure_existing_stream);
2016 UpdateLocalSinkMetadata(audio_source);
2017
2018 /* Stream has been automatically restarted on UpdateLocalSourceMetadata */
2019 if (reconfigure_existing_stream) {
2020 return;
2021 }
2022
2023 LocalAudioSourceResume(expected_resume_confirmation);
2024 SyncOnMainLoop();
2025 Mock::VerifyAndClearExpectations(&mock_state_machine_);
2026
2027 if (usage == AUDIO_USAGE_VOICE_COMMUNICATION || audio_source != AUDIO_SOURCE_INVALID) {
2028 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2029 do_in_main_thread(
2030 base::BindOnce([](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
2031 unicast_sink_hal_cb_));
2032 }
2033 SyncOnMainLoop();
2034 }
2035
StopStreaming(int,bool suspend_source=false)2036 void StopStreaming(int /*group_id*/, bool suspend_source = false) {
2037 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2038
2039 /* TODO We should have a way to confirm Stop() otherwise, audio framework
2040 * might have different state that it is in the le_audio code - as tearing
2041 * down CISes might take some time
2042 */
2043 /* It's enough to call only one resume even if it'll be bi-directional
2044 * streaming. First suspend will trigger GroupStop.
2045 *
2046 * There is no - 'only source receiver' scenario (e.g. single microphone).
2047 * If there will be such test oriented scenario, such resume choose logic
2048 * should be applied.
2049 */
2050 unicast_source_hal_cb_->OnAudioSuspend();
2051
2052 if (suspend_source) {
2053 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2054 unicast_sink_hal_cb_->OnAudioSuspend();
2055 }
2056 SyncOnMainLoop();
2057 }
2058
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)2059 void set_sample_database(uint16_t conn_id, RawAddress addr,
2060 std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,
2061 std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,
2062 std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,
2063 std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs) {
2064 gatt::DatabaseBuilder bob;
2065
2066 /* Generic Access Service */
2067 bob.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
2068 /* Device Name Char. */
2069 bob.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00), GATT_CHAR_PROP_BIT_READ);
2070
2071 if (csis->start) {
2072 bool is_primary = true;
2073 bob.AddService(csis->start, csis->end, bluetooth::csis::kCsisServiceUuid, is_primary);
2074 if (csis->sirk_char) {
2075 bob.AddCharacteristic(csis->sirk_char, csis->sirk_char + 1, bluetooth::csis::kCsisSirkUuid,
2076 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
2077 if (csis->sirk_ccc) {
2078 bob.AddDescriptor(csis->sirk_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2079 }
2080 }
2081
2082 if (csis->size_char) {
2083 bob.AddCharacteristic(csis->size_char, csis->size_char + 1, bluetooth::csis::kCsisSizeUuid,
2084 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
2085 if (csis->size_ccc) {
2086 bob.AddDescriptor(csis->size_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2087 }
2088 }
2089
2090 if (csis->lock_char) {
2091 bob.AddCharacteristic(
2092 csis->lock_char, csis->lock_char + 1, bluetooth::csis::kCsisLockUuid,
2093 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_WRITE);
2094 if (csis->lock_ccc) {
2095 bob.AddDescriptor(csis->lock_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2096 }
2097 }
2098
2099 if (csis->rank_char) {
2100 bob.AddCharacteristic(csis->rank_char, csis->rank_char + 1, bluetooth::csis::kCsisRankUuid,
2101 GATT_CHAR_PROP_BIT_READ);
2102 }
2103 }
2104
2105 if (cas->start) {
2106 bool is_primary = true;
2107 bob.AddService(cas->start, cas->end, bluetooth::le_audio::uuid::kCapServiceUuid, is_primary);
2108 // Include CSIS service inside
2109 if (cas->csis_include) {
2110 bob.AddIncludedService(cas->csis_include, bluetooth::csis::kCsisServiceUuid, csis->start,
2111 csis->end);
2112 }
2113 }
2114
2115 if (pacs->start) {
2116 bool is_primary = true;
2117 bob.AddService(pacs->start, pacs->end,
2118 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid, is_primary);
2119
2120 if (pacs->sink_pac_char) {
2121 bob.AddCharacteristic(
2122 pacs->sink_pac_char, pacs->sink_pac_char + 1,
2123 bluetooth::le_audio::uuid::kSinkPublishedAudioCapabilityCharacteristicUuid,
2124 GATT_CHAR_PROP_BIT_READ);
2125 if (pacs->sink_pac_ccc) {
2126 bob.AddDescriptor(pacs->sink_pac_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2127 }
2128 }
2129
2130 if (pacs->sink_audio_loc_char) {
2131 bob.AddCharacteristic(pacs->sink_audio_loc_char, pacs->sink_audio_loc_char + 1,
2132 bluetooth::le_audio::uuid::kSinkAudioLocationCharacteristicUuid,
2133 GATT_CHAR_PROP_BIT_READ);
2134 if (pacs->sink_audio_loc_ccc) {
2135 bob.AddDescriptor(pacs->sink_audio_loc_ccc,
2136 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2137 }
2138 }
2139
2140 if (pacs->source_pac_char) {
2141 bob.AddCharacteristic(
2142 pacs->source_pac_char, pacs->source_pac_char + 1,
2143 bluetooth::le_audio::uuid::kSourcePublishedAudioCapabilityCharacteristicUuid,
2144 GATT_CHAR_PROP_BIT_READ);
2145 if (pacs->source_pac_ccc) {
2146 bob.AddDescriptor(pacs->source_pac_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2147 }
2148 }
2149
2150 if (pacs->source_audio_loc_char) {
2151 bob.AddCharacteristic(pacs->source_audio_loc_char, pacs->source_audio_loc_char + 1,
2152 bluetooth::le_audio::uuid::kSourceAudioLocationCharacteristicUuid,
2153 GATT_CHAR_PROP_BIT_READ);
2154 if (pacs->source_audio_loc_ccc) {
2155 bob.AddDescriptor(pacs->source_audio_loc_ccc,
2156 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2157 }
2158 }
2159
2160 if (pacs->avail_contexts_char) {
2161 bob.AddCharacteristic(
2162 pacs->avail_contexts_char, pacs->avail_contexts_char + 1,
2163 bluetooth::le_audio::uuid::kAudioContextAvailabilityCharacteristicUuid,
2164 GATT_CHAR_PROP_BIT_READ);
2165 if (pacs->avail_contexts_ccc) {
2166 bob.AddDescriptor(pacs->avail_contexts_ccc,
2167 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2168 }
2169 }
2170
2171 if (pacs->supp_contexts_char) {
2172 bob.AddCharacteristic(pacs->supp_contexts_char, pacs->supp_contexts_char + 1,
2173 bluetooth::le_audio::uuid::kAudioSupportedContextCharacteristicUuid,
2174 GATT_CHAR_PROP_BIT_READ);
2175 if (pacs->supp_contexts_ccc) {
2176 bob.AddDescriptor(pacs->supp_contexts_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2177 }
2178 }
2179 }
2180
2181 if (ascs->start) {
2182 bool is_primary = true;
2183 bob.AddService(ascs->start, ascs->end,
2184 bluetooth::le_audio::uuid::kAudioStreamControlServiceUuid, is_primary);
2185 for (int i = 0; i < max_num_of_ases; i++) {
2186 if (ascs->sink_ase_char[i]) {
2187 bob.AddCharacteristic(ascs->sink_ase_char[i], ascs->sink_ase_char[i] + 1,
2188 bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid,
2189 GATT_CHAR_PROP_BIT_READ);
2190 if (ascs->sink_ase_ccc[i]) {
2191 bob.AddDescriptor(ascs->sink_ase_ccc[i], Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2192 }
2193 }
2194 if (ascs->source_ase_char[i]) {
2195 bob.AddCharacteristic(ascs->source_ase_char[i], ascs->source_ase_char[i] + 1,
2196 bluetooth::le_audio::uuid::kSourceAudioStreamEndpointUuid,
2197 GATT_CHAR_PROP_BIT_READ);
2198 if (ascs->source_ase_ccc[i]) {
2199 bob.AddDescriptor(ascs->source_ase_ccc[i],
2200 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2201 }
2202 }
2203 }
2204 if (ascs->ctp_char) {
2205 bob.AddCharacteristic(
2206 ascs->ctp_char, ascs->ctp_char + 1,
2207 bluetooth::le_audio::uuid::kAudioStreamEndpointControlPointCharacteristicUuid,
2208 GATT_CHAR_PROP_BIT_READ);
2209 if (ascs->ctp_ccc) {
2210 bob.AddDescriptor(ascs->ctp_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2211 }
2212 }
2213 }
2214
2215 // Assign conn_id to a certain device - this does not mean it is connected
2216 auto dev_wrapper = std::make_unique<NiceMock<MockDeviceWrapper>>(
2217 addr, bob.Build().Services(), std::move(csis), std::move(cas), std::move(ascs),
2218 std::move(pacs));
2219 peer_devices.emplace(conn_id, std::move(dev_wrapper));
2220 }
2221
SetSampleDatabaseEmpty(uint16_t conn_id,RawAddress addr)2222 void SetSampleDatabaseEmpty(uint16_t conn_id, RawAddress addr) {
2223 auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
2224 auto cas = std::make_unique<NiceMock<MockDeviceWrapper::cas_mock>>();
2225 auto pacs = std::make_unique<NiceMock<MockDeviceWrapper::pacs_mock>>();
2226 auto ascs = std::make_unique<NiceMock<MockDeviceWrapper::ascs_mock>>();
2227 set_sample_database(conn_id, addr, std::move(csis), std::move(cas), std::move(ascs),
2228 std::move(pacs));
2229 }
2230
2231 struct SampleDatabaseParameters {
2232 uint16_t conn_id;
2233 RawAddress addr;
2234
2235 std::optional<uint32_t> sink_audio_allocation = std::nullopt;
2236 std::optional<uint32_t> source_audio_allocation = std::nullopt;
2237 uint8_t sink_channel_cnt = 0x03;
2238 uint8_t source_channel_cnt = 0x03;
2239 uint16_t sample_freq_mask = 0x0004;
2240 bool add_csis = true;
2241 bool add_cas = true;
2242 bool add_pacs = true;
2243 int add_ascs_cnt = 1;
2244 uint8_t set_size = 2;
2245 uint8_t rank = 1;
2246 GattStatus gatt_status = GATT_SUCCESS;
2247 uint8_t max_supported_codec_frames_per_sdu = 1;
2248 };
2249
SetSampleDatabaseEarbudsValid(uint16_t conn_id,RawAddress addr,uint32_t sink_audio_allocation,uint32_t source_audio_allocation,uint8_t sink_channel_cnt=0x03,uint8_t source_channel_cnt=0x03,uint16_t sample_freq_mask=0x0004,bool add_csis=true,bool add_cas=true,bool add_pacs=true,int add_ascs_cnt=1,uint8_t set_size=2,uint8_t rank=1,GattStatus gatt_status=GATT_SUCCESS)2250 void SetSampleDatabaseEarbudsValid(
2251 uint16_t conn_id, RawAddress addr, uint32_t sink_audio_allocation,
2252 uint32_t source_audio_allocation, uint8_t sink_channel_cnt = 0x03,
2253 uint8_t source_channel_cnt = 0x03, uint16_t sample_freq_mask = 0x0004,
2254 bool add_csis = true, bool add_cas = true, bool add_pacs = true, int add_ascs_cnt = 1,
2255 uint8_t set_size = 2, uint8_t rank = 1, GattStatus gatt_status = GATT_SUCCESS) {
2256 SetSampleDatabaseEarbudsValid(SampleDatabaseParameters{
2257 .conn_id = conn_id,
2258 .addr = addr,
2259 .sink_audio_allocation = sink_audio_allocation,
2260 .source_audio_allocation = source_audio_allocation,
2261 .sink_channel_cnt = sink_channel_cnt,
2262 .source_channel_cnt = source_channel_cnt,
2263 .sample_freq_mask = sample_freq_mask,
2264 .add_csis = add_csis,
2265 .add_cas = add_cas,
2266 .add_pacs = add_pacs,
2267 .add_ascs_cnt = add_ascs_cnt,
2268 .set_size = set_size,
2269 .rank = rank,
2270 .gatt_status = gatt_status,
2271 .max_supported_codec_frames_per_sdu = 1,
2272 });
2273 }
2274
SetSampleDatabaseEarbudsValid(const SampleDatabaseParameters & params)2275 void SetSampleDatabaseEarbudsValid(const SampleDatabaseParameters& params) {
2276 auto conn_id = params.conn_id;
2277 auto addr = params.addr;
2278 auto sink_audio_allocation = params.sink_audio_allocation;
2279 auto source_audio_allocation = params.source_audio_allocation;
2280 auto sink_channel_cnt = params.sink_channel_cnt;
2281 auto source_channel_cnt = params.source_channel_cnt;
2282 auto sample_freq_mask = params.sample_freq_mask;
2283 auto add_csis = params.add_csis;
2284 auto add_cas = params.add_cas;
2285 auto add_pacs = params.add_pacs;
2286 auto add_ascs_cnt = params.add_ascs_cnt;
2287 auto set_size = params.set_size;
2288 auto rank = params.rank;
2289 auto gatt_status = params.gatt_status;
2290 auto max_supported_codec_frames_per_sdu = params.max_supported_codec_frames_per_sdu;
2291
2292 auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
2293 if (add_csis) {
2294 // attribute handles
2295 csis->start = 0x0010;
2296 csis->sirk_char = 0x0020;
2297 csis->sirk_ccc = 0x0022;
2298 csis->size_char = 0x0023;
2299 csis->size_ccc = 0x0025;
2300 csis->lock_char = 0x0026;
2301 csis->lock_ccc = 0x0028;
2302 csis->rank_char = 0x0029;
2303 csis->end = 0x0030;
2304 // other params
2305 csis->size = set_size;
2306 csis->rank = rank;
2307 }
2308
2309 auto cas = std::make_unique<NiceMock<MockDeviceWrapper::cas_mock>>();
2310 if (add_cas) {
2311 // attribute handles
2312 cas->start = 0x0040;
2313 if (add_csis) {
2314 cas->csis_include = 0x0041;
2315 }
2316 cas->end = 0x0050;
2317 // other params
2318 }
2319
2320 auto pacs = std::make_unique<NiceMock<MockDeviceWrapper::pacs_mock>>();
2321 if (add_pacs) {
2322 // attribute handles
2323 pacs->start = 0x0060;
2324 if (sink_audio_allocation.has_value()) {
2325 pacs->sink_pac_char = 0x0061;
2326 pacs->sink_pac_ccc = 0x0063;
2327 pacs->sink_audio_loc_char = 0x0064;
2328 pacs->sink_audio_loc_ccc = 0x0066;
2329 }
2330 if (source_audio_allocation.has_value()) {
2331 pacs->source_pac_char = 0x0067;
2332 pacs->source_pac_ccc = 0x0069;
2333 pacs->source_audio_loc_char = 0x0070;
2334 pacs->source_audio_loc_ccc = 0x0072;
2335 }
2336 pacs->avail_contexts_char = 0x0073;
2337 pacs->avail_contexts_ccc = 0x0075;
2338 pacs->supp_contexts_char = 0x0076;
2339 pacs->supp_contexts_ccc = 0x0078;
2340 pacs->end = 0x0080;
2341 // other params
2342 }
2343
2344 auto ascs = std::make_unique<NiceMock<MockDeviceWrapper::ascs_mock>>();
2345 if (add_ascs_cnt > 0) {
2346 // attribute handles
2347 ascs->start = 0x0090;
2348 uint16_t handle = 0x0091;
2349 for (int i = 0; i < add_ascs_cnt; i++) {
2350 if (sink_audio_allocation.has_value()) {
2351 ascs->sink_ase_char[i] = handle;
2352 handle += 2;
2353 ascs->sink_ase_ccc[i] = handle;
2354 handle++;
2355 }
2356
2357 if (source_audio_allocation.has_value()) {
2358 ascs->source_ase_char[i] = handle;
2359 handle += 2;
2360 ascs->source_ase_ccc[i] = handle;
2361 handle++;
2362 }
2363 }
2364 ascs->ctp_char = handle;
2365 handle += 2;
2366 ascs->ctp_ccc = handle;
2367 handle++;
2368 ascs->end = handle;
2369 // other params
2370 }
2371
2372 set_sample_database(conn_id, addr, std::move(csis), std::move(cas), std::move(ascs),
2373 std::move(pacs));
2374
2375 if (add_pacs) {
2376 uint8_t sample_freq[2];
2377 sample_freq[0] = (uint8_t)(sample_freq_mask);
2378 sample_freq[1] = (uint8_t)(sample_freq_mask >> 8);
2379
2380 // Set pacs default read values
2381 ON_CALL(*peer_devices.at(conn_id)->pacs, OnGetCharacteristicValue(_))
2382 .WillByDefault([=, this](uint16_t handle) {
2383 auto& pacs = peer_devices.at(conn_id)->pacs;
2384 std::vector<uint8_t> value;
2385 if (gatt_status == GATT_SUCCESS) {
2386 if (handle == pacs->sink_pac_char + 1) {
2387 if (empty_sink_pack_) {
2388 value = {0x00};
2389 } else {
2390 value = {
2391 // Num records
2392 0x02,
2393 // Codec_ID
2394 0x06,
2395 0x00,
2396 0x00,
2397 0x00,
2398 0x00,
2399 // Codec Spec. Caps. Len
2400 0x10,
2401 0x03, /* sample freq */
2402 0x01,
2403 sample_freq[0],
2404 sample_freq[1],
2405 0x02,
2406 0x02, /* frame duration */
2407 0x03,
2408 0x02, /* channel count */
2409 0x03,
2410 sink_channel_cnt,
2411 0x05,
2412 0x04,
2413 0x1E,
2414 0x00,
2415 0x78,
2416 0x00,
2417 // Metadata Length
2418 0x00,
2419 // Codec_ID
2420 0x06,
2421 0x00,
2422 0x00,
2423 0x00,
2424 0x00,
2425 // Codec Spec. Caps. Len
2426 0x13,
2427 0x03, /* sample freq */
2428 0x01,
2429 0x80, /* 48kHz */
2430 0x00,
2431 0x02, /* frame duration */
2432 0x02,
2433 0x03,
2434 0x02, /* channel count */
2435 0x03,
2436 sink_channel_cnt,
2437 0x05, /* octects per frame */
2438 0x04,
2439 0x78,
2440 0x00,
2441 0x78,
2442 0x00,
2443 0x02, /* Max supported codec frames per SDU */
2444 0x05,
2445 max_supported_codec_frames_per_sdu,
2446 // Metadata Length
2447 0x00,
2448 };
2449 }
2450 } else if (handle == pacs->sink_audio_loc_char + 1) {
2451 value = {
2452 (uint8_t)(sink_audio_allocation.value_or(0)),
2453 (uint8_t)(sink_audio_allocation.value_or(0) >> 8),
2454 (uint8_t)(sink_audio_allocation.value_or(0) >> 16),
2455 (uint8_t)(sink_audio_allocation.value_or(0) >> 24),
2456 };
2457 } else if (handle == pacs->source_pac_char + 1) {
2458 if (empty_source_pack_) {
2459 value = {0x00};
2460 } else {
2461 value = {
2462 // Num records
2463 0x02,
2464 // Codec_ID
2465 0x06,
2466 0x00,
2467 0x00,
2468 0x00,
2469 0x00,
2470 // Codec Spec. Caps. Len
2471 0x10,
2472 0x03,
2473 0x01,
2474 sample_freq[0],
2475 sample_freq[1],
2476 0x02,
2477 0x02,
2478 0x03,
2479 0x02,
2480 0x03,
2481 source_channel_cnt,
2482 0x05,
2483 0x04,
2484 0x1E,
2485 0x00,
2486 0x78,
2487 0x00,
2488 // Metadata Length
2489 0x00,
2490 // Codec_ID
2491 0x06,
2492 0x00,
2493 0x00,
2494 0x00,
2495 0x00,
2496 // Codec Spec. Caps. Len
2497 0x10,
2498 0x03,
2499 0x01,
2500 0x24,
2501 0x00,
2502 0x02,
2503 0x02,
2504 0x03,
2505 0x02,
2506 0x03,
2507 source_channel_cnt,
2508 0x05,
2509 0x04,
2510 0x1E,
2511 0x00,
2512 0x50,
2513 0x00,
2514 // Metadata Length
2515 0x00,
2516 };
2517 }
2518 } else if (handle == pacs->source_audio_loc_char + 1) {
2519 value = {
2520 (uint8_t)(source_audio_allocation.value_or(0)),
2521 (uint8_t)(source_audio_allocation.value_or(0) >> 8),
2522 (uint8_t)(source_audio_allocation.value_or(0) >> 16),
2523 (uint8_t)(source_audio_allocation.value_or(0) >> 24),
2524 };
2525 } else if (handle == pacs->avail_contexts_char + 1) {
2526 value = {
2527 // Sink Avail Contexts
2528 (uint8_t)(available_snk_context_types_),
2529 (uint8_t)(available_snk_context_types_ >> 8),
2530 // Source Avail Contexts
2531 (uint8_t)(available_src_context_types_),
2532 (uint8_t)(available_src_context_types_ >> 8),
2533 };
2534 } else if (handle == pacs->supp_contexts_char + 1) {
2535 value = {
2536 // Sink Supp Contexts
2537 (uint8_t)(supported_snk_context_types_),
2538 (uint8_t)(supported_snk_context_types_ >> 8),
2539 // Source Supp Contexts
2540 (uint8_t)(supported_src_context_types_),
2541 (uint8_t)(supported_src_context_types_ >> 8),
2542 };
2543 }
2544 }
2545 return std::make_pair(gatt_status, value);
2546 });
2547 }
2548
2549 if (add_ascs_cnt > 0) {
2550 // Set ascs default read values
2551 ON_CALL(*peer_devices.at(conn_id)->ascs, OnGetCharacteristicValue(_))
2552 .WillByDefault([this, conn_id, gatt_status](uint16_t handle) {
2553 auto& ascs = peer_devices.at(conn_id)->ascs;
2554 std::vector<uint8_t> value;
2555 bool is_ase_sink_request = false;
2556 bool is_ase_src_request = false;
2557 uint8_t idx;
2558
2559 if (handle == ascs->ctp_ccc && ccc_stored_byte_val_.has_value()) {
2560 value = {*ccc_stored_byte_val_, 00};
2561 return std::make_pair(gatt_read_ctp_ccc_status_, value);
2562 }
2563
2564 if (gatt_status == GATT_SUCCESS) {
2565 if (handle == ascs->ctp_ccc) {
2566 value = UINT16_TO_VEC_UINT8(ascs->ctp_ccc_val);
2567 } else {
2568 for (idx = 0; idx < max_num_of_ases; idx++) {
2569 if (handle == ascs->sink_ase_ccc[idx] + 1) {
2570 value = UINT16_TO_VEC_UINT8(ascs->sink_ase_ccc_val[idx]);
2571 break;
2572 }
2573 if (handle == ascs->source_ase_char[idx] + 1) {
2574 value = UINT16_TO_VEC_UINT8(ascs->source_ase_ccc_val[idx]);
2575 break;
2576 }
2577 }
2578 }
2579
2580 for (idx = 0; idx < max_num_of_ases; idx++) {
2581 if (handle == ascs->sink_ase_char[idx] + 1) {
2582 is_ase_sink_request = true;
2583 break;
2584 }
2585 if (handle == ascs->source_ase_char[idx] + 1) {
2586 is_ase_src_request = true;
2587 break;
2588 }
2589 }
2590
2591 if (is_ase_sink_request) {
2592 value = {
2593 // ASE ID
2594 static_cast<uint8_t>(idx + 1),
2595 // State
2596 static_cast<uint8_t>(bluetooth::le_audio::types::AseState::
2597 BTA_LE_AUDIO_ASE_STATE_IDLE),
2598 // No Additional ASE params for IDLE state
2599 };
2600 } else if (is_ase_src_request) {
2601 value = {
2602 // ASE ID
2603 static_cast<uint8_t>(idx + 6),
2604 // State
2605 static_cast<uint8_t>(bluetooth::le_audio::types::AseState::
2606 BTA_LE_AUDIO_ASE_STATE_IDLE),
2607 // No Additional ASE params for IDLE state
2608 };
2609 }
2610 }
2611 return std::make_pair(gatt_status, value);
2612 });
2613 }
2614 }
2615
TestAudioDataTransfer(int group_id,uint8_t cis_count_out,uint8_t cis_count_in,int data_len,int in_data_len=40,uint16_t decoded_in_data_len=0)2616 void TestAudioDataTransfer(int group_id, uint8_t cis_count_out, uint8_t cis_count_in,
2617 int data_len, int in_data_len = 40, uint16_t decoded_in_data_len = 0) {
2618 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2619 ASSERT_NE(mock_le_audio_sink_hal_client_, nullptr);
2620
2621 // Expect two channels ISO Data to be sent
2622 std::vector<uint16_t> handles;
2623 if (cis_count_out) {
2624 EXPECT_CALL(*mock_iso_manager_, SendIsoData(_, _, _))
2625 .Times(cis_count_out)
2626 .WillRepeatedly([&handles](uint16_t iso_handle, const uint8_t* /*data*/,
2627 uint16_t /*data_len*/) { handles.push_back(iso_handle); });
2628 }
2629 std::vector<uint8_t> data(data_len);
2630 unicast_source_hal_cb_->OnAudioDataReady(data);
2631
2632 // Inject microphone data from group (2 CISes - pass stereo data in 1 call)
2633 if (decoded_in_data_len) {
2634 EXPECT_CALL(*mock_le_audio_sink_hal_client_, SendData(_, decoded_in_data_len))
2635 .Times(cis_count_in > 0 ? 1 : 0);
2636 } else {
2637 EXPECT_CALL(*mock_le_audio_sink_hal_client_, SendData(_, _)).Times(cis_count_in > 0 ? 1 : 0);
2638 }
2639 ASSERT_EQ(streaming_groups.count(group_id), 1u);
2640
2641 if (cis_count_in) {
2642 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2643
2644 ASSERT_NE(0lu, streaming_groups.count(group_id));
2645 auto group = streaming_groups.at(group_id);
2646 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
2647 device = group->GetNextDevice(device)) {
2648 for (auto& ase : device->ases_) {
2649 if (ase.direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
2650 InjectIncomingIsoData(group_id, ase.cis_conn_hdl, in_data_len);
2651 --cis_count_in;
2652 if (!cis_count_in) {
2653 break;
2654 }
2655 }
2656 }
2657 if (!cis_count_in) {
2658 break;
2659 }
2660 }
2661 }
2662
2663 SyncOnMainLoop();
2664 std::sort(handles.begin(), handles.end());
2665 ASSERT_EQ(cis_count_in, 0);
2666 handles.clear();
2667
2668 Mock::VerifyAndClearExpectations(mock_iso_manager_);
2669 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
2670 }
2671
InjectIncomingIsoData(uint16_t cig_id,uint16_t cis_con_hdl,size_t payload_size)2672 void InjectIncomingIsoData(uint16_t cig_id, uint16_t cis_con_hdl, size_t payload_size) {
2673 BT_HDR* bt_hdr = (BT_HDR*)malloc(sizeof(BT_HDR) + payload_size);
2674
2675 bt_hdr->offset = 0;
2676 bt_hdr->len = payload_size;
2677
2678 bluetooth::hci::iso_manager::cis_data_evt cis_evt;
2679 cis_evt.cig_id = cig_id;
2680 cis_evt.cis_conn_hdl = cis_con_hdl;
2681 cis_evt.ts = 0;
2682 cis_evt.evt_lost = 0;
2683 cis_evt.p_msg = bt_hdr;
2684
2685 ASSERT_NE(cig_callbacks_, nullptr);
2686 cig_callbacks_->OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDataAvailable, &cis_evt);
2687 free(bt_hdr);
2688 }
2689
InjectCisDisconnected(uint16_t cig_id,uint16_t cis_con_hdl,uint8_t reason=0)2690 void InjectCisDisconnected(uint16_t cig_id, uint16_t cis_con_hdl, uint8_t reason = 0) {
2691 bluetooth::hci::iso_manager::cis_disconnected_evt cis_evt;
2692 cis_evt.cig_id = cig_id;
2693 cis_evt.cis_conn_hdl = cis_con_hdl;
2694 cis_evt.reason = reason;
2695
2696 ASSERT_NE(cig_callbacks_, nullptr);
2697 cig_callbacks_->OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDisconnected, &cis_evt);
2698 }
2699
InjectCigRemoved(uint8_t cig_id)2700 void InjectCigRemoved(uint8_t cig_id) {
2701 bluetooth::hci::iso_manager::cig_remove_cmpl_evt evt;
2702 evt.status = 0;
2703 evt.cig_id = cig_id;
2704
2705 ASSERT_NE(cig_callbacks_, nullptr);
2706 cig_callbacks_->OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCigOnRemoveCmpl, &evt);
2707 }
2708
2709 NiceMock<MockAudioHalClientCallbacks> mock_audio_hal_client_callbacks_;
2710 LeAudioSourceAudioHalClient::Callbacks* unicast_source_hal_cb_ = nullptr;
2711 LeAudioSinkAudioHalClient::Callbacks* unicast_sink_hal_cb_ = nullptr;
2712
2713 uint8_t default_channel_cnt = 0x03;
2714 uint8_t default_src_channel_cnt = default_channel_cnt;
2715 uint8_t default_ase_cnt = 1;
2716
2717 NiceMock<MockCsisClient> mock_csis_client_module_;
2718 NiceMock<MockDeviceGroups> mock_groups_module_;
2719 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks_;
2720 NiceMock<MockLeAudioGroupStateMachine> mock_state_machine_;
2721
2722 NiceMock<MockFunction<void()>> mock_storage_load;
2723 NiceMock<MockFunction<bool()>> mock_hal_2_1_verifier;
2724
2725 NiceMock<bluetooth::manager::MockBtmInterface> mock_btm_interface_;
2726 NiceMock<gatt::MockBtaGattInterface> mock_gatt_interface_;
2727 NiceMock<gatt::MockBtaGattQueue> mock_gatt_queue_;
2728 tBTA_GATTC_CBACK* gatt_callback;
2729 const uint8_t gatt_if = 0xfe;
2730 uint16_t global_conn_id = 1;
2731 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks_;
2732 std::map<int, LeAudioDeviceGroup*> streaming_groups;
2733 bool stay_at_qos_config_in_start_stream = false;
2734 bool stay_at_releasing_stop_stream = false;
2735
2736 bool attach_to_stream_scheduled = false;
2737
2738 bluetooth::hci::IsoManager* iso_manager_;
2739 MockIsoManager* mock_iso_manager_;
2740 bluetooth::hci::iso_manager::CigCallbacks* cig_callbacks_ = nullptr;
2741 uint16_t iso_con_counter_ = 1;
2742
2743 bluetooth::le_audio::CodecManager* codec_manager_;
2744 MockCodecManager* mock_codec_manager_;
2745
2746 uint16_t available_snk_context_types_ = 0xffff;
2747 uint16_t available_src_context_types_ = 0xffff;
2748 uint16_t supported_snk_context_types_ = 0xffff;
2749 uint16_t supported_src_context_types_ = 0xffff;
2750
2751 bool empty_source_pack_;
2752 bool empty_sink_pack_;
2753
2754 NiceMock<bluetooth::storage::MockBtifStorageInterface> mock_btif_storage_;
2755
2756 std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>> peer_devices;
2757 std::list<int> group_locks;
2758 std::map<RawAddress, int> groups;
2759
2760 /* CCC descriptor data */
2761 tGATT_STATUS gatt_read_ctp_ccc_status_ = GATT_SUCCESS;
2762 std::optional<uint8_t> ccc_stored_byte_val_ = std::nullopt;
2763
2764 /* Audio track metadata */
2765 char* test_tags_ptr_ = nullptr;
2766 };
2767
2768 class UnicastTest : public UnicastTestNoInit {
2769 protected:
SetUp()2770 void SetUp() override {
2771 UnicastTestNoInit::SetUp();
2772
2773 EXPECT_CALL(mock_hal_2_1_verifier, Call()).Times(1);
2774 EXPECT_CALL(mock_storage_load, Call()).Times(1);
2775
2776 ON_CALL(mock_btm_interface_, GetHCIConnHandle(_, _))
2777 .WillByDefault(
2778 [this](RawAddress const& bd_addr, tBT_TRANSPORT /*transport*/) -> uint16_t {
2779 for (auto const& [conn_id, dev_wrapper] : peer_devices) {
2780 if (dev_wrapper->addr == bd_addr) {
2781 return conn_id;
2782 }
2783 }
2784 log::error("GetHCIConnHandle Mock: not a valid test device!");
2785 return 0x00FE;
2786 });
2787 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
2788 .WillByDefault([this](uint16_t handle, tHCI_STATUS /*rs*/) {
2789 ASSERT_NE(handle, GATT_INVALID_CONN_ID);
2790 InjectDisconnectedEvent(handle, GATT_CONN_TERMINATE_LOCAL_HOST);
2791 });
2792
2793 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
2794 BtaAppRegisterCallback app_register_callback;
2795 EXPECT_CALL(mock_gatt_interface_, AppRegister(_, _, _, _))
2796 .WillOnce(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
2797 LeAudioClient::Initialize(
2798 &mock_audio_hal_client_callbacks_,
2799 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
2800 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2801 &mock_hal_2_1_verifier),
2802 framework_encode_preference);
2803
2804 SyncOnMainLoop();
2805 ASSERT_TRUE(gatt_callback);
2806 ASSERT_TRUE(group_callbacks_);
2807 ASSERT_TRUE(app_register_callback);
2808 app_register_callback.Run(gatt_if, GATT_SUCCESS);
2809 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
2810 }
2811
TearDown()2812 void TearDown() override {
2813 MockCodecInterface::ClearMockInstanceHookList();
2814
2815 // Clear the default actions before the parent class teardown is called
2816 Mock::VerifyAndClear(&mock_btm_interface_);
2817 Mock::VerifyAndClear(&mock_gatt_interface_);
2818 Mock::VerifyAndClear(&mock_audio_hal_client_callbacks_);
2819 groups.clear();
2820 UnicastTestNoInit::TearDown();
2821 }
2822
TestSetupRemoteDevices(int group_id)2823 void TestSetupRemoteDevices(int group_id) {
2824 uint8_t group_size = 2;
2825
2826 // Report working CSIS
2827 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
2828
2829 // First earbud
2830 const RawAddress test_address0 = GetTestAddress(0);
2831 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
2832 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
2833 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id,
2834 1 /* rank*/);
2835
2836 // Second earbud
2837 const RawAddress test_address1 = GetTestAddress(1);
2838 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
2839 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
2840 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id,
2841 2 /* rank*/, true /*connect_through_csis*/);
2842
2843 constexpr int gmcs_ccid = 1;
2844 constexpr int gtbs_ccid = 2;
2845 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
2846 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
2847 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid,
2848 static_cast<int>(LeAudioContextType::MEDIA));
2849 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid,
2850 static_cast<int>(LeAudioContextType::CONVERSATIONAL));
2851 LeAudioClient::Get()->GroupSetActive(group_id);
2852 }
2853
TestSetCodecPreference(const btle_audio_codec_config_t * preferred_codec_config_before_streaming,const btle_audio_codec_config_t * preferred_codec_config_during_streaming,LeAudioContextType context_type,int group_id,bool set_before_streaming,bool set_while_streaming,bool is_using_set_before_streaming_codec_during_streaming,bool is_using_set_while_streaming_codec_during_streaming,bool is_reconfig)2854 void TestSetCodecPreference(
2855 const btle_audio_codec_config_t* preferred_codec_config_before_streaming,
2856 const btle_audio_codec_config_t* preferred_codec_config_during_streaming,
2857 LeAudioContextType context_type, int group_id, bool set_before_streaming,
2858 bool set_while_streaming, bool is_using_set_before_streaming_codec_during_streaming,
2859 bool is_using_set_while_streaming_codec_during_streaming, bool is_reconfig) {
2860 auto config_before_streaming_str = preferred_codec_config_before_streaming
2861 ? preferred_codec_config_before_streaming->ToString()
2862 : "null";
2863 auto config_during_streaming_str = preferred_codec_config_during_streaming
2864 ? preferred_codec_config_during_streaming->ToString()
2865 : "null";
2866 log::debug(
2867 "preferred_codec_config_before_streaming: {}, "
2868 "preferred_codec_config_during_streaming: {}, context_type: {}, "
2869 "group_id: {}, set_before_streaming: {}, "
2870 "set_while_streaming: {}, "
2871 "is_using_set_before_streaming_codec_during_streaming: "
2872 "{},is_using_set_while_streaming_codec_during_streaming:{}, "
2873 "is_reconfig: {}",
2874 config_before_streaming_str, config_during_streaming_str,
2875 bluetooth::common::ToString(context_type), group_id, set_before_streaming,
2876 set_while_streaming, is_using_set_before_streaming_codec_during_streaming,
2877 is_using_set_while_streaming_codec_during_streaming, is_reconfig);
2878
2879 if (context_type != LeAudioContextType::MEDIA &&
2880 context_type != LeAudioContextType::CONVERSATIONAL) {
2881 return;
2882 }
2883
2884 if (set_before_streaming) {
2885 do_in_main_thread(base::BindOnce(&LeAudioClient::SetCodecConfigPreference,
2886 base::Unretained(LeAudioClient::Get()), group_id,
2887 *preferred_codec_config_before_streaming,
2888 *preferred_codec_config_before_streaming));
2889 SyncOnMainLoop();
2890 }
2891
2892 types::BidirectionalPair<std::vector<uint8_t>> ccids;
2893 constexpr int gmcs_ccid = 1;
2894 constexpr int gtbs_ccid = 2;
2895 if (context_type == LeAudioContextType::MEDIA) {
2896 ccids = types::BidirectionalPair<std::vector<uint8_t>>{{gmcs_ccid}, {}};
2897 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
2898 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
2899 } else {
2900 ccids = types::BidirectionalPair<std::vector<uint8_t>>{{gtbs_ccid}, {gtbs_ccid}};
2901 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
2902 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
2903 }
2904 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
2905 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
2906
2907 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(group_id,
2908 static_cast<int>(context_type)),
2909 is_using_set_before_streaming_codec_during_streaming);
2910
2911 uint8_t cis_count_out = 2;
2912 uint8_t cis_count_in = context_type == LeAudioContextType::MEDIA ? 0 : 2;
2913 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
2914
2915 if (set_while_streaming) {
2916 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(is_reconfig);
2917 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(is_reconfig);
2918
2919 do_in_main_thread(base::BindOnce(&LeAudioClient::SetCodecConfigPreference,
2920 base::Unretained(LeAudioClient::Get()), group_id,
2921 *preferred_codec_config_during_streaming,
2922 *preferred_codec_config_during_streaming));
2923 SyncOnMainLoop();
2924 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(group_id,
2925 static_cast<int>(context_type)),
2926 is_using_set_while_streaming_codec_during_streaming);
2927
2928 if (context_type == LeAudioContextType::MEDIA) {
2929 ccids = types::BidirectionalPair<std::vector<uint8_t>>{{gmcs_ccid}, {}};
2930 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
2931 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
2932 } else {
2933 ccids = types::BidirectionalPair<std::vector<uint8_t>>{{gtbs_ccid}, {gtbs_ccid}};
2934 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
2935 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
2936 }
2937 }
2938
2939 StopStreaming(group_id, context_type == LeAudioContextType::CONVERSATIONAL);
2940 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
2941 Mock::VerifyAndClearExpectations(&mock_state_machine_);
2942 }
2943 };
2944
2945 class UnicastTestHealthStatus : public UnicastTest {
2946 protected:
SetUp()2947 void SetUp() override {
2948 UnicastTest::SetUp();
2949 group_ = new LeAudioDeviceGroup(group_id_);
2950 }
2951
TearDown()2952 void TearDown() override {
2953 delete group_;
2954 UnicastTest::TearDown();
2955 }
2956
2957 const int group_id_ = 0;
2958 LeAudioDeviceGroup* group_ = nullptr;
2959 };
2960
2961 class UnicastTestHandoverMode : public UnicastTest {
2962 protected:
SetUp()2963 void SetUp() override {
2964 use_handover_mode = true;
2965 UnicastTest::SetUp();
2966 group_ = new LeAudioDeviceGroup(group_id_);
2967 }
2968
TearDown()2969 void TearDown() override {
2970 delete group_;
2971 UnicastTest::TearDown();
2972 }
2973
2974 const int group_id_ = 0;
2975 LeAudioDeviceGroup* group_ = nullptr;
2976 };
2977
TEST_F(UnicastTest,Initialize)2978 TEST_F(UnicastTest, Initialize) {
2979 ASSERT_NE(LeAudioClient::Get(), nullptr);
2980 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
2981 }
2982
TEST_F(UnicastTestNoInit,InitializeNoHal_2_1)2983 TEST_F(UnicastTestNoInit, InitializeNoHal_2_1) {
2984 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
2985
2986 // Report False when asked for Audio HAL 2.1 support
2987 ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool { return false; });
2988
2989 BtaAppRegisterCallback app_register_callback;
2990 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _, _))
2991 .WillByDefault(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
2992 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
2993
2994 EXPECT_DEATH(
2995 LeAudioClient::Initialize(
2996 &mock_audio_hal_client_callbacks_,
2997 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
2998 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2999 &mock_hal_2_1_verifier),
3000 framework_encode_preference),
3001 "LE Audio Client requires Bluetooth Audio HAL V2.1 at least. Either "
3002 "disable LE Audio Profile, or update your HAL");
3003 }
3004
TEST_F(UnicastTest,CleanupWhenUserConnecting)3005 TEST_F(UnicastTest, CleanupWhenUserConnecting) {
3006 const RawAddress test_address0 = GetTestAddress(0);
3007 uint16_t conn_id = 1;
3008 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3009 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3010 default_src_channel_cnt, 0x0004,
3011 /* source sample freq 16khz */ true, /*add_csis*/
3012 true, /*add_cas*/
3013 true, /*add_pacs*/
3014 default_ase_cnt /*add_ascs*/);
3015
3016 /* Remove default action on the direct connect */
3017 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
3018 ConnectLeAudio(test_address0, false, false);
3019
3020 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
3021 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
3022 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(0);
3023 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
3024
3025 LeAudioClient::Cleanup();
3026 SyncOnMainLoop();
3027
3028 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3029 }
3030
TEST_F(UnicastTest,CleanupWhenAutoConnecting)3031 TEST_F(UnicastTest, CleanupWhenAutoConnecting) {
3032 const RawAddress test_address0 = GetTestAddress(0);
3033 uint16_t conn_id = 1;
3034 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3035 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3036 default_channel_cnt, 0x0004,
3037 /* source sample freq 16khz */ true, /*add_csis*/
3038 true, /*add_cas*/
3039 true, /*add_pacs*/
3040 default_ase_cnt /*add_ascs*/);
3041
3042 log::info("Connect device");
3043 ConnectLeAudio(test_address0);
3044
3045 /* Remove default action on the autoconnect */
3046 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3047 .WillByDefault(Return());
3048
3049 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3050 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3051 .Times(1);
3052 /* Make sure when remote device disconnects us, TA is used */
3053 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
3054 EXPECT_CALL(mock_gatt_interface_,
3055 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3056 .Times(1);
3057
3058 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
3059 SyncOnMainLoop();
3060
3061 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3062
3063 log::info("Device is in auto connect");
3064
3065 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
3066 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(0);
3067 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(0);
3068 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
3069
3070 LeAudioClient::Cleanup();
3071 SyncOnMainLoop();
3072
3073 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3074 }
3075
TEST_F(UnicastTest,CleanupWhenConnected)3076 TEST_F(UnicastTest, CleanupWhenConnected) {
3077 const RawAddress test_address0 = GetTestAddress(0);
3078 uint16_t conn_id = 1;
3079 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3080 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3081 default_channel_cnt, 0x0004,
3082 /* source sample freq 16khz */ true, /*add_csis*/
3083 true, /*add_cas*/
3084 true, /*add_pacs*/
3085 default_ase_cnt /*add_ascs*/);
3086
3087 log::info("Connect device");
3088 ConnectLeAudio(test_address0);
3089
3090 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
3091 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(0);
3092 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(1);
3093 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3094
3095 LeAudioClient::Cleanup();
3096 SyncOnMainLoop();
3097
3098 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3099 }
3100
TEST_F(UnicastTest,ConnectAndSetupPhy)3101 TEST_F(UnicastTest, ConnectAndSetupPhy) {
3102 const RawAddress test_address0 = GetTestAddress(0);
3103 uint16_t conn_id = 1;
3104 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3105 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3106 default_channel_cnt, 0x0004,
3107 /* source sample freq 16khz */ true, /*add_csis*/
3108 true, /*add_cas*/
3109 true, /*add_pacs*/
3110 default_ase_cnt /*add_ascs*/);
3111
3112 EXPECT_CALL(mock_btm_interface_, BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0)).Times(1);
3113 ConnectLeAudio(test_address0, false);
3114 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3115
3116 EXPECT_CALL(mock_btm_interface_, BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0)).Times(1);
3117 InjectPhyChangedEvent(conn_id, 0, 0, GATT_REQ_NOT_SUPPORTED);
3118 SyncOnMainLoop();
3119 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3120 .WillByDefault(DoAll(Return(true)));
3121 InjectEncryptionChangedEvent(test_address0);
3122 SyncOnMainLoop();
3123 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3124
3125 /* Make sure flag `acl_phy_update_done_` is cleared after disconnect.
3126 * Just repeat previous steps after reconnection
3127 */
3128 InjectDisconnectedEvent(conn_id);
3129 SyncOnMainLoop();
3130
3131 EXPECT_CALL(mock_btm_interface_, BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0)).Times(1);
3132
3133 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3134 .WillByDefault(DoAll(Return(false)));
3135 InjectConnectedEvent(test_address0, 1);
3136 SyncOnMainLoop();
3137 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3138
3139 EXPECT_CALL(mock_btm_interface_, BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0)).Times(1);
3140 InjectPhyChangedEvent(conn_id, 0, 0, GATT_REQ_NOT_SUPPORTED);
3141 SyncOnMainLoop();
3142 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3143 .WillByDefault(DoAll(Return(true)));
3144 InjectEncryptionChangedEvent(test_address0);
3145 SyncOnMainLoop();
3146 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3147 }
3148
TEST_F(UnicastTest,ConnectOneEarbudEmpty)3149 TEST_F(UnicastTest, ConnectOneEarbudEmpty) {
3150 const RawAddress test_address0 = GetTestAddress(0);
3151 SetSampleDatabaseEmpty(1, test_address0);
3152 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3153 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3154 .Times(1);
3155 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3156 ConnectLeAudio(test_address0);
3157 }
3158
TEST_F(UnicastTest,ConnectOneEarbudNoPacs)3159 TEST_F(UnicastTest, ConnectOneEarbudNoPacs) {
3160 const RawAddress test_address0 = GetTestAddress(0);
3161 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3162 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3163 default_channel_cnt, 0x0004,
3164 /* source sample freq 16khz */ true, /*add_csis*/
3165 true, /*add_cas*/
3166 false, /*add_pacs*/
3167 default_ase_cnt /*add_ascs*/);
3168 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3169 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3170 .Times(1);
3171 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3172 ConnectLeAudio(test_address0);
3173 }
3174
TEST_F(UnicastTest,ConnectOneEarbudNoAscs)3175 TEST_F(UnicastTest, ConnectOneEarbudNoAscs) {
3176 const RawAddress test_address0 = GetTestAddress(0);
3177 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3178 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3179 default_channel_cnt, 0x0004,
3180 /* source sample freq 16khz */ true, /*add_csis*/
3181 true, /*add_cas*/
3182 true, /*add_pacs*/
3183 0 /*add_ascs*/);
3184 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3185 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3186 .Times(1);
3187 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3188 ConnectLeAudio(test_address0);
3189 }
3190
TEST_F(UnicastTest,ConnectOneEarbudNoCas)3191 TEST_F(UnicastTest, ConnectOneEarbudNoCas) {
3192 const RawAddress test_address0 = GetTestAddress(0);
3193 uint16_t conn_id = 1;
3194 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3195 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3196 default_channel_cnt, 0x0004,
3197 /* source sample freq 16khz */ true, /*add_csis*/
3198 false, /*add_cas*/
3199 true, /*add_pacs*/
3200 default_ase_cnt /*add_ascs*/);
3201
3202 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3203 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3204 .Times(1);
3205 ConnectLeAudio(test_address0);
3206 }
3207
TEST_F(UnicastTest,ConnectOneEarbudNoCsis)3208 TEST_F(UnicastTest, ConnectOneEarbudNoCsis) {
3209 const RawAddress test_address0 = GetTestAddress(0);
3210 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3211 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3212 default_channel_cnt, 0x0004,
3213 /* source sample freq 16khz */ false, /*add_csis*/
3214 true, /*add_cas*/
3215 true, /*add_pacs*/
3216 default_ase_cnt /*add_ascs*/);
3217 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3218 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3219 .Times(1);
3220 ConnectLeAudio(test_address0);
3221 }
3222
TEST_F(UnicastTest,ConnectOneEarbudWithInvalidCsis)3223 TEST_F(UnicastTest, ConnectOneEarbudWithInvalidCsis) {
3224 const RawAddress test_address0 = GetTestAddress(0);
3225 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3226 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3227 default_channel_cnt, 0x0004,
3228 /* source sample freq 16khz */ true, /*add_csis*/
3229 true, /*add_cas*/
3230 true, /*add_pacs*/
3231 default_ase_cnt /*add_ascs*/);
3232 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3233 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3234 .Times(1);
3235 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3236
3237 // Report working CSIS
3238 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
3239
3240 /* Make sure Group has not knowledge about the device */
3241 ON_CALL(mock_groups_module_, GetGroupId(_, _))
3242 .WillByDefault([](const RawAddress& /*addr*/, bluetooth::Uuid /*uuid*/) {
3243 return bluetooth::groups::kGroupUnknown;
3244 });
3245
3246 ConnectLeAudio(test_address0);
3247 SyncOnMainLoop();
3248 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3249 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3250 }
3251
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudEmpty_withHealthStatus)3252 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudEmpty_withHealthStatus) {
3253 const RawAddress test_address0 = GetTestAddress(0);
3254 SetSampleDatabaseEmpty(1, test_address0);
3255 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3256 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3257 .Times(1);
3258 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3259 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3260 .Times(1);
3261 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3262 ConnectLeAudio(test_address0);
3263 SyncOnMainLoop();
3264 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3265 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3266
3267 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3268 }
3269
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoPacs_withHealthStatus)3270 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoPacs_withHealthStatus) {
3271 const RawAddress test_address0 = GetTestAddress(0);
3272 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3273 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3274 default_channel_cnt, 0x0004,
3275 /* source sample freq 16khz */ true, /*add_csis*/
3276 true, /*add_cas*/
3277 false, /*add_pacs*/
3278 default_ase_cnt /*add_ascs*/);
3279 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3280 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3281 .Times(1);
3282 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3283 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3284 .Times(1);
3285 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3286 ConnectLeAudio(test_address0);
3287 SyncOnMainLoop();
3288 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3289 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3290
3291 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3292 }
3293
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoAscs_withHealthStatus)3294 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoAscs_withHealthStatus) {
3295 const RawAddress test_address0 = GetTestAddress(0);
3296 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3297 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3298 default_channel_cnt, 0x0004,
3299 /* source sample freq 16khz */ true, /*add_csis*/
3300 true, /*add_cas*/
3301 true, /*add_pacs*/
3302 0 /*add_ascs*/);
3303 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3304 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3305 .Times(1);
3306 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3307 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3308 .Times(1);
3309 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3310 ConnectLeAudio(test_address0);
3311 SyncOnMainLoop();
3312 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3313 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3314
3315 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3316 }
3317
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoCas_withHealthStatus)3318 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoCas_withHealthStatus) {
3319 const RawAddress test_address0 = GetTestAddress(0);
3320 uint16_t conn_id = 1;
3321 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3322 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3323 default_channel_cnt, 0x0004,
3324 /* source sample freq 16khz */ true, /*add_csis*/
3325 false, /*add_cas*/
3326 true, /*add_pacs*/
3327 default_ase_cnt /*add_ascs*/);
3328
3329 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3330 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3331 .Times(0);
3332 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3333 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3334 .Times(1);
3335 ConnectLeAudio(test_address0);
3336 SyncOnMainLoop();
3337 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3338
3339 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3340 }
3341
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoCsis_withHealthStatus)3342 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoCsis_withHealthStatus) {
3343 const RawAddress test_address0 = GetTestAddress(0);
3344 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3345 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3346 default_channel_cnt, 0x0004,
3347 /* source sample freq 16khz */ false, /*add_csis*/
3348 true, /*add_cas*/
3349 true, /*add_pacs*/
3350 default_ase_cnt /*add_ascs*/);
3351 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3352 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3353 .Times(0);
3354 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3355 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3356 .Times(1);
3357 ConnectLeAudio(test_address0);
3358 SyncOnMainLoop();
3359 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3360
3361 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3362 }
3363
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudWithInvalidCsis_withHealthStatus)3364 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudWithInvalidCsis_withHealthStatus) {
3365 const RawAddress test_address0 = GetTestAddress(0);
3366 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3367 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3368 default_channel_cnt, 0x0004,
3369 /* source sample freq 16khz */ true, /*add_csis*/
3370 true, /*add_cas*/
3371 true, /*add_pacs*/
3372 default_ase_cnt /*add_ascs*/);
3373 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3374 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3375 .Times(1);
3376 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3377 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3378 .Times(1);
3379
3380 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3381
3382 // Report working CSIS
3383 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
3384
3385 /* Make sure Group has not knowledge about the device */
3386 ON_CALL(mock_groups_module_, GetGroupId(_, _))
3387 .WillByDefault([](const RawAddress& /*addr*/, bluetooth::Uuid /*uuid*/) {
3388 return bluetooth::groups::kGroupUnknown;
3389 });
3390
3391 ConnectLeAudio(test_address0);
3392 SyncOnMainLoop();
3393 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3394 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3395
3396 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3397 }
3398
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudDisable_withHealthStatus)3399 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudDisable_withHealthStatus) {
3400 const RawAddress test_address0 = GetTestAddress(0);
3401 int conn_id = 1;
3402
3403 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3404 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3405 default_channel_cnt, 0x0004, false);
3406 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3407 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3408 .Times(1);
3409
3410 ConnectLeAudio(test_address0);
3411 SyncOnMainLoop();
3412 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3413
3414 LeAudioClient::Get()->GroupSetActive(group_id_);
3415 auto device = std::make_shared<LeAudioDevice>(test_address0, DeviceConnectState::DISCONNECTED);
3416 group_->AddNode(device);
3417 SyncOnMainLoop();
3418
3419 auto health_status = LeAudioHealthStatus::Get();
3420
3421 /* Inject stream error */
3422 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3423 OnHealthBasedGroupRecommendationAction(group_id_, LeAudioHealthBasedAction::DISABLE))
3424 .Times(1);
3425 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3426 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3427
3428 /* Do not act on disconnect */
3429 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
3430 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).WillByDefault(DoAll(Return()));
3431
3432 state_machine_callbacks_->OnStateTransitionTimeout(group_id_);
3433 SyncOnMainLoop();
3434 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3435
3436 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3437 OnHealthBasedGroupRecommendationAction(group_id_, LeAudioHealthBasedAction::DISABLE))
3438 .Times(0);
3439 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3440 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3441 SyncOnMainLoop();
3442 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3443 }
3444
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudConsiderDisabling_withHealthStatus)3445 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudConsiderDisabling_withHealthStatus) {
3446 const RawAddress test_address0 = GetTestAddress(0);
3447 int conn_id = 1;
3448
3449 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3450 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3451 default_channel_cnt, 0x0004, false);
3452 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3453 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3454 .Times(1);
3455
3456 ConnectLeAudio(test_address0);
3457 SyncOnMainLoop();
3458 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3459
3460 LeAudioClient::Get()->GroupSetActive(group_id_);
3461 auto device = std::make_shared<LeAudioDevice>(test_address0, DeviceConnectState::DISCONNECTED);
3462 group_->AddNode(device);
3463 SyncOnMainLoop();
3464
3465 auto health_status = LeAudioHealthStatus::Get();
3466
3467 /* Inject stream success and error */
3468 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3469 OnHealthBasedGroupRecommendationAction(group_id_,
3470 LeAudioHealthBasedAction::CONSIDER_DISABLING))
3471 .Times(1);
3472 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
3473 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3474 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3475
3476 /* Do not act on disconnect */
3477 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
3478 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).WillByDefault(DoAll(Return()));
3479
3480 state_machine_callbacks_->OnStateTransitionTimeout(group_id_);
3481 SyncOnMainLoop();
3482 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3483
3484 EXPECT_CALL(
3485 mock_audio_hal_client_callbacks_,
3486 OnHealthBasedGroupRecommendationAction(1, LeAudioHealthBasedAction::CONSIDER_DISABLING))
3487 .Times(0);
3488 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3489 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3490 SyncOnMainLoop();
3491 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3492 }
3493
TEST_F(UnicastTest,ConnectDisconnectOneEarbud)3494 TEST_F(UnicastTest, ConnectDisconnectOneEarbud) {
3495 const RawAddress test_address0 = GetTestAddress(0);
3496 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3497 codec_spec_conf::kLeAudioLocationStereo);
3498 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3499 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3500 .Times(1);
3501 ConnectLeAudio(test_address0);
3502 DisconnectLeAudioWithAclClose(test_address0, 1);
3503 }
3504
TEST_F(UnicastTest,ConnectRemoteServiceDiscoveryCompleteBeforeEncryption)3505 TEST_F(UnicastTest, ConnectRemoteServiceDiscoveryCompleteBeforeEncryption) {
3506 const RawAddress test_address0 = GetTestAddress(0);
3507 uint16_t conn_id = 1;
3508 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3509 codec_spec_conf::kLeAudioLocationStereo);
3510 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3511 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3512 .Times(0);
3513 ConnectLeAudio(test_address0, false);
3514 InjectSearchCompleteEvent(conn_id);
3515
3516 SyncOnMainLoop();
3517 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3518
3519 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3520 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3521 .Times(1);
3522 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3523 .WillByDefault(DoAll(Return(true)));
3524 InjectEncryptionChangedEvent(test_address0);
3525 SyncOnMainLoop();
3526 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3527 }
3528
TEST_F(UnicastTest,DisconnectWhenLinkKeyIsGone)3529 TEST_F(UnicastTest, DisconnectWhenLinkKeyIsGone) {
3530 const RawAddress test_address0 = GetTestAddress(0);
3531 uint16_t conn_id = 1;
3532 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3533 codec_spec_conf::kLeAudioLocationStereo);
3534 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3535 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3536 .Times(1);
3537
3538 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3539 .WillByDefault(DoAll(Return(false)));
3540
3541 ON_CALL(mock_btm_interface_, SetEncryption(test_address0, _, _, _, _))
3542 .WillByDefault(Return(tBTM_STATUS::BTM_ERR_KEY_MISSING));
3543
3544 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3545 do_in_main_thread(base::BindOnce(&LeAudioClient::Connect, base::Unretained(LeAudioClient::Get()),
3546 test_address0));
3547
3548 SyncOnMainLoop();
3549 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3550 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3551 }
3552
3553 /* same as above case except the disconnect is initiated by remote */
TEST_F(UnicastTest,ConnectRemoteDisconnectOneEarbud)3554 TEST_F(UnicastTest, ConnectRemoteDisconnectOneEarbud) {
3555 const RawAddress test_address0 = GetTestAddress(0);
3556 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3557 codec_spec_conf::kLeAudioLocationStereo);
3558 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3559 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3560 .Times(1);
3561 ConnectLeAudio(test_address0);
3562 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3563
3564 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3565 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3566 .Times(1);
3567 /* Make sure when remote device disconnects us, TA is used */
3568 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
3569 EXPECT_CALL(mock_gatt_interface_,
3570 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3571 .Times(1);
3572
3573 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
3574 SyncOnMainLoop();
3575
3576 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3577
3578 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3579 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3580 .Times(1);
3581
3582 /* When reconnected, we always remove background connect, as we do not track
3583 * which type (allow list or TA) was used and then make sure the TA is used.
3584 */
3585 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
3586 EXPECT_CALL(mock_gatt_interface_,
3587 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3588 .Times(1);
3589
3590 /* For background connect, test needs to Inject Connected Event */
3591 InjectConnectedEvent(test_address0, 1);
3592 SyncOnMainLoop();
3593 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3594 }
3595
3596 /* same as above case except the disconnect is initiated by remote */
TEST_F(UnicastTest,ConnectRemoteDisconnectOnTimeoutOneEarbud)3597 TEST_F(UnicastTest, ConnectRemoteDisconnectOnTimeoutOneEarbud) {
3598 const RawAddress test_address0 = GetTestAddress(0);
3599 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3600 codec_spec_conf::kLeAudioLocationStereo);
3601 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3602 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3603 .Times(1);
3604 ConnectLeAudio(test_address0);
3605 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3606 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3607 .Times(1);
3608
3609 /* Remove default action on the direct connect */
3610 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
3611
3612 /* For remote disconnection, expect stack to try background re-connect */
3613 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3614 .Times(1);
3615
3616 InjectDisconnectedEvent(1, GATT_CONN_TIMEOUT);
3617 SyncOnMainLoop();
3618
3619 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3620
3621 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3622 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3623 .Times(1);
3624
3625 /* For background connect, test needs to Inject Connected Event */
3626 InjectConnectedEvent(test_address0, 1);
3627 SyncOnMainLoop();
3628 }
3629
TEST_F(UnicastTest,ConnectTwoEarbudsCsisGrouped)3630 TEST_F(UnicastTest, ConnectTwoEarbudsCsisGrouped) {
3631 uint8_t group_size = 2;
3632 int group_id = 2;
3633
3634 // Report working CSIS
3635 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
3636
3637 // First earbud
3638 const RawAddress test_address0 = GetTestAddress(0);
3639 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
3640 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
3641 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
3642
3643 // Second earbud
3644 const RawAddress test_address1 = GetTestAddress(1);
3645 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
3646 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
3647 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
3648 true /*connect_through_csis*/);
3649
3650 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3651
3652 /* for Target announcements AutoConnect is always there, until
3653 * device is removed
3654 */
3655 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false)).Times(0);
3656 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(0);
3657
3658 // Verify grouping information
3659 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
3660 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3661 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3662
3663 DisconnectLeAudioWithAclClose(test_address0, 1);
3664 DisconnectLeAudioWithAclClose(test_address1, 2);
3665 }
3666
TEST_F(UnicastTest,ConnectTwoEarbudsCsisGroupUnknownAtConnect)3667 TEST_F(UnicastTest, ConnectTwoEarbudsCsisGroupUnknownAtConnect) {
3668 uint8_t group_size = 2;
3669 uint8_t group_id = 2;
3670
3671 // Report working CSIS
3672 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
3673
3674 // First earbud connects without known grouping
3675 const RawAddress test_address0 = GetTestAddress(0);
3676 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
3677 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
3678 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
3679
3680 // Second earbud
3681 const RawAddress test_address1 = GetTestAddress(1);
3682 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
3683 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
3684 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
3685 true /*connect_through_csis*/);
3686
3687 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3688
3689 // Verify grouping information
3690 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
3691 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3692 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3693
3694 /* for Target announcements AutoConnect is always there, until
3695 * device is removed
3696 */
3697 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false)).Times(0);
3698 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(0);
3699 DisconnectLeAudioWithAclClose(test_address0, 1);
3700 DisconnectLeAudioWithAclClose(test_address1, 2);
3701 }
3702
TEST_F(UnicastTestNoInit,ConnectFailedDueToInvalidParameters)3703 TEST_F(UnicastTestNoInit, ConnectFailedDueToInvalidParameters) {
3704 // Prepare two devices
3705 uint8_t group_size = 2;
3706 uint8_t group_id = 2;
3707
3708 /* Prepare mock to not inject connect event so the device can stay in
3709 * CONNECTING state*/
3710 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3711 .WillByDefault(DoAll(Return()));
3712
3713 const RawAddress test_address0 = GetTestAddress(0);
3714 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3715 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3716 default_channel_cnt, 0x0004,
3717 /* source sample freq 16khz */ true, /*add_csis*/
3718 true, /*add_cas*/
3719 true, /*add_pacs*/
3720 default_ase_cnt, /*add_ascs_cnt*/
3721 group_size, 1);
3722
3723 const RawAddress test_address1 = GetTestAddress(1);
3724 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
3725 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
3726 default_channel_cnt, 0x0004,
3727 /* source sample freq 16khz */ true, /*add_csis*/
3728 true, /*add_cas*/
3729 true, /*add_pacs*/
3730 default_ase_cnt, /*add_ascs_cnt*/
3731 group_size, 2);
3732
3733 // Load devices from the storage when storage API is called
3734 bool autoconnect = true;
3735
3736 /* Common storage values */
3737 std::vector<uint8_t> handles;
3738 LeAudioClient::GetHandlesForStorage(test_address0, handles);
3739
3740 std::vector<uint8_t> ases;
3741 LeAudioClient::GetAsesForStorage(test_address0, ases);
3742
3743 std::vector<uint8_t> src_pacs;
3744 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
3745
3746 std::vector<uint8_t> snk_pacs;
3747 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
3748
3749 std::vector<uint8_t> gmap_data;
3750 LeAudioClient::GetGmapForStorage(test_address0, gmap_data);
3751
3752 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
3753 do_in_main_thread(base::Bind(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
3754 codec_spec_conf::kLeAudioLocationFrontLeft,
3755 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
3756 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
3757 std::move(ases), std::move(gmap_data)));
3758 do_in_main_thread(base::Bind(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
3759 codec_spec_conf::kLeAudioLocationFrontRight,
3760 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
3761 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
3762 std::move(ases), std::move(gmap_data)));
3763 });
3764
3765 // Expect stored device0 to connect automatically (first directed connection )
3766 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3767 .Times(1);
3768
3769 // Expect stored device1 to connect automatically (first direct connection)
3770 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
3771 .Times(1);
3772
3773 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
3774 .WillByDefault(DoAll(Return(true)));
3775 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3776 .WillByDefault(DoAll(Return(true)));
3777
3778 ON_CALL(mock_groups_module_, GetGroupId(_, _)).WillByDefault(DoAll(Return(group_id)));
3779
3780 ON_CALL(mock_btm_interface_, GetSecurityFlagsByTransport(test_address0, NotNull(), _))
3781 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
3782
3783 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
3784
3785 // Initialize
3786 BtaAppRegisterCallback app_register_callback;
3787 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _, _))
3788 .WillByDefault(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
3789 LeAudioClient::Initialize(
3790 &mock_audio_hal_client_callbacks_,
3791 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
3792 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
3793 framework_encode_preference);
3794 if (app_register_callback) {
3795 app_register_callback.Run(gatt_if, GATT_SUCCESS);
3796 }
3797
3798 // We need to wait for the storage callback before verifying stuff
3799 SyncOnMainLoop();
3800 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
3801 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3802
3803 // Simulate connect parameters are invalid and phone does not fallback
3804 // to background connect.
3805 EXPECT_CALL(mock_gatt_interface_,
3806 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3807 .Times(0);
3808
3809 EXPECT_CALL(mock_gatt_interface_,
3810 Open(gatt_if, test_address1, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3811 .Times(0);
3812
3813 // Devices not found
3814 InjectConnectedEvent(test_address0, 0, GATT_ILLEGAL_PARAMETER);
3815 InjectConnectedEvent(test_address1, 0, GATT_ILLEGAL_PARAMETER);
3816
3817 SyncOnMainLoop();
3818 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3819 }
3820
TEST_F(UnicastTestNoInit,LoadStoredEarbudsBroakenStorage)3821 TEST_F(UnicastTestNoInit, LoadStoredEarbudsBroakenStorage) {
3822 // Prepare two devices
3823 uint8_t group_size = 2;
3824 uint8_t group_id = 2;
3825 /* If the storage has been broken, make sure device will be rediscovered after
3826 * reconnection
3827 */
3828
3829 /* Prepare mock to not inject connect event so the device can stay in
3830 * CONNECTING state*/
3831 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3832 .WillByDefault(DoAll(Return()));
3833
3834 const RawAddress test_address0 = GetTestAddress(0);
3835 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3836 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3837 default_channel_cnt, 0x0004,
3838 /* source sample freq 16khz */ true, /*add_csis*/
3839 true, /*add_cas*/
3840 true, /*add_pacs*/
3841 default_ase_cnt, /*add_ascs_cnt*/
3842 group_size, 1);
3843
3844 const RawAddress test_address1 = GetTestAddress(1);
3845 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
3846 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
3847 default_channel_cnt, 0x0004,
3848 /* source sample freq 16khz */ true, /*add_csis*/
3849 true, /*add_cas*/
3850 true, /*add_pacs*/
3851 default_ase_cnt, /*add_ascs_cnt*/
3852 group_size, 2);
3853
3854 // Load devices from the storage when storage API is called
3855 bool autoconnect = true;
3856 std::vector<uint8_t> empty_buf;
3857
3858 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
3859 do_in_main_thread(base::BindOnce(
3860 &LeAudioClient::AddFromStorage, test_address0, autoconnect,
3861 codec_spec_conf::kLeAudioLocationFrontLeft, codec_spec_conf::kLeAudioLocationFrontLeft,
3862 0xff, 0xff, std::move(empty_buf), std::move(empty_buf), std::move(empty_buf),
3863 std::move(empty_buf), std::move(empty_buf)));
3864 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
3865 codec_spec_conf::kLeAudioLocationFrontRight,
3866 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
3867 std::move(empty_buf), std::move(empty_buf),
3868 std::move(empty_buf), std::move(empty_buf),
3869 std::move(empty_buf)));
3870 SyncOnMainLoop();
3871 });
3872
3873 // Expect stored device0 to connect automatically (first directed connection )
3874 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3875 .Times(1);
3876
3877 // Expect stored device1 to connect automatically (first direct connection)
3878 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
3879 .Times(1);
3880
3881 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
3882 .WillByDefault(DoAll(Return(true)));
3883 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3884 .WillByDefault(DoAll(Return(true)));
3885
3886 ON_CALL(mock_groups_module_, GetGroupId(_, _)).WillByDefault(DoAll(Return(group_id)));
3887
3888 ON_CALL(mock_btm_interface_, GetSecurityFlagsByTransport(test_address0, NotNull(), _))
3889 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
3890
3891 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
3892
3893 // Initialize
3894 BtaAppRegisterCallback app_register_callback;
3895 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _, _))
3896 .WillByDefault(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
3897 LeAudioClient::Initialize(
3898 &mock_audio_hal_client_callbacks_,
3899 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
3900 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
3901 framework_encode_preference);
3902 if (app_register_callback) {
3903 app_register_callback.Run(gatt_if, GATT_SUCCESS);
3904 }
3905
3906 // We need to wait for the storage callback before verifying stuff
3907 SyncOnMainLoop();
3908 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
3909 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3910
3911 // Simulate devices are not there and phone fallbacks to targeted
3912 // announcements
3913 EXPECT_CALL(mock_gatt_interface_,
3914 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3915 .Times(1);
3916
3917 EXPECT_CALL(mock_gatt_interface_,
3918 Open(gatt_if, test_address1, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3919 .Times(1);
3920
3921 // Devices not found
3922 InjectConnectedEvent(test_address0, 0, GATT_ERROR);
3923 InjectConnectedEvent(test_address1, 0, GATT_ERROR);
3924
3925 SyncOnMainLoop();
3926 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3927
3928 /* Stack should rediscover services as storage is broken */
3929 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(2, _)).Times(1);
3930 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(1, _)).Times(1);
3931
3932 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3933 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3934 .Times(1);
3935
3936 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3937 OnConnectionState(ConnectionState::CONNECTED, test_address1))
3938 .Times(1);
3939
3940 /* For background connect, test needs to Inject Connected Event */
3941 InjectConnectedEvent(test_address0, 1);
3942 InjectConnectedEvent(test_address1, 2);
3943 SyncOnMainLoop();
3944
3945 // Verify if all went well and we got the proper group
3946 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
3947 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3948 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3949
3950 DisconnectLeAudioWithAclClose(test_address0, 1);
3951 DisconnectLeAudioWithAclClose(test_address1, 2);
3952 }
3953
TEST_F(UnicastTestNoInit,LoadStoredEarbudsCsisGrouped)3954 TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) {
3955 // Prepare two devices
3956 uint8_t group_size = 2;
3957 uint8_t group_id = 2;
3958
3959 /* Prepare mock to not inject connect event so the device can stay in
3960 * CONNECTING state*/
3961 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3962 .WillByDefault(DoAll(Return()));
3963
3964 const RawAddress test_address0 = GetTestAddress(0);
3965 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3966 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3967 default_channel_cnt, 0x0004,
3968 /* source sample freq 16khz */ true, /*add_csis*/
3969 true, /*add_cas*/
3970 true, /*add_pacs*/
3971 default_ase_cnt, /*add_ascs_cnt*/
3972 group_size, 1);
3973
3974 const RawAddress test_address1 = GetTestAddress(1);
3975 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
3976 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
3977 default_channel_cnt, 0x0004,
3978 /* source sample freq 16khz */ true, /*add_csis*/
3979 true, /*add_cas*/
3980 true, /*add_pacs*/
3981 default_ase_cnt, /*add_ascs_cnt*/
3982 group_size, 2);
3983
3984 // Load devices from the storage when storage API is called
3985 bool autoconnect = true;
3986
3987 /* Common storage values */
3988 std::vector<uint8_t> handles;
3989 LeAudioClient::GetHandlesForStorage(test_address0, handles);
3990
3991 std::vector<uint8_t> ases;
3992 LeAudioClient::GetAsesForStorage(test_address0, ases);
3993
3994 std::vector<uint8_t> src_pacs;
3995 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
3996
3997 std::vector<uint8_t> snk_pacs;
3998 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
3999
4000 std::vector<uint8_t> gmap_data;
4001 LeAudioClient::GetGmapForStorage(test_address0, gmap_data);
4002
4003 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4004 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
4005 codec_spec_conf::kLeAudioLocationFrontLeft,
4006 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
4007 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4008 std::move(ases), std::move(gmap_data)));
4009 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
4010 codec_spec_conf::kLeAudioLocationFrontRight,
4011 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
4012 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4013 std::move(ases), std::move(gmap_data)));
4014 SyncOnMainLoop();
4015 });
4016
4017 // Expect stored device0 to connect automatically (first directed connection )
4018 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
4019 .Times(1);
4020
4021 // Expect stored device1 to connect automatically (first direct connection)
4022 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
4023 .Times(1);
4024
4025 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4026 .WillByDefault(DoAll(Return(true)));
4027 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4028 .WillByDefault(DoAll(Return(true)));
4029
4030 ON_CALL(mock_groups_module_, GetGroupId(_, _)).WillByDefault(DoAll(Return(group_id)));
4031
4032 ON_CALL(mock_btm_interface_, GetSecurityFlagsByTransport(test_address0, NotNull(), _))
4033 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
4034
4035 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
4036
4037 // Initialize
4038 BtaAppRegisterCallback app_register_callback;
4039 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _, _))
4040 .WillByDefault(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
4041 LeAudioClient::Initialize(
4042 &mock_audio_hal_client_callbacks_,
4043 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
4044 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
4045 framework_encode_preference);
4046 if (app_register_callback) {
4047 app_register_callback.Run(gatt_if, GATT_SUCCESS);
4048 }
4049
4050 // We need to wait for the storage callback before verifying stuff
4051 SyncOnMainLoop();
4052 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4053 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4054
4055 // Simulate devices are not there and phone fallbacks to targeted
4056 // announcements
4057 EXPECT_CALL(mock_gatt_interface_,
4058 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4059 .Times(1);
4060
4061 EXPECT_CALL(mock_gatt_interface_,
4062 Open(gatt_if, test_address1, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4063 .Times(1);
4064
4065 // Devices not found
4066 InjectConnectedEvent(test_address0, 0, GATT_ERROR);
4067 InjectConnectedEvent(test_address1, 0, GATT_ERROR);
4068
4069 SyncOnMainLoop();
4070 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4071
4072 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4073 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4074 .Times(1);
4075
4076 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4077 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4078 .Times(1);
4079
4080 /* For background connect, test needs to Inject Connected Event */
4081 InjectConnectedEvent(test_address0, 1);
4082 InjectConnectedEvent(test_address1, 2);
4083 SyncOnMainLoop();
4084
4085 // Verify if all went well and we got the proper group
4086 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
4087 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4088 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4089
4090 DisconnectLeAudioWithAclClose(test_address0, 1);
4091 DisconnectLeAudioWithAclClose(test_address1, 2);
4092 }
4093
TEST_F(UnicastTest,LoadStoredBandedHeadphones)4094 TEST_F(UnicastTest, LoadStoredBandedHeadphones) {
4095 const RawAddress test_address0 = GetTestAddress(0);
4096 uint16_t conn_id = 1;
4097
4098 SetSampleDatabaseEarbudsValid(
4099 conn_id, test_address0,
4100 codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight,
4101 codec_spec_conf::kLeAudioLocationMonoAudio, 2, 1, 0x0004,
4102 /* source sample freq 16khz */ false, /*add_csis*/
4103 true, /*add_cas*/
4104 true, /*add_pacs*/
4105 true, /*add_ascs*/
4106 0, 0);
4107 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4108 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4109 .Times(1);
4110
4111 /* Connect and fill the device storage */
4112 ConnectLeAudio(test_address0);
4113
4114 std::vector<uint8_t> handles;
4115 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4116
4117 std::vector<uint8_t> ases;
4118 LeAudioClient::GetAsesForStorage(test_address0, ases);
4119
4120 std::vector<uint8_t> src_pacs;
4121 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4122
4123 std::vector<uint8_t> snk_pacs;
4124 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4125
4126 std::vector<uint8_t> gmap_data;
4127 LeAudioClient::GetGmapForStorage(test_address0, gmap_data);
4128
4129 /* Disconnect & Cleanup */
4130 DisconnectLeAudioWithAclClose(test_address0, conn_id);
4131 if (LeAudioClient::IsLeAudioClientRunning()) {
4132 LeAudioClient::Cleanup();
4133 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
4134 }
4135
4136 Mock::VerifyAndClearExpectations(&mock_hal_2_1_verifier);
4137 Mock::VerifyAndClearExpectations(&mock_storage_load);
4138
4139 // Load devices from the storage when storage API is called
4140 bool autoconnect = true;
4141 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4142 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
4143 codec_spec_conf::kLeAudioLocationFrontLeft |
4144 codec_spec_conf::kLeAudioLocationFrontRight,
4145 codec_spec_conf::kLeAudioLocationMonoAudio, 0xff, 0xff,
4146 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4147 std::move(ases), std::move(gmap_data)));
4148 SyncOnMainLoop();
4149 });
4150
4151 /* Prepare mock to not inject connect event so the device can stay in
4152 * CONNECTING state*/
4153 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
4154 .WillByDefault(DoAll(Return()));
4155
4156 // Re-Initialize & load from storage
4157 BtaAppRegisterCallback app_register_callback;
4158 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _, _))
4159 .WillByDefault(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
4160 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
4161 LeAudioClient::Initialize(
4162 &mock_audio_hal_client_callbacks_,
4163 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
4164 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
4165 framework_encode_preference);
4166 if (app_register_callback) {
4167 app_register_callback.Run(gatt_if, GATT_SUCCESS);
4168 }
4169
4170 InjectConnectedEvent(test_address0, conn_id);
4171 SyncOnMainLoop();
4172 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4173
4174 // Verify if all went well and we got the proper group
4175 auto group_id = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
4176 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
4177 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4178
4179 SetUpMockCodecManager(::bluetooth::le_audio::types::CodecLocation::HOST);
4180
4181 // Start streaming
4182 LeAudioClient::Get()->GroupSetActive(group_id);
4183 SyncOnMainLoop();
4184
4185 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4186 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _))
4187 .Times(1);
4188 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
4189
4190 SyncOnMainLoop();
4191 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4192 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4193
4194 ASSERT_NE(0lu, streaming_groups.count(group_id));
4195 auto group = streaming_groups.at(group_id);
4196 ASSERT_NE(group, nullptr);
4197
4198 auto device = group->GetFirstDevice();
4199 ASSERT_NE(device, nullptr);
4200 ASSERT_EQ(device->audio_directions_, bluetooth::le_audio::types::kLeAudioDirectionSink |
4201 bluetooth::le_audio::types::kLeAudioDirectionSource);
4202
4203 DisconnectLeAudioWithAclClose(test_address0, conn_id);
4204 }
4205
TEST_F(UnicastTestNoInit,ServiceChangedBeforeServiceIsConnected)4206 TEST_F(UnicastTestNoInit, ServiceChangedBeforeServiceIsConnected) {
4207 // Prepare two devices
4208 uint8_t group_size = 2;
4209 uint8_t group_id = 2;
4210
4211 /* Prepare mock to not inject connect event so the device can stay in
4212 * CONNECTING state*/
4213 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
4214 .WillByDefault(DoAll(Return()));
4215
4216 const RawAddress test_address0 = GetTestAddress(0);
4217 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
4218 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
4219 default_channel_cnt, 0x0004,
4220 /* source sample freq 16khz */ true, /*add_csis*/
4221 true, /*add_cas*/
4222 true, /*add_pacs*/
4223 default_ase_cnt, /*add_ascs_cnt*/
4224 group_size, 1);
4225
4226 const RawAddress test_address1 = GetTestAddress(1);
4227 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
4228 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
4229 default_channel_cnt, 0x0004,
4230 /* source sample freq 16khz */ true, /*add_csis*/
4231 true, /*add_cas*/
4232 true, /*add_pacs*/
4233 default_ase_cnt, /*add_ascs_cnt*/
4234 group_size, 2);
4235
4236 // Load devices from the storage when storage API is called
4237 bool autoconnect = true;
4238
4239 /* Common storage values */
4240 std::vector<uint8_t> handles;
4241 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4242
4243 std::vector<uint8_t> ases;
4244 LeAudioClient::GetAsesForStorage(test_address0, ases);
4245
4246 std::vector<uint8_t> src_pacs;
4247 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4248
4249 std::vector<uint8_t> snk_pacs;
4250 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4251
4252 std::vector<uint8_t> gmap_data;
4253 LeAudioClient::GetGmapForStorage(test_address0, gmap_data);
4254
4255 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4256 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
4257 codec_spec_conf::kLeAudioLocationFrontLeft,
4258 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
4259 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4260 std::move(ases), std::move(gmap_data)));
4261 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
4262 codec_spec_conf::kLeAudioLocationFrontRight,
4263 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
4264 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4265 std::move(ases), std::move(gmap_data)));
4266 SyncOnMainLoop();
4267 });
4268
4269 // Expect stored device0 to connect automatically (first directed connection )
4270 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
4271 .Times(1);
4272
4273 // Expect stored device1 to connect automatically (first direct connection)
4274 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
4275 .Times(1);
4276
4277 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4278 .WillByDefault(DoAll(Return(true)));
4279 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4280 .WillByDefault(DoAll(Return(true)));
4281
4282 ON_CALL(mock_groups_module_, GetGroupId(_, _)).WillByDefault(DoAll(Return(group_id)));
4283
4284 ON_CALL(mock_btm_interface_, GetSecurityFlagsByTransport(test_address0, NotNull(), _))
4285 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
4286
4287 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
4288
4289 // Initialize
4290 BtaAppRegisterCallback app_register_callback;
4291 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _, _))
4292 .WillByDefault(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
4293 LeAudioClient::Initialize(
4294 &mock_audio_hal_client_callbacks_,
4295 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
4296 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
4297 framework_encode_preference);
4298 if (app_register_callback) {
4299 app_register_callback.Run(gatt_if, GATT_SUCCESS);
4300 }
4301
4302 // We need to wait for the storage callback before verifying stuff
4303 SyncOnMainLoop();
4304 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4305 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4306
4307 /* Inject Service Changed */
4308 InjectServiceChangedEvent(test_address1, 0xffff);
4309 SyncOnMainLoop();
4310 InjectServiceChangedEvent(test_address0, 0xffff);
4311 SyncOnMainLoop();
4312 /* Stack should rediscover services as storage is broken */
4313 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(2, _)).Times(1);
4314 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(1, _)).Times(1);
4315
4316 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4317 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4318 .Times(1);
4319
4320 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4321 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4322 .Times(1);
4323
4324 /* For background connect, test needs to Inject Connected Event */
4325 InjectConnectedEvent(test_address0, 1);
4326 InjectConnectedEvent(test_address1, 2);
4327 SyncOnMainLoop();
4328
4329 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4330 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4331 }
4332
TEST_F(UnicastTestNoInit,LoadStoredEarbudsCsisGroupedDifferently)4333 TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGroupedDifferently) {
4334 // Prepare two devices
4335 uint8_t group_size = 1;
4336
4337 // Device 0
4338 uint8_t group_id0 = 2;
4339 bool autoconnect0 = true;
4340 const RawAddress test_address0 = GetTestAddress(0);
4341 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
4342 codec_spec_conf::kLeAudioLocationFrontLeft, 0x0004,
4343 /* source sample freq 16khz */ true, /*add_csis*/
4344 true, /*add_cas*/
4345 true, /*add_pacs*/
4346 true, /*add_ascs*/
4347 group_size, 1);
4348
4349 ON_CALL(mock_groups_module_, GetGroupId(test_address0, _))
4350 .WillByDefault(DoAll(Return(group_id0)));
4351
4352 // Device 1
4353 uint8_t group_id1 = 3;
4354 bool autoconnect1 = false;
4355 const RawAddress test_address1 = GetTestAddress(1);
4356 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
4357 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
4358 default_channel_cnt, 0x0004,
4359 /* source sample freq 16khz */ true, /*add_csis*/
4360 true, /*add_cas*/
4361 true, /*add_pacs*/
4362 default_ase_cnt, /*add_ascs_cnt*/
4363 group_size, 2);
4364
4365 ON_CALL(mock_groups_module_, GetGroupId(test_address1, _))
4366 .WillByDefault(DoAll(Return(group_id1)));
4367
4368 /* Commont storage values */
4369 std::vector<uint8_t> handles;
4370 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4371
4372 std::vector<uint8_t> ases;
4373 LeAudioClient::GetAsesForStorage(test_address0, ases);
4374
4375 std::vector<uint8_t> src_pacs;
4376 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4377
4378 std::vector<uint8_t> snk_pacs;
4379 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4380
4381 std::vector<uint8_t> gmap_data;
4382 LeAudioClient::GetGmapForStorage(test_address0, gmap_data);
4383
4384 // Load devices from the storage when storage API is called
4385 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4386 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect0,
4387 codec_spec_conf::kLeAudioLocationFrontLeft,
4388 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
4389 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4390 std::move(ases), std::move(gmap_data)));
4391 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect1,
4392 codec_spec_conf::kLeAudioLocationFrontRight,
4393 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
4394 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4395 std::move(ases), std::move(gmap_data)));
4396 });
4397
4398 // Expect stored device0 to connect automatically
4399 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4400 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4401 .Times(1);
4402 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4403 .WillByDefault(DoAll(Return(true)));
4404
4405 // First device will got connected
4406 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
4407 .Times(1);
4408 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
4409 EXPECT_CALL(mock_gatt_interface_,
4410 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4411 .Times(1);
4412
4413 // Expect stored device1 to NOT connect automatically
4414 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4415 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4416 .Times(0);
4417 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4418 .WillByDefault(DoAll(Return(true)));
4419
4420 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
4421 .Times(0);
4422
4423 // Initialize
4424 BtaAppRegisterCallback app_register_callback;
4425 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _, _))
4426 .WillByDefault(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
4427 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
4428 LeAudioClient::Initialize(
4429 &mock_audio_hal_client_callbacks_,
4430 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
4431 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
4432 framework_encode_preference);
4433 if (app_register_callback) {
4434 app_register_callback.Run(gatt_if, GATT_SUCCESS);
4435 }
4436
4437 // We need to wait for the storage callback before verifying stuff
4438 SyncOnMainLoop();
4439 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4440 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4441 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4442
4443 // Simulate device is not there and phone fallbacks to targeted announcements
4444 EXPECT_CALL(mock_gatt_interface_,
4445 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4446 .Times(1);
4447
4448 // Devices 0 is connected. Disconnect it
4449 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
4450
4451 SyncOnMainLoop();
4452 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4453
4454 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
4455 EXPECT_CALL(mock_gatt_interface_,
4456 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4457 .Times(1);
4458
4459 /* Keep device in Getting Ready state */
4460 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4461 .WillByDefault(DoAll(Return(false)));
4462 ON_CALL(mock_btm_interface_, SetEncryption(test_address0, _, _, _, _))
4463 .WillByDefault(Return(tBTM_STATUS::BTM_SUCCESS));
4464
4465 /* For background connect, test needs to Inject Connected Event */
4466 InjectConnectedEvent(test_address0, 1);
4467
4468 // We need to wait for the storage callback before verifying stuff
4469 SyncOnMainLoop();
4470 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4471 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4472
4473 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id0);
4474 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4475 ASSERT_EQ(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4476
4477 devs = LeAudioClient::Get()->GetGroupDevices(group_id1);
4478 ASSERT_EQ(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4479 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4480
4481 /* Disconnects while being in getting ready state */
4482 DisconnectLeAudioWithGattClose(test_address0, 1);
4483 }
4484
TEST_F(UnicastTest,GroupingAddRemove)4485 TEST_F(UnicastTest, GroupingAddRemove) {
4486 // Earbud connects without known grouping
4487 uint8_t group_id0 = bluetooth::groups::kGroupUnknown;
4488 const RawAddress test_address0 = GetTestAddress(0);
4489
4490 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
4491 ConnectNonCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
4492 codec_spec_conf::kLeAudioLocationFrontLeft);
4493
4494 group_id0 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
4495
4496 // Earbud connects without known grouping
4497 uint8_t group_id1 = bluetooth::groups::kGroupUnknown;
4498 const RawAddress test_address1 = GetTestAddress(1);
4499 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
4500 ConnectNonCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
4501 codec_spec_conf::kLeAudioLocationFrontRight);
4502
4503 group_id1 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
4504
4505 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
4506
4507 // Verify individual groups
4508 ASSERT_NE(group_id0, bluetooth::groups::kGroupUnknown);
4509 ASSERT_NE(group_id1, bluetooth::groups::kGroupUnknown);
4510 ASSERT_NE(group_id0, group_id1);
4511 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 1u);
4512 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 1u);
4513
4514 // Expectations on reassigning second earbud to the first group
4515 int dev1_storage_group = bluetooth::groups::kGroupUnknown;
4516 int dev1_new_group = bluetooth::groups::kGroupUnknown;
4517
4518 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4519 OnGroupNodeStatus(test_address1, group_id1, GroupNodeStatus::REMOVED))
4520 .Times(AtLeast(1));
4521 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4522 OnGroupNodeStatus(test_address1, _, GroupNodeStatus::ADDED))
4523 .WillRepeatedly(SaveArg<1>(&dev1_new_group));
4524 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id1)).Times(AtLeast(1));
4525 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, _)).Times(AnyNumber());
4526
4527 LeAudioClient::Get()->GroupRemoveNode(group_id1, test_address1);
4528 SyncOnMainLoop();
4529
4530 Mock::VerifyAndClearExpectations(&mock_groups_module_);
4531 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
4532
4533 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, group_id0)).Times(1);
4534
4535 LeAudioClient::Get()->GroupAddNode(group_id0, test_address1);
4536 SyncOnMainLoop();
4537 Mock::VerifyAndClearExpectations(&mock_groups_module_);
4538
4539 dev1_storage_group = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
4540
4541 // Verify regrouping results
4542 EXPECT_EQ(dev1_new_group, group_id0);
4543 EXPECT_EQ(dev1_new_group, dev1_storage_group);
4544 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 0u);
4545 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 2u);
4546 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id0);
4547 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4548 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4549 }
4550
TEST_F(UnicastTest,DoubleResumeFromAF)4551 TEST_F(UnicastTest, DoubleResumeFromAF) {
4552 const RawAddress test_address0 = GetTestAddress(0);
4553 int group_id = bluetooth::groups::kGroupUnknown;
4554
4555 SetSampleDatabaseEarbudsValid(
4556 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4557 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4558 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4559 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 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 constexpr int gmcs_ccid = 1;
4571 constexpr int gtbs_ccid = 2;
4572
4573 // Audio sessions are started only when device gets active
4574 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4575 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4576 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
4577 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
4578 LeAudioClient::Get()->GroupSetActive(group_id);
4579 SyncOnMainLoop();
4580
4581 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
4582 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
4583
4584 stay_at_qos_config_in_start_stream = true;
4585
4586 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
4587 LocalAudioSourceResume(false);
4588
4589 SyncOnMainLoop();
4590 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4591 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4592
4593 // Additional resume shall be ignored.
4594 LocalAudioSourceResume(false, false);
4595
4596 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
4597
4598 do_in_main_thread(base::BindOnce(
4599 [](int group_id,
4600 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks) {
4601 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
4602 },
4603 group_id, base::Unretained(state_machine_callbacks_)));
4604 SyncOnMainLoop();
4605 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4606
4607 // Verify Data transfer on one audio source cis
4608 constexpr uint8_t cis_count_out = 1;
4609 constexpr uint8_t cis_count_in = 0;
4610 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4611 }
4612
TEST_F(UnicastTest,DoubleResumeFromAFOnLocalSink)4613 TEST_F(UnicastTest, DoubleResumeFromAFOnLocalSink) {
4614 const RawAddress test_address0 = GetTestAddress(0);
4615 int group_id = bluetooth::groups::kGroupUnknown;
4616
4617 default_channel_cnt = 1;
4618
4619 SetSampleDatabaseEarbudsValid(
4620 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4621 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4622 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4623 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4624 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4625 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4626 .Times(1);
4627 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4628 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4629 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4630
4631 ConnectLeAudio(test_address0);
4632 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4633
4634 // Audio sessions are started only when device gets active
4635 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4636 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4637 LeAudioClient::Get()->GroupSetActive(group_id);
4638 SyncOnMainLoop();
4639
4640 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4641
4642 stay_at_qos_config_in_start_stream = true;
4643
4644 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
4645 LocalAudioSinkResume();
4646
4647 SyncOnMainLoop();
4648 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4649 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4650
4651 EXPECT_CALL(*mock_le_audio_sink_hal_client_, CancelStreamingRequest()).Times(0);
4652
4653 // Actuall test here: send additional resume which shall be ignored.
4654 LocalAudioSinkResume();
4655
4656 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
4657
4658 do_in_main_thread(base::BindOnce(
4659 [](int group_id,
4660 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks) {
4661 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
4662 },
4663 group_id, base::Unretained(state_machine_callbacks_)));
4664 SyncOnMainLoop();
4665 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4666
4667 // Verify Data transfer on local audio sink which is started
4668 constexpr uint8_t cis_count_out = 0;
4669 constexpr uint8_t cis_count_in = 1;
4670 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
4671 }
4672
TEST_F(UnicastTest,HandleResumeWithoutMetadataUpdateOnLocalSink)4673 TEST_F(UnicastTest, HandleResumeWithoutMetadataUpdateOnLocalSink) {
4674 const RawAddress test_address0 = GetTestAddress(0);
4675 int group_id = bluetooth::groups::kGroupUnknown;
4676
4677 /**
4678 * In this test we want to make sure that if MetadataUpdate is
4679 * not called before Resume, but the context type is supported,
4680 * stream should be created
4681 */
4682
4683 default_channel_cnt = 1;
4684
4685 SetSampleDatabaseEarbudsValid(
4686 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4687 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4688 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4689 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4690 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4691 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4692 .Times(1);
4693 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4694 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4695 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4696
4697 ConnectLeAudio(test_address0);
4698 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4699
4700 // Audio sessions are started only when device gets active
4701 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4702 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4703 LeAudioClient::Get()->GroupSetActive(group_id);
4704 SyncOnMainLoop();
4705
4706 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4707
4708 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
4709 LocalAudioSinkResume();
4710
4711 SyncOnMainLoop();
4712 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4713 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4714 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4715
4716 // Verify Data transfer on local audio sink which is started
4717 constexpr uint8_t cis_count_out = 0;
4718 constexpr uint8_t cis_count_in = 1;
4719 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
4720
4721 SyncOnMainLoop();
4722 /* Clear cache by changing context types, this is required for the test
4723 * as setting active device actually generate cache
4724 */
4725 auto sink_available_context = types::kLeAudioContextAllRemoteSinkOnly;
4726 auto source_available_context = types::kLeAudioContextAllRemoteSource;
4727 InjectAvailableContextTypes(test_address0, 1, sink_available_context, source_available_context);
4728
4729 StopStreaming(group_id, true);
4730 SyncOnMainLoop();
4731
4732 // simulate suspend timeout passed, alarm executing
4733 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
4734 SyncOnMainLoop();
4735
4736 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4737
4738 // Resume without metadata update while cached configuration is cleared
4739 LocalAudioSinkResume();
4740 SyncOnMainLoop();
4741 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4742 }
4743
TEST_F(UnicastTest,GroupSetActiveNonConnectedGroup)4744 TEST_F(UnicastTest, GroupSetActiveNonConnectedGroup) {
4745 const RawAddress test_address0 = GetTestAddress(0);
4746 int group_id = bluetooth::groups::kGroupUnknown;
4747
4748 /**
4749 * In this test we want to make sure that Available context change reach Java
4750 * when group is in Configured state
4751 */
4752
4753 default_channel_cnt = 1;
4754 int conn_id = 1;
4755 SetSampleDatabaseEarbudsValid(
4756 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4757 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4758 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4759 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4760 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4761 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4762 .Times(1);
4763 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4764 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4765 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4766
4767 ConnectLeAudio(test_address0);
4768 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4769
4770 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4771
4772 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, GroupStatus::INACTIVE))
4773 .Times(1);
4774
4775 InjectDisconnectedEvent(conn_id);
4776 SyncOnMainLoop();
4777
4778 // Audio sessions are started only when device gets active
4779 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupSelectableCodecConf(group_id, _, _))
4780 .Times(0);
4781 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _))
4782 .Times(0);
4783 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(0);
4784 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(0);
4785
4786 // try to set active group on non connected group
4787
4788 LeAudioClient::Get()->GroupSetActive(group_id);
4789 SyncOnMainLoop();
4790 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4791 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4792 }
4793
TEST_F(UnicastTest,GroupSetActive_CurrentCodecSentOfActive)4794 TEST_F(UnicastTest, GroupSetActive_CurrentCodecSentOfActive) {
4795 const RawAddress test_address0 = GetTestAddress(0);
4796 int group_id = bluetooth::groups::kGroupUnknown;
4797
4798 /**
4799 * In this test we want to make sure that Available context change reach Java
4800 * when group is in Configured state
4801 */
4802
4803 default_channel_cnt = 1;
4804
4805 SetSampleDatabaseEarbudsValid(
4806 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4807 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4808 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4809 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4810 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4811 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4812 .Times(1);
4813 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4814 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4815 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4816
4817 ConnectLeAudio(test_address0);
4818 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4819
4820 // Audio sessions are started only when device gets active
4821 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupSelectableCodecConf(group_id, _, _))
4822 .Times(1);
4823 btle_audio_codec_config_t empty_conf{};
4824 btle_audio_codec_config_t output_config = {
4825 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
4826 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
4827 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
4828 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
4829 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
4830 .octets_per_frame = 120};
4831
4832 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4833 OnAudioGroupCurrentCodecConf(group_id, empty_conf, output_config))
4834 .Times(1);
4835
4836 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4837 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4838 LeAudioClient::Get()->GroupSetActive(group_id);
4839 SyncOnMainLoop();
4840 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4841 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4842 }
4843
TEST_F(UnicastTest,GroupSetActive)4844 TEST_F(UnicastTest, GroupSetActive) {
4845 const RawAddress test_address0 = GetTestAddress(0);
4846 int group_id = bluetooth::groups::kGroupUnknown;
4847
4848 /**
4849 * In this test we want to make sure that Available context change reach Java
4850 * when group is in Configured state
4851 */
4852
4853 default_channel_cnt = 1;
4854
4855 SetSampleDatabaseEarbudsValid(
4856 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4857 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4858 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4859 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4860 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4861 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4862 .Times(1);
4863 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4864 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4865 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4866
4867 ConnectLeAudio(test_address0);
4868 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4869
4870 // Audio sessions are started only when device gets active
4871 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupSelectableCodecConf(group_id, _, _))
4872 .Times(1);
4873 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, GroupStatus::ACTIVE))
4874 .Times(1);
4875 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(_, GroupStatus::INACTIVE)).Times(0);
4876 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4877 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4878
4879 EXPECT_CALL(*mock_codec_manager_,
4880 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
4881 mock_le_audio_sink_hal_client_, true))
4882 .Times(1);
4883
4884 LeAudioClient::Get()->GroupSetActive(group_id);
4885 SyncOnMainLoop();
4886 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4887 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4888 Mock::VerifyAndClearExpectations(mock_codec_manager_);
4889 }
4890
TEST_F(UnicastTest,GroupSetActive_SinkPacksEmpty)4891 TEST_F(UnicastTest, GroupSetActive_SinkPacksEmpty) {
4892 const RawAddress test_address0 = GetTestAddress(0);
4893 int group_id = bluetooth::groups::kGroupUnknown;
4894 empty_sink_pack_ = true;
4895
4896 /**
4897 * In this test we want to make sure that Available context change reach Java
4898 * when group is in Configured state
4899 */
4900
4901 default_channel_cnt = 1;
4902
4903 SetSampleDatabaseEarbudsValid(
4904 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4905 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4906 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4907 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4908 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4909 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4910 .Times(1);
4911 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4912 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4913 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4914
4915 ConnectLeAudio(test_address0);
4916 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4917
4918 // Audio sessions are started only when device gets active
4919 std::vector<btle_audio_codec_config_t> empty_confs;
4920
4921 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4922 OnAudioGroupSelectableCodecConf(group_id, _, empty_confs))
4923 .Times(1);
4924 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4925 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4926
4927 EXPECT_CALL(*mock_codec_manager_,
4928 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
4929 mock_le_audio_sink_hal_client_, true))
4930 .Times(1);
4931
4932 LeAudioClient::Get()->GroupSetActive(group_id);
4933 SyncOnMainLoop();
4934 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4935 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4936 Mock::VerifyAndClearExpectations(mock_codec_manager_);
4937 }
4938
TEST_F(UnicastTest,GroupSetActive_SourcePacksEmpty)4939 TEST_F(UnicastTest, GroupSetActive_SourcePacksEmpty) {
4940 const RawAddress test_address0 = GetTestAddress(0);
4941 int group_id = bluetooth::groups::kGroupUnknown;
4942 empty_source_pack_ = true;
4943
4944 /**
4945 * In this test we want to make sure that Available context change reach Java
4946 * when group is in Configured state
4947 */
4948
4949 default_channel_cnt = 1;
4950
4951 SetSampleDatabaseEarbudsValid(
4952 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4953 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4954 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4955 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4956 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4957 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4958 .Times(1);
4959 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4960 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4961 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4962
4963 ConnectLeAudio(test_address0);
4964 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4965
4966 // Audio sessions are started only when device gets active
4967 std::vector<btle_audio_codec_config_t> empty_confs;
4968
4969 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4970 OnAudioGroupSelectableCodecConf(group_id, empty_confs, _))
4971 .Times(1);
4972 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4973 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4974 LeAudioClient::Get()->GroupSetActive(group_id);
4975 SyncOnMainLoop();
4976 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4977 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4978 }
4979
TEST_F(UnicastTest,GroupSetActive_and_InactiveDuringStreamConfiguration)4980 TEST_F(UnicastTest, GroupSetActive_and_InactiveDuringStreamConfiguration) {
4981 const RawAddress test_address0 = GetTestAddress(0);
4982 int group_id = bluetooth::groups::kGroupUnknown;
4983 empty_source_pack_ = true;
4984
4985 /**
4986 * In this test we want to make sure that StopStream is called when group is set to inactive
4987 * while being between IDLE and CONFIGURED state
4988 */
4989
4990 default_channel_cnt = 1;
4991
4992 SetSampleDatabaseEarbudsValid(
4993 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4994 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4995 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4996 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4997 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4998 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4999 .Times(1);
5000 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5001 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5002 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5003
5004 ConnectLeAudio(test_address0);
5005 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5006
5007 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5008
5009 stay_at_qos_config_in_start_stream = true;
5010
5011 LeAudioClient::Get()->GroupSetActive(group_id);
5012 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID, false,
5013 false);
5014
5015 SyncOnMainLoop();
5016
5017 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5018 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
5019
5020 SyncOnMainLoop();
5021 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5022 }
5023
TEST_F(UnicastTest,AnotherGroupSetActive_DuringMediaStream)5024 TEST_F(UnicastTest, AnotherGroupSetActive_DuringMediaStream) {
5025 const RawAddress test_address0 = GetTestAddress(0);
5026 const RawAddress test_address1 = GetTestAddress(1);
5027 int group_id_1 = 1;
5028 int group_id_2 = 2;
5029 int group_size = 1;
5030
5031 default_channel_cnt = 2;
5032 default_src_channel_cnt = 1;
5033
5034 /**
5035 * Scenario:
5036 * 1. Voip is started
5037 * 2. Group 1 is set active - no fast configuration is expected
5038 * 3. Audio HAL resumse the stream and Group 1 is streaming
5039 * 3. Group 2 is set to active - it is expected that stream to Group 1 is stopped and Group 2
5040 * configuration goes to QoS configured
5041 */
5042 // Report working CSIS
5043 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
5044 ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Return(group_size));
5045
5046 log::info("Connecting first Group with device {}", test_address0);
5047 ConnectCsisDevice(
5048 test_address0, 1 /* conn_id*/,
5049 codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight,
5050 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_1, 1 /* rank*/);
5051
5052 SyncOnMainLoop();
5053
5054 log::info("Connecting second Group with device {}", test_address1);
5055 ConnectCsisDevice(
5056 test_address1, 2 /* conn_id*/,
5057 codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight,
5058 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_2, 1 /* rank*/);
5059 SyncOnMainLoop();
5060 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5061
5062 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
5063 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0);
5064
5065 log::info("Group is getting Active");
5066 LeAudioClient::Get()->GroupSetActive(group_id_1);
5067
5068 SyncOnMainLoop();
5069 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5070
5071 log::info("Audio HAL opens for Media");
5072
5073 constexpr int gmcs_ccid = 1;
5074 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, static_cast<int>(LeAudioContextType::MEDIA));
5075
5076 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
5077 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::MEDIA, _, ccids))
5078 .Times(AtLeast(1));
5079
5080 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_1);
5081
5082 SyncOnMainLoop();
5083 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5084 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5085
5086 log::info("Set group 2 as active one ");
5087 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5088 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
5089 EXPECT_CALL(mock_state_machine_,
5090 ConfigureStream(_, types::LeAudioContextType::MEDIA, _, _, false))
5091 .Times(1);
5092
5093 LeAudioClient::Get()->GroupSetActive(group_id_2);
5094
5095 SyncOnMainLoop();
5096 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5097
5098 LocalAudioSourceResume();
5099 SyncOnMainLoop();
5100 }
5101
TEST_F(UnicastTest,AnotherGroupSetActive_DuringVoip)5102 TEST_F(UnicastTest, AnotherGroupSetActive_DuringVoip) {
5103 const RawAddress test_address0 = GetTestAddress(0);
5104 const RawAddress test_address1 = GetTestAddress(1);
5105 int group_id_1 = 1;
5106 int group_id_2 = 2;
5107 int group_size = 1;
5108
5109 default_channel_cnt = 2;
5110 default_src_channel_cnt = 1;
5111
5112 /**
5113 * Scenario:
5114 * 1. Voip is started
5115 * 2. Group 1 is set active - no fast configuration is expected
5116 * 3. Audio HAL resumse the stream and Group 1 is streaming
5117 * 3. Group 2 is set to active - it is expected that stream to Group 1 is stopped and Group 2
5118 * configuration goes to QoS configured
5119 */
5120 // Report working CSIS
5121 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
5122 ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Return(group_size));
5123
5124 log::info("Connecting first Group with device {}", test_address0);
5125 ConnectCsisDevice(
5126 test_address0, 1 /* conn_id*/,
5127 codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight,
5128 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_1, 1 /* rank*/);
5129
5130 SyncOnMainLoop();
5131
5132 log::info("Connecting second Group with device {}", test_address1);
5133 ConnectCsisDevice(
5134 test_address1, 2 /* conn_id*/,
5135 codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight,
5136 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_2, 1 /* rank*/);
5137 SyncOnMainLoop();
5138 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5139
5140 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
5141 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0);
5142
5143 log::info("Group is getting Active");
5144 LeAudioClient::Get()->GroupSetActive(group_id_1);
5145
5146 SyncOnMainLoop();
5147 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5148
5149 log::info("Audio HAL opens for Converstational");
5150
5151 // VOIP not using Telecom API has no ccids.
5152 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {}, .source = {}};
5153 EXPECT_CALL(mock_state_machine_,
5154 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
5155 .Times(AtLeast(1));
5156
5157 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id_1);
5158
5159 SyncOnMainLoop();
5160 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5161 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5162
5163 log::info("Set group 2 as active one ");
5164 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5165 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
5166 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, true)).Times(1);
5167
5168 LeAudioClient::Get()->GroupSetActive(group_id_2);
5169
5170 SyncOnMainLoop();
5171 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5172 }
5173
TEST_F(UnicastTest,GroupSetActive_and_GroupSetInactive_DuringPhoneCall)5174 TEST_F(UnicastTest, GroupSetActive_and_GroupSetInactive_DuringPhoneCall) {
5175 const RawAddress test_address0 = GetTestAddress(0);
5176 int group_id = bluetooth::groups::kGroupUnknown;
5177
5178 /**
5179 * Scenario:
5180 * 1. Call is started
5181 * 2. Group is set active - it is expected the state machine to be instructed to Configure to Qos
5182 * 3. Group is set to inactive - it is expected that state machine is instructed to stop *
5183 */
5184
5185 default_channel_cnt = 1;
5186
5187 SetSampleDatabaseEarbudsValid(
5188 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5189 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5190 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5191 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5192 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5193 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5194 .Times(1);
5195 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5196 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5197 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5198
5199 ConnectLeAudio(test_address0);
5200 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5201
5202 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
5203 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, true)).Times(1);
5204
5205 log::info("Call is started and group is getting Active");
5206 LeAudioClient::Get()->SetInCall(true);
5207 LeAudioClient::Get()->GroupSetActive(group_id);
5208
5209 SyncOnMainLoop();
5210 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5211
5212 log::info("Group is getting inctive");
5213 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5214 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
5215
5216 SyncOnMainLoop();
5217 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5218 }
5219
TEST_F(UnicastTest,GroupSetActive_DuringPhoneCall_ThenResume)5220 TEST_F(UnicastTest, GroupSetActive_DuringPhoneCall_ThenResume) {
5221 const RawAddress test_address0 = GetTestAddress(0);
5222 int group_id = bluetooth::groups::kGroupUnknown;
5223
5224 /**
5225 * Scenario:
5226 * 1. Call is started
5227 * 2. Group is set active - it is expected the state machine to be instructed to Configure to Qos
5228 * 3. Audio Framework callse Resume - expect stream is started.
5229 * 4. Group is set to inactive - it is expected that state machine is instructed to stop *
5230 */
5231
5232 default_channel_cnt = 1;
5233
5234 SetSampleDatabaseEarbudsValid(
5235 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5236 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5237 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5238 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5239 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5240 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5241 .Times(1);
5242 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5243 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5244 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5245
5246 ConnectLeAudio(test_address0);
5247 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5248
5249 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
5250 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, true)).Times(1);
5251
5252 log::info("Call is started and group is getting Active");
5253 LeAudioClient::Get()->SetInCall(true);
5254 LeAudioClient::Get()->GroupSetActive(group_id);
5255
5256 SyncOnMainLoop();
5257 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5258
5259 log::info("AF resumes the stream");
5260 /* Simulate resume and expect StartStream to be called.
5261 * Do not expect confirmation on resume, as this part is not mocked on the state machine
5262 */
5263 EXPECT_CALL(mock_state_machine_, StartStream(_, LeAudioContextType::CONVERSATIONAL, _, _))
5264 .Times(1);
5265 LocalAudioSourceResume(true, false);
5266 SyncOnMainLoop();
5267 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5268
5269 log::info("Group is getting inactive");
5270 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5271 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
5272
5273 SyncOnMainLoop();
5274 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5275 }
5276
TEST_F(UnicastTest,ChangeAvailableContextTypeWhenInCodecConfigured)5277 TEST_F(UnicastTest, ChangeAvailableContextTypeWhenInCodecConfigured) {
5278 const RawAddress test_address0 = GetTestAddress(0);
5279 int group_id = bluetooth::groups::kGroupUnknown;
5280
5281 /**
5282 * In this test we want to make sure that Available context change reach Java
5283 * when group is in Configured state
5284 */
5285
5286 default_channel_cnt = 1;
5287
5288 SetSampleDatabaseEarbudsValid(
5289 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5290 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5291 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5292 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5293 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5294 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5295 .Times(1);
5296 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5297 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5298 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5299
5300 ConnectLeAudio(test_address0);
5301 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5302
5303 // Audio sessions are started only when device gets active
5304 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5305 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5306 LeAudioClient::Get()->GroupSetActive(group_id);
5307 SyncOnMainLoop();
5308
5309 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5310
5311 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
5312 LocalAudioSinkResume();
5313
5314 SyncOnMainLoop();
5315 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5316 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5317 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5318
5319 // Verify Data transfer on local audio sink which is started
5320 constexpr uint8_t cis_count_out = 0;
5321 constexpr uint8_t cis_count_in = 1;
5322 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
5323
5324 // Remember group to set the state after stopping the stream
5325 ASSERT_NE(0lu, streaming_groups.count(group_id));
5326 auto group = streaming_groups.at(group_id);
5327
5328 SyncOnMainLoop();
5329 StopStreaming(group_id, true);
5330 SyncOnMainLoop();
5331
5332 // simulate suspend timeout passed, alarm executing
5333 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
5334 SyncOnMainLoop();
5335
5336 // Simulate state Configured
5337 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
5338
5339 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioConf(_, _, _, _, _));
5340
5341 /* Check if available context will be sent to Java */
5342 auto sink_available_context = types::kLeAudioContextAllRemoteSinkOnly;
5343 auto source_available_context = types::kLeAudioContextAllRemoteSource;
5344
5345 InjectAvailableContextTypes(test_address0, 1, sink_available_context, source_available_context);
5346
5347 SyncOnMainLoop();
5348 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5349 }
5350
TEST_F(UnicastTest,TestUpdateConfigurationCallbackWhileStreaming)5351 TEST_F(UnicastTest, TestUpdateConfigurationCallbackWhileStreaming) {
5352 const RawAddress test_address0 = GetTestAddress(0);
5353 int group_id = bluetooth::groups::kGroupUnknown;
5354
5355 SetSampleDatabaseEarbudsValid(
5356 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5357 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5358 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5359 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5360 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5361 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5362 .Times(1);
5363 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5364 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5365 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5366
5367 ConnectLeAudio(test_address0);
5368 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5369
5370 // Start streaming
5371 LeAudioClient::Get()->GroupSetActive(group_id);
5372 SyncOnMainLoop();
5373
5374 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5375 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _))
5376 .Times(1);
5377 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5378
5379 SyncOnMainLoop();
5380 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5381 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5382 SyncOnMainLoop();
5383
5384 // When metadata update happen, there should be no configuration change
5385 // callback sent
5386 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _))
5387 .Times(0);
5388
5389 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5390 UpdateLocalSourceMetadata(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN);
5391
5392 // Inject STREAMING Status from state machine.
5393 auto group = streaming_groups.at(group_id);
5394 do_in_main_thread(base::BindOnce(
5395 [](int group_id,
5396 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
5397 LeAudioDeviceGroup* /*group*/) {
5398 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
5399 },
5400 group_id, base::Unretained(this->state_machine_callbacks_), std::move(group)));
5401
5402 SyncOnMainLoop();
5403 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5404 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5405 }
5406
TEST_F(UnicastTest,TestDeactivateWhileStartingStream)5407 TEST_F(UnicastTest, TestDeactivateWhileStartingStream) {
5408 const RawAddress test_address0 = GetTestAddress(0);
5409 int group_id = bluetooth::groups::kGroupUnknown;
5410
5411 SetSampleDatabaseEarbudsValid(
5412 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5413 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5414 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5415 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5416 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5417 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5418 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5419
5420 ConnectLeAudio(test_address0);
5421 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5422
5423 // Start streaming
5424 LeAudioClient::Get()->GroupSetActive(group_id);
5425 SyncOnMainLoop();
5426 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5427
5428 // Deactivate while starting to stream
5429 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
5430
5431 // Inject STREAMING Status from state machine.
5432 auto group = streaming_groups.at(group_id);
5433 do_in_main_thread(base::BindOnce(
5434 [](int group_id,
5435 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
5436 LeAudioDeviceGroup* /*group*/) {
5437 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
5438 },
5439 group_id, base::Unretained(this->state_machine_callbacks_), std::move(group)));
5440 SyncOnMainLoop();
5441 }
5442
TEST_F(UnicastTest,RemoveNodeWhileStreaming)5443 TEST_F(UnicastTest, RemoveNodeWhileStreaming) {
5444 const RawAddress test_address0 = GetTestAddress(0);
5445 int group_id = bluetooth::groups::kGroupUnknown;
5446
5447 SetSampleDatabaseEarbudsValid(
5448 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5449 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5450 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5451 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5452 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5453 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5454 .Times(1);
5455 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5456 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5457 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5458
5459 ConnectLeAudio(test_address0);
5460 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5461
5462 // Start streaming
5463 constexpr uint8_t cis_count_out = 1;
5464 constexpr uint8_t cis_count_in = 0;
5465
5466 constexpr int gmcs_ccid = 1;
5467 constexpr int gtbs_ccid = 2;
5468
5469 // Audio sessions are started only when device gets active
5470 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5471 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5472 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5473 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5474 LeAudioClient::Get()->GroupSetActive(group_id);
5475 SyncOnMainLoop();
5476
5477 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
5478 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5479
5480 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5481
5482 SyncOnMainLoop();
5483 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5484 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5485 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5486 SyncOnMainLoop();
5487
5488 // Verify Data transfer on one audio source cis
5489 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5490
5491 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id)).Times(1);
5492 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5493 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _)).Times(1);
5494 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5495 OnGroupNodeStatus(test_address0, group_id, GroupNodeStatus::REMOVED));
5496 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5497 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5498 .Times(1);
5499
5500 LeAudioClient::Get()->GroupRemoveNode(group_id, test_address0);
5501
5502 SyncOnMainLoop();
5503 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5504 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5505 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5506 }
5507
TEST_F(UnicastTest,InactiveDeviceOnInternalStateMachineError)5508 TEST_F(UnicastTest, InactiveDeviceOnInternalStateMachineError) {
5509 const RawAddress test_address0 = GetTestAddress(0);
5510 int group_id = bluetooth::groups::kGroupUnknown;
5511
5512 SetSampleDatabaseEarbudsValid(
5513 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5514 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5515 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5516 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5517 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5518 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5519 .Times(1);
5520 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5521 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5522 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5523
5524 ConnectLeAudio(test_address0);
5525 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5526
5527 // Start streaming
5528 constexpr uint8_t cis_count_out = 1;
5529 constexpr uint8_t cis_count_in = 0;
5530
5531 constexpr int gmcs_ccid = 1;
5532 constexpr int gtbs_ccid = 2;
5533
5534 // Audio sessions are started only when device gets active
5535 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5536 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5537 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5538 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5539 LeAudioClient::Get()->GroupSetActive(group_id);
5540 SyncOnMainLoop();
5541
5542 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
5543 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5544
5545 btle_audio_codec_config_t empty_conf{};
5546 btle_audio_codec_config_t output_config = {
5547 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
5548 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
5549 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
5550 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_2,
5551 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
5552 .octets_per_frame = 120};
5553
5554 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5555 OnAudioGroupCurrentCodecConf(group_id, empty_conf, output_config))
5556 .Times(1);
5557
5558 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5559
5560 SyncOnMainLoop();
5561 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5562 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5563 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
5564 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5565 SyncOnMainLoop();
5566
5567 // Verify Data transfer on one audio source cis
5568 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5569
5570 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
5571 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
5572
5573 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, GroupStatus::INACTIVE))
5574 .Times(1);
5575
5576 /* This is internal error of the state machine */
5577 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::RELEASING);
5578
5579 SyncOnMainLoop();
5580 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5581 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5582 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
5583 }
5584
TEST_F(UnicastTest,GroupingAddTwiceNoRemove)5585 TEST_F(UnicastTest, GroupingAddTwiceNoRemove) {
5586 // Earbud connects without known grouping
5587 uint8_t group_id0 = bluetooth::groups::kGroupUnknown;
5588 const RawAddress test_address0 = GetTestAddress(0);
5589 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
5590 .WillOnce(Return())
5591 .RetiresOnSaturation();
5592 ConnectNonCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
5593 codec_spec_conf::kLeAudioLocationFrontLeft);
5594
5595 group_id0 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
5596
5597 // Earbud connects without known grouping
5598 uint8_t group_id1 = bluetooth::groups::kGroupUnknown;
5599 const RawAddress test_address1 = GetTestAddress(1);
5600 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
5601 .WillOnce(Return())
5602 .RetiresOnSaturation();
5603 ConnectNonCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
5604 codec_spec_conf::kLeAudioLocationFrontRight);
5605
5606 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5607
5608 group_id1 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
5609 // Verify individual groups
5610 ASSERT_NE(group_id0, bluetooth::groups::kGroupUnknown);
5611 ASSERT_NE(group_id1, bluetooth::groups::kGroupUnknown);
5612 ASSERT_NE(group_id0, group_id1);
5613 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 1u);
5614 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 1u);
5615
5616 // Expectations on reassigning second earbud to the first group
5617 int dev1_storage_group = bluetooth::groups::kGroupUnknown;
5618 int dev1_new_group = bluetooth::groups::kGroupUnknown;
5619
5620 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5621 OnGroupNodeStatus(test_address1, group_id1, GroupNodeStatus::REMOVED))
5622 .Times(AtLeast(1));
5623 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5624 OnGroupNodeStatus(test_address1, _, GroupNodeStatus::ADDED))
5625 .WillRepeatedly(SaveArg<1>(&dev1_new_group));
5626
5627 // FIXME: We should expect removal with group_id context. No such API exists.
5628 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id1)).Times(AtLeast(1));
5629 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, _)).Times(AnyNumber());
5630 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, group_id0)).Times(1);
5631
5632 // Regroup device: assign new group without removing it from the first one
5633 LeAudioClient::Get()->GroupAddNode(group_id0, test_address1);
5634 SyncOnMainLoop();
5635 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5636
5637 dev1_storage_group = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
5638
5639 // Verify regrouping results
5640 EXPECT_EQ(dev1_new_group, group_id0);
5641 EXPECT_EQ(dev1_new_group, dev1_storage_group);
5642 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 0u);
5643 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 2u);
5644 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id0);
5645 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
5646 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
5647 }
5648
TEST_F(UnicastTest,RemoveTwoEarbudsCsisGrouped)5649 TEST_F(UnicastTest, RemoveTwoEarbudsCsisGrouped) {
5650 uint8_t group_size = 2;
5651 int group_id0 = 2;
5652 int group_id1 = 3;
5653
5654 // Report working CSIS
5655 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
5656
5657 // First group - First earbud
5658 const RawAddress test_address0 = GetTestAddress(0);
5659 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
5660 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
5661 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id0, 1 /* rank*/);
5662
5663 // First group - Second earbud
5664 const RawAddress test_address1 = GetTestAddress(1);
5665 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
5666 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
5667 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id0, 2 /* rank*/,
5668 true /*connect_through_csis*/);
5669
5670 // Second group - First earbud
5671 const RawAddress test_address2 = GetTestAddress(2);
5672 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address2, true)).Times(1);
5673 ConnectCsisDevice(test_address2, 3 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
5674 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id1, 1 /* rank*/);
5675
5676 // Second group - Second earbud
5677 const RawAddress test_address3 = GetTestAddress(3);
5678 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address3, true)).Times(1);
5679 ConnectCsisDevice(test_address3, 4 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
5680 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id1, 2 /* rank*/,
5681 true /*connect_through_csis*/);
5682
5683 // First group - verify grouping information
5684 std::vector<RawAddress> group0_devs = LeAudioClient::Get()->GetGroupDevices(group_id0);
5685 ASSERT_NE(std::find(group0_devs.begin(), group0_devs.end(), test_address0), group0_devs.end());
5686 ASSERT_NE(std::find(group0_devs.begin(), group0_devs.end(), test_address1), group0_devs.end());
5687
5688 // Second group - verify grouping information
5689 std::vector<RawAddress> group1_devs = LeAudioClient::Get()->GetGroupDevices(group_id1);
5690 ASSERT_NE(std::find(group1_devs.begin(), group1_devs.end(), test_address2), group1_devs.end());
5691 ASSERT_NE(std::find(group1_devs.begin(), group1_devs.end(), test_address3), group1_devs.end());
5692 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5693
5694 // Expect one of the groups to be dropped and devices to be disconnected
5695 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id0)).Times(1);
5696 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id0)).Times(1);
5697 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5698 OnGroupNodeStatus(test_address0, group_id0, GroupNodeStatus::REMOVED));
5699 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5700 OnGroupNodeStatus(test_address1, group_id0, GroupNodeStatus::REMOVED));
5701 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5702 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5703 .Times(1);
5704 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5705 OnConnectionState(ConnectionState::DISCONNECTED, test_address1))
5706 .Times(1);
5707
5708 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
5709 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(2, _)).Times(1);
5710
5711 // Expect the other groups to be left as is
5712 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id1, _)).Times(0);
5713 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5714 OnConnectionState(ConnectionState::DISCONNECTED, test_address2))
5715 .Times(0);
5716 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5717 OnConnectionState(ConnectionState::DISCONNECTED, test_address3))
5718 .Times(0);
5719
5720 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(3, _)).Times(0);
5721 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(4, _)).Times(0);
5722
5723 do_in_main_thread(base::BindOnce(&LeAudioClient::GroupDestroy,
5724 base::Unretained(LeAudioClient::Get()), group_id0));
5725
5726 SyncOnMainLoop();
5727 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5728 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
5729 }
5730
TEST_F(UnicastTest,ConnectAfterRemove)5731 TEST_F(UnicastTest, ConnectAfterRemove) {
5732 const RawAddress test_address0 = GetTestAddress(0);
5733 int group_id = bluetooth::groups::kGroupUnknown;
5734 uint16_t conn_id = 1;
5735
5736 SetSampleDatabaseEarbudsValid(
5737 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5738 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5739 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5740 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5741 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5742 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5743 .Times(1);
5744
5745 /* RemoveDevice */
5746 do_in_main_thread(base::BindOnce(
5747 [](LeAudioClient* client, const RawAddress& test_address0) {
5748 client->RemoveDevice(test_address0);
5749 },
5750 LeAudioClient::Get(), test_address0));
5751 SyncOnMainLoop();
5752
5753 ON_CALL(mock_btm_interface_, IsDeviceBonded(_, _)).WillByDefault(DoAll(Return(false)));
5754
5755 do_in_main_thread(base::BindOnce(&LeAudioClient::Connect, base::Unretained(LeAudioClient::Get()),
5756 test_address0));
5757 SyncOnMainLoop();
5758
5759 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5760 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5761 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5762 }
5763
TEST_F(UnicastTest,RemoveDeviceWhenConnected)5764 TEST_F(UnicastTest, RemoveDeviceWhenConnected) {
5765 const RawAddress test_address0 = GetTestAddress(0);
5766 int group_id = bluetooth::groups::kGroupUnknown;
5767 uint16_t conn_id = 1;
5768
5769 SetSampleDatabaseEarbudsValid(
5770 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5771 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5772 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5773 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5774 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5775 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5776 .Times(1);
5777 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5778 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5779 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5780 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
5781 ConnectLeAudio(test_address0);
5782 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5783
5784 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5785 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5786
5787 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(1);
5788 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5789 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
5790
5791 /*
5792 * StopStream will put calls on main_loop so to keep the correct order
5793 * of operations and to avoid races we put the test command on main_loop as
5794 * well.
5795 */
5796 do_in_main_thread(base::BindOnce(
5797 [](LeAudioClient* client, const RawAddress& test_address0) {
5798 client->RemoveDevice(test_address0);
5799 },
5800 LeAudioClient::Get(), test_address0));
5801 SyncOnMainLoop();
5802
5803 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5804 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5805 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5806 }
5807
TEST_F(UnicastTest,RemoveDeviceWhenUserConnecting)5808 TEST_F(UnicastTest, RemoveDeviceWhenUserConnecting) {
5809 const RawAddress test_address0 = GetTestAddress(0);
5810 uint16_t conn_id = 1;
5811
5812 /* Prepare mock to not inject connect event so the device can stay in
5813 * CONNECTING state*/
5814 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
5815 .WillByDefault(DoAll(Return()));
5816
5817 SetSampleDatabaseEarbudsValid(
5818 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5819 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5820 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5821 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5822 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5823 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5824 .Times(0);
5825 ConnectLeAudio(test_address0, true, false);
5826
5827 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5828
5829 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
5830 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
5831 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5832
5833 /*
5834 * StopStream will put calls on main_loop so to keep the correct order
5835 * of operations and to avoid races we put the test command on main_loop as
5836 * well.
5837 */
5838 do_in_main_thread(base::BindOnce(
5839 [](LeAudioClient* client, const RawAddress& test_address0) {
5840 client->RemoveDevice(test_address0);
5841 },
5842 LeAudioClient::Get(), test_address0));
5843
5844 SyncOnMainLoop();
5845
5846 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5847 }
5848
TEST_F(UnicastTest,RemoveDeviceWhenAutoConnectingWithTargetedAnnouncements)5849 TEST_F(UnicastTest, RemoveDeviceWhenAutoConnectingWithTargetedAnnouncements) {
5850 const RawAddress test_address0 = GetTestAddress(0);
5851 uint16_t conn_id = 1;
5852
5853 /* Scenario
5854 * 1. Connect device
5855 * 2. Disconnect by remote device -> this shall start Reconnection Using TA
5856 * 3. Remove device
5857 */
5858 SetSampleDatabaseEarbudsValid(
5859 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5860 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5861 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5862 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5863
5864 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5865 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5866 .Times(1);
5867 ConnectLeAudio(test_address0, true);
5868
5869 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5870 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5871
5872 EXPECT_CALL(mock_gatt_interface_,
5873 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
5874 .Times(1);
5875
5876 // Inject disconnected event, Reconnect with TA shall start
5877 InjectDisconnectedEvent(conn_id);
5878 SyncOnMainLoop();
5879 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5880
5881 // Remove device when being in auto connect state.
5882 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
5883 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
5884 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5885
5886 do_in_main_thread(base::BindOnce(
5887 [](LeAudioClient* client, const RawAddress& test_address0) {
5888 client->RemoveDevice(test_address0);
5889 },
5890 LeAudioClient::Get(), test_address0));
5891
5892 SyncOnMainLoop();
5893
5894 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5895 }
5896
TEST_F(UnicastTest,RemoveDeviceWhenAutoConnectingAfterConnectionTimeout)5897 TEST_F(UnicastTest, RemoveDeviceWhenAutoConnectingAfterConnectionTimeout) {
5898 const RawAddress test_address0 = GetTestAddress(0);
5899 uint16_t conn_id = 1;
5900
5901 /* Scenario
5902 * 1. Connect device
5903 * 2. Disconnect remote device with connection timeout -> this shall start direct connect
5904 * 3. Remove device
5905 */
5906 SetSampleDatabaseEarbudsValid(
5907 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5908 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5909 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5910 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5911
5912 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5913 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5914 .Times(1);
5915 ConnectLeAudio(test_address0, true);
5916
5917 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5918 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5919
5920 // Prepare mock for direct connect and inject connection timeout
5921 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
5922 .WillByDefault(DoAll(Return()));
5923 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
5924 .Times(1);
5925
5926 InjectDisconnectedEvent(conn_id, GATT_CONN_TIMEOUT);
5927 SyncOnMainLoop();
5928 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5929
5930 // Remove device when being in auto connect state after connection timeout
5931 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
5932 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
5933 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5934
5935 do_in_main_thread(base::BindOnce(
5936 [](LeAudioClient* client, const RawAddress& test_address0) {
5937 client->RemoveDevice(test_address0);
5938 },
5939 LeAudioClient::Get(), test_address0));
5940
5941 SyncOnMainLoop();
5942
5943 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5944 }
5945
TEST_F(UnicastTest,RemoveDeviceWhenGettingConnectionReady)5946 TEST_F(UnicastTest, RemoveDeviceWhenGettingConnectionReady) {
5947 const RawAddress test_address0 = GetTestAddress(0);
5948 uint16_t conn_id = 1;
5949
5950 /* Prepare mock to not inject Service Search Complete*/
5951 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _)).WillByDefault(DoAll(Return()));
5952
5953 SetSampleDatabaseEarbudsValid(
5954 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5955 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5956 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5957 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5958 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5959 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5960 .Times(0);
5961 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(0);
5962 ConnectLeAudio(test_address0);
5963
5964 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5965 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5966
5967 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5968 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
5969
5970 /* Cancel should be called in RemoveDevice */
5971 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
5972 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5973
5974 /*
5975 * StopStream will put calls on main_loop so to keep the correct order
5976 * of operations and to avoid races we put the test command on main_loop as
5977 * well.
5978 */
5979 do_in_main_thread(base::BindOnce(
5980 [](LeAudioClient* client, const RawAddress& test_address0) {
5981 client->RemoveDevice(test_address0);
5982 },
5983 LeAudioClient::Get(), test_address0));
5984
5985 SyncOnMainLoop();
5986
5987 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5988 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5989 }
5990
TEST_F(UnicastTest,DisconnectDeviceWhenConnected)5991 TEST_F(UnicastTest, DisconnectDeviceWhenConnected) {
5992 const RawAddress test_address0 = GetTestAddress(0);
5993 int group_id = bluetooth::groups::kGroupUnknown;
5994 uint16_t conn_id = 1;
5995
5996 SetSampleDatabaseEarbudsValid(
5997 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5998 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5999 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6000 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6001 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6002 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6003 .Times(1);
6004 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6005 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6006 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6007 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
6008 ConnectLeAudio(test_address0);
6009 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6010
6011 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
6012 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6013
6014 /* for Target announcements AutoConnect is always there, until
6015 * device is removed
6016 */
6017 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(0);
6018 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
6019 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
6020
6021 LeAudioClient::Get()->Disconnect(test_address0);
6022 SyncOnMainLoop();
6023
6024 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
6025 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
6026 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
6027 }
6028
TEST_F(UnicastTest,DisconnectDeviceWhenConnecting)6029 TEST_F(UnicastTest, DisconnectDeviceWhenConnecting) {
6030 const RawAddress test_address0 = GetTestAddress(0);
6031 uint16_t conn_id = 1;
6032
6033 /* Prepare mock to not inject connect event so the device can stay in
6034 * CONNECTING state*/
6035 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
6036 .WillByDefault(DoAll(Return()));
6037
6038 SetSampleDatabaseEarbudsValid(
6039 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6040 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6041 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6042 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6043 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6044 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6045 .Times(0);
6046 ConnectLeAudio(test_address0, true, false);
6047
6048 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6049
6050 /* Prepare on call mock on Close - to not trigger Inject Disconnection, as it
6051 * is done in default mock.
6052 */
6053 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
6054 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
6055 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
6056
6057 LeAudioClient::Get()->Disconnect(test_address0);
6058 SyncOnMainLoop();
6059
6060 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
6061 }
6062
TEST_F(UnicastTest,DisconnectDeviceWhenGettingConnectionReady)6063 TEST_F(UnicastTest, DisconnectDeviceWhenGettingConnectionReady) {
6064 const RawAddress test_address0 = GetTestAddress(0);
6065 uint16_t conn_id = global_conn_id;
6066
6067 /* Prepare mock to not inject Service Search Complete*/
6068 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _)).WillByDefault(DoAll(Return()));
6069
6070 SetSampleDatabaseEarbudsValid(
6071 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6072 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6073 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6074 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6075 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6076 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6077 .Times(0);
6078 ConnectLeAudio(test_address0);
6079
6080 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6081 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
6082
6083 /* TA reconnect is enabled in ConnectLeAudio. Make sure this is not removed */
6084 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
6085 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
6086 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(0);
6087 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
6088
6089 LeAudioClient::Get()->Disconnect(test_address0);
6090 SyncOnMainLoop();
6091
6092 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
6093 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
6094 }
6095
TEST_F(UnicastTest,RemoveWhileStreaming)6096 TEST_F(UnicastTest, RemoveWhileStreaming) {
6097 const RawAddress test_address0 = GetTestAddress(0);
6098 int group_id = bluetooth::groups::kGroupUnknown;
6099
6100 SetSampleDatabaseEarbudsValid(
6101 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6102 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6103 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6104 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6105 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6106 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6107 .Times(1);
6108 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6109 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6110 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6111
6112 ConnectLeAudio(test_address0);
6113 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6114
6115 // Start streaming
6116 constexpr uint8_t cis_count_out = 1;
6117 constexpr uint8_t cis_count_in = 0;
6118
6119 constexpr int gmcs_ccid = 1;
6120 constexpr int gtbs_ccid = 2;
6121
6122 // Audio sessions are started only when device gets active
6123 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6124 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6125 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
6126 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
6127 LeAudioClient::Get()->GroupSetActive(group_id);
6128 SyncOnMainLoop();
6129
6130 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
6131 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
6132
6133 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6134
6135 SyncOnMainLoop();
6136 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6137 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6138 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6139 SyncOnMainLoop();
6140
6141 // Verify Data transfer on one audio source cis
6142 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6143
6144 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id)).Times(1);
6145
6146 LeAudioDeviceGroup* group = nullptr;
6147 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
6148 .WillOnce(DoAll(SaveArg<0>(&group)));
6149 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6150 OnGroupNodeStatus(test_address0, group_id, GroupNodeStatus::REMOVED));
6151
6152 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6153 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
6154 .Times(1);
6155
6156 /*
6157 * StopStream will put calls on main_loop so to keep the correct order
6158 * of operations and to avoid races we put the test command on main_loop as
6159 * well.
6160 */
6161 do_in_main_thread(base::BindOnce(
6162 [](LeAudioClient* client, const RawAddress& test_address0) {
6163 client->RemoveDevice(test_address0);
6164 },
6165 LeAudioClient::Get(), test_address0));
6166
6167 SyncOnMainLoop();
6168 Mock::VerifyAndClearExpectations(&mock_groups_module_);
6169 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6170 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6171
6172 ASSERT_EQ(group, nullptr);
6173 }
6174
TEST_F(UnicastTest,DisconnecteWhileAlmostStreaming)6175 TEST_F(UnicastTest, DisconnecteWhileAlmostStreaming) {
6176 const RawAddress test_address0 = GetTestAddress(0);
6177 int group_id = bluetooth::groups::kGroupUnknown;
6178
6179 SetSampleDatabaseEarbudsValid(
6180 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6181 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6182 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6183 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6184 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6185 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6186 .Times(1);
6187 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6188 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6189 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6190
6191 ConnectLeAudio(test_address0);
6192 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6193
6194 constexpr int gmcs_ccid = 1;
6195 constexpr int gtbs_ccid = 2;
6196
6197 // Audio sessions are started only when device gets active
6198 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6199 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6200 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
6201 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
6202 LeAudioClient::Get()->GroupSetActive(group_id);
6203 SyncOnMainLoop();
6204
6205 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
6206 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
6207
6208 /* We want here to CIS be established but device not being yet in streaming
6209 * state
6210 */
6211 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6212
6213 SyncOnMainLoop();
6214 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6215 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6216 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6217 SyncOnMainLoop();
6218
6219 /* This is test code, which will change the group state to the one which
6220 * is required by test
6221 */
6222 ASSERT_NE(0lu, streaming_groups.count(group_id));
6223 auto group_inject = streaming_groups.at(group_id);
6224 group_inject->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING);
6225
6226 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
6227
6228 LeAudioDeviceGroup* group = nullptr;
6229 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
6230 .WillOnce(DoAll(SaveArg<0>(&group)));
6231
6232 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6233 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
6234 .Times(1);
6235
6236 /*
6237 * StopStream will put calls on main_loop so to keep the correct order
6238 * of operations and to avoid races we put the test command on main_loop as
6239 * well.
6240 */
6241 do_in_main_thread(
6242 base::BindOnce([](LeAudioClient* client,
6243 const RawAddress& test_address0) { client->Disconnect(test_address0); },
6244 LeAudioClient::Get(), test_address0));
6245
6246 SyncOnMainLoop();
6247 Mock::VerifyAndClearExpectations(&mock_groups_module_);
6248 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6249 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6250
6251 ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
6252 }
6253
TEST_F(UnicastTest,DisconnecteWhileAlmostStreaming_twoDevices)6254 TEST_F(UnicastTest, DisconnecteWhileAlmostStreaming_twoDevices) {
6255 const RawAddress test_address0 = GetTestAddress(0);
6256 const RawAddress test_address1 = GetTestAddress(1);
6257 int group_id = 5;
6258
6259 TestSetupRemoteDevices(group_id);
6260 SyncOnMainLoop();
6261
6262 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
6263
6264 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6265
6266 SyncOnMainLoop();
6267 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6268 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6269 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6270 SyncOnMainLoop();
6271
6272 ASSERT_NE(0lu, streaming_groups.count(group_id));
6273 auto group_inject = streaming_groups.at(group_id);
6274
6275 // This shall be called once only when first device from the group is disconnecting.
6276 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
6277
6278 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnConnectionState(ConnectionState::DISCONNECTED, _))
6279 .Times(0);
6280
6281 // Do not got to IDLE state imidiatelly.
6282 stay_at_releasing_stop_stream = true;
6283
6284 log::info("First of all disconnect: {}", test_address0);
6285 TriggerDisconnectionFromApp(test_address0);
6286 SyncOnMainLoop();
6287
6288 log::info("Secondly disconnect: {}", test_address1);
6289 TriggerDisconnectionFromApp(test_address1);
6290 SyncOnMainLoop();
6291
6292 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6293 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6294
6295 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6296 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
6297 .Times(1);
6298 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6299 OnConnectionState(ConnectionState::DISCONNECTED, test_address1))
6300 .Times(1);
6301
6302 do_in_main_thread(base::BindOnce(
6303 [](bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* cb, int group_id) {
6304 cb->StatusReportCb(group_id, GroupStreamStatus::IDLE);
6305 },
6306 state_machine_callbacks_, group_id));
6307 SyncOnMainLoop();
6308 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6309 }
6310
TEST_F(UnicastTest,EarbudsTwsStyleStreaming)6311 TEST_F(UnicastTest, EarbudsTwsStyleStreaming) {
6312 const RawAddress test_address0 = GetTestAddress(0);
6313 int group_id = bluetooth::groups::kGroupUnknown;
6314
6315 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6316 codec_spec_conf::kLeAudioLocationStereo, 0x01, 0x01,
6317 codec_spec_caps::kLeAudioSamplingFreq16000Hz, false /*add_csis*/,
6318 true /*add_cas*/, true /*add_pacs*/, 2 /*add_asc_cnt*/,
6319 1 /*set_size*/, 0 /*rank*/);
6320 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6321 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6322 .Times(1);
6323 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6324 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6325 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6326
6327 log::info("Connect device");
6328 ConnectLeAudio(test_address0);
6329 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6330
6331 // Expected CIS count on streaming
6332 uint8_t cis_count_out = 2;
6333 uint8_t cis_count_in = 0;
6334
6335 log::info("Group is getting Active");
6336 // Audio sessions are started only when device gets active
6337 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6338 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6339 LeAudioClient::Get()->GroupSetActive(group_id);
6340 SyncOnMainLoop();
6341
6342 log::info("Start stream");
6343 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6344
6345 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6346 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6347 SyncOnMainLoop();
6348
6349 log::info("Verify Data transfer on one audio source cis");
6350 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6351
6352 log::info("Suspend");
6353 EXPECT_CALL(mock_state_machine_, SuspendStream(_)).Times(1);
6354 LeAudioClient::Get()->GroupSuspend(group_id);
6355 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6356 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6357
6358 log::info("Resume");
6359 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6360 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6361 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6362
6363 log::info("Stop");
6364 StopStreaming(group_id);
6365 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6366
6367 // Release
6368 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6369 EXPECT_CALL(*mock_codec_manager_,
6370 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6371 mock_le_audio_sink_hal_client_, false))
6372 .Times(1);
6373
6374 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6375 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6376 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6377 SyncOnMainLoop();
6378 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6379 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6380 }
6381
TEST_F(UnicastTest,SpeakerFailedConversationalStreaming)6382 TEST_F(UnicastTest, SpeakerFailedConversationalStreaming) {
6383 const RawAddress test_address0 = GetTestAddress(0);
6384 int group_id = bluetooth::groups::kGroupUnknown;
6385
6386 available_src_context_types_ = 0;
6387 supported_src_context_types_ =
6388 available_src_context_types_ |
6389 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
6390 available_snk_context_types_ = 0x0004;
6391 supported_snk_context_types_ =
6392 available_snk_context_types_ |
6393 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
6394
6395 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo, 0,
6396 default_channel_cnt, default_channel_cnt, 0x0004,
6397 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
6398 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
6399 0 /*rank*/);
6400 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6401 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6402 .Times(1);
6403 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6404 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6405 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6406
6407 ConnectLeAudio(test_address0);
6408 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6409
6410 // Audio sessions are started only when device gets active
6411 LeAudioClient::Get()->GroupSetActive(group_id);
6412 SyncOnMainLoop();
6413
6414 /* Nothing to do - expect no crash */
6415 }
6416
TEST_F(UnicastTest,SpeakerStreaming)6417 TEST_F(UnicastTest, SpeakerStreaming) {
6418 const RawAddress test_address0 = GetTestAddress(0);
6419 int group_id = bluetooth::groups::kGroupUnknown;
6420
6421 SetSampleDatabaseEarbudsValid(
6422 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6423 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6424 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6425 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6426 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6427 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6428 .Times(1);
6429 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6430 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6431 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6432
6433 ConnectLeAudio(test_address0);
6434 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6435
6436 // Start streaming
6437 uint8_t cis_count_out = 1;
6438 uint8_t cis_count_in = 0;
6439
6440 // Audio sessions are started only when device gets active
6441 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6442 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6443 LeAudioClient::Get()->GroupSetActive(group_id);
6444 SyncOnMainLoop();
6445
6446 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6447
6448 SyncOnMainLoop();
6449 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6450 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6451
6452 // Verify Data transfer on one audio source cis
6453 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6454
6455 // Suspend
6456 /*TODO Need a way to verify STOP */
6457 LeAudioClient::Get()->GroupSuspend(group_id);
6458 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6459 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6460
6461 // Resume
6462 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6463 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6464 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6465
6466 // Stop
6467 StopStreaming(group_id);
6468 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6469
6470 // Release
6471 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6472
6473 EXPECT_CALL(*mock_codec_manager_,
6474 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6475 mock_le_audio_sink_hal_client_, false))
6476 .Times(1);
6477
6478 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6479 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6480 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6481 SyncOnMainLoop();
6482 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6483 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6484 }
6485
TEST_F(UnicastTest,SpeakerStreamingNonDefault)6486 TEST_F(UnicastTest, SpeakerStreamingNonDefault) {
6487 const RawAddress test_address0 = GetTestAddress(0);
6488 int group_id = bluetooth::groups::kGroupUnknown;
6489
6490 /**
6491 * Scenario test steps
6492 * 1. Set group active and stream VOICEASSISTANT
6493 * 2. Suspend group and resume with VOICEASSISTANT
6494 * 3. Stop Stream and make group inactive
6495 * 4. Start stream without setting metadata.
6496 * 5. Verify that UNSPECIFIED context type is used.
6497 */
6498
6499 available_snk_context_types_ =
6500 (types::LeAudioContextType::VOICEASSISTANTS | types::LeAudioContextType::MEDIA |
6501 types::LeAudioContextType::UNSPECIFIED)
6502 .value();
6503 supported_snk_context_types_ = available_snk_context_types_;
6504
6505 SetSampleDatabaseEarbudsValid(
6506 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6507 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6508 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6509 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6510 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6511 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6512 .Times(1);
6513 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6514 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6515 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6516
6517 ConnectLeAudio(test_address0);
6518 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6519
6520 // Start streaming
6521 uint8_t cis_count_out = 1;
6522 uint8_t cis_count_in = 0;
6523
6524 // Audio sessions are started only when device gets active
6525 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6526 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6527 LeAudioClient::Get()->GroupSetActive(group_id);
6528 SyncOnMainLoop();
6529
6530 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6531
6532 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6533 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6534 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6535 SyncOnMainLoop();
6536
6537 // Verify Data transfer on one audio source cis
6538 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6539
6540 // Suspend
6541 /*TODO Need a way to verify STOP */
6542 LeAudioClient::Get()->GroupSuspend(group_id);
6543 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6544 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6545
6546 // Resume
6547 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6548 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6549 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6550
6551 // Stop
6552 StopStreaming(group_id);
6553 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6554
6555 // Release
6556 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6557 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6558 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6559 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6560 SyncOnMainLoop();
6561 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6562
6563 /* When session is closed, the hal client mocks are freed - get new ones */
6564 SetUpMockAudioHal();
6565 /* Expect the previous release to clear the old audio session metadata */
6566 LeAudioClient::Get()->GroupSetActive(group_id);
6567 SyncOnMainLoop();
6568 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, _, _))
6569 .Times(0);
6570 EXPECT_CALL(mock_state_machine_, StartStream(_, kLeAudioDefaultConfigurationContext, _, _))
6571 .Times(1);
6572 LocalAudioSourceResume();
6573 }
6574
TEST_F(UnicastTest,TestUnidirectionalGameAndLiveRecording)6575 TEST_F(UnicastTest, TestUnidirectionalGameAndLiveRecording) {
6576 const RawAddress test_address0 = GetTestAddress(0);
6577 int group_id = bluetooth::groups::kGroupUnknown;
6578
6579 /**
6580 * Scenario test steps
6581 * 1. Configure group to support GAME only on SINK
6582 * 2. Configure group to support LIVE
6583 * 3. Start recording with LIVE
6584 * 4. Update context type with GAME
6585 * 5. Verify that Configuration did not changed.
6586 */
6587
6588 available_snk_context_types_ =
6589 (types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA |
6590 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::LIVE)
6591 .value();
6592 supported_snk_context_types_ = available_snk_context_types_;
6593
6594 available_src_context_types_ =
6595 (types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED).value();
6596 supported_src_context_types_ = available_src_context_types_;
6597
6598 default_channel_cnt = 1;
6599
6600 SetSampleDatabaseEarbudsValid(
6601 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6602 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6603 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6604 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6605 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6606 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6607 .Times(1);
6608 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6609 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6610 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6611
6612 types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
6613 .sink = types::AudioContexts(types::LeAudioContextType::LIVE),
6614 .source = types::AudioContexts(types::LeAudioContextType::LIVE)};
6615 EXPECT_CALL(mock_state_machine_,
6616 StartStream(_, types::LeAudioContextType::LIVE, metadata_contexts, _))
6617 .Times(1);
6618
6619 log::info("Connecting LeAudio to {}", test_address0);
6620 ConnectLeAudio(test_address0);
6621 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6622
6623 // Audio sessions are started only when device gets active
6624 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6625 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6626
6627 EXPECT_CALL(*mock_codec_manager_,
6628 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6629 mock_le_audio_sink_hal_client_, true))
6630 .Times(1);
6631
6632 LeAudioClient::Get()->GroupSetActive(group_id);
6633 SyncOnMainLoop();
6634
6635 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
6636 LocalAudioSinkResume();
6637 SyncOnMainLoop();
6638
6639 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6640 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6641 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6642 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6643 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6644 SyncOnMainLoop();
6645
6646 // We do expect only unidirectional CIS
6647 uint8_t cis_count_out = 0;
6648 uint8_t cis_count_in = 1;
6649
6650 // Verify Data transfer on one local audio source cis
6651 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
6652 SyncOnMainLoop();
6653
6654 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
6655 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN);
6656 LocalAudioSourceResume();
6657 SyncOnMainLoop();
6658 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6659 }
6660
TEST_F(UnicastTest,TestUnidirectionalGameAndLiveRecordingMicOnlyDev)6661 TEST_F(UnicastTest, TestUnidirectionalGameAndLiveRecordingMicOnlyDev) {
6662 const RawAddress test_address0 = GetTestAddress(0);
6663 int group_id = bluetooth::groups::kGroupUnknown;
6664
6665 /**
6666 * Scenario test steps
6667 * 1. Configure group to support GAME | LIVE | CONVERSATIONAL | VOICEASSISTANTS only on Source
6668 * 2. Start a GAME
6669 * 3. Start recording during the GAME
6670 */
6671
6672 // No sink at all
6673 available_snk_context_types_ = 0;
6674 supported_snk_context_types_ = 0;
6675
6676 // Source available for
6677 available_src_context_types_ =
6678 (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::GAME |
6679 types::LeAudioContextType::LIVE | types::LeAudioContextType::VOICEASSISTANTS |
6680 types::LeAudioContextType::UNSPECIFIED)
6681 .value();
6682 supported_src_context_types_ = available_src_context_types_;
6683
6684 // Setup a single mic-only device
6685 empty_sink_pack_ = true;
6686 default_channel_cnt = 1;
6687 SampleDatabaseParameters db_params{
6688 .conn_id = 1,
6689 .addr = test_address0,
6690 .sink_audio_allocation = std::nullopt,
6691 .source_audio_allocation = codec_spec_conf::kLeAudioLocationMonoAudio,
6692 .sink_channel_cnt = 0,
6693 .source_channel_cnt = default_channel_cnt,
6694 .sample_freq_mask = le_audio::codec_spec_caps::kLeAudioSamplingFreq32000Hz,
6695 .add_csis = false,
6696 .add_cas = false,
6697 .add_pacs = true,
6698 .add_ascs_cnt = 1,
6699 .set_size = 0,
6700 .rank = 0,
6701 .gatt_status = GATT_SUCCESS,
6702 .max_supported_codec_frames_per_sdu = 1,
6703 };
6704 SetSampleDatabaseEarbudsValid(db_params);
6705
6706 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6707 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6708 .Times(1);
6709 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6710 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6711 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6712
6713 types::BidirectionalPair<types::AudioContexts> expected_metadata_contexts = {
6714 .sink = types::AudioContexts(),
6715 .source = types::AudioContexts(types::LeAudioContextType::GAME)};
6716 EXPECT_CALL(mock_state_machine_,
6717 StartStream(_, types::LeAudioContextType::GAME, expected_metadata_contexts, _))
6718 .Times(1);
6719
6720 log::info("Connecting LeAudio to {}", test_address0);
6721 ConnectLeAudio(test_address0);
6722 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6723
6724 // Both audio sessions are always started to monitor the metadata (even for mic only devices)
6725 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6726 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6727
6728 EXPECT_CALL(*mock_codec_manager_,
6729 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6730 mock_le_audio_sink_hal_client_, true))
6731 .Times(1);
6732
6733 LeAudioClient::Get()->GroupSetActive(group_id);
6734 SyncOnMainLoop();
6735
6736 // Configure a bidirectional GAME scenario (on a mic-only device)
6737 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN);
6738 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
6739 LocalAudioSinkResume();
6740 SyncOnMainLoop();
6741
6742 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6743 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6744 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6745 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6746 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6747 SyncOnMainLoop();
6748
6749 // We do expect only unidirectional CIS
6750 uint8_t cis_count_out = 0;
6751 uint8_t cis_count_in = 1;
6752
6753 // Verify Data transfer on one local audio sink
6754 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
6755 SyncOnMainLoop();
6756
6757 // Expect no reconfiguration triggered by the GAME updates
6758 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
6759 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN);
6760 LocalAudioSinkSuspend();
6761 SyncOnMainLoop();
6762 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6763 }
6764
TEST_F(UnicastTest,TestUnidirectionalVoiceAssistant_Sink)6765 TEST_F(UnicastTest, TestUnidirectionalVoiceAssistant_Sink) {
6766 const RawAddress test_address0 = GetTestAddress(0);
6767 int group_id = bluetooth::groups::kGroupUnknown;
6768
6769 /**
6770 * Scenario test steps
6771 * 1. Configure group to support VOICEASSISTANT only on SINK
6772 * 2. Start stream
6773 * 5. Verify that Unidirectional VOICEASSISTANT has been created
6774 */
6775
6776 available_snk_context_types_ =
6777 (types::LeAudioContextType::VOICEASSISTANTS | types::LeAudioContextType::MEDIA |
6778 types::LeAudioContextType::UNSPECIFIED)
6779 .value();
6780 supported_snk_context_types_ = available_snk_context_types_;
6781
6782 available_src_context_types_ =
6783 (types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED).value();
6784 supported_src_context_types_ = available_src_context_types_;
6785
6786 SetSampleDatabaseEarbudsValid(
6787 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6788 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6789 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6790 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6791 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6792 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6793 .Times(1);
6794 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6795 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6796 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6797
6798 types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
6799 .sink = types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS),
6800 .source = types::AudioContexts()};
6801 EXPECT_CALL(mock_state_machine_,
6802 StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, metadata_contexts, _))
6803 .Times(1);
6804
6805 log::info("Connecting LeAudio to {}", test_address0);
6806 ConnectLeAudio(test_address0);
6807 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6808
6809 // We do expect only unidirectional CIS
6810 uint8_t cis_count_out = 1;
6811 uint8_t cis_count_in = 0;
6812
6813 // Audio sessions are started only when device gets active
6814 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6815 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6816
6817 EXPECT_CALL(*mock_codec_manager_,
6818 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6819 mock_le_audio_sink_hal_client_, true))
6820 .Times(1);
6821
6822 LeAudioClient::Get()->GroupSetActive(group_id);
6823 SyncOnMainLoop();
6824
6825 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6826
6827 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6828 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6829 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6830 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6831 SyncOnMainLoop();
6832
6833 // Verify Data transfer on one local audio source cis
6834 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6835 SyncOnMainLoop();
6836 }
6837
TEST_F(UnicastTest,TestUnidirectionalVoiceAssistant_Source)6838 TEST_F(UnicastTest, TestUnidirectionalVoiceAssistant_Source) {
6839 const RawAddress test_address0 = GetTestAddress(0);
6840 int group_id = bluetooth::groups::kGroupUnknown;
6841
6842 /**
6843 * Scenario test steps
6844 * 1. Configure group to support VOICEASSISTANT only on SOURCE
6845 * 2. Start stream
6846 * 5. Verify that uni-direction VOICEASSISTANT has been created
6847 */
6848
6849 available_snk_context_types_ =
6850 (types::LeAudioContextType::MEDIA | types::LeAudioContextType::UNSPECIFIED).value();
6851 supported_snk_context_types_ = available_snk_context_types_;
6852
6853 available_src_context_types_ =
6854 (types::LeAudioContextType::VOICEASSISTANTS | types::LeAudioContextType::LIVE |
6855 types::LeAudioContextType::UNSPECIFIED)
6856 .value();
6857 supported_src_context_types_ = available_src_context_types_;
6858
6859 SetSampleDatabaseEarbudsValid(
6860 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeftOfCenter,
6861 codec_spec_conf::kLeAudioLocationFrontLeftOfCenter, default_channel_cnt,
6862 default_channel_cnt, 0x0004,
6863 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6864 default_ase_cnt /*add_ascs_cnt*/, 2 /*set_size*/, 1 /*rank*/);
6865 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6866 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6867 .Times(1);
6868 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6869 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6870 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6871
6872 types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
6873 .sink = types::AudioContexts(),
6874 .source = types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS)};
6875 EXPECT_CALL(mock_state_machine_,
6876 StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, metadata_contexts, _))
6877 .Times(1);
6878
6879 log::info("Connecting LeAudio device {}", test_address0);
6880
6881 ConnectLeAudio(test_address0);
6882 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6883
6884 // Expected only unidirectional CIS
6885 uint8_t cis_count_out = 0;
6886 uint8_t cis_count_in = 1;
6887
6888 // Audio sessions are started only when device gets active
6889 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6890 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6891 LeAudioClient::Get()->GroupSetActive(group_id);
6892 SyncOnMainLoop();
6893
6894 UpdateLocalSinkMetadata(AUDIO_SOURCE_VOICE_RECOGNITION);
6895 LocalAudioSinkResume();
6896
6897 // Verify Data transfer on one local audio source cis
6898 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6899
6900 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6901 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6902 SyncOnMainLoop();
6903 }
6904
TEST_F(UnicastTest,SpeakerStreamingAutonomousRelease)6905 TEST_F(UnicastTest, SpeakerStreamingAutonomousRelease) {
6906 const RawAddress test_address0 = GetTestAddress(0);
6907 int group_id = bluetooth::groups::kGroupUnknown;
6908
6909 SetSampleDatabaseEarbudsValid(
6910 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6911 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6912 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6913 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6914 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6915 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6916 .Times(1);
6917 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6918 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6919 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6920
6921 ConnectLeAudio(test_address0);
6922 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6923
6924 // Start streaming
6925 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6926 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6927 LeAudioClient::Get()->GroupSetActive(group_id);
6928 SyncOnMainLoop();
6929
6930 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6931
6932 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6933 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6934 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6935 SyncOnMainLoop();
6936
6937 // Verify Data transfer on one audio source cis
6938 TestAudioDataTransfer(group_id, 1 /* cis_count_out */, 0 /* cis_count_in */, 1920);
6939
6940 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, GroupStatus::INACTIVE))
6941 .Times(1);
6942 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6943 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
6944 .Times(1);
6945
6946 // Inject the IDLE state as if an autonomous release happened
6947 ASSERT_NE(0lu, streaming_groups.count(group_id));
6948 auto group = streaming_groups.at(group_id);
6949 ASSERT_NE(group, nullptr);
6950 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
6951 device = group->GetNextDevice(device)) {
6952 for (auto& ase : device->ases_) {
6953 ase.cis_state = types::CisState::IDLE;
6954 ase.data_path_state = types::DataPathState::IDLE;
6955 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
6956 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
6957 }
6958 }
6959 // Verify no Data transfer after the autonomous release
6960 TestAudioDataTransfer(group_id, 0 /* cis_count_out */, 0 /* cis_count_in */, 1920);
6961
6962 // Inject Releasing
6963 state_machine_callbacks_->StatusReportCb(group->group_id_,
6964 GroupStreamStatus::RELEASING_AUTONOMOUS);
6965 SyncOnMainLoop();
6966 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6967 }
6968
TEST_F(UnicastTest,TwoEarbudsStreaming)6969 TEST_F(UnicastTest, TwoEarbudsStreaming) {
6970 uint8_t group_size = 2;
6971 int group_id = 2;
6972
6973 // Report working CSIS
6974 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
6975 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6976 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
6977
6978 // First earbud
6979 const RawAddress test_address0 = GetTestAddress(0);
6980 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
6981 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
6982 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
6983
6984 // Second earbud
6985 const RawAddress test_address1 = GetTestAddress(1);
6986 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
6987 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
6988 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
6989 true /*connect_through_csis*/);
6990
6991 // Start streaming
6992 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6993 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6994 LeAudioClient::Get()->GroupSetActive(group_id);
6995 SyncOnMainLoop();
6996
6997 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6998
6999 /* Make sure configurations are non empty */
7000 btle_audio_codec_config_t call_config = {.codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7001 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
7002 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7003 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7004 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7005 .octets_per_frame = 80};
7006
7007 EXPECT_CALL(mock_audio_hal_client_callbacks_,
7008 OnAudioGroupCurrentCodecConf(group_id, call_config, call_config))
7009 .Times(1);
7010
7011 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
7012
7013 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7014 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7015 SyncOnMainLoop();
7016
7017 // Verify Data transfer on two peer sinks and one source
7018 uint8_t cis_count_out = 2;
7019 uint8_t cis_count_in = 2;
7020 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
7021
7022 // Suspend
7023 LeAudioClient::Get()->GroupSuspend(group_id);
7024 SyncOnMainLoop();
7025
7026 // Resume
7027 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
7028 SyncOnMainLoop();
7029 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7030
7031 // Verify Data transfer still works
7032 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
7033
7034 ASSERT_NE(0lu, streaming_groups.count(group_id));
7035 auto group = streaming_groups.at(group_id);
7036
7037 // Stop
7038 StopStreaming(group_id, true);
7039 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7040
7041 // Check if cache configuration is still present
7042 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
7043 ->confs.get(le_audio::types::kLeAudioDirectionSink)
7044 .size());
7045 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
7046 ->confs.get(le_audio::types::kLeAudioDirectionSource)
7047 .size());
7048
7049 // Release
7050 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
7051 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
7052 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
7053 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
7054 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
7055 SyncOnMainLoop();
7056
7057 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7058
7059 // Setting group inactive, shall not change cached configuration
7060 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
7061 ->confs.get(le_audio::types::kLeAudioDirectionSink)
7062 .size());
7063 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
7064 ->confs.get(le_audio::types::kLeAudioDirectionSource)
7065 .size());
7066 }
7067
TEST_F(UnicastTest,TestSetValidSingleOutputPreferredCodecConfig)7068 TEST_F(UnicastTest, TestSetValidSingleOutputPreferredCodecConfig) {
7069 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7070
7071 btle_audio_codec_config_t preferred_output_codec_config = {
7072 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7073 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7074 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7075 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7076 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7077 .octets_per_frame = 60};
7078 // We did not set input preferred codec config
7079 btle_audio_codec_config_t empty_input_codec_config;
7080
7081 int group_id = 2;
7082 TestSetupRemoteDevices(group_id);
7083 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7084 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
7085 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7086
7087 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7088 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7089 false);
7090 do_in_main_thread(base::BindOnce(&LeAudioClient::SetCodecConfigPreference,
7091 base::Unretained(LeAudioClient::Get()), group_id,
7092 empty_input_codec_config, preferred_output_codec_config));
7093 SyncOnMainLoop();
7094 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7095 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7096 true);
7097 // We only set output preferred codec config so bidirectional context would
7098 // use default config
7099 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7100 group_id, static_cast<int>(types::LeAudioContextType::CONVERSATIONAL)),
7101 false);
7102 }
7103
TEST_F(UnicastTest,TestSetPreferredCodecConfigToNonActiveGroup)7104 TEST_F(UnicastTest, TestSetPreferredCodecConfigToNonActiveGroup) {
7105 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7106
7107 int group_id = 2;
7108 TestSetupRemoteDevices(group_id);
7109 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7110 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7111 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7112 false);
7113
7114 // Inactivate group 2
7115 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
7116
7117 btle_audio_codec_config_t preferred_codec_config = {
7118 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7119 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7120 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7121 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7122 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7123 .octets_per_frame = 40};
7124
7125 // Re-initialize mock for destroyed hal client
7126 RegisterSourceHalClientMock();
7127 RegisterSinkHalClientMock();
7128
7129 // Reconfiguration not needed as set preferred config to non active group
7130 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
7131 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0);
7132
7133 do_in_main_thread(base::BindOnce(&LeAudioClient::SetCodecConfigPreference,
7134 base::Unretained(LeAudioClient::Get()), group_id,
7135 preferred_codec_config, preferred_codec_config));
7136 SyncOnMainLoop();
7137
7138 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7139 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7140 true);
7141 Mock::VerifyAndClearExpectations(&mock_state_machine_);
7142 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
7143
7144 // Activate group 2 again
7145 do_in_main_thread(base::BindOnce(&LeAudioClient::GroupSetActive,
7146 base::Unretained(LeAudioClient::Get()), group_id));
7147 SyncOnMainLoop();
7148
7149 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
7150 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7151 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7152 true);
7153 }
7154
TEST_F(UnicastTest,TwoEarbudsClearPreferenceBeforeMedia)7155 TEST_F(UnicastTest, TwoEarbudsClearPreferenceBeforeMedia) {
7156 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7157
7158 int group_id = 2;
7159 TestSetupRemoteDevices(group_id);
7160
7161 btle_audio_codec_config_t preferred_codec_config_before_media = {.codec_priority = -1};
7162
7163 bool set_before_media = true;
7164 bool set_while_media = false;
7165 bool is_using_set_before_media_codec_during_media = false;
7166 bool is_using_set_while_media_codec_during_media = false;
7167 // Use legacy codec and should not reconfig while streaming
7168 bool is_reconfig = false;
7169 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7170 group_id, set_before_media, set_while_media,
7171 is_using_set_before_media_codec_during_media,
7172 is_using_set_while_media_codec_during_media, is_reconfig);
7173 }
7174
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessBeforeMedia)7175 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessBeforeMedia) {
7176 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7177
7178 int group_id = 2;
7179 TestSetupRemoteDevices(group_id);
7180
7181 // This codec can be used by media
7182 btle_audio_codec_config_t preferred_codec_config_before_media = {
7183 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7184 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7185 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7186 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7187 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7188 .octets_per_frame = 40};
7189
7190 bool set_before_media = true;
7191 bool set_while_media = false;
7192 bool is_using_set_before_media_codec_during_media = true;
7193 bool is_using_set_while_media_codec_during_media = false;
7194 // Use preferred codec and should not reconfig while streaming
7195 bool is_reconfig = false;
7196 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7197 group_id, set_before_media, set_while_media,
7198 is_using_set_before_media_codec_during_media,
7199 is_using_set_while_media_codec_during_media, is_reconfig);
7200 }
7201
TEST_F(UnicastTest,TwoEarbudsSetPreferenceFailBeforeMedia)7202 TEST_F(UnicastTest, TwoEarbudsSetPreferenceFailBeforeMedia) {
7203 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7204
7205 int group_id = 2;
7206 TestSetupRemoteDevices(group_id);
7207
7208 // This codec can not be used by media
7209 btle_audio_codec_config_t preferred_codec_config_before_media = {
7210 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7211 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7212 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7213 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7214 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7215 .octets_per_frame = 70};
7216
7217 bool set_before_media = true;
7218 bool set_while_media = false;
7219 bool is_using_set_before_media_codec_during_media = false;
7220 bool is_using_set_while_media_codec_during_media = false;
7221 // Use legacy codec and should not reconfig while streaming
7222 bool is_reconfig = false;
7223 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7224 group_id, set_before_media, set_while_media,
7225 is_using_set_before_media_codec_during_media,
7226 is_using_set_while_media_codec_during_media, is_reconfig);
7227 }
7228
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessDuringMediaWithReconfig)7229 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessDuringMediaWithReconfig) {
7230 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7231
7232 int group_id = 2;
7233 TestSetupRemoteDevices(group_id);
7234
7235 // This codec can be used by media
7236 btle_audio_codec_config_t preferred_codec_config_during_media = {
7237 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7238 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7239 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7240 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7241 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7242 .octets_per_frame = 60};
7243
7244 bool set_before_media = false;
7245 bool set_while_media = true;
7246 bool is_using_set_before_media_codec_during_media = false;
7247 bool is_using_set_while_media_codec_during_media = true;
7248 // Should reconfig and use preferred codec while streaming
7249 bool is_reconfig = true;
7250 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
7251 group_id, set_before_media, set_while_media,
7252 is_using_set_before_media_codec_during_media,
7253 is_using_set_while_media_codec_during_media, is_reconfig);
7254 }
7255
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessDuringMediaWithoutReconfig)7256 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessDuringMediaWithoutReconfig) {
7257 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7258
7259 int group_id = 2;
7260 TestSetupRemoteDevices(group_id);
7261
7262 // This codec can be used by media
7263 btle_audio_codec_config_t preferred_codec_config_during_media = {
7264 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7265 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
7266 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7267 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7268 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7269 .octets_per_frame = 120};
7270
7271 bool set_before_media = false;
7272 bool set_while_media = true;
7273 bool is_using_set_before_media_codec_during_media = false;
7274 bool is_using_set_while_media_codec_during_media = true;
7275 // Use preferred codec but not reconfig while streaming since same codec with
7276 // original
7277 bool is_reconfig = false;
7278 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
7279 group_id, set_before_media, set_while_media,
7280 is_using_set_before_media_codec_during_media,
7281 is_using_set_while_media_codec_during_media, is_reconfig);
7282 }
7283
TEST_F(UnicastTest,TwoEarbudsSetPreferenceFailDuringMediaWithoutReconfig)7284 TEST_F(UnicastTest, TwoEarbudsSetPreferenceFailDuringMediaWithoutReconfig) {
7285 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7286
7287 int group_id = 2;
7288 TestSetupRemoteDevices(group_id);
7289
7290 // This codec can not be used by media
7291 btle_audio_codec_config_t preferred_codec_config_during_media = {
7292 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7293 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7294 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7295 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7296 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7297 .octets_per_frame = 70};
7298
7299 bool set_before_media = false;
7300 bool set_while_media = true;
7301 bool is_using_set_before_media_codec_during_media = false;
7302 bool is_using_set_while_media_codec_during_media = false;
7303 // Use original codec and should not reconfig while streaming
7304 bool is_reconfig = false;
7305 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
7306 group_id, set_before_media, set_while_media,
7307 is_using_set_before_media_codec_during_media,
7308 is_using_set_while_media_codec_during_media, is_reconfig);
7309 }
7310
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeMediaClearPreferenceDuringMediaWithReconfig)7311 TEST_F(UnicastTest,
7312 TwoEarbudsSetPreferenceSucessBeforeMediaClearPreferenceDuringMediaWithReconfig) {
7313 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7314
7315 int group_id = 2;
7316 TestSetupRemoteDevices(group_id);
7317
7318 // This codec can be used by media
7319 btle_audio_codec_config_t preferred_codec_config_before_media = {
7320 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7321 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7322 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7323 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7324 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7325 .octets_per_frame = 40};
7326 btle_audio_codec_config_t preferred_codec_config_during_media = {.codec_priority = -1};
7327
7328 bool set_before_media = true;
7329 bool set_while_media = true;
7330 bool is_using_set_before_media_codec_during_media = true;
7331 bool is_using_set_while_media_codec_during_media = false;
7332 // Should reconfig to legacy codec while streaming as we clear preferred codec
7333 bool is_reconfig = true;
7334 TestSetCodecPreference(&preferred_codec_config_before_media, &preferred_codec_config_during_media,
7335 LeAudioContextType::MEDIA, group_id, set_before_media, set_while_media,
7336 is_using_set_before_media_codec_during_media,
7337 is_using_set_while_media_codec_during_media, is_reconfig);
7338 }
7339
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceSuccessDuringMediaWithReconfig)7340 TEST_F(UnicastTest,
7341 TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceSuccessDuringMediaWithReconfig) {
7342 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7343
7344 int group_id = 2;
7345 TestSetupRemoteDevices(group_id);
7346
7347 // This codec can be used by media
7348 btle_audio_codec_config_t preferred_codec_config_before_media = {
7349 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7350 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7351 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7352 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7353 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7354 .octets_per_frame = 40};
7355 // This codec can be used by media
7356 btle_audio_codec_config_t preferred_codec_config_during_media = {
7357 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7358 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7359 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7360 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7361 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7362 .octets_per_frame = 60};
7363
7364 bool set_before_media = true;
7365 bool set_while_media = true;
7366 bool is_using_set_before_media_codec_during_media = true;
7367 bool is_using_set_while_media_codec_during_media = true;
7368 // Should reconfig to new preferred codec from old preferred codec while streaming
7369 bool is_reconfig = true;
7370 TestSetCodecPreference(&preferred_codec_config_before_media, &preferred_codec_config_during_media,
7371 LeAudioContextType::MEDIA, group_id, set_before_media, set_while_media,
7372 is_using_set_before_media_codec_during_media,
7373 is_using_set_while_media_codec_during_media, is_reconfig);
7374 }
7375
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceSuccessDuringMediaWithoutReconfig)7376 TEST_F(UnicastTest,
7377 TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceSuccessDuringMediaWithoutReconfig) {
7378 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7379
7380 int group_id = 2;
7381 TestSetupRemoteDevices(group_id);
7382
7383 // This codec can be used by media
7384 btle_audio_codec_config_t preferred_codec_config_before_media = {
7385 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7386 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7387 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7388 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7389 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7390 .octets_per_frame = 40};
7391 // This codec can be used by media
7392 btle_audio_codec_config_t preferred_codec_config_during_media = {
7393 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7394 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7395 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7396 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7397 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7398 .octets_per_frame = 40};
7399
7400 bool set_before_media = true;
7401 bool set_while_media = true;
7402 bool is_using_set_before_media_codec_during_media = true;
7403 bool is_using_set_while_media_codec_during_media = true;
7404 // Should not reconfig while streaming because same as previous preferred codec
7405 bool is_reconfig = false;
7406 TestSetCodecPreference(&preferred_codec_config_before_media, &preferred_codec_config_during_media,
7407 LeAudioContextType::MEDIA, group_id, set_before_media, set_while_media,
7408 is_using_set_before_media_codec_during_media,
7409 is_using_set_while_media_codec_during_media, is_reconfig);
7410 }
7411
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceFailDuringMediaWithReconfig)7412 TEST_F(UnicastTest,
7413 TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceFailDuringMediaWithReconfig) {
7414 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7415
7416 int group_id = 2;
7417 TestSetupRemoteDevices(group_id);
7418
7419 // This codec can be used by media
7420 btle_audio_codec_config_t preferred_codec_config_before_media = {
7421 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7422 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7423 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7424 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7425 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7426 .octets_per_frame = 40};
7427 // This codec can not be used by media
7428 btle_audio_codec_config_t preferred_codec_config_during_media = {
7429 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7430 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7431 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7432 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7433 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7434 .octets_per_frame = 70};
7435
7436 bool set_before_media = true;
7437 bool set_while_media = true;
7438 bool is_using_set_before_media_codec_during_media = true;
7439 bool is_using_set_while_media_codec_during_media = false;
7440 // Should reconfig to legacy codec while streaming because invalid preferred codec
7441 bool is_reconfig = true;
7442 TestSetCodecPreference(&preferred_codec_config_before_media, &preferred_codec_config_during_media,
7443 LeAudioContextType::MEDIA, group_id, set_before_media, set_while_media,
7444 is_using_set_before_media_codec_during_media,
7445 is_using_set_while_media_codec_during_media, is_reconfig);
7446 }
7447
TEST_F(UnicastTest,TwoEarbudsClearPreferenceBeforeConv)7448 TEST_F(UnicastTest, TwoEarbudsClearPreferenceBeforeConv) {
7449 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7450
7451 int group_id = 2;
7452 TestSetupRemoteDevices(group_id);
7453
7454 btle_audio_codec_config_t preferred_codec_config_before_conv = {.codec_priority = -1};
7455
7456 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7457 LeAudioClient::Get()->SetInCall(true);
7458
7459 bool set_before_conv = true;
7460 bool set_while_conv = false;
7461 bool is_using_set_before_conv_codec_during_conv = false;
7462 bool is_using_set_while_conv_codec_during_conv = false;
7463 // Use legacy codec and should not reconfig while streaming
7464 bool is_reconfig = false;
7465 TestSetCodecPreference(&preferred_codec_config_before_conv, nullptr,
7466 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7467 set_while_conv, is_using_set_before_conv_codec_during_conv,
7468 is_using_set_while_conv_codec_during_conv, is_reconfig);
7469 LeAudioClient::Get()->SetInCall(false);
7470 }
7471
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessBeforeConv)7472 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessBeforeConv) {
7473 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7474
7475 int group_id = 2;
7476 TestSetupRemoteDevices(group_id);
7477
7478 // This codec can be used by conv
7479 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7480 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7481 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7482 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7483 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7484 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7485 .octets_per_frame = 40};
7486
7487 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7488 LeAudioClient::Get()->SetInCall(true);
7489
7490 bool set_before_conv = true;
7491 bool set_while_conv = false;
7492 bool is_using_set_before_conv_codec_during_conv = true;
7493 bool is_using_set_while_conv_codec_during_conv = false;
7494 // Use preferred codec and should not reconfig while streaming
7495 bool is_reconfig = false;
7496 TestSetCodecPreference(&preferred_codec_config_before_conv, nullptr,
7497 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7498 set_while_conv, is_using_set_before_conv_codec_during_conv,
7499 is_using_set_while_conv_codec_during_conv, is_reconfig);
7500 LeAudioClient::Get()->SetInCall(false);
7501 }
7502
TEST_F(UnicastTest,TwoEarbudsSetPreferenceFailBeforeConv)7503 TEST_F(UnicastTest, TwoEarbudsSetPreferenceFailBeforeConv) {
7504 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7505
7506 int group_id = 2;
7507 TestSetupRemoteDevices(group_id);
7508
7509 // This codec can not be used by conv
7510 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7511 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7512 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7513 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7514 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7515 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7516 .octets_per_frame = 70};
7517
7518 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7519 LeAudioClient::Get()->SetInCall(true);
7520
7521 bool set_before_conv = true;
7522 bool set_while_conv = false;
7523 bool is_using_set_before_conv_codec_during_conv = false;
7524 bool is_using_set_while_conv_codec_during_conv = false;
7525 // Use legacy codec and should not reconfig while streaming
7526 bool is_reconfig = false;
7527 TestSetCodecPreference(&preferred_codec_config_before_conv, nullptr,
7528 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7529 set_while_conv, is_using_set_before_conv_codec_during_conv,
7530 is_using_set_while_conv_codec_during_conv, is_reconfig);
7531 LeAudioClient::Get()->SetInCall(false);
7532 }
7533
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessDuringConvWithReconfig)7534 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessDuringConvWithReconfig) {
7535 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7536
7537 int group_id = 2;
7538 TestSetupRemoteDevices(group_id);
7539
7540 // This codec can be used by conv
7541 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7542 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7543 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7544 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7545 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7546 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7547 .octets_per_frame = 40};
7548
7549 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7550 LeAudioClient::Get()->SetInCall(true);
7551
7552 bool set_before_conv = false;
7553 bool set_while_conv = true;
7554 bool is_using_set_before_conv_codec_during_conv = false;
7555 bool is_using_set_while_conv_codec_during_conv = true;
7556 // Should reconfig and use preferred codec while streaming
7557 bool is_reconfig = true;
7558 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
7559 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7560 set_while_conv, is_using_set_before_conv_codec_during_conv,
7561 is_using_set_while_conv_codec_during_conv, is_reconfig);
7562 LeAudioClient::Get()->SetInCall(false);
7563 }
7564
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessDuringConvWithoutReconfig)7565 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessDuringConvWithoutReconfig) {
7566 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7567
7568 int group_id = 2;
7569 TestSetupRemoteDevices(group_id);
7570
7571 // This codec can be used by conv
7572 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7573 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7574 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
7575 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7576 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7577 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7578 .octets_per_frame = 80};
7579
7580 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7581 LeAudioClient::Get()->SetInCall(true);
7582
7583 bool set_before_conv = false;
7584 bool set_while_conv = true;
7585 bool is_using_set_before_conv_codec_during_conv = false;
7586 bool is_using_set_while_conv_codec_during_conv = true;
7587 // Use preferred codec but not reconfig while streaming since same codec with
7588 // original
7589 bool is_reconfig = false;
7590 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
7591 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7592 set_while_conv, is_using_set_before_conv_codec_during_conv,
7593 is_using_set_while_conv_codec_during_conv, is_reconfig);
7594 LeAudioClient::Get()->SetInCall(false);
7595 }
7596
TEST_F(UnicastTest,TwoEarbudsSetPreferenceFailDuringConvWithoutReconfig)7597 TEST_F(UnicastTest, TwoEarbudsSetPreferenceFailDuringConvWithoutReconfig) {
7598 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7599
7600 int group_id = 2;
7601 TestSetupRemoteDevices(group_id);
7602
7603 // This codec can not be used by conv
7604 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7605 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7606 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7607 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7608 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7609 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7610 .octets_per_frame = 70};
7611
7612 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7613 LeAudioClient::Get()->SetInCall(true);
7614
7615 bool set_before_conv = false;
7616 bool set_while_conv = true;
7617 bool is_using_set_before_conv_codec_during_conv = false;
7618 bool is_using_set_while_conv_codec_during_conv = false;
7619 // Use original codec and should not reconfig while streaming
7620 bool is_reconfig = false;
7621 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
7622 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7623 set_while_conv, is_using_set_before_conv_codec_during_conv,
7624 is_using_set_while_conv_codec_during_conv, is_reconfig);
7625 LeAudioClient::Get()->SetInCall(false);
7626 }
7627
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeConvClearPreferenceDuringConvWithReconfig)7628 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSucessBeforeConvClearPreferenceDuringConvWithReconfig) {
7629 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7630
7631 int group_id = 2;
7632 TestSetupRemoteDevices(group_id);
7633
7634 // This codec can be used by conv
7635 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7636 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7637 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7638 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7639 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7640 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7641 .octets_per_frame = 40};
7642 btle_audio_codec_config_t preferred_codec_config_during_conv = {.codec_priority = -1};
7643
7644 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7645 LeAudioClient::Get()->SetInCall(true);
7646
7647 bool set_before_conv = true;
7648 bool set_while_conv = true;
7649 bool is_using_set_before_conv_codec_during_conv = true;
7650 bool is_using_set_while_conv_codec_during_conv = false;
7651 // Should reconfig to legacy codec while streaming as we clear preferred codec
7652 bool is_reconfig = true;
7653 TestSetCodecPreference(&preferred_codec_config_before_conv, &preferred_codec_config_during_conv,
7654 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7655 set_while_conv, is_using_set_before_conv_codec_during_conv,
7656 is_using_set_while_conv_codec_during_conv, is_reconfig);
7657 LeAudioClient::Get()->SetInCall(false);
7658 }
7659
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceSuccessDuringConvWithReconfig)7660 TEST_F(UnicastTest,
7661 TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceSuccessDuringConvWithReconfig) {
7662 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7663
7664 int group_id = 2;
7665 TestSetupRemoteDevices(group_id);
7666
7667 // This codec can be used by conv
7668 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7669 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7670 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7671 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7672 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7673 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7674 .octets_per_frame = 40};
7675 // This codec can be used by conv
7676 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7677 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7678 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
7679 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7680 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7681 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7682 .octets_per_frame = 80};
7683
7684 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7685 LeAudioClient::Get()->SetInCall(true);
7686
7687 bool set_before_conv = true;
7688 bool set_while_conv = true;
7689 bool is_using_set_before_conv_codec_during_conv = true;
7690 bool is_using_set_while_conv_codec_during_conv = true;
7691 // Should reconfig to new preferred codec from old preferred codec while
7692 // streaming
7693 bool is_reconfig = true;
7694 TestSetCodecPreference(&preferred_codec_config_before_conv, &preferred_codec_config_during_conv,
7695 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7696 set_while_conv, is_using_set_before_conv_codec_during_conv,
7697 is_using_set_while_conv_codec_during_conv, is_reconfig);
7698 LeAudioClient::Get()->SetInCall(false);
7699 }
7700
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceSuccessDuringConvWithoutReconfig)7701 TEST_F(UnicastTest,
7702 TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceSuccessDuringConvWithoutReconfig) {
7703 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7704
7705 int group_id = 2;
7706 TestSetupRemoteDevices(group_id);
7707
7708 // This codec can be used by conv
7709 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7710 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7711 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7712 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7713 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7714 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7715 .octets_per_frame = 40};
7716 // This codec can be used by conv
7717 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7718 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7719 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7720 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7721 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7722 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7723 .octets_per_frame = 40};
7724
7725 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7726 LeAudioClient::Get()->SetInCall(true);
7727
7728 bool set_before_conv = true;
7729 bool set_while_conv = true;
7730 bool is_using_set_before_conv_codec_during_conv = true;
7731 bool is_using_set_while_conv_codec_during_conv = true;
7732 // Should not reconfig while streaming because same as previous preferred
7733 // codec
7734 bool is_reconfig = false;
7735 TestSetCodecPreference(&preferred_codec_config_before_conv, &preferred_codec_config_during_conv,
7736 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7737 set_while_conv, is_using_set_before_conv_codec_during_conv,
7738 is_using_set_while_conv_codec_during_conv, is_reconfig);
7739 LeAudioClient::Get()->SetInCall(false);
7740 }
7741
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceFailDuringConvWithReconfig)7742 TEST_F(UnicastTest,
7743 TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceFailDuringConvWithReconfig) {
7744 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7745
7746 int group_id = 2;
7747 TestSetupRemoteDevices(group_id);
7748
7749 // This codec can be used by conv
7750 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7751 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7752 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7753 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7754 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7755 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7756 .octets_per_frame = 40};
7757 // This codec can not be used by conv
7758 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7759 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7760 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7761 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7762 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7763 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7764 .octets_per_frame = 70};
7765
7766 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7767 LeAudioClient::Get()->SetInCall(true);
7768
7769 bool set_before_conv = true;
7770 bool set_while_conv = true;
7771 bool is_using_set_before_conv_codec_during_conv = true;
7772 bool is_using_set_while_conv_codec_during_conv = false;
7773 // Should reconfig to legacy codec while streaming because invalid preferred
7774 // codec
7775 bool is_reconfig = true;
7776 TestSetCodecPreference(&preferred_codec_config_before_conv, &preferred_codec_config_during_conv,
7777 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7778 set_while_conv, is_using_set_before_conv_codec_during_conv,
7779 is_using_set_while_conv_codec_during_conv, is_reconfig);
7780 LeAudioClient::Get()->SetInCall(false);
7781 }
7782
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenIdleForBothMediaAndConv)7783 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenIdleForBothMediaAndConv) {
7784 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7785
7786 int group_id = 2;
7787 TestSetupRemoteDevices(group_id);
7788
7789 // This codec can be used by media and conv
7790 btle_audio_codec_config_t preferred_codec_config_before_media = {
7791 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7792 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7793 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7794 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7795 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7796 .octets_per_frame = 40};
7797
7798 bool set_before_media = true;
7799 bool set_while_media = false;
7800 bool is_using_set_before_media_codec_during_media = true;
7801 bool is_using_set_while_media_codec_during_media = false;
7802 bool is_reconfig = false;
7803 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7804 group_id, set_before_media, set_while_media,
7805 is_using_set_before_media_codec_during_media,
7806 is_using_set_while_media_codec_during_media, is_reconfig);
7807
7808 // simulate suspend timeout passed, alarm executing
7809 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7810 SyncOnMainLoop();
7811
7812 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7813 LeAudioClient::Get()->SetInCall(true);
7814
7815 bool set_before_conv = false;
7816 bool set_while_conv = false;
7817 bool is_using_set_before_conv_codec_during_conv = true;
7818 bool is_using_set_while_conv_codec_during_conv = false;
7819 is_reconfig = false;
7820 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7821 set_before_conv, set_while_conv,
7822 is_using_set_before_conv_codec_during_conv,
7823 is_using_set_while_conv_codec_during_conv, is_reconfig);
7824 LeAudioClient::Get()->SetInCall(false);
7825
7826 // should use preferred codec when switching back to media
7827 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7828 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7829 true);
7830 }
7831
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenIdleForMediaNotForConv)7832 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenIdleForMediaNotForConv) {
7833 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7834
7835 int group_id = 2;
7836 TestSetupRemoteDevices(group_id);
7837
7838 // This codec can be used by media but not by conv
7839 btle_audio_codec_config_t preferred_codec_config_before_media = {
7840 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7841 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7842 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7843 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7844 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7845 .octets_per_frame = 60};
7846
7847 bool set_before_media = true;
7848 bool set_while_media = false;
7849 bool is_using_set_before_media_codec_during_media = true;
7850 bool is_using_set_while_media_codec_during_media = false;
7851 bool is_reconfig = false;
7852 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7853 group_id, set_before_media, set_while_media,
7854 is_using_set_before_media_codec_during_media,
7855 is_using_set_while_media_codec_during_media, is_reconfig);
7856
7857 // simulate suspend timeout passed, alarm executing
7858 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7859 SyncOnMainLoop();
7860
7861 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7862 LeAudioClient::Get()->SetInCall(true);
7863
7864 bool set_before_conv = false;
7865 bool set_while_conv = false;
7866 bool is_using_set_before_conv_codec_during_conv = false;
7867 bool is_using_set_while_conv_codec_during_conv = false;
7868 is_reconfig = false;
7869 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7870 set_before_conv, set_while_conv,
7871 is_using_set_before_conv_codec_during_conv,
7872 is_using_set_while_conv_codec_during_conv, is_reconfig);
7873 LeAudioClient::Get()->SetInCall(false);
7874
7875 // should use preferred codec when switching back to media
7876 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7877 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7878 true);
7879 }
7880
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenIdleNotForMediaForConv)7881 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenIdleNotForMediaForConv) {
7882 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7883
7884 int group_id = 2;
7885 TestSetupRemoteDevices(group_id);
7886
7887 // This codec can not be used by media but by conv
7888 btle_audio_codec_config_t preferred_codec_config_before_media = {
7889 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7890 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
7891 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7892 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7893 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7894 .octets_per_frame = 80};
7895
7896 bool set_before_media = true;
7897 bool set_while_media = false;
7898 bool is_using_set_before_media_codec_during_media = false;
7899 bool is_using_set_while_media_codec_during_media = false;
7900 bool is_reconfig = false;
7901 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7902 group_id, set_before_media, set_while_media,
7903 is_using_set_before_media_codec_during_media,
7904 is_using_set_while_media_codec_during_media, is_reconfig);
7905
7906 // simulate suspend timeout passed, alarm executing
7907 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7908 SyncOnMainLoop();
7909
7910 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7911 LeAudioClient::Get()->SetInCall(true);
7912
7913 bool set_before_conv = false;
7914 bool set_while_conv = false;
7915 bool is_using_set_before_conv_codec_during_conv = true;
7916 bool is_using_set_while_conv_codec_during_conv = false;
7917 is_reconfig = false;
7918 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7919 set_before_conv, set_while_conv,
7920 is_using_set_before_conv_codec_during_conv,
7921 is_using_set_while_conv_codec_during_conv, is_reconfig);
7922 LeAudioClient::Get()->SetInCall(false);
7923
7924 // should use legacy codec when switching back to media
7925 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7926 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7927 false);
7928 }
7929
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenIdleNotForBothMediaAndConv)7930 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenIdleNotForBothMediaAndConv) {
7931 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7932
7933 int group_id = 2;
7934 TestSetupRemoteDevices(group_id);
7935
7936 // This codec can not be used by media and conv
7937 btle_audio_codec_config_t preferred_codec_config_before_media = {
7938 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7939 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7940 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7941 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7942 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7943 .octets_per_frame = 10};
7944
7945 bool set_before_media = true;
7946 bool set_while_media = false;
7947 bool is_using_set_before_media_codec_during_media = false;
7948 bool is_using_set_while_media_codec_during_media = false;
7949 bool is_reconfig = false;
7950 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7951 group_id, set_before_media, set_while_media,
7952 is_using_set_before_media_codec_during_media,
7953 is_using_set_while_media_codec_during_media, is_reconfig);
7954
7955 // simulate suspend timeout passed, alarm executing
7956 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7957 SyncOnMainLoop();
7958
7959 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7960 LeAudioClient::Get()->SetInCall(true);
7961
7962 bool set_before_conv = false;
7963 bool set_while_conv = false;
7964 bool is_using_set_before_conv_codec_during_conv = false;
7965 bool is_using_set_while_conv_codec_during_conv = false;
7966 is_reconfig = false;
7967 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7968 set_before_conv, set_while_conv,
7969 is_using_set_before_conv_codec_during_conv,
7970 is_using_set_while_conv_codec_during_conv, is_reconfig);
7971 LeAudioClient::Get()->SetInCall(false);
7972
7973 // should use legacy codec when switching back to media
7974 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7975 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7976 false);
7977 }
7978
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenMediaForBothMediaAndConv)7979 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaForBothMediaAndConv) {
7980 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7981
7982 int group_id = 2;
7983 TestSetupRemoteDevices(group_id);
7984
7985 // This codec can be used by media and conv
7986 btle_audio_codec_config_t preferred_codec_config_during_media = {
7987 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7988 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7989 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7990 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7991 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7992 .octets_per_frame = 40};
7993
7994 bool set_before_media = false;
7995 bool set_while_media = true;
7996 bool is_using_set_before_media_codec_during_media = false;
7997 bool is_using_set_while_media_codec_during_media = true;
7998 // should use preferred codec and reconfig
7999 bool is_reconfig = true;
8000 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
8001 group_id, set_before_media, set_while_media,
8002 is_using_set_before_media_codec_during_media,
8003 is_using_set_while_media_codec_during_media, is_reconfig);
8004
8005 log::info("simulate suspend timeout passed, alarm executing");
8006 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8007 SyncOnMainLoop();
8008
8009 log::info("SetInCall is used by GTBS - and only then we can expect CCID to be set.");
8010 LeAudioClient::Get()->SetInCall(true);
8011
8012 bool set_before_conv = false;
8013 bool set_while_conv = false;
8014 bool is_using_set_before_conv_codec_during_conv = true;
8015 bool is_using_set_while_conv_codec_during_conv = false;
8016 is_reconfig = false;
8017 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
8018 set_before_conv, set_while_conv,
8019 is_using_set_before_conv_codec_during_conv,
8020 is_using_set_while_conv_codec_during_conv, is_reconfig);
8021 LeAudioClient::Get()->SetInCall(false);
8022
8023 log::info("should use preferred codec when switching back to media");
8024 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8025 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8026 true);
8027 }
8028
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenMediaForMediaNotForConv)8029 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaForMediaNotForConv) {
8030 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
8031
8032 int group_id = 2;
8033 TestSetupRemoteDevices(group_id);
8034
8035 // This codec can be used by media but not by conv
8036 btle_audio_codec_config_t preferred_codec_config_during_media = {
8037 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8038 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
8039 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8040 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8041 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8042 .octets_per_frame = 60};
8043
8044 bool set_before_media = false;
8045 bool set_while_media = true;
8046 bool is_using_set_before_media_codec_during_media = false;
8047 bool is_using_set_while_media_codec_during_media = true;
8048 // should use preferred codec and reconfig
8049 bool is_reconfig = true;
8050 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
8051 group_id, set_before_media, set_while_media,
8052 is_using_set_before_media_codec_during_media,
8053 is_using_set_while_media_codec_during_media, is_reconfig);
8054
8055 // simulate suspend timeout passed, alarm executing
8056 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8057 SyncOnMainLoop();
8058
8059 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8060 LeAudioClient::Get()->SetInCall(true);
8061
8062 bool set_before_conv = false;
8063 bool set_while_conv = false;
8064 bool is_using_set_before_conv_codec_during_conv = false;
8065 bool is_using_set_while_conv_codec_during_conv = false;
8066 is_reconfig = false;
8067 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
8068 set_before_conv, set_while_conv,
8069 is_using_set_before_conv_codec_during_conv,
8070 is_using_set_while_conv_codec_during_conv, is_reconfig);
8071 LeAudioClient::Get()->SetInCall(false);
8072
8073 // should use preferred codec when switching back to media
8074 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8075 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8076 true);
8077 }
8078
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenMediaNotForMediaForConv)8079 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaNotForMediaForConv) {
8080 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
8081
8082 int group_id = 2;
8083 TestSetupRemoteDevices(group_id);
8084
8085 // This codec can not be used by media and but by conv
8086 btle_audio_codec_config_t preferred_codec_config_during_media = {
8087 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8088 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
8089 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8090 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8091 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8092 .octets_per_frame = 80};
8093
8094 bool set_before_media = false;
8095 bool set_while_media = true;
8096 bool is_using_set_before_media_codec_during_media = false;
8097 bool is_using_set_while_media_codec_during_media = false;
8098 // should use legacy codec
8099 bool is_reconfig = false;
8100 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
8101 group_id, set_before_media, set_while_media,
8102 is_using_set_before_media_codec_during_media,
8103 is_using_set_while_media_codec_during_media, is_reconfig);
8104
8105 // simulate suspend timeout passed, alarm executing
8106 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8107 SyncOnMainLoop();
8108
8109 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8110 LeAudioClient::Get()->SetInCall(true);
8111
8112 bool set_before_conv = false;
8113 bool set_while_conv = false;
8114 bool is_using_set_before_conv_codec_during_conv = true;
8115 bool is_using_set_while_conv_codec_during_conv = false;
8116 is_reconfig = false;
8117 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
8118 set_before_conv, set_while_conv,
8119 is_using_set_before_conv_codec_during_conv,
8120 is_using_set_while_conv_codec_during_conv, is_reconfig);
8121 LeAudioClient::Get()->SetInCall(false);
8122
8123 // should use legacy codec when switching back to media
8124 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8125 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8126 false);
8127 }
8128
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenMediaNotForBothMediaAndConv)8129 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaNotForBothMediaAndConv) {
8130 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
8131
8132 int group_id = 2;
8133 TestSetupRemoteDevices(group_id);
8134
8135 // This codec can not be used by media and conv
8136 btle_audio_codec_config_t preferred_codec_config_during_media = {
8137 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8138 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
8139 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8140 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8141 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8142 .octets_per_frame = 70};
8143
8144 bool set_before_media = false;
8145 bool set_while_media = true;
8146 bool is_using_set_before_media_codec_during_media = false;
8147 bool is_using_set_while_media_codec_during_media = false;
8148 // should use legacy codec
8149 bool is_reconfig = false;
8150 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
8151 group_id, set_before_media, set_while_media,
8152 is_using_set_before_media_codec_during_media,
8153 is_using_set_while_media_codec_during_media, is_reconfig);
8154
8155 // simulate suspend timeout passed, alarm executing
8156 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8157 SyncOnMainLoop();
8158
8159 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8160 LeAudioClient::Get()->SetInCall(true);
8161
8162 bool set_before_conv = false;
8163 bool set_while_conv = false;
8164 bool is_using_set_before_conv_codec_during_conv = false;
8165 bool is_using_set_while_conv_codec_during_conv = false;
8166 is_reconfig = false;
8167 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
8168 set_before_conv, set_while_conv,
8169 is_using_set_before_conv_codec_during_conv,
8170 is_using_set_while_conv_codec_during_conv, is_reconfig);
8171 LeAudioClient::Get()->SetInCall(false);
8172
8173 // should use legacy codec when switching back to media
8174 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8175 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8176 false);
8177 }
8178
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenConvForBothMediaAndConv)8179 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenConvForBothMediaAndConv) {
8180 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
8181
8182 int group_id = 2;
8183 TestSetupRemoteDevices(group_id);
8184
8185 bool set_before_media = false;
8186 bool set_while_media = false;
8187 bool is_using_set_before_media_codec_during_media = false;
8188 bool is_using_set_while_media_codec_during_media = false;
8189 bool is_reconfig = false;
8190 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::MEDIA, group_id, set_before_media,
8191 set_while_media, is_using_set_before_media_codec_during_media,
8192 is_using_set_while_media_codec_during_media, is_reconfig);
8193
8194 // simulate suspend timeout passed, alarm executing
8195 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8196 SyncOnMainLoop();
8197
8198 // This codec can be used by media and conv
8199 btle_audio_codec_config_t preferred_codec_config_during_conv = {
8200 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8201 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
8202 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8203 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8204 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8205 .octets_per_frame = 40};
8206
8207 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8208 LeAudioClient::Get()->SetInCall(true);
8209
8210 bool set_before_conv = false;
8211 bool set_while_conv = true;
8212 bool is_using_set_before_conv_codec_during_conv = false;
8213 bool is_using_set_while_conv_codec_during_conv = true;
8214 // should use preferred codec and reconfig
8215 is_reconfig = true;
8216 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
8217 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
8218 set_while_conv, is_using_set_before_conv_codec_during_conv,
8219 is_using_set_while_conv_codec_during_conv, is_reconfig);
8220 LeAudioClient::Get()->SetInCall(false);
8221
8222 // should use preferred codec when switching back to media
8223 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8224 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8225 true);
8226 }
8227
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenConvForMediaNotForConv)8228 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenConvForMediaNotForConv) {
8229 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
8230
8231 int group_id = 2;
8232 TestSetupRemoteDevices(group_id);
8233
8234 bool set_before_media = false;
8235 bool set_while_media = false;
8236 bool is_using_set_before_media_codec_during_media = false;
8237 bool is_using_set_while_media_codec_during_media = false;
8238 bool is_reconfig = false;
8239 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::MEDIA, group_id, set_before_media,
8240 set_while_media, is_using_set_before_media_codec_during_media,
8241 is_using_set_while_media_codec_during_media, is_reconfig);
8242
8243 // simulate suspend timeout passed, alarm executing
8244 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8245 SyncOnMainLoop();
8246
8247 // This codec can be used by media but not by conv
8248 btle_audio_codec_config_t preferred_codec_config_during_conv = {
8249 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8250 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
8251 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8252 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8253 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8254 .octets_per_frame = 60};
8255
8256 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8257 LeAudioClient::Get()->SetInCall(true);
8258
8259 bool set_before_conv = false;
8260 bool set_while_conv = true;
8261 bool is_using_set_before_conv_codec_during_conv = false;
8262 bool is_using_set_while_conv_codec_during_conv = false;
8263 // should use legacy codec
8264 is_reconfig = false;
8265 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
8266 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
8267 set_while_conv, is_using_set_before_conv_codec_during_conv,
8268 is_using_set_while_conv_codec_during_conv, is_reconfig);
8269 LeAudioClient::Get()->SetInCall(false);
8270
8271 // should use preferred codec when switching back to media
8272 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8273 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8274 true);
8275 }
8276
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenConvNotForMediaForConv)8277 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenConvNotForMediaForConv) {
8278 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
8279
8280 int group_id = 2;
8281 TestSetupRemoteDevices(group_id);
8282
8283 bool set_before_media = false;
8284 bool set_while_media = false;
8285 bool is_using_set_before_media_codec_during_media = false;
8286 bool is_using_set_while_media_codec_during_media = false;
8287 bool is_reconfig = false;
8288 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::MEDIA, group_id, set_before_media,
8289 set_while_media, is_using_set_before_media_codec_during_media,
8290 is_using_set_while_media_codec_during_media, is_reconfig);
8291
8292 // simulate suspend timeout passed, alarm executing
8293 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8294 SyncOnMainLoop();
8295
8296 // This codec can not be used by media but by conv
8297 btle_audio_codec_config_t preferred_codec_config_during_conv = {
8298 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8299 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
8300 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8301 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8302 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8303 .octets_per_frame = 80};
8304
8305 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8306 LeAudioClient::Get()->SetInCall(true);
8307
8308 bool set_before_conv = false;
8309 bool set_while_conv = true;
8310 bool is_using_set_before_conv_codec_during_conv = false;
8311 bool is_using_set_while_conv_codec_during_conv = true;
8312 // should use preferred codec but not reconfig
8313 is_reconfig = false;
8314 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
8315 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
8316 set_while_conv, is_using_set_before_conv_codec_during_conv,
8317 is_using_set_while_conv_codec_during_conv, is_reconfig);
8318 LeAudioClient::Get()->SetInCall(false);
8319
8320 // should use legacy codec when switching back to media
8321 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8322 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8323 false);
8324 }
8325
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenConvNotForBothMediaAndConv)8326 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenConvNotForBothMediaAndConv) {
8327 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
8328
8329 int group_id = 2;
8330 TestSetupRemoteDevices(group_id);
8331
8332 bool set_before_media = false;
8333 bool set_while_media = false;
8334 bool is_using_set_before_media_codec_during_media = false;
8335 bool is_using_set_while_media_codec_during_media = false;
8336 bool is_reconfig = false;
8337 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::MEDIA, group_id, set_before_media,
8338 set_while_media, is_using_set_before_media_codec_during_media,
8339 is_using_set_while_media_codec_during_media, is_reconfig);
8340
8341 // simulate suspend timeout passed, alarm executing
8342 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8343 SyncOnMainLoop();
8344
8345 // This codec can not be used by media and conv
8346 btle_audio_codec_config_t preferred_codec_config_during_conv = {
8347 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8348 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
8349 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8350 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8351 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8352 .octets_per_frame = 70};
8353
8354 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8355 LeAudioClient::Get()->SetInCall(true);
8356
8357 bool set_before_conv = false;
8358 bool set_while_conv = true;
8359 bool is_using_set_before_conv_codec_during_conv = false;
8360 bool is_using_set_while_conv_codec_during_conv = false;
8361 // should use legacy codec
8362 is_reconfig = false;
8363 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
8364 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
8365 set_while_conv, is_using_set_before_conv_codec_during_conv,
8366 is_using_set_while_conv_codec_during_conv, is_reconfig);
8367 LeAudioClient::Get()->SetInCall(false);
8368
8369 // should use legacy codec when switching back to media
8370 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8371 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8372 false);
8373 }
8374
TEST_F(UnicastTest,StreamingVxAospSampleSound)8375 TEST_F(UnicastTest, StreamingVxAospSampleSound) {
8376 uint8_t group_size = 2;
8377 int group_id = 2;
8378
8379 /* Test to verify that tag VX_AOSP_SAMPLESOUND is always mapped to
8380 * LeAudioContextType::SOUNDEFFECTS
8381 */
8382
8383 // Report working CSIS
8384 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8385
8386 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8387 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8388
8389 // First earbud
8390 const RawAddress test_address0 = GetTestAddress(0);
8391 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8392 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8393 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8394
8395 // Second earbud
8396 const RawAddress test_address1 = GetTestAddress(1);
8397 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8398 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8399 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8400 true /*connect_through_csis*/);
8401
8402 // Start streaming
8403 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8404 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8405 LeAudioClient::Get()->GroupSetActive(group_id);
8406 SyncOnMainLoop();
8407
8408 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8409
8410 // Set a test TAG
8411 char test_tag[] = "TEST_TAG2;VX_AOSP_SAMPLESOUND;TEST_TAG1";
8412
8413 test_tags_ptr_ = test_tag;
8414
8415 auto initial_context = types::LeAudioContextType::SOUNDEFFECTS;
8416 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {}, .source = {}};
8417 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, _, ccids)).Times(1);
8418 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8419
8420 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8421 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8422 SyncOnMainLoop();
8423
8424 // Verify Data transfer on two peer sinks and one source
8425 uint8_t cis_count_out = 2;
8426 uint8_t cis_count_in = 0;
8427 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 0);
8428 }
8429
TEST_F(UnicastTest,UpdateActiveAudioConfigForLocalSinkSource)8430 TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSinkSource) {
8431 uint8_t group_size = 2;
8432 int group_id = 2;
8433
8434 // Report working CSIS
8435 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8436
8437 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8438 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8439
8440 // First earbud
8441 const RawAddress test_address0 = GetTestAddress(0);
8442 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8443 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8444 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8445
8446 // Second earbud
8447 const RawAddress test_address1 = GetTestAddress(1);
8448 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8449 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8450 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8451 true /*connect_through_csis*/);
8452
8453 // Set group as active
8454 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8455 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8456 LeAudioClient::Get()->GroupSetActive(group_id);
8457 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8458
8459 // Start streaming - expect HAL being notified by both directions config change
8460 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8461 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8462
8463 /* Expect one update per direction - 2 in total for voice communication usage */
8464 EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
8465 .WillRepeatedly([&](const types::BidirectionalPair<stream_parameters>& stream_params,
8466 std::function<void(const stream_config& config, uint8_t direction)>
8467 update_receiver,
8468 uint8_t directions_to_update) {
8469 bluetooth::le_audio::stream_config unicast_cfg;
8470 if ((directions_to_update & bluetooth::le_audio::types::kLeAudioDirectionSink) &&
8471 stream_params.sink.stream_config.peer_delay_ms != 0) {
8472 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSink);
8473 }
8474 if ((directions_to_update & bluetooth::le_audio::types::kLeAudioDirectionSource) &&
8475 stream_params.source.stream_config.peer_delay_ms != 0) {
8476 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSource);
8477 }
8478 });
8479 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8480
8481 SyncOnMainLoop();
8482 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8483 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8484 Mock::VerifyAndClearExpectations(&mock_codec_manager_);
8485
8486 // Verify Data transfer on two peer sinks and two sources
8487 uint8_t cis_count_out = 2;
8488 uint8_t cis_count_in = 2;
8489 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8490
8491 // Suspend
8492 LeAudioClient::Get()->GroupSuspend(group_id);
8493 SyncOnMainLoop();
8494 }
8495
TEST_F(UnicastTest,UpdateActiveAudioConfigForLocalSinkSourceLateJoin)8496 TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSinkSourceLateJoin) {
8497 uint8_t group_size = 2;
8498 int group_id = 2;
8499
8500 // Report working CSIS
8501 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8502
8503 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8504 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8505
8506 // First earbud
8507 const RawAddress test_address0 = GetTestAddress(0);
8508 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8509 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8510 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8511
8512 // Set group as active
8513 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8514 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8515 LeAudioClient::Get()->GroupSetActive(group_id);
8516 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8517
8518 // Start streaming - expect HAL being notified by both directions config change
8519 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8520 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8521
8522 /* Expect one update per direction - 2 in total for voice communication usage */
8523 EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
8524 .WillRepeatedly([&](const types::BidirectionalPair<stream_parameters>& stream_params,
8525 std::function<void(const stream_config& config, uint8_t direction)>
8526 update_receiver,
8527 uint8_t directions_to_update) {
8528 bluetooth::le_audio::stream_config unicast_cfg;
8529 if ((directions_to_update & bluetooth::le_audio::types::kLeAudioDirectionSink) &&
8530 stream_params.sink.stream_config.peer_delay_ms != 0) {
8531 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSink);
8532 }
8533 if ((directions_to_update & bluetooth::le_audio::types::kLeAudioDirectionSource) &&
8534 stream_params.source.stream_config.peer_delay_ms != 0) {
8535 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSource);
8536 }
8537 });
8538 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8539 SyncOnMainLoop();
8540 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8541 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8542
8543 // Second earbud join should trigger audio config update to HAL
8544 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8545 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8546
8547 const RawAddress test_address1 = GetTestAddress(1);
8548 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8549 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8550 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8551 true /*connect_through_csis*/);
8552
8553 SyncOnMainLoop();
8554 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8555 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8556 Mock::VerifyAndClearExpectations(&mock_codec_manager_);
8557
8558 // Verify Data transfer on two peer sinks and two sources
8559 uint8_t cis_count_out = 2;
8560 uint8_t cis_count_in = 2;
8561 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8562
8563 SyncOnMainLoop();
8564 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8565 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8566
8567 // Second earbud disconnect should trigger audio config update to HAL
8568 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8569 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8570
8571 /* Simulate ASE releasing and CIS Disconnection */
8572 ASSERT_NE(0lu, streaming_groups.count(group_id));
8573 auto group = streaming_groups.at(group_id);
8574 ASSERT_NE(group, nullptr);
8575 auto device = group->GetFirstDevice();
8576 for (auto& ase : device->ases_) {
8577 /* Releasing state */
8578 if (!ase.active) {
8579 continue;
8580 }
8581
8582 std::vector<uint8_t> releasing_state = {
8583 ase.id, static_cast<uint8_t>(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
8584 InjectNotificationEvent(device->address_, device->conn_id_, ase.hdls.val_hdl, releasing_state);
8585 SyncOnMainLoop();
8586 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
8587 SyncOnMainLoop();
8588 }
8589
8590 SyncOnMainLoop();
8591 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8592 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8593 Mock::VerifyAndClearExpectations(&mock_codec_manager_);
8594
8595 // Suspend
8596 LeAudioClient::Get()->GroupSuspend(group_id);
8597 SyncOnMainLoop();
8598 }
8599
TEST_F(UnicastTest,UpdateActiveAudioConfigForLocalSource)8600 TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSource) {
8601 uint8_t group_size = 2;
8602 int group_id = 2;
8603
8604 // Report working CSIS
8605 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8606
8607 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8608 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8609
8610 // First earbud
8611 const RawAddress test_address0 = GetTestAddress(0);
8612 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8613 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8614 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8615
8616 // Second earbud
8617 const RawAddress test_address1 = GetTestAddress(1);
8618 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8619 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8620 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8621 true /*connect_through_csis*/);
8622
8623 // Set group as active
8624 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8625 LeAudioClient::Get()->GroupSetActive(group_id);
8626 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8627
8628 // Start streaming
8629 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8630 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_)).Times(0);
8631 EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
8632 .Times(1)
8633 .WillOnce([](const types::BidirectionalPair<stream_parameters>& stream_params,
8634 std::function<void(const stream_config& config, uint8_t direction)>
8635 update_receiver,
8636 uint8_t directions_to_update) {
8637 bluetooth::le_audio::stream_config unicast_cfg;
8638 if ((directions_to_update & bluetooth::le_audio::types::kLeAudioDirectionSink) &&
8639 stream_params.sink.stream_config.peer_delay_ms != 0) {
8640 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSink);
8641 }
8642 if ((directions_to_update & bluetooth::le_audio::types::kLeAudioDirectionSource) &&
8643 stream_params.source.stream_config.peer_delay_ms != 0) {
8644 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSource);
8645 }
8646 });
8647 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8648
8649 SyncOnMainLoop();
8650 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8651 Mock::VerifyAndClearExpectations(&mock_codec_manager_);
8652
8653 // Verify Data transfer on two peer sinks and no source
8654 uint8_t cis_count_out = 2;
8655 uint8_t cis_count_in = 0;
8656 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8657
8658 // Suspend
8659 LeAudioClient::Get()->GroupSuspend(group_id);
8660 SyncOnMainLoop();
8661 }
8662
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchNoReconfigure)8663 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) {
8664 uint8_t group_size = 2;
8665 int group_id = 2;
8666
8667 // Report working CSIS
8668 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8669
8670 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8671 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8672
8673 // First earbud
8674 const RawAddress test_address0 = GetTestAddress(0);
8675 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8676 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8677 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8678
8679 // Second earbud
8680 const RawAddress test_address1 = GetTestAddress(1);
8681 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8682 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8683 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8684 true /*connect_through_csis*/);
8685
8686 // Start streaming
8687 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8688 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8689 LeAudioClient::Get()->GroupSetActive(group_id);
8690 SyncOnMainLoop();
8691 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8692
8693 // Start streaming with new metadata, there was no previous stream so start
8694 // with this new configuration
8695 auto initial_context = types::LeAudioContextType::NOTIFICATIONS;
8696 types::BidirectionalPair<types::AudioContexts> contexts = {
8697 .sink = types::AudioContexts(initial_context), .source = types::AudioContexts()};
8698 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8699
8700 StartStreaming(AUDIO_USAGE_NOTIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8701
8702 SyncOnMainLoop();
8703 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8704 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8705 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8706
8707 // Do a metadata content switch to ALERTS but stay on previous configuration
8708 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
8709 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
8710 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
8711 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::ALERTS),
8712 .source = types::AudioContexts()};
8713 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8714 UpdateLocalSourceMetadata(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN);
8715
8716 SyncOnMainLoop();
8717 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8718 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8719 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8720
8721 // Do a metadata content switch to EMERGENCY but stay on previous
8722 // configuration
8723 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
8724 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
8725 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
8726
8727 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::EMERGENCYALARM),
8728 .source = types::AudioContexts()};
8729 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8730 UpdateLocalSourceMetadata(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN);
8731
8732 SyncOnMainLoop();
8733 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8734 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8735
8736 // Do a metadata content switch to INSTRUCTIONAL but stay on previous
8737 // configuration
8738 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
8739 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
8740 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
8741 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::INSTRUCTIONAL),
8742 .source = types::AudioContexts()};
8743 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8744 UpdateLocalSourceMetadata(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, AUDIO_CONTENT_TYPE_UNKNOWN);
8745
8746 SyncOnMainLoop();
8747 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8748 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8749 }
8750
TEST_F(UnicastTest,TwoEarbudsStopConversational_StartStreamSonification)8751 TEST_F(UnicastTest, TwoEarbudsStopConversational_StartStreamSonification) {
8752 uint8_t group_size = 2;
8753 int group_id = 2;
8754
8755 // Report working CSIS
8756 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8757
8758 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8759 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8760
8761 // First earbud
8762 const RawAddress test_address0 = GetTestAddress(0);
8763 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8764 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8765 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8766
8767 // Second earbud
8768 const RawAddress test_address1 = GetTestAddress(1);
8769 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8770 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8771 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8772 true /*connect_through_csis*/);
8773
8774 // Start streaming
8775 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8776 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8777 LeAudioClient::Get()->GroupSetActive(group_id);
8778 SyncOnMainLoop();
8779 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8780
8781 // Start streaming with CONVERSATIONAL, there was no previous stream so start
8782 // with this new configuration
8783 auto initial_context = types::LeAudioContextType::CONVERSATIONAL;
8784 types::BidirectionalPair<types::AudioContexts> contexts = {
8785 .sink = types::AudioContexts(initial_context),
8786 .source = types::AudioContexts(initial_context)};
8787 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8788
8789 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8790
8791 SyncOnMainLoop();
8792 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8793 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8794 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8795
8796 // Stop the stream but KEEP cis UP
8797 StopStreaming(group_id, true);
8798 SyncOnMainLoop();
8799 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8800
8801 types::BidirectionalPair<types::AudioContexts> reconfigure_contexts = {
8802 .sink = types::AudioContexts(types::LeAudioContextType::ALERTS),
8803 .source = types::AudioContexts()};
8804
8805 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, reconfigure_contexts, _))
8806 .Times(1);
8807
8808 // Change context type but expect configuration to by as previous
8809 StartStreaming(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8810
8811 SyncOnMainLoop();
8812 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8813
8814 // Stop the stream and drop CISes
8815 StopStreaming(group_id, true);
8816 SyncOnMainLoop();
8817 // simulate suspend timeout passed, alarm executing
8818 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8819 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8820
8821 auto reconfigure_context = types::LeAudioContextType::ALERTS;
8822
8823 EXPECT_CALL(mock_state_machine_, StartStream(_, reconfigure_context, reconfigure_contexts, _))
8824 .Times(1);
8825
8826 // Update metadata
8827 StartStreaming(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8828 SyncOnMainLoop();
8829 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8830 }
8831
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchReconfigure_SpeedUpReconfigFlagEnabled)8832 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure_SpeedUpReconfigFlagEnabled) {
8833 uint8_t group_size = 2;
8834 int group_id = 2;
8835
8836 // Report working CSIS
8837 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8838
8839 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8840 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8841
8842 // First earbud
8843 const RawAddress test_address0 = GetTestAddress(0);
8844 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8845 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8846 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8847
8848 // Second earbud
8849 const RawAddress test_address1 = GetTestAddress(1);
8850 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8851 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8852 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8853 true /*connect_through_csis*/);
8854
8855 constexpr int gmcs_ccid = 1;
8856 constexpr int gtbs_ccid = 2;
8857
8858 log::info("Start streaming MEDIA");
8859 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8860 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8861 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
8862 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
8863 LeAudioClient::Get()->GroupSetActive(group_id);
8864 SyncOnMainLoop();
8865
8866 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
8867 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
8868 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8869
8870 SyncOnMainLoop();
8871 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8872 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8873 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8874
8875 // Verify Data transfer on two peer sinks
8876 uint8_t cis_count_out = 2;
8877 uint8_t cis_count_in = 0;
8878 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8879
8880 log::info("Simulate incoming call");
8881
8882 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
8883 Expectation reconfigure =
8884 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(1);
8885 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
8886 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
8887 .Times(1)
8888 .After(reconfigure);
8889 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1);
8890 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8891 LeAudioClient::Get()->SetInCall(true);
8892 SyncOnMainLoop();
8893 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8894 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8895
8896 // Conversational is a bidirectional scenario so expect GTBS CCID
8897 // in the metadata for both directions. Can be called twice when one
8898 // direction resume after the other and metadata is updated.
8899 ccids = {.sink = {gtbs_ccid}, .source = {gtbs_ccid}};
8900 EXPECT_CALL(mock_state_machine_,
8901 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
8902 .Times(AtLeast(1));
8903 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8904
8905 SyncOnMainLoop();
8906 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8907 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8908
8909 // Verify Data transfer on two peer sinks and one source
8910 cis_count_out = 2;
8911 cis_count_in = 2;
8912 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8913
8914 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8915
8916 // Stop stream will be called by SetInCall
8917 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
8918 reconfigure =
8919 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(1);
8920 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
8921 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
8922 .Times(1)
8923 .After(reconfigure);
8924 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1);
8925
8926 LeAudioClient::Get()->SetInCall(false);
8927 SyncOnMainLoop();
8928
8929 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8930 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8931
8932 log::info("Switch back to media");
8933
8934 ccids = {.sink = {gmcs_ccid}, .source = {}};
8935 types::BidirectionalPair<types::AudioContexts> contexts = {
8936 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
8937 .source = types::AudioContexts()};
8938 EXPECT_CALL(mock_state_machine_,
8939 ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts,
8940 ccids, _))
8941 .Times(0);
8942 EXPECT_CALL(
8943 mock_state_machine_,
8944 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, ccids))
8945 .Times(1);
8946 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID,
8947 false);
8948
8949 SyncOnMainLoop();
8950 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8951 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8952 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8953 }
8954
TEST_F(UnicastTest,TwoEarbudsVoipStreamingVerifyMetadataUpdate)8955 TEST_F(UnicastTest, TwoEarbudsVoipStreamingVerifyMetadataUpdate) {
8956 uint8_t group_size = 2;
8957 int group_id = 2;
8958
8959 /*
8960 * Scenario
8961 * 1. Configure stream for the VOIP
8962 * 2. Verify CONVERSATIONAL metadata and context is used.
8963 * 3. Resume LocalSink
8964 * 4. Make sure there is no change of the metadata and context
8965 */
8966
8967 // Report working CSIS
8968 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8969
8970 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8971 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8972
8973 // First earbud
8974 const RawAddress test_address0 = GetTestAddress(0);
8975 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8976 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8977 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8978
8979 // Second earbud
8980 const RawAddress test_address1 = GetTestAddress(1);
8981 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8982 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8983 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8984 true /*connect_through_csis*/);
8985
8986 constexpr int gtbs_ccid = 2;
8987
8988 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
8989 LeAudioClient::Get()->GroupSetActive(group_id);
8990 SyncOnMainLoop();
8991
8992 // VOIP not using Telecom API has no ccids.
8993 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {}, .source = {}};
8994 EXPECT_CALL(mock_state_machine_,
8995 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
8996 .Times(AtLeast(1));
8997
8998 UpdateLocalSourceMetadata(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH);
8999 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
9000
9001 LocalAudioSourceResume();
9002 SyncOnMainLoop();
9003 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9004
9005 SyncOnMainLoop();
9006 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9007 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9008
9009 // Verify Data transfer are sending. The LocalSink is not yet resumed.
9010 uint8_t cis_count_out = 2;
9011 uint8_t cis_count_in = 0;
9012 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 0);
9013
9014 types::BidirectionalPair<types::AudioContexts> contexts = {
9015 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
9016 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
9017 EXPECT_CALL(mock_state_machine_,
9018 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, contexts, ccids))
9019 .Times(AtLeast(1));
9020
9021 LocalAudioSinkResume();
9022 SyncOnMainLoop();
9023 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9024 }
9025
TEST_F(UnicastTest,TwoEarbudsVoipDuringLiveVerifyMetadataUpdate)9026 TEST_F(UnicastTest, TwoEarbudsVoipDuringLiveVerifyMetadataUpdate) {
9027 uint8_t group_size = 2;
9028 int group_id = 2;
9029
9030 /*
9031 * Scenario
9032 * 1. Configure stream for the mixed CONVERSATIONAL and MEDIA
9033 * 2. Start and Stop streaming
9034 * 3. Update CONVERSATIONAL metadata with additional LIVE usage for the mixed contexts
9035 * 4. Resume LocalSink and LocalSource
9036 * 5. Make sure there is only the leading CONVERSATIONAL context in the metadata and
9037 * LIVE is not mixed in, as the remote devices often are confused when any other
9038 * bidirectional audio context is mixed with CONVERSATIONAL
9039 */
9040
9041 // Report working CSIS
9042 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9043
9044 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9045 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9046
9047 available_snk_context_types_ =
9048 (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::MEDIA |
9049 types::LeAudioContextType::LIVE)
9050 .value();
9051 available_src_context_types_ = available_snk_context_types_;
9052
9053 // First earbud
9054 const RawAddress test_address0 = GetTestAddress(0);
9055 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
9056 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9057 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9058
9059 // Second earbud
9060 const RawAddress test_address1 = GetTestAddress(1);
9061 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
9062 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9063 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9064 true /*connect_through_csis*/);
9065
9066 constexpr int gtbs_ccid = 2;
9067
9068 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
9069 LeAudioClient::Get()->GroupSetActive(group_id);
9070 SyncOnMainLoop();
9071
9072 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9073 StopStreaming(group_id);
9074
9075 // Add LIVE into the mix but expect staying with CONVERSATIONAL for the configuration and the
9076 // metadata
9077 types::BidirectionalPair<types::AudioContexts> meta_contexts = {
9078 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
9079 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
9080 EXPECT_CALL(mock_state_machine_,
9081 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, meta_contexts, _))
9082 .Times(AtLeast(1));
9083
9084 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC, AUDIO_SOURCE_VOICE_COMMUNICATION);
9085 UpdateLocalSourceMetadata(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, false);
9086 SyncOnMainLoop();
9087
9088 LocalAudioSourceResume();
9089 LocalAudioSinkResume();
9090
9091 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9092 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9093 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9094 }
9095
TEST_F(UnicastTest,TwoReconfigureAndVerifyEnableContextType)9096 TEST_F(UnicastTest, TwoReconfigureAndVerifyEnableContextType) {
9097 uint8_t group_size = 2;
9098 int group_id = 2;
9099
9100 /* Scenario
9101 * 1. Earbuds streaming MEDIA
9102 * 2. Reconfigure to VOIP
9103 * 3. Check if Metadata in Enable command are set to CONVERSATIONAL
9104 */
9105
9106 // Report working CSIS
9107 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9108
9109 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9110 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9111
9112 // First earbud
9113 const RawAddress test_address0 = GetTestAddress(0);
9114 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
9115 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9116 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9117
9118 // Second earbud
9119 const RawAddress test_address1 = GetTestAddress(1);
9120 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
9121 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9122 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9123 true /*connect_through_csis*/);
9124
9125 constexpr int gmcs_ccid = 1;
9126 constexpr int gtbs_ccid = 2;
9127
9128 // Start streaming MEDIA
9129 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9130 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9131 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
9132 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
9133 LeAudioClient::Get()->GroupSetActive(group_id);
9134 SyncOnMainLoop();
9135
9136 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
9137 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
9138 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9139
9140 SyncOnMainLoop();
9141 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9142 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9143 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9144
9145 // Verify Data transfer on two peer sinks
9146 uint8_t cis_count_out = 2;
9147 uint8_t cis_count_in = 0;
9148 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9149
9150 // Conversational is a bidirectional scenario so expect GTBS CCID
9151 // in the metadata for both directions. Can be called twice when one
9152 // direction resume after the other and metadata is updated.
9153 ccids = {.sink = {gtbs_ccid}, .source = {gtbs_ccid}};
9154 types::BidirectionalPair<types::AudioContexts> conversiational_contexts = {
9155 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
9156 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
9157
9158 EXPECT_CALL(mock_state_machine_,
9159 ConfigureStream(_, types::LeAudioContextType::CONVERSATIONAL, _, _, _))
9160 .Times(AtLeast(1));
9161
9162 // Update metadata and resume
9163 UpdateLocalSourceMetadata(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, true);
9164 SyncOnMainLoop();
9165
9166 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9167 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9168 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9169
9170 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::CONVERSATIONAL,
9171 conversiational_contexts, ccids))
9172 .Times(AtLeast(1));
9173
9174 LeAudioClient::Get()->SetInCall(true);
9175
9176 LocalAudioSourceResume(true);
9177 SyncOnMainLoop();
9178
9179 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9180 }
9181
TEST_F(UnicastTest,TwoEarbuds2ndLateConnect)9182 TEST_F(UnicastTest, TwoEarbuds2ndLateConnect) {
9183 uint8_t group_size = 2;
9184 int group_id = 2;
9185
9186 // Report working CSIS
9187 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9188
9189 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9190 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9191
9192 const RawAddress test_address0 = GetTestAddress(0);
9193 const RawAddress test_address1 = GetTestAddress(1);
9194
9195 // First earbud
9196 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9197 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9198
9199 // Start streaming
9200 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9201 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9202 LeAudioClient::Get()->GroupSetActive(group_id);
9203 SyncOnMainLoop();
9204
9205 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9206
9207 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9208 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9209 SyncOnMainLoop();
9210
9211 // Expect one iso channel to be fed with data
9212 uint8_t cis_count_out = 1;
9213 uint8_t cis_count_in = 0;
9214 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9215
9216 // Second earbud connects during stream
9217 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9218 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9219 true /*connect_through_csis*/);
9220
9221 cis_count_out = 2;
9222 cis_count_in = 0;
9223
9224 /* The above will trigger reconfiguration. After that Audio Hal action
9225 * is needed to restart the stream */
9226 LocalAudioSourceResume();
9227
9228 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9229 }
9230
TEST_F(UnicastTest,TestStreamingContextTypeBehaviour)9231 TEST_F(UnicastTest, TestStreamingContextTypeBehaviour) {
9232 uint8_t group_size = 2;
9233 int group_id = 2;
9234 int conn_id_1 = 1;
9235 int conn_id_2 = 2;
9236
9237 /* Scenario
9238 * 1. Connect Set of devices with all the context types available
9239 * 2. Create stream for Media
9240 * 3. Remote devices removes all the Available Contexts but UNSPECIFIED
9241 * 4. Verify GetAvailableContexts() returns accepted MEDIA and UNSPECIFIED
9242 */
9243
9244 // Report working CSIS
9245 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9246
9247 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9248 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9249
9250 const RawAddress test_address0 = GetTestAddress(0);
9251 const RawAddress test_address1 = GetTestAddress(1);
9252
9253 // First earbud connects
9254 ConnectCsisDevice(test_address0, conn_id_1, codec_spec_conf::kLeAudioLocationFrontLeft,
9255 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9256
9257 // Second earbud connects
9258 ConnectCsisDevice(test_address1, conn_id_2, codec_spec_conf::kLeAudioLocationFrontRight,
9259 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9260 true /*connect_through_csis*/);
9261
9262 // Start streaming
9263 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9264 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9265 LeAudioClient::Get()->GroupSetActive(group_id);
9266 SyncOnMainLoop();
9267
9268 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
9269 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9270 SyncOnMainLoop();
9271 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9272
9273 auto group = streaming_groups.at(group_id);
9274
9275 /* Simulate available context type being cleared */
9276 InjectAvailableContextTypes(test_address0, conn_id_1,
9277 types::AudioContexts(LeAudioContextType::UNSPECIFIED),
9278 types::AudioContexts(LeAudioContextType::UNSPECIFIED));
9279 InjectAvailableContextTypes(test_address1, conn_id_2,
9280 types::AudioContexts(LeAudioContextType::UNSPECIFIED),
9281 types::AudioContexts(LeAudioContextType::UNSPECIFIED));
9282
9283 auto remote_sink_contexts =
9284 group->GetAvailableContexts(bluetooth::le_audio::types::kLeAudioDirectionSink);
9285 auto remote_source_contexts =
9286 group->GetAvailableContexts(bluetooth::le_audio::types::kLeAudioDirectionSource);
9287 ASSERT_EQ(remote_sink_contexts,
9288 types::AudioContexts(LeAudioContextType::MEDIA | LeAudioContextType::UNSPECIFIED));
9289 ASSERT_EQ(remote_source_contexts, types::AudioContexts(LeAudioContextType::UNSPECIFIED));
9290 }
9291
TEST_F(UnicastTest,LateStreamConnectBasedOnContextType)9292 TEST_F(UnicastTest, LateStreamConnectBasedOnContextType) {
9293 uint8_t group_size = 2;
9294 int group_id = 2;
9295
9296 /* Scenario
9297 * 1. Two devices A and B are connect. Device A has all available context
9298 * types, Device B has no available context types.
9299 * 2. Stream creation to Device A has been started
9300 * 3. Device B notified us with new available Context Types - while A is not
9301 * yet streaming
9302 * 4. Make sure AttachToStream was called for Device B
9303 */
9304
9305 // Report working CSIS
9306 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9307
9308 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9309 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9310
9311 const RawAddress test_address0 = GetTestAddress(0);
9312 const RawAddress test_address1 = GetTestAddress(1);
9313
9314 // First earbud connects
9315 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9316 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9317
9318 // Second earbud connects
9319 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9320 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9321 true /*connect_through_csis*/);
9322
9323 // Start streaming
9324 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9325 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9326 LeAudioClient::Get()->GroupSetActive(group_id);
9327 SyncOnMainLoop();
9328
9329 /* Simulate available context type being cleared */
9330 InjectAvailableContextTypes(test_address1, 2, types::AudioContexts(0), types::AudioContexts(0));
9331
9332 // Block streaming state
9333 stay_at_qos_config_in_start_stream = true;
9334
9335 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
9336 LocalAudioSourceResume(false);
9337
9338 SyncOnMainLoop();
9339 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9340
9341 InjectAvailableContextTypes(test_address1, 2, types::kLeAudioContextAllRemoteSinkOnly,
9342 types::AudioContexts(0), false);
9343
9344 // Now simulate group is finally streaming
9345 auto group = streaming_groups.at(group_id);
9346 do_in_main_thread(base::BindOnce(
9347 [](int group_id,
9348 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
9349 LeAudioDeviceGroup* group) {
9350 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9351
9352 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
9353 },
9354 group_id, base::Unretained(this->state_machine_callbacks_), std::move(group)));
9355
9356 SyncOnMainLoop();
9357
9358 /* verify AttachToStream was called while stream was not yet created. */
9359 ASSERT_TRUE(attach_to_stream_scheduled);
9360
9361 // Expect two iso channel to be fed with data
9362 uint8_t cis_count_out = 2;
9363 uint8_t cis_count_in = 0;
9364 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9365 SyncOnMainLoop();
9366 }
9367
TEST_F(UnicastTest,LateStreamConnectBasedOnContextTypeNotFullyConnected)9368 TEST_F(UnicastTest, LateStreamConnectBasedOnContextTypeNotFullyConnected) {
9369 uint8_t group_size = 2;
9370 int group_id = 2;
9371
9372 /* Scenario
9373 * 1. Device A is connected
9374 * 2. Stream creation to Device A has been started
9375 * 3. Stream is stopped
9376 * 4. Device B is connected but has ongoing operations of available context types read.
9377 * 5. Device B sends available context type read response
9378 * 6. Make sure AttachToStream was NOT called for Device B since it is not in a CONNECTED state
9379 * yet
9380 */
9381
9382 // Report working CSIS
9383 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9384
9385 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9386 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9387
9388 const RawAddress test_address0 = GetTestAddress(0);
9389 const RawAddress test_address1 = GetTestAddress(1);
9390
9391 // First earbud connects
9392 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9393 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9394 // Start streaming
9395 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9396 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9397 LeAudioClient::Get()->GroupSetActive(group_id);
9398 SyncOnMainLoop();
9399
9400 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9401 auto group = streaming_groups.at(group_id);
9402
9403 // Stop streaming - simulate suspend timeout passed, alarm executing
9404 StopStreaming(group_id);
9405 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
9406 SyncOnMainLoop();
9407
9408 // Second earbud connects and is set to Getting Ready state
9409 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9410 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9411 true /*connect_through_csis*/);
9412 auto device1 = group->GetNextDevice(group->GetFirstDevice());
9413 device1->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
9414
9415 // Resume but block the final streaming state - keep the group in transition
9416 stay_at_qos_config_in_start_stream = true;
9417 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
9418 LocalAudioSourceResume(false);
9419
9420 // Do not expect to attach the device on context update as it is not fully connected
9421 EXPECT_CALL(mock_state_machine_, AttachToStream(_, _, _)).Times(0);
9422 InjectAvailableContextTypes(test_address1, 2, types::kLeAudioContextAllRemoteSinkOnly,
9423 types::AudioContexts(0), false);
9424
9425 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9426 SyncOnMainLoop();
9427 }
9428
TEST_F(UnicastTest,CheckDeviceIsNotAttachedToStreamWhenNotNeeded)9429 TEST_F(UnicastTest, CheckDeviceIsNotAttachedToStreamWhenNotNeeded) {
9430 uint8_t group_size = 2;
9431 int group_id = 2;
9432
9433 /* Scenario
9434 * 1. Two devices A and B are connect. Both Devices have all available
9435 * contexts types
9436 * 2. Stream creation to Device A and B has been started
9437 * 3. Device B notified us with new available Context Types - while Group is
9438 * not yet streaming
9439 * 4. Make sure AttachToStream was not called for Device B since it is taking
9440 * part in Stream creation already
9441 */
9442
9443 // Report working CSIS
9444 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9445
9446 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9447 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9448
9449 const RawAddress test_address0 = GetTestAddress(0);
9450 const RawAddress test_address1 = GetTestAddress(1);
9451
9452 // First earbud connects
9453 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9454 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9455
9456 // Second earbud connects
9457 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9458 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9459 true /*connect_through_csis*/);
9460
9461 // Start streaming
9462 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9463 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9464 LeAudioClient::Get()->GroupSetActive(group_id);
9465 SyncOnMainLoop();
9466
9467 // Block streaming state
9468 stay_at_qos_config_in_start_stream = true;
9469
9470 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
9471 LocalAudioSourceResume(false);
9472
9473 SyncOnMainLoop();
9474 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9475
9476 InjectAvailableContextTypes(test_address1, 2, types::kLeAudioContextAllRemoteSinkOnly,
9477 types::AudioContexts(0), false);
9478
9479 // Now simulate group is finally streaming
9480 auto group = streaming_groups.at(group_id);
9481 do_in_main_thread(base::BindOnce(
9482 [](int group_id,
9483 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
9484 LeAudioDeviceGroup* group) {
9485 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9486
9487 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
9488 },
9489 group_id, base::Unretained(this->state_machine_callbacks_), std::move(group)));
9490
9491 SyncOnMainLoop();
9492
9493 /* verify AttachToStream was NOT called while stream was not yet created. */
9494 ASSERT_FALSE(attach_to_stream_scheduled);
9495
9496 // Expect two iso channel to be fed with data
9497 uint8_t cis_count_out = 2;
9498 uint8_t cis_count_in = 0;
9499 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9500 SyncOnMainLoop();
9501 }
9502
TEST_F(UnicastTest,ReconnectedDeviceAndAttachedToStreamBecauseOfAvailableContextTypeChange)9503 TEST_F(UnicastTest, ReconnectedDeviceAndAttachedToStreamBecauseOfAvailableContextTypeChange) {
9504 com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true);
9505
9506 uint8_t group_size = 2;
9507 int group_id = 2;
9508
9509 /* Scenario
9510 * 1. Two devices A and B are streaming
9511 * 2. Device A Release ASE and removes all available context types
9512 * 3. Device B keeps streaming
9513 * 4. Device A disconnectes
9514 * 5. Device A reconnect
9515 * 6. Device A has context available for streaming and should be attached to the stream
9516 */
9517
9518 // Report working CSIS
9519 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9520
9521 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9522 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9523
9524 const RawAddress test_address0 = GetTestAddress(0);
9525 const RawAddress test_address1 = GetTestAddress(1);
9526
9527 // First earbud connects
9528 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9529 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9530
9531 // Second earbud connects
9532 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9533 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9534 true /*connect_through_csis*/);
9535
9536 // Start streaming
9537 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9538 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9539 LeAudioClient::Get()->GroupSetActive(group_id);
9540 SyncOnMainLoop();
9541
9542 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9543
9544 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9545 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9546 SyncOnMainLoop();
9547
9548 // Expect two iso channel to be fed with data
9549 uint8_t cis_count_out = 2;
9550 uint8_t cis_count_in = 0;
9551 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9552
9553 /* Get group and Device A */
9554 ASSERT_NE(0lu, streaming_groups.count(group_id));
9555 auto group = streaming_groups.at(group_id);
9556 ASSERT_NE(group, nullptr);
9557 auto device = group->GetFirstDevice();
9558
9559 /* Simulate available context type being cleared */
9560 InjectAvailableContextTypes(device->address_, device->conn_id_, types::AudioContexts(0),
9561 types::AudioContexts(0));
9562
9563 /* Simulate ASE releasing and CIS Disconnection */
9564 for (auto& ase : device->ases_) {
9565 /* Releasing state */
9566 if (!ase.active) {
9567 continue;
9568 }
9569
9570 std::vector<uint8_t> releasing_state = {
9571 ase.id, static_cast<uint8_t>(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
9572 InjectNotificationEvent(device->address_, device->conn_id_, ase.hdls.val_hdl, releasing_state);
9573 SyncOnMainLoop();
9574 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
9575 SyncOnMainLoop();
9576 }
9577
9578 cis_count_out = 1;
9579 cis_count_in = 0;
9580 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9581
9582 /* Device A will disconnect, and do not reconnect automatically */
9583 ON_CALL(mock_gatt_interface_, Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, _))
9584 .WillByDefault(Return());
9585
9586 /* Disconnect first device */
9587 auto conn_id = device->conn_id_;
9588 InjectDisconnectedEvent(conn_id, GATT_CONN_TERMINATE_PEER_USER);
9589 SyncOnMainLoop();
9590
9591 /* For background connect, test needs to Inject Connected Event.
9592 * Note that initial available_snk_context_types_ available_src_context_types_ will
9593 * be read after reconnection, which should bring device to the stream again. */
9594
9595 InjectConnectedEvent(device->address_, conn_id);
9596 SyncOnMainLoop();
9597
9598 /* Check single device is streaming */
9599 cis_count_out = 2;
9600 cis_count_in = 0;
9601 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9602 }
9603
TEST_F(UnicastTest,ReconnectedDeviceNotAttachedToStreamBecauseOfNotAvailableContext)9604 TEST_F(UnicastTest, ReconnectedDeviceNotAttachedToStreamBecauseOfNotAvailableContext) {
9605 uint8_t group_size = 2;
9606 int group_id = 2;
9607
9608 /* Scenario
9609 * 1. Two devices A and B are streaming
9610 * 2. Device A Release ASE and removes all available context types
9611 * 3. Device B keeps streaming
9612 * 4. Device A disconnectes
9613 * 5. Device A reconnect and should not be attached to the stream
9614 */
9615
9616 // Report working CSIS
9617 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9618
9619 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9620 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9621
9622 const RawAddress test_address0 = GetTestAddress(0);
9623 const RawAddress test_address1 = GetTestAddress(1);
9624
9625 // First earbud connects
9626 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9627 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9628
9629 // Second earbud connects
9630 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9631 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9632 true /*connect_through_csis*/);
9633
9634 // Start streaming
9635 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9636 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9637 LeAudioClient::Get()->GroupSetActive(group_id);
9638 SyncOnMainLoop();
9639
9640 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9641
9642 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9643 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9644 SyncOnMainLoop();
9645
9646 // Expect two iso channel to be fed with data
9647 uint8_t cis_count_out = 2;
9648 uint8_t cis_count_in = 0;
9649 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9650
9651 /* Get group and Device A */
9652 ASSERT_NE(0lu, streaming_groups.count(group_id));
9653 auto group = streaming_groups.at(group_id);
9654 ASSERT_NE(group, nullptr);
9655 auto device = group->GetFirstDevice();
9656
9657 /* Simulate available context type being cleared */
9658 InjectAvailableContextTypes(device->address_, device->conn_id_, types::AudioContexts(0),
9659 types::AudioContexts(0));
9660
9661 /* Simulate ASE releasing and CIS Disconnection */
9662 for (auto& ase : device->ases_) {
9663 /* Releasing state */
9664 if (!ase.active) {
9665 continue;
9666 }
9667
9668 std::vector<uint8_t> releasing_state = {
9669 ase.id, static_cast<uint8_t>(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
9670 InjectNotificationEvent(device->address_, device->conn_id_, ase.hdls.val_hdl, releasing_state);
9671 SyncOnMainLoop();
9672 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
9673 SyncOnMainLoop();
9674 }
9675
9676 cis_count_out = 1;
9677 cis_count_in = 0;
9678 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9679
9680 /* Device A will disconnect, and do not reconnect automatically */
9681 ON_CALL(mock_gatt_interface_, Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, _))
9682 .WillByDefault(Return());
9683
9684 /* Disconnect first device */
9685 auto conn_id = device->conn_id_;
9686 InjectDisconnectedEvent(conn_id, GATT_CONN_TERMINATE_PEER_USER);
9687 SyncOnMainLoop();
9688
9689 /* For background connect, test needs to Inject Connected Event.
9690 * Since after reconnect Android reads available context types, make sure
9691 * 0 is read */
9692 available_snk_context_types_ = 0;
9693 available_src_context_types_ = 0;
9694
9695 InjectConnectedEvent(device->address_, conn_id);
9696 SyncOnMainLoop();
9697
9698 /* Check single device is streaming */
9699 cis_count_out = 1;
9700 cis_count_in = 0;
9701 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9702 }
9703
TEST_F(UnicastTest,TwoEarbuds2ndReleaseAseRemoveAvailableContextAndBack)9704 TEST_F(UnicastTest, TwoEarbuds2ndReleaseAseRemoveAvailableContextAndBack) {
9705 uint8_t group_size = 2;
9706 int group_id = 2;
9707
9708 /* Scenario
9709 * 1. Two devices A and B are streaming
9710 * 2. Device A Release ASE and removes all available context types
9711 * 3. Device B keeps streaming
9712 * 4. Device A sets available context types
9713 * 5. Device A should be attached to the stream
9714 */
9715
9716 // Report working CSIS
9717 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9718
9719 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9720 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9721
9722 const RawAddress test_address0 = GetTestAddress(0);
9723 const RawAddress test_address1 = GetTestAddress(1);
9724
9725 // First earbud connects
9726 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9727 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9728
9729 // Second earbud connects
9730 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9731 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9732 true /*connect_through_csis*/);
9733
9734 // Start streaming
9735 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9736 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9737 LeAudioClient::Get()->GroupSetActive(group_id);
9738 SyncOnMainLoop();
9739
9740 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9741
9742 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9743 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9744 SyncOnMainLoop();
9745
9746 // Expect two iso channel to be fed with data
9747 uint8_t cis_count_out = 2;
9748 uint8_t cis_count_in = 0;
9749 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9750
9751 /* Get group and Device A */
9752 ASSERT_NE(0lu, streaming_groups.count(group_id));
9753 auto group = streaming_groups.at(group_id);
9754 ASSERT_NE(group, nullptr);
9755 auto device = group->GetFirstDevice();
9756
9757 /* Simulate available context type being cleared */
9758 InjectAvailableContextTypes(device->address_, device->conn_id_, types::AudioContexts(0),
9759 types::AudioContexts(0));
9760
9761 /* Simulate ASE releasing and CIS Disconnection */
9762 for (auto& ase : device->ases_) {
9763 /* Releasing state */
9764 if (!ase.active) {
9765 continue;
9766 }
9767
9768 std::vector<uint8_t> releasing_state = {
9769 ase.id, static_cast<uint8_t>(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
9770 InjectNotificationEvent(device->address_, device->conn_id_, ase.hdls.val_hdl, releasing_state);
9771 SyncOnMainLoop();
9772 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
9773 SyncOnMainLoop();
9774 }
9775
9776 cis_count_out = 1;
9777 cis_count_in = 0;
9778 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9779
9780 /* Bring back available context types */
9781 InjectAvailableContextTypes(device->address_, device->conn_id_, types::kLeAudioContextAllTypes,
9782 types::kLeAudioContextAllTypes);
9783
9784 /* Check both devices are streaming */
9785 cis_count_out = 2;
9786 cis_count_in = 0;
9787 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9788 }
9789
TEST_F(UnicastTest,StartStream_AvailableContextTypeNotifiedLater)9790 TEST_F(UnicastTest, StartStream_AvailableContextTypeNotifiedLater) {
9791 uint8_t group_size = 2;
9792 int group_id = 2;
9793
9794 available_snk_context_types_ = 0;
9795
9796 /* Scenario (Devices A and B called "Remote")
9797 * 1. Remote does supports all the context types, but has NO available
9798 * contexts at the beginning
9799 * 2. After connection Remote add Available context types
9800 * 3. Android start stream with MEDIA
9801 * 4. Make sure stream will be started
9802 */
9803
9804 // Report working CSIS
9805 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9806
9807 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9808 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9809
9810 const RawAddress test_address0 = GetTestAddress(0);
9811 const RawAddress test_address1 = GetTestAddress(1);
9812
9813 // First earbud connects
9814 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9815 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9816
9817 // Second earbud connects
9818 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9819 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9820 true /*connect_through_csis*/);
9821
9822 // Inject Supported and available context types
9823 auto sink_available_contexts = types::kLeAudioContextAllRemoteSinkOnly;
9824 auto source_available_contexts = types::kLeAudioContextAllRemoteSource;
9825
9826 InjectAvailableContextTypes(test_address0, 1, sink_available_contexts, source_available_contexts);
9827 InjectAvailableContextTypes(test_address1, 2, sink_available_contexts, source_available_contexts);
9828 // Start streaming
9829 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9830 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9831 LeAudioClient::Get()->GroupSetActive(group_id);
9832 SyncOnMainLoop();
9833
9834 BidirectionalPair<AudioContexts> contexts = {
9835 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
9836 .source = types::AudioContexts()};
9837
9838 EXPECT_CALL(mock_state_machine_,
9839 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
9840 .Times(1);
9841
9842 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9843 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9844 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9845
9846 // Expect two iso channel to be fed with data
9847 uint8_t cis_count_out = 2;
9848 uint8_t cis_count_in = 0;
9849 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9850 }
9851
TEST_F(UnicastTest,ModifyContextTypeOnDeviceA_WhileDeviceB_IsDisconnected)9852 TEST_F(UnicastTest, ModifyContextTypeOnDeviceA_WhileDeviceB_IsDisconnected) {
9853 uint8_t group_size = 2;
9854 int group_id = 2;
9855
9856 /* Scenario (Device A and B called Remote)
9857 * 1. Remote set does supports all the context types and make them available
9858 * 2. Android start stream with MEDIA, verify it works.
9859 * 3. Android stops the stream
9860 * 4. Device B disconnects
9861 * 5. Device A removes Media from Available Contexts
9862 * 6. Android start stream with MEDIA, verify it will not be started
9863 */
9864
9865 // Report working CSIS
9866 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9867
9868 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9869 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9870
9871 const RawAddress test_address0 = GetTestAddress(0);
9872 const RawAddress test_address1 = GetTestAddress(1);
9873
9874 // First earbud connects
9875 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9876 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9877
9878 // Second earbud connects
9879 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9880 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9881 true /*connect_through_csis*/);
9882
9883 // Start streaming
9884 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9885 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9886 LeAudioClient::Get()->GroupSetActive(group_id);
9887 SyncOnMainLoop();
9888
9889 BidirectionalPair<AudioContexts> contexts = {
9890 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
9891 .source = types::AudioContexts()};
9892
9893 EXPECT_CALL(mock_state_machine_,
9894 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
9895 .Times(1);
9896
9897 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9898
9899 SyncOnMainLoop();
9900 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9901 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9902 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9903
9904 // Expect two iso channel to be fed with data
9905 uint8_t cis_count_out = 2;
9906 uint8_t cis_count_in = 0;
9907 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9908
9909 // Stop
9910 StopStreaming(group_id);
9911 // simulate suspend timeout passed, alarm executing
9912 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
9913 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9914
9915 // Device B got disconnected and will not reconnect.
9916 ON_CALL(mock_gatt_interface_, Open(_, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
9917 .WillByDefault(Return());
9918 InjectDisconnectedEvent(2, GATT_CONN_TERMINATE_PEER_USER);
9919 SyncOnMainLoop();
9920
9921 // Device A changes available context type
9922 // Inject Supported and available context types
9923 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
9924 sink_supported_context.unset(LeAudioContextType::MEDIA);
9925 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
9926
9927 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
9928 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
9929
9930 InjectSupportedContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9931 InjectAvailableContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9932
9933 /* Android starts stream. */
9934 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
9935
9936 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID, false,
9937 false);
9938 SyncOnMainLoop();
9939
9940 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9941 }
9942
TEST_F(UnicastTest,StartStreamToUnsupportedContextTypeUsingUnspecified)9943 TEST_F(UnicastTest, StartStreamToUnsupportedContextTypeUsingUnspecified) {
9944 uint8_t group_size = 2;
9945 int group_id = 2;
9946
9947 /* Scenario (Devices A and B called "Remote")
9948 * 1. Remote does supports all the context types and make them available
9949 * 2. Remote removes SoundEffect from the supported and available context
9950 * types
9951 * 3. Android start stream with SoundEffects
9952 * 4. Make sure stream will be started with Unspecified context type
9953 */
9954
9955 // Report working CSIS
9956 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9957
9958 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9959 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9960
9961 const RawAddress test_address0 = GetTestAddress(0);
9962 const RawAddress test_address1 = GetTestAddress(1);
9963
9964 // First earbud connects
9965 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9966 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9967
9968 // Second earbud connects
9969 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9970 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9971 true /*connect_through_csis*/);
9972
9973 // Inject Supported and available context types
9974 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
9975 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
9976 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
9977
9978 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
9979 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
9980
9981 InjectSupportedContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9982 InjectAvailableContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9983 InjectSupportedContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
9984 InjectAvailableContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
9985 // Start streaming
9986 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9987 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9988 LeAudioClient::Get()->GroupSetActive(group_id);
9989 SyncOnMainLoop();
9990
9991 BidirectionalPair<AudioContexts> contexts = {
9992 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
9993 .source = types::AudioContexts(0)};
9994
9995 EXPECT_CALL(
9996 mock_state_machine_,
9997 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::SOUNDEFFECTS, contexts, _))
9998 .Times(1);
9999
10000 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION, group_id);
10001
10002 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10003 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10004 SyncOnMainLoop();
10005
10006 // Expect two iso channel to be fed with data
10007 uint8_t cis_count_out = 2;
10008 uint8_t cis_count_in = 0;
10009 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10010 }
10011
TEST_F(UnicastTest,StartStreamToUnsupportedContextTypeUnspecifiedNotAvailable)10012 TEST_F(UnicastTest, StartStreamToUnsupportedContextTypeUnspecifiedNotAvailable) {
10013 uint8_t group_size = 2;
10014 int group_id = 2;
10015
10016 /* Scenario (Device A and B called Remote)
10017 * 1. Remote does supports all the context types and make them available
10018 * 2. Remote removes SoundEffect from the Available Context Types
10019 * 3. Remote also removes UNSPECIFIED from the Available Context Types.
10020 * 4. Android start stream with SoundEffects
10021 * 5. Make sure stream will be NOT be started
10022 */
10023
10024 // Report working CSIS
10025 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
10026
10027 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10028 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
10029
10030 const RawAddress test_address0 = GetTestAddress(0);
10031 const RawAddress test_address1 = GetTestAddress(1);
10032
10033 // First earbud connects
10034 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
10035 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
10036
10037 // Second earbud connects
10038 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
10039 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
10040 true /*connect_through_csis*/);
10041
10042 // Inject Supported and available context types
10043 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
10044 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
10045 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
10046
10047 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
10048 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
10049
10050 InjectSupportedContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
10051 InjectSupportedContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
10052
10053 auto sink_available_context = sink_supported_context;
10054 sink_available_context.unset(LeAudioContextType::UNSPECIFIED);
10055
10056 auto source_available_context = source_supported_context;
10057 source_available_context.unset(LeAudioContextType::UNSPECIFIED);
10058
10059 InjectAvailableContextTypes(test_address0, 1, sink_available_context, source_available_context);
10060 InjectAvailableContextTypes(test_address1, 2, sink_available_context, source_available_context);
10061 // Start streaming
10062 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10063 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10064 LeAudioClient::Get()->GroupSetActive(group_id);
10065 SyncOnMainLoop();
10066
10067 BidirectionalPair<AudioContexts> contexts = {
10068 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
10069 .source = types::AudioContexts()};
10070
10071 EXPECT_CALL(
10072 mock_state_machine_,
10073 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::SOUNDEFFECTS, contexts, _))
10074 .Times(0);
10075
10076 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION, group_id,
10077 AUDIO_SOURCE_INVALID, false, false);
10078
10079 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10080 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10081 SyncOnMainLoop();
10082 }
10083
TEST_F(UnicastTest,StartStreamToSupportedContextTypeThenMixUnavailable)10084 TEST_F(UnicastTest, StartStreamToSupportedContextTypeThenMixUnavailable) {
10085 uint8_t group_size = 2;
10086 int group_id = 2;
10087
10088 /* Scenario (Device A and B called Remote)
10089 * 1. Remote set does supports all the context types and make them available
10090 * 2. Abdriud start stream with MEDIA, verify it works.
10091 * 3. Stream becomes to be mixed with Soundeffect and Media - verify metadata
10092 * update
10093 * 4. Android Stop stream.
10094 * 5. Remote removes SoundEffect from the supported and available context
10095 * types
10096 * 6. Android start stream with MEDIA, verify it works.
10097 * 7. Stream becomes to be mixed with Soundeffect and Media
10098 * 8. Make sure metadata updated does not contain unavailable context
10099 * note: eventually, Audio framework should not give us unwanted context
10100 * types
10101 */
10102
10103 // Report working CSIS
10104 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
10105
10106 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10107 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
10108
10109 const RawAddress test_address0 = GetTestAddress(0);
10110 const RawAddress test_address1 = GetTestAddress(1);
10111
10112 // First earbud connects
10113 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
10114 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
10115
10116 // Second earbud connects
10117 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
10118 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
10119 true /*connect_through_csis*/);
10120
10121 // Start streaming
10122 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10123 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10124 LeAudioClient::Get()->GroupSetActive(group_id);
10125 SyncOnMainLoop();
10126
10127 BidirectionalPair<AudioContexts> contexts = {
10128 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
10129 .source = types::AudioContexts()};
10130
10131 EXPECT_CALL(mock_state_machine_,
10132 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
10133 .Times(1);
10134
10135 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
10136
10137 SyncOnMainLoop();
10138 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10139 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10140 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10141
10142 ASSERT_NE(0lu, streaming_groups.count(group_id));
10143 auto group = streaming_groups.at(group_id);
10144
10145 // Expect two iso channel to be fed with data
10146 uint8_t cis_count_out = 2;
10147 uint8_t cis_count_in = 0;
10148 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10149
10150 contexts.sink = types::AudioContexts(types::LeAudioContextType::MEDIA |
10151 types::LeAudioContextType::SOUNDEFFECTS);
10152 EXPECT_CALL(mock_state_machine_,
10153 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
10154 .Times(1);
10155
10156 /* Simulate metadata update, expect upadate , metadata */
10157 std::vector<struct playback_track_metadata> tracks = {
10158 {{AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, 0},
10159 {AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION, 0}}};
10160 UpdateLocalSourceMetadata(tracks);
10161 SyncOnMainLoop();
10162
10163 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10164
10165 /* Stop stream */
10166 StopStreaming(group_id);
10167 // simulate suspend timeout passed, alarm executing
10168 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
10169 SyncOnMainLoop();
10170
10171 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10172
10173 // Inject Supported and available context types
10174 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
10175 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
10176 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
10177
10178 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
10179 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
10180
10181 InjectSupportedContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
10182 InjectAvailableContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
10183 InjectSupportedContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
10184 InjectAvailableContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
10185
10186 // Verify cache has been removed due to available context change
10187 ASSERT_EQ(nullptr, group->GetCachedConfiguration(types::LeAudioContextType::MEDIA));
10188 /* Start Media again */
10189 contexts.sink = types::AudioContexts(types::LeAudioContextType::MEDIA);
10190 EXPECT_CALL(mock_state_machine_,
10191 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
10192 .Times(1);
10193
10194 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
10195
10196 SyncOnMainLoop();
10197
10198 // Verify cache has been rebuilt
10199 ASSERT_NE(nullptr, group->GetCachedConfiguration(types::LeAudioContextType::MEDIA));
10200 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::MEDIA)
10201 ->confs.get(le_audio::types::kLeAudioDirectionSink)
10202 .size());
10203
10204 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10205 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10206 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10207
10208 // Expect two iso channel to be fed with data
10209 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10210
10211 /* Update metadata, and do not expect new context type*/
10212 EXPECT_CALL(mock_state_machine_,
10213 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
10214 .Times(1);
10215
10216 /* Simulate metadata update */
10217 UpdateLocalSourceMetadata(tracks);
10218 SyncOnMainLoop();
10219 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10220 }
10221
TEST_F(UnicastTest,TwoEarbuds2ndDisconnected)10222 TEST_F(UnicastTest, TwoEarbuds2ndDisconnected) {
10223 uint8_t group_size = 2;
10224 int group_id = 2;
10225
10226 // Report working CSIS
10227 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
10228
10229 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10230 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
10231
10232 // First earbud
10233 const RawAddress test_address0 = GetTestAddress(0);
10234 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
10235 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
10236
10237 // Second earbud
10238 const RawAddress test_address1 = GetTestAddress(1);
10239 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
10240 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
10241 true /*connect_through_csis*/);
10242
10243 // Audio sessions are started only when device gets active
10244 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10245 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10246 LeAudioClient::Get()->GroupSetActive(group_id);
10247 SyncOnMainLoop();
10248
10249 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
10250 ASSERT_NE(0lu, streaming_groups.count(group_id));
10251 auto group = streaming_groups.at(group_id);
10252
10253 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10254 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10255 SyncOnMainLoop();
10256 ASSERT_EQ(2, group->NumOfConnected());
10257
10258 // Expect two iso channels to be fed with data
10259 uint8_t cis_count_out = 2;
10260 uint8_t cis_count_in = 0;
10261 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10262
10263 // Disconnect one device and expect the group to keep on streaming
10264 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10265 auto device = group->GetFirstDevice();
10266 for (auto& ase : device->ases_) {
10267 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
10268 }
10269
10270 /* Disconnect ACL and do not reconnect. */
10271 ON_CALL(mock_gatt_interface_, Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, _))
10272 .WillByDefault(Return());
10273 EXPECT_CALL(mock_gatt_interface_, Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, false))
10274 .Times(1);
10275
10276 // Record NumOfConnected when groupStateMachine_ gets notified about the
10277 // disconnection
10278 int num_of_connected = 0;
10279 ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
10280 .WillByDefault(
10281 [&num_of_connected](LeAudioDeviceGroup* group, LeAudioDevice* /*leAudioDevice*/) {
10282 num_of_connected = group->NumOfConnected();
10283 });
10284
10285 auto conn_id = device->conn_id_;
10286 InjectDisconnectedEvent(device->conn_id_, GATT_CONN_TERMINATE_PEER_USER);
10287 SyncOnMainLoop();
10288
10289 // Make sure the state machine knows about the disconnected device
10290 ASSERT_EQ(1, num_of_connected);
10291
10292 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
10293 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10294
10295 // Expect one channel ISO Data to be sent
10296 cis_count_out = 1;
10297 cis_count_in = 0;
10298 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10299
10300 InjectConnectedEvent(device->address_, conn_id);
10301 SyncOnMainLoop();
10302
10303 // Expect two iso channels to be fed with data
10304 cis_count_out = 2;
10305 cis_count_in = 0;
10306 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10307 }
10308
TEST_F(UnicastTest,TwoEarbudsStreamingProfileDisconnect)10309 TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnect) {
10310 uint8_t group_size = 2;
10311 int group_id = 2;
10312
10313 // Report working CSIS
10314 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
10315
10316 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10317 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
10318
10319 // First earbud
10320 const RawAddress test_address0 = GetTestAddress(0);
10321 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
10322 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
10323
10324 // Second earbud
10325 const RawAddress test_address1 = GetTestAddress(1);
10326 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
10327 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
10328 true /*connect_through_csis*/);
10329
10330 // Audio sessions are started only when device gets active
10331 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10332 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10333 LeAudioClient::Get()->GroupSetActive(group_id);
10334 SyncOnMainLoop();
10335
10336 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
10337
10338 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10339 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10340 SyncOnMainLoop();
10341
10342 // Expect two iso channels to be fed with data
10343 uint8_t cis_count_out = 2;
10344 uint8_t cis_count_in = 0;
10345 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10346
10347 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
10348
10349 /* Do not inject OPEN_EVENT by default */
10350 ON_CALL(mock_gatt_interface_, Open(_, _, _, _)).WillByDefault(DoAll(Return()));
10351 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
10352 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).WillByDefault(DoAll(Return()));
10353
10354 DisconnectLeAudioNoDisconnectedEvtExpected(test_address0, 1);
10355 DisconnectLeAudioNoDisconnectedEvtExpected(test_address1, 2);
10356
10357 EXPECT_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
10358 .Times(2);
10359
10360 InjectDisconnectedEvent(1);
10361 InjectDisconnectedEvent(2);
10362
10363 SyncOnMainLoop();
10364 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10365 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
10366 }
10367
TEST_F(UnicastTest,TwoEarbudsStreamingProfileDisconnectStreamStopTimeout)10368 TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnectStreamStopTimeout) {
10369 uint8_t group_size = 2;
10370 int group_id = 2;
10371
10372 // Report working CSIS
10373 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
10374
10375 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10376 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
10377
10378 // First earbud
10379 const RawAddress test_address0 = GetTestAddress(0);
10380 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
10381 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
10382
10383 // Second earbud
10384 const RawAddress test_address1 = GetTestAddress(1);
10385 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
10386 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
10387 true /*connect_through_csis*/);
10388
10389 // Audio sessions are started only when device gets active
10390 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10391 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10392 LeAudioClient::Get()->GroupSetActive(group_id);
10393 SyncOnMainLoop();
10394
10395 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
10396
10397 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10398 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10399 SyncOnMainLoop();
10400
10401 // Expect two iso channels to be fed with data
10402 uint8_t cis_count_out = 2;
10403 uint8_t cis_count_in = 0;
10404 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10405
10406 // Expect StopStream to be called before Close or ACL Disconnect is called.
10407 ON_CALL(mock_state_machine_, StopStream(_)).WillByDefault([](LeAudioDeviceGroup* group) {
10408 /* Stub the process of stopping stream, just set the target state.
10409 * this simulates issue with stopping the stream
10410 */
10411 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
10412 });
10413
10414 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(2);
10415 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
10416 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).Times(0);
10417
10418 do_in_main_thread(base::Bind(&LeAudioClient::Disconnect, base::Unretained(LeAudioClient::Get()),
10419 test_address0));
10420 do_in_main_thread(base::Bind(&LeAudioClient::Disconnect, base::Unretained(LeAudioClient::Get()),
10421 test_address1));
10422
10423 SyncOnMainLoop();
10424 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
10425 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
10426 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10427
10428 /* Now stream is trying to be stopped and devices are about to be
10429 * disconnected. Simulate stop stream failure and timeout fired. Make sure
10430 * code will not try to do recovery connect
10431 */
10432 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).WillByDefault(DoAll(Return()));
10433 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
10434 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).Times(2);
10435
10436 ASSERT_NE(0lu, streaming_groups.count(group_id));
10437 auto group = streaming_groups.at(group_id);
10438 ASSERT_TRUE(group != nullptr);
10439 ASSERT_GT(group->NumOfConnected(), 0);
10440
10441 state_machine_callbacks_->OnStateTransitionTimeout(group_id);
10442 SyncOnMainLoop();
10443
10444 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
10445 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
10446
10447 auto device = group->GetFirstDevice();
10448 ASSERT_TRUE(device != nullptr);
10449 ASSERT_NE(device->GetConnectionState(), DeviceConnectState::DISCONNECTING_AND_RECOVER);
10450 device = group->GetNextDevice(device);
10451 ASSERT_TRUE(device != nullptr);
10452 ASSERT_NE(device->GetConnectionState(), DeviceConnectState::DISCONNECTING_AND_RECOVER);
10453 }
10454
TEST_F(UnicastTest,TwoEarbudsStreamingProfileDisconnectForSingleEarbudStreamStopTimeout)10455 TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnectForSingleEarbudStreamStopTimeout) {
10456 uint8_t group_size = 2;
10457 int group_id = 2;
10458
10459 // Report working CSIS
10460 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
10461
10462 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
10463 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
10464
10465 // First earbud
10466 const RawAddress test_address0 = GetTestAddress(0);
10467 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
10468 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
10469
10470 // Second earbud
10471 const RawAddress test_address1 = GetTestAddress(1);
10472 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
10473 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
10474 true /*connect_through_csis*/);
10475
10476 // Audio sessions are started only when device gets active
10477 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10478 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10479 LeAudioClient::Get()->GroupSetActive(group_id);
10480 SyncOnMainLoop();
10481
10482 /* Use StartStream to generate situation when target state is IDLE, one device is streaming and
10483 * other one reached IDLE state.
10484 */
10485 ON_CALL(mock_state_machine_, StartStream(_, _, _, _))
10486 .WillByDefault([this](LeAudioDeviceGroup* group,
10487 types::LeAudioContextType /* context_type */,
10488 types::BidirectionalPair<
10489 types::AudioContexts> /* metadata_context_types */,
10490 types::BidirectionalPair<std::vector<uint8_t>> /* ccid_lists */) {
10491 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
10492 auto group_state = group->GetState();
10493 LeAudioDevice* device = group->GetFirstDevice();
10494 for (auto& ase : device->ases_) {
10495 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
10496 ase.active = true;
10497 }
10498 device = group->GetNextDevice(device);
10499 for (auto& ase : device->ases_) {
10500 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
10501 ase.active = false;
10502 }
10503
10504 state_machine_callbacks_->OnStateTransitionTimeout(group->group_id_);
10505
10506 return true;
10507 });
10508
10509 // Do not accept direct connect, but expect it to arrive.
10510 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
10511
10512 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).Times(1);
10513 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, GroupStatus::INACTIVE))
10514 .Times(0);
10515 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID, false,
10516 false);
10517 SyncOnMainLoop();
10518 }
10519
TEST_F(UnicastTest,EarbudsWithStereoSinkMonoSourceSupporting32kHz)10520 TEST_F(UnicastTest, EarbudsWithStereoSinkMonoSourceSupporting32kHz) {
10521 const RawAddress test_address0 = GetTestAddress(0);
10522 int group_id = 0;
10523 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10524 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
10525 default_channel_cnt, 0x0024,
10526 /* source sample freq 32/16khz */ true, /*add_csis*/
10527 true, /*add_cas*/
10528 true, /*add_pacs*/
10529 default_ase_cnt /*add_ascs_cnt*/);
10530 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10531 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10532 .Times(1);
10533 ConnectLeAudio(test_address0);
10534
10535 // LeAudioCodecConfiguration received_af_sink_config;
10536 const LeAudioCodecConfiguration expected_af_sink_config = {
10537 .num_channels = 2,
10538 .sample_rate = bluetooth::audio::le_audio::kSampleRate32000,
10539 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
10540 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
10541 };
10542
10543 // Audio sessions are started only when device gets active
10544 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10545 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(expected_af_sink_config, _, _)).Times(1);
10546 LeAudioClient::Get()->GroupSetActive(group_id);
10547 SyncOnMainLoop();
10548 }
10549
TEST_F(UnicastTest,TwoEarbudsWithSourceSupporting32kHz)10550 TEST_F(UnicastTest, TwoEarbudsWithSourceSupporting32kHz) {
10551 const RawAddress test_address0 = GetTestAddress(0);
10552 int group_id = 0;
10553 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10554 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10555 default_channel_cnt, 0x0024,
10556 /* source sample freq 32/16khz */ true, /*add_csis*/
10557 true, /*add_cas*/
10558 true, /*add_pacs*/
10559 default_ase_cnt /*add_ascs_cnt*/);
10560 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10561 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10562 .Times(1);
10563 ConnectLeAudio(test_address0);
10564
10565 // LeAudioCodecConfiguration received_af_sink_config;
10566 const LeAudioCodecConfiguration expected_af_sink_config = {
10567 .num_channels = 2,
10568 .sample_rate = bluetooth::audio::le_audio::kSampleRate32000,
10569 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
10570 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
10571 };
10572
10573 // Audio sessions are started only when device gets active
10574 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10575 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(expected_af_sink_config, _, _)).Times(1);
10576 LeAudioClient::Get()->GroupSetActive(group_id);
10577 SyncOnMainLoop();
10578 }
10579
TEST_F(UnicastTest,MicrophoneAttachToCurrentMediaScenario)10580 TEST_F(UnicastTest, MicrophoneAttachToCurrentMediaScenario) {
10581 const RawAddress test_address0 = GetTestAddress(0);
10582 int group_id = bluetooth::groups::kGroupUnknown;
10583
10584 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10585 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
10586 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10587 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10588 0 /*rank*/);
10589 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10590 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10591 .Times(1);
10592 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10593 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10594 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10595
10596 ConnectLeAudio(test_address0);
10597 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10598
10599 // Audio sessions are started only when device gets active
10600 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10601 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10602 LeAudioClient::Get()->GroupSetActive(group_id);
10603 SyncOnMainLoop();
10604
10605 // When the local audio source resumes we have no knowledge of recording
10606 EXPECT_CALL(mock_state_machine_,
10607 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, _, _))
10608 .Times(1);
10609
10610 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID);
10611 SyncOnMainLoop();
10612
10613 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10614 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10615
10616 // Verify Data transfer on one audio source cis
10617 uint8_t cis_count_out = 1;
10618 uint8_t cis_count_in = 0;
10619 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10620
10621 // When the local audio sink resumes we should reconfigure
10622 EXPECT_CALL(mock_state_machine_,
10623 ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, _, _, _))
10624 .Times(1);
10625 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(1);
10626
10627 // Update metadata on local audio sink
10628 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
10629
10630 // Resume on local audio sink
10631 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
10632 do_in_main_thread(
10633 base::BindOnce([](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
10634 unicast_sink_hal_cb_));
10635
10636 /* The above will trigger reconfiguration. After that Audio Hal action
10637 * is needed to restart the stream */
10638 SyncOnMainLoop();
10639
10640 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10641 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10642
10643 LocalAudioSourceResume();
10644 do_in_main_thread(
10645 base::BindOnce([](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
10646 unicast_sink_hal_cb_));
10647 SyncOnMainLoop();
10648
10649 auto group = streaming_groups.at(group_id);
10650 group->PrintDebugState();
10651
10652 // Verify Data transfer on one audio source and sink cis
10653 cis_count_out = 1;
10654 cis_count_in = 1;
10655 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
10656
10657 // Stop
10658 StopStreaming(group_id);
10659 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10660
10661 // Release
10662 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10663 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10664 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10665 do_in_main_thread(base::BindOnce(
10666 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
10667 LeAudioClient::Get()));
10668 SyncOnMainLoop();
10669
10670 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10671 }
10672
TEST_F(UnicastTest,SwitchBetweenMicrophoneAndSoundEffectScenario)10673 TEST_F(UnicastTest, SwitchBetweenMicrophoneAndSoundEffectScenario) {
10674 const RawAddress test_address0 = GetTestAddress(0);
10675 int group_id = bluetooth::groups::kGroupUnknown;
10676
10677 /* Scenario:
10678 * 1. User starts Recording - this creates bidiretional CISes
10679 * 2. User stops recording - this starts suspend timeout (500ms)
10680 * 3. Since user touch the screen it generates touch tone - this shall reuse existing CISes when
10681 * it happens 500ms before stop
10682 */
10683 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10684 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
10685 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10686 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10687 0 /*rank*/);
10688 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10689 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10690 .Times(1);
10691 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10692 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10693 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10694
10695 ConnectLeAudio(test_address0);
10696 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10697
10698 // Audio sessions are started only when device gets active
10699 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10700 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10701 LeAudioClient::Get()->GroupSetActive(group_id);
10702 SyncOnMainLoop();
10703
10704 // When the local audio source resumes we have no knowledge of recording
10705 EXPECT_CALL(mock_state_machine_,
10706 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, _, _))
10707 .Times(1);
10708
10709 log::info("Start Microphone recording - bidirectional CISes are expected");
10710 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
10711 LocalAudioSinkResume();
10712
10713 ASSERT_EQ(0, get_func_call_count("alarm_set_on_mloop"));
10714 SyncOnMainLoop();
10715
10716 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10717 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10718 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10719
10720 // Verify Data transfer on one audio source cis
10721 uint8_t cis_count_out = 0;
10722 uint8_t cis_count_in = 1;
10723 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
10724
10725 log::info("Suspend microphone recording - suspend timeout is not fired");
10726 LocalAudioSinkSuspend();
10727 SyncOnMainLoop();
10728
10729 log::info("Expect VBC and Suspend timeouts to be started");
10730 ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
10731 ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
10732
10733 log::info("Resume local source with touch tone - expect suspend timeout to be canceled");
10734
10735 UpdateLocalSourceMetadata(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION);
10736 LocalAudioSourceResume();
10737 SyncOnMainLoop();
10738
10739 log::info("Expect VBC and Suspend timeouts to be started");
10740 ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
10741
10742 auto group = streaming_groups.at(group_id);
10743 group->PrintDebugState();
10744
10745 // Verify Data transfer on one audio source and sink cis
10746 cis_count_out = 1;
10747 cis_count_in = 0;
10748 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
10749 }
10750
TEST_F(UnicastTest,SwitchBetweenSoundEffectAndMicrophoneScenario)10751 TEST_F(UnicastTest, SwitchBetweenSoundEffectAndMicrophoneScenario) {
10752 const RawAddress test_address0 = GetTestAddress(0);
10753 int group_id = bluetooth::groups::kGroupUnknown;
10754
10755 /* Scenario:
10756 * 1. User starts Recording which first triggers SoundEffect
10757 * 2. Just after that LIVE metadata arrives and this creates bidiretional CISes
10758 */
10759 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10760 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
10761 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10762 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10763 0 /*rank*/);
10764 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10765 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10766 .Times(1);
10767 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10768 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10769 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10770
10771 ConnectLeAudio(test_address0);
10772 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10773
10774 // Audio sessions are started only when device gets active
10775 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10776 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10777 LeAudioClient::Get()->GroupSetActive(group_id);
10778 SyncOnMainLoop();
10779
10780 // When the local audio source resumes we have no knowledge of recording
10781 EXPECT_CALL(mock_state_machine_,
10782 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::SOUNDEFFECTS, _, _))
10783 .Times(1);
10784
10785 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION, group_id);
10786 SyncOnMainLoop();
10787
10788 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10789 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10790 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10791 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10792
10793 auto group = streaming_groups.at(group_id);
10794 group->PrintDebugState();
10795
10796 log::info("Start Microphone recording - reconfiguration is expected");
10797 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
10798 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
10799 EXPECT_CALL(*mock_le_audio_sink_hal_client_, CancelStreamingRequest()).Times(1);
10800
10801 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
10802 LocalAudioSinkResume();
10803
10804 SyncOnMainLoop();
10805 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10806 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10807 group->PrintDebugState();
10808
10809 log::info("Resume after reconfiguration - bidirectional CISes are expected");
10810 LocalAudioSourceResume();
10811 LocalAudioSinkResume();
10812
10813 // Verify Data transfer on one audio source cis
10814 uint8_t cis_count_out = 0;
10815 uint8_t cis_count_in = 1;
10816 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
10817
10818 ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
10819 ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
10820 }
10821
10822 /* When a certain context is unavailable and not supported we should stream
10823 * as UNSPECIFIED for the backwards compatibility.
10824 * Since UNSPECIFIED is available, put the UNSPECIFIED into the metadata instead
10825 * What we can do now is to keep streaming (and reconfigure if needed for the
10826 * use case).
10827 */
TEST_F(UnicastTest,UpdateNotSupportedContextTypeUnspecifiedAvailable_SpeedUpReconfigFlagEnabled)10828 TEST_F(UnicastTest, UpdateNotSupportedContextTypeUnspecifiedAvailable_SpeedUpReconfigFlagEnabled) {
10829 const RawAddress test_address0 = GetTestAddress(0);
10830 int group_id = bluetooth::groups::kGroupUnknown;
10831
10832 available_snk_context_types_ =
10833 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
10834 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
10835 .value();
10836 supported_snk_context_types_ = available_snk_context_types_;
10837 available_src_context_types_ = available_snk_context_types_;
10838 supported_src_context_types_ = available_src_context_types_;
10839
10840 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10841 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10842 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
10843 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10844 0 /*rank*/);
10845 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10846 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10847 .Times(1);
10848 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10849 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10850 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10851
10852 ConnectLeAudio(test_address0);
10853 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10854
10855 // Start streaming
10856 uint8_t cis_count_out = 1;
10857 uint8_t cis_count_in = 0;
10858
10859 LeAudioClient::Get()->SetInCall(true);
10860
10861 // Audio sessions are started only when device gets active
10862 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10863 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10864 LeAudioClient::Get()->GroupSetActive(group_id);
10865 SyncOnMainLoop();
10866
10867 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
10868 LocalAudioSourceResume();
10869 LocalAudioSinkResume();
10870
10871 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10872 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10873 SyncOnMainLoop();
10874
10875 // Verify Data transfer on one audio source cis
10876 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10877
10878 LeAudioClient::Get()->SetInCall(false);
10879 LocalAudioSinkSuspend();
10880
10881 /* We should use GAME configuration, but do not send the GAME context type, as
10882 * it is not available on the remote device.
10883 */
10884 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10885 types::BidirectionalPair<types::AudioContexts> contexts = {
10886 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
10887 .source = types::AudioContexts()};
10888 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::GAME, contexts, _))
10889 .Times(1);
10890 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false);
10891 SyncOnMainLoop();
10892 }
10893
10894 /* Some bidirectional scenarios are triggered by the local sink, local source
10895 * metadata or the In Call preference callback call. Since each call invalidates
10896 * previous context source, make sure that getting all of these in a sequence,
10897 * always results with one bidirectional context, so that the remote device
10898 * is not confused about our intentions.
10899 */
TEST_F(UnicastTest,UpdateMultipleBidirContextTypes_SpeedUpReconfigFlagEnabled)10900 TEST_F(UnicastTest, UpdateMultipleBidirContextTypes_SpeedUpReconfigFlagEnabled) {
10901 const RawAddress test_address0 = GetTestAddress(0);
10902 int group_id = bluetooth::groups::kGroupUnknown;
10903
10904 available_snk_context_types_ = (types::LeAudioContextType::CONVERSATIONAL |
10905 types::LeAudioContextType::GAME | types::LeAudioContextType::LIVE)
10906 .value();
10907 supported_snk_context_types_ =
10908 available_snk_context_types_ |
10909 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10910 available_src_context_types_ = available_snk_context_types_;
10911 supported_src_context_types_ =
10912 available_src_context_types_ |
10913 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10914
10915 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
10916 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10917 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10918 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10919 0 /*rank*/);
10920 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10921 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10922 .Times(1);
10923 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10924 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10925 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10926
10927 ConnectLeAudio(test_address0);
10928 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10929
10930 // Audio sessions are started only when device gets active
10931 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10932 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10933 LeAudioClient::Get()->GroupSetActive(group_id);
10934 SyncOnMainLoop();
10935
10936 // When the local audio sink resumes expect only LIVE context
10937 types::BidirectionalPair<types::AudioContexts> contexts = {
10938 .sink = types::AudioContexts(types::LeAudioContextType::LIVE),
10939 .source = types::AudioContexts(types::LeAudioContextType::LIVE)};
10940 EXPECT_CALL(mock_state_machine_,
10941 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, contexts, _))
10942 .Times(1);
10943
10944 log::info("Step 1 Start the recording. Sink resume will trigger the reconfiguration");
10945 // ---------------------------------------------------------------------
10946 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
10947 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
10948 LocalAudioSinkResume();
10949
10950 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10951 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10952 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10953
10954 log::info("After the reconfiguration the local Audio Sink HAL has to resume again");
10955
10956 LocalAudioSourceResume();
10957 LocalAudioSinkResume();
10958
10959 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10960 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10961 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10962
10963 log::info("Verify Data transfer on one audio source and sink cis");
10964
10965 uint8_t cis_count_out = 1;
10966 uint8_t cis_count_in = 1;
10967 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10968
10969 log::info("Step 2 Now set in call preference to get CONVERSATIONAL into the mix");
10970 // -----------------------------------------------------------------
10971
10972 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(0);
10973 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(0);
10974 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0);
10975 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0);
10976 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10977 LeAudioClient::Get()->SetInCall(true);
10978 SyncOnMainLoop();
10979
10980 // Verify that we only got CONVERSATIONAL context and no LIVE
10981 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
10982 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
10983 EXPECT_CALL(mock_state_machine_,
10984 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
10985 contexts, _))
10986 .Times(1);
10987
10988 log::info("Start with ringtone on local source");
10989 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
10990 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
10991
10992 // Resume both directions
10993 LocalAudioSourceResume();
10994 LocalAudioSinkResume();
10995
10996 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10997 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10998 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10999
11000 // Verify Data transfer on one audio source cis
11001 cis_count_out = 1;
11002 cis_count_in = 1;
11003 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
11004
11005 log::info("Step 3 Disable call so we could go to GAME");
11006 // ---------------------------------------
11007 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(0);
11008 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(0);
11009 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0);
11010 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0);
11011 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
11012
11013 LeAudioClient::Get()->SetInCall(false);
11014 SyncOnMainLoop();
11015 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11016 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11017
11018 log::info("Start the game on local source - expect no previous sink (LIVE) metadata");
11019
11020 /* Stream shall keep streaming */
11021 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::GAME),
11022 .source = types::AudioContexts(types::LeAudioContextType::GAME)};
11023 EXPECT_CALL(mock_state_machine_, StartStream(_, _, contexts, _)).Times(1);
11024
11025 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false);
11026 LocalAudioSourceResume();
11027 SyncOnMainLoop();
11028
11029 // Verify Data transfer on one audio source cis
11030 cis_count_out = 1;
11031 cis_count_in = 1;
11032 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
11033 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11034
11035 log::info(" Step 4 Stop streaming");
11036 // ------------------
11037 StopStreaming(group_id);
11038 SyncOnMainLoop();
11039 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11040
11041 // Release
11042 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
11043 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
11044 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
11045 do_in_main_thread(base::BindOnce(
11046 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
11047 LeAudioClient::Get()));
11048 SyncOnMainLoop();
11049 }
11050
TEST_F(UnicastTest,UpdateDisableLocalAudioSinkOnGame)11051 TEST_F(UnicastTest, UpdateDisableLocalAudioSinkOnGame) {
11052 const RawAddress test_address0 = GetTestAddress(0);
11053 int group_id = bluetooth::groups::kGroupUnknown;
11054
11055 available_snk_context_types_ = (types::LeAudioContextType::CONVERSATIONAL |
11056 types::LeAudioContextType::GAME | types::LeAudioContextType::LIVE)
11057 .value();
11058 supported_snk_context_types_ =
11059 available_snk_context_types_ |
11060 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
11061 available_src_context_types_ = available_snk_context_types_;
11062 supported_src_context_types_ =
11063 available_src_context_types_ |
11064 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
11065
11066 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
11067 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11068 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
11069 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11070 0 /*rank*/);
11071 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11072 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11073 .Times(1);
11074 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11075 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11076 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11077
11078 ConnectLeAudio(test_address0);
11079 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11080
11081 // Audio sessions are started only when device gets active
11082 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11083 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11084 LeAudioClient::Get()->GroupSetActive(group_id);
11085 SyncOnMainLoop();
11086
11087 // Start GAME stream
11088 types::BidirectionalPair<types::AudioContexts> contexts = {
11089 .sink = types::AudioContexts(types::LeAudioContextType::GAME),
11090 .source = types::AudioContexts(types::LeAudioContextType::GAME)};
11091 EXPECT_CALL(mock_state_machine_,
11092 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::GAME, contexts, _))
11093 .Times(1);
11094
11095 // 1) Start the recording. Sink resume will trigger the reconfiguration
11096 // ---------------------------------------------------------------------
11097 StartStreaming(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_MIC);
11098
11099 SyncOnMainLoop();
11100
11101 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11102 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11103 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11104
11105 // Verify Data transfer on one audio source and sink cis
11106 uint8_t cis_count_out = 1;
11107 uint8_t cis_count_in = 1;
11108 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
11109
11110 SyncOnMainLoop();
11111
11112 // 2) Now Lets suspend MIC and do not expect reconfiguration
11113 // -----------------------------------------------------------------
11114
11115 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
11116 LocalAudioSinkSuspend();
11117 // simulate suspend timeout passed, alarm executing
11118 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
11119 SyncOnMainLoop();
11120 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11121 }
11122
11123 /* Start music when in a call, end the call, continue with music only */
TEST_F(UnicastTest,MetadataUpdateDuringReconfiguration)11124 TEST_F(UnicastTest, MetadataUpdateDuringReconfiguration) {
11125 const RawAddress test_address0 = GetTestAddress(0);
11126 int group_id = bluetooth::groups::kGroupUnknown;
11127
11128 /* Scenario
11129 * 1. Start reconfiguration
11130 * 2. Send metadata update
11131 * 3. Make sure metadata updates are ignored
11132 */
11133 available_snk_context_types_ =
11134 (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::RINGTONE |
11135 types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA |
11136 types::LeAudioContextType::LIVE | types::LeAudioContextType::NOTIFICATIONS)
11137 .value();
11138 supported_snk_context_types_ =
11139 available_snk_context_types_ |
11140 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
11141 available_src_context_types_ = available_snk_context_types_;
11142 supported_src_context_types_ =
11143 available_src_context_types_ |
11144 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
11145
11146 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
11147 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11148 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
11149 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11150 0 /*rank*/);
11151 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11152 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11153 .Times(1);
11154 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11155 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11156 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11157
11158 ConnectLeAudio(test_address0);
11159 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11160
11161 // Audio sessions are started only when device gets active
11162 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11163 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11164 LeAudioClient::Get()->GroupSetActive(group_id);
11165 SyncOnMainLoop();
11166 EXPECT_CALL(mock_state_machine_,
11167 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, _, _))
11168 .Times(1);
11169 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
11170 SyncOnMainLoop();
11171 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11172
11173 auto group = streaming_groups.at(group_id);
11174
11175 stay_at_qos_config_in_start_stream = true;
11176 log::info("Reconfigure to conversational and stay in Codec Config");
11177
11178 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
11179 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1);
11180
11181 LeAudioClient::Get()->SetInCall(true);
11182 SyncOnMainLoop();
11183
11184 ASSERT_TRUE(group->GetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
11185
11186 log::info("Expect not action on metadata change");
11187
11188 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
11189 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0);
11190
11191 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
11192 SyncOnMainLoop();
11193 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11194 }
11195
TEST_F(UnicastTest,MusicDuringCallContextTypes_SpeedUpReconfigFlagEnabled)11196 TEST_F(UnicastTest, MusicDuringCallContextTypes_SpeedUpReconfigFlagEnabled) {
11197 const RawAddress test_address0 = GetTestAddress(0);
11198 int group_id = bluetooth::groups::kGroupUnknown;
11199
11200 available_snk_context_types_ =
11201 (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::RINGTONE |
11202 types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA |
11203 types::LeAudioContextType::LIVE | types::LeAudioContextType::NOTIFICATIONS)
11204 .value();
11205 supported_snk_context_types_ =
11206 available_snk_context_types_ |
11207 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
11208 available_src_context_types_ = available_snk_context_types_;
11209 supported_src_context_types_ =
11210 available_src_context_types_ |
11211 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
11212
11213 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
11214 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11215 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
11216 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11217 0 /*rank*/);
11218 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11219 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11220 .Times(1);
11221 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11222 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11223 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11224
11225 ConnectLeAudio(test_address0);
11226 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11227
11228 // Audio sessions are started only when device gets active
11229 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11230 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11231 LeAudioClient::Get()->GroupSetActive(group_id);
11232 SyncOnMainLoop();
11233
11234 log::info("Step 1 Start with the call first");
11235 // -----------------------------
11236 // CONVERSATIONAL is from In Call preference, and RINGTONE is from metadata
11237 LeAudioClient::Get()->SetInCall(true);
11238 types::BidirectionalPair<types::AudioContexts> contexts = {
11239 .sink = types::AudioContexts(types::LeAudioContextType::RINGTONE |
11240 types::LeAudioContextType::CONVERSATIONAL),
11241 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
11242 EXPECT_CALL(mock_state_machine_,
11243 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
11244 contexts, _))
11245 .Times(1);
11246 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
11247 LocalAudioSourceResume();
11248 LocalAudioSinkResume();
11249
11250 // Verify
11251 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11252 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11253 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11254
11255 // Verify Data transfer
11256 uint8_t cis_count_out = 1;
11257 uint8_t cis_count_in = 1;
11258 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
11259
11260 log::info("Step 2) Start MEDIA during the call, expect MEDIA only on the remote sink");
11261
11262 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL |
11263 types::LeAudioContextType::MEDIA),
11264 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
11265 EXPECT_CALL(mock_state_machine_,
11266 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
11267 contexts, _))
11268 .Times(1);
11269 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, false);
11270 SyncOnMainLoop();
11271
11272 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11273 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11274 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11275
11276 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
11277 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::MEDIA |
11278 types::LeAudioContextType::CONVERSATIONAL),
11279 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
11280 EXPECT_CALL(mock_state_machine_,
11281 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, contexts, _))
11282 .Times(1);
11283 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC,
11284 /*reconfigure=*/false);
11285 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11286 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11287 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11288
11289 log::info("Step 3) Disable call so we could go back to MEDIA");
11290 // ---------------------------------------
11291 // Suspend should stop the stream
11292 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
11293 LocalAudioSourceSuspend();
11294 LocalAudioSinkSuspend();
11295 // simulate suspend timeout passed, alarm executing
11296 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
11297
11298 LeAudioClient::Get()->SetInCall(false);
11299 SyncOnMainLoop();
11300 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11301
11302 // Restart the stream with MEDIA
11303 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
11304 .source = types::AudioContexts()};
11305 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::MEDIA, contexts, _))
11306 .Times(1);
11307 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC,
11308 /*reconfigure=*/false);
11309 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11310 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11311
11312 /* The source needs to resume to reconfigure to MEDIA */
11313 LocalAudioSourceResume(/*expect_confirm=*/false);
11314 LocalAudioSourceResume(/*expect_confirm=*/true);
11315 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11316 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11317 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11318
11319 log::info("Step 3) Stop streaming");
11320
11321 // ------------------
11322 StopStreaming(group_id);
11323 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11324
11325 // Release
11326 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
11327 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
11328 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
11329 do_in_main_thread(base::BindOnce(
11330 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
11331 LeAudioClient::Get()));
11332 SyncOnMainLoop();
11333 }
11334
11335 /* When a certain context is unavailable but supported we should not stream that
11336 * context - either stop the stream or eliminate this strim from the mix
11337 * This could be na IOP issue so continue streaming (and reconfigure if needed
11338 * for that use case).
11339 * Since the unavailable context is supported, do not put this context into
11340 * the metadata, and do not replace it with UNSPECIFIED.
11341 */
TEST_F(UnicastTest,StartNotAvailableSupportedContextType)11342 TEST_F(UnicastTest, StartNotAvailableSupportedContextType) {
11343 const RawAddress test_address0 = GetTestAddress(0);
11344 int group_id = bluetooth::groups::kGroupUnknown;
11345
11346 // EMERGENCYALARM is not available, but supported
11347 available_snk_context_types_ =
11348 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
11349 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
11350 .value();
11351 available_src_context_types_ = available_snk_context_types_;
11352 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
11353 supported_src_context_types_ =
11354 (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED).value();
11355
11356 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11357 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11358 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11359 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11360 0 /*rank*/);
11361 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11362 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11363 .Times(1);
11364 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11365 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11366 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11367
11368 ConnectLeAudio(test_address0);
11369 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11370
11371 // Expect configuring to (or staying with) the right configuration but the
11372 // metadata should not get the EMERGENCYALARM context, nor the UNSPECIFIED
11373 // Since the initial config is UNSPECIFIED, then even for sonification events
11374 // we should reconfigure to less generic EMERGENCYALARM scenario
11375 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11376 types::BidirectionalPair<types::AudioContexts> metadata = {.sink = types::AudioContexts(),
11377 .source = types::AudioContexts()};
11378 EXPECT_CALL(mock_state_machine_,
11379 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
11380 .Times(0);
11381
11382 LeAudioClient::Get()->GroupSetActive(group_id);
11383 SyncOnMainLoop();
11384
11385 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID,
11386 false, false);
11387
11388 SyncOnMainLoop();
11389 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11390 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11391 }
11392
11393 /* When a certain context is unavailable and not supported and the UNSPECIFIED
11394 * is not available we should stop the stream.
11395 * For now, stream will not be started in such a case.
11396 * In future we should be able to eliminate this context from the track mix.
11397 */
TEST_F(UnicastTest,StartNotAvailableUnsupportedContextTypeUnspecifiedUnavail)11398 TEST_F(UnicastTest, StartNotAvailableUnsupportedContextTypeUnspecifiedUnavail) {
11399 const RawAddress test_address0 = GetTestAddress(0);
11400 int group_id = bluetooth::groups::kGroupUnknown;
11401
11402 // EMERGENCYALARM is not available, nor supported
11403 available_snk_context_types_ =
11404 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
11405 types::LeAudioContextType::MEDIA)
11406 .value();
11407 available_src_context_types_ = available_snk_context_types_;
11408 supported_snk_context_types_ =
11409 (available_snk_context_types_ | types::LeAudioContextType::UNSPECIFIED).value();
11410 supported_src_context_types_ =
11411 (available_src_context_types_ | types::LeAudioContextType::UNSPECIFIED).value();
11412
11413 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11414 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11415 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11416 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11417 0 /*rank*/);
11418 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11419 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11420 .Times(1);
11421 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11422 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11423 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11424
11425 ConnectLeAudio(test_address0);
11426 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11427
11428 // Expect configuring to the default config since the EMERGENCYALARM is
11429 // not on the list of supported contexts and UNSPECIFIED should not be
11430 // in the metadata as it is unavailable.
11431 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11432 types::BidirectionalPair<types::AudioContexts> metadata = {.sink = types::AudioContexts(),
11433 .source = types::AudioContexts()};
11434 EXPECT_CALL(mock_state_machine_,
11435 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
11436 .Times(0);
11437
11438 LeAudioClient::Get()->GroupSetActive(group_id);
11439 SyncOnMainLoop();
11440
11441 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID,
11442 false, false);
11443
11444 SyncOnMainLoop();
11445 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11446 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11447 }
11448
11449 /* This test verifies if we use UNSPCIFIED context when another context is
11450 * unavailable and not supported but UNSPCIFIED is in available audio contexts.
11451 */
TEST_F(UnicastTest,StartNotAvailableUnsupportedContextTypeUnspecifiedAvail)11452 TEST_F(UnicastTest, StartNotAvailableUnsupportedContextTypeUnspecifiedAvail) {
11453 const RawAddress test_address0 = GetTestAddress(0);
11454 int group_id = bluetooth::groups::kGroupUnknown;
11455
11456 // EMERGENCYALARM is not available, nor supported
11457 available_snk_context_types_ =
11458 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
11459 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
11460 .value();
11461 available_src_context_types_ = available_snk_context_types_;
11462 supported_snk_context_types_ = available_snk_context_types_;
11463 supported_src_context_types_ = available_src_context_types_;
11464
11465 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11466 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11467 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11468 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11469 0 /*rank*/);
11470 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11471 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11472 .Times(1);
11473 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11474 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11475 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11476
11477 ConnectLeAudio(test_address0);
11478 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11479
11480 // Expect configuring to the default config since the EMERGENCYALARM is
11481 // not on the list of supported contexts and UNSPECIFIED will be used in
11482 // the metadata.
11483 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11484 types::BidirectionalPair<types::AudioContexts> metadata = {
11485 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
11486 .source = types::AudioContexts()};
11487 EXPECT_CALL(mock_state_machine_,
11488 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
11489 .Times(1);
11490
11491 LeAudioClient::Get()->GroupSetActive(group_id);
11492 SyncOnMainLoop();
11493
11494 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
11495
11496 SyncOnMainLoop();
11497 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11498 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11499
11500 // Verify Data transfer on one audio source cis
11501 uint8_t cis_count_out = 1;
11502 uint8_t cis_count_in = 0;
11503 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
11504 }
11505
TEST_F(UnicastTest,NotifyAboutGroupTunrnedIdleEnabled)11506 TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleEnabled) {
11507 const RawAddress test_address0 = GetTestAddress(0);
11508 int group_id = bluetooth::groups::kGroupUnknown;
11509
11510 osi_property_set_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall, true);
11511
11512 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11513 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11514 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11515 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11516 0 /*rank*/);
11517 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11518 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11519 .Times(1);
11520 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11521 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11522 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11523
11524 ConnectLeAudio(test_address0);
11525 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11526
11527 // Start streaming
11528 uint8_t cis_count_out = 1;
11529 uint8_t cis_count_in = 0;
11530
11531 LeAudioClient::Get()->SetInCall(true);
11532
11533 // Audio sessions are started only when device gets active
11534 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11535 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11536 LeAudioClient::Get()->GroupSetActive(group_id);
11537 SyncOnMainLoop();
11538
11539 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
11540
11541 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11542 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11543 SyncOnMainLoop();
11544
11545 // Verify Data transfer on one audio source cis
11546 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
11547
11548 // Release
11549
11550 /* To be called twice
11551 * 1. GroupStatus::INACTIVE
11552 * 2. GroupStatus::TURNED_IDLE_DURING_CALL
11553 */
11554 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, _)).Times(2);
11555
11556 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
11557 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
11558 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
11559
11560 do_in_main_thread(base::BindOnce(
11561 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
11562 LeAudioClient::Get()));
11563
11564 SyncOnMainLoop();
11565 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11566
11567 LeAudioClient::Get()->SetInCall(false);
11568 osi_property_set_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall, false);
11569 }
11570
TEST_F(UnicastTest,NotifyAboutGroupTunrnedIdleDisabled)11571 TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleDisabled) {
11572 const RawAddress test_address0 = GetTestAddress(0);
11573 int group_id = bluetooth::groups::kGroupUnknown;
11574
11575 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11576 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11577 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11578 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11579 0 /*rank*/);
11580 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11581 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11582 .Times(1);
11583 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11584 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11585 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11586
11587 ConnectLeAudio(test_address0);
11588 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11589
11590 // Start streaming
11591 uint8_t cis_count_out = 1;
11592 uint8_t cis_count_in = 0;
11593
11594 LeAudioClient::Get()->SetInCall(true);
11595
11596 // Audio sessions are started only when device gets active
11597 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11598 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11599 LeAudioClient::Get()->GroupSetActive(group_id);
11600 SyncOnMainLoop();
11601
11602 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
11603
11604 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11605 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11606 SyncOnMainLoop();
11607
11608 // Verify Data transfer on one audio source cis
11609 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
11610
11611 // Release
11612
11613 /* To be called once only
11614 * 1. GroupStatus::INACTIVE
11615 */
11616 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, _)).Times(1);
11617
11618 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
11619 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
11620 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
11621
11622 do_in_main_thread(base::BindOnce(
11623 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
11624 LeAudioClient::Get()));
11625
11626 SyncOnMainLoop();
11627 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11628
11629 LeAudioClient::Get()->SetInCall(false);
11630 }
11631
TEST_F(UnicastTest,HandleDatabaseOutOfSync)11632 TEST_F(UnicastTest, HandleDatabaseOutOfSync) {
11633 const RawAddress test_address0 = GetTestAddress(0);
11634 int group_id = bluetooth::groups::kGroupUnknown;
11635
11636 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11637 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11638 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11639 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11640 0 /*rank*/);
11641 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11642 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11643 .Times(1);
11644 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11645 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11646 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11647
11648 ConnectLeAudio(test_address0);
11649 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11650
11651 SyncOnMainLoop();
11652 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11653
11654 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11655 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
11656 .Times(1);
11657 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
11658 SyncOnMainLoop();
11659 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11660 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11661
11662 /* Simulate DATABASE OUT OF SYNC */
11663 ccc_stored_byte_val_ = 0x01;
11664 gatt_read_ctp_ccc_status_ = GATT_DATABASE_OUT_OF_SYNC;
11665
11666 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)).Times(0);
11667 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _)).WillByDefault(Return());
11668 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _));
11669
11670 InjectConnectedEvent(test_address0, 1);
11671 SyncOnMainLoop();
11672 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11673 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11674 }
11675
TEST_F(UnicastTest,TestRemoteDeviceKeepCccValues)11676 TEST_F(UnicastTest, TestRemoteDeviceKeepCccValues) {
11677 const RawAddress test_address0 = GetTestAddress(0);
11678 int group_id = bluetooth::groups::kGroupUnknown;
11679
11680 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11681 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11682 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11683 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11684 0 /*rank*/);
11685 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11686 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11687 .Times(1);
11688 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11689 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11690 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11691
11692 ConnectLeAudio(test_address0);
11693 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11694
11695 SyncOnMainLoop();
11696 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11697
11698 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11699 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
11700 .Times(1);
11701 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
11702 SyncOnMainLoop();
11703 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11704 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11705
11706 /* Simulate remote cache is good */
11707 ccc_stored_byte_val_ = 0x01;
11708
11709 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)).Times(0);
11710 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11711 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11712 .Times(1);
11713
11714 InjectConnectedEvent(test_address0, 1);
11715 SyncOnMainLoop();
11716 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11717 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11718 }
11719
TEST_F(UnicastTest,TestRemoteDeviceForgetsCccValues)11720 TEST_F(UnicastTest, TestRemoteDeviceForgetsCccValues) {
11721 const RawAddress test_address0 = GetTestAddress(0);
11722 int group_id = bluetooth::groups::kGroupUnknown;
11723
11724 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11725 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11726 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11727 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11728 0 /*rank*/);
11729 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11730 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11731 .Times(1);
11732 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11733 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11734 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11735
11736 ConnectLeAudio(test_address0);
11737 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11738
11739 SyncOnMainLoop();
11740 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11741
11742 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11743 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
11744 .Times(1);
11745 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
11746 SyncOnMainLoop();
11747 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11748 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11749
11750 /* Simulate remote cache is broken */
11751 ccc_stored_byte_val_ = 0;
11752 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)).Times(AtLeast(1));
11753 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11754 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11755 .Times(1);
11756
11757 InjectConnectedEvent(test_address0, 1);
11758 SyncOnMainLoop();
11759 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11760 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11761 }
11762
TEST_F(UnicastTest,SpeakerStreamingTimeout)11763 TEST_F(UnicastTest, SpeakerStreamingTimeout) {
11764 const RawAddress test_address0 = GetTestAddress(0);
11765 int group_id = bluetooth::groups::kGroupUnknown;
11766
11767 SetSampleDatabaseEarbudsValid(
11768 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11769 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
11770 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
11771 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
11772 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11773 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11774 .Times(1);
11775 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11776 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11777 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11778
11779 ConnectLeAudio(test_address0);
11780 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11781
11782 // Start streaming
11783 uint8_t cis_count_out = 1;
11784 uint8_t cis_count_in = 0;
11785
11786 // Audio sessions are started only when device gets active
11787 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11788 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11789 LeAudioClient::Get()->GroupSetActive(group_id);
11790 SyncOnMainLoop();
11791
11792 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
11793
11794 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11795 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11796 SyncOnMainLoop();
11797
11798 // Verify Data transfer on one audio source cis
11799 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
11800
11801 auto group = streaming_groups.at(group_id);
11802 auto device = group->GetFirstActiveDevice();
11803
11804 // Do not accept direct connect, but expect it to arrive.
11805 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
11806
11807 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(device->conn_id_, _)).Times(1);
11808 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
11809 .WillByDefault([](uint16_t handle, tHCI_STATUS /*rs*/) {
11810 ASSERT_NE(handle, GATT_INVALID_CONN_ID);
11811 // Do nothing here now.
11812 });
11813
11814 state_machine_callbacks_->OnStateTransitionTimeout(group_id);
11815 SyncOnMainLoop();
11816 ASSERT_EQ(device->GetConnectionState(), DeviceConnectState::DISCONNECTING_AND_RECOVER);
11817
11818 InjectDisconnectedEvent(device->conn_id_, GATT_CONN_TERMINATE_LOCAL_HOST);
11819 SyncOnMainLoop();
11820
11821 /* No assigned cises should remain when transition remains in IDLE state */
11822 ASSERT_NE(0lu, streaming_groups.count(group_id));
11823 ASSERT_EQ(0, static_cast<int>(group->cig.cises.size()));
11824 ASSERT_TRUE(device != nullptr);
11825 ASSERT_EQ(device->GetConnectionState(), DeviceConnectState::CONNECTING_AUTOCONNECT);
11826 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
11827 }
11828
TEST_F(UnicastTest,AddMemberToAllowListWhenOneDeviceConnected)11829 TEST_F(UnicastTest, AddMemberToAllowListWhenOneDeviceConnected) {
11830 uint8_t group_size = 2;
11831 int group_id = 2;
11832 int conn_id_dev_0 = 1;
11833 int conn_id_dev_1 = 2;
11834
11835 /*Scenario to test
11836 * 1. Connect Device A and disconnect
11837 * 2. Connect Device B
11838 * 3. verify Device B is in the allow list with direct connect.
11839 */
11840 // Report working CSIS
11841 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
11842
11843 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
11844 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
11845
11846 // First earbud
11847 const RawAddress test_address0 = GetTestAddress(0);
11848 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
11849
11850 ConnectCsisDevice(test_address0, conn_id_dev_0, codec_spec_conf::kLeAudioLocationFrontLeft,
11851 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
11852
11853 SyncOnMainLoop();
11854
11855 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
11856 EXPECT_CALL(mock_gatt_interface_,
11857 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11858 .Times(1);
11859
11860 InjectDisconnectedEvent(conn_id_dev_0);
11861
11862 SyncOnMainLoop();
11863 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11864
11865 // Second earbud
11866 const RawAddress test_address1 = GetTestAddress(1);
11867 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
11868
11869 /* Do not connect first device but expect Open will arrive.*/
11870 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
11871 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11872 .Times(1);
11873 ON_CALL(mock_gatt_interface_, Open(_, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11874 .WillByDefault(Return());
11875
11876 ConnectCsisDevice(test_address1, conn_id_dev_1, codec_spec_conf::kLeAudioLocationFrontRight,
11877 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
11878 true /*connect_through_csis*/);
11879
11880 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11881 }
11882
TEST_F(UnicastTest,ResetToDefaultReconnectionMode)11883 TEST_F(UnicastTest, ResetToDefaultReconnectionMode) {
11884 uint8_t group_size = 2;
11885 int group_id = 2;
11886 int conn_id_dev_0 = 1;
11887 int conn_id_dev_1 = 2;
11888
11889 /*Scenario to test
11890 * 1. Connect Device A and disconnect
11891 * 2. Connect Device B
11892 * 3. verify Device B is in the allow list.
11893 * 4. Disconnect B device
11894 * 5, Verify A and B device are back in targeted announcement reconnection
11895 * mode
11896 */
11897 // Report working CSIS
11898 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
11899
11900 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
11901 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
11902
11903 // First earbud
11904 const RawAddress test_address0 = GetTestAddress(0);
11905 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
11906
11907 ConnectCsisDevice(test_address0, conn_id_dev_0, codec_spec_conf::kLeAudioLocationFrontLeft,
11908 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
11909
11910 SyncOnMainLoop();
11911
11912 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
11913 EXPECT_CALL(mock_gatt_interface_,
11914 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11915 .Times(1);
11916
11917 InjectDisconnectedEvent(conn_id_dev_0);
11918
11919 SyncOnMainLoop();
11920 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11921
11922 // Second earbud
11923 const RawAddress test_address1 = GetTestAddress(1);
11924 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
11925
11926 /* Verify first earbud will start doing direct connect first */
11927 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
11928 ON_CALL(mock_gatt_interface_, Open(_, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11929 .WillByDefault(Return());
11930 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11931 .Times(1);
11932
11933 ConnectCsisDevice(test_address1, conn_id_dev_1, codec_spec_conf::kLeAudioLocationFrontRight,
11934 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
11935 true /*connect_through_csis*/);
11936
11937 SyncOnMainLoop();
11938 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11939
11940 // Disconnect Device B, expect default reconnection mode for Device A.
11941 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
11942 EXPECT_CALL(mock_gatt_interface_,
11943 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11944 .Times(1);
11945 EXPECT_CALL(mock_gatt_interface_,
11946 Open(gatt_if, test_address1, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11947 .Times(1);
11948 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address1, false)).Times(1);
11949
11950 InjectDisconnectedEvent(conn_id_dev_1, GATT_CONN_TERMINATE_PEER_USER);
11951 SyncOnMainLoop();
11952
11953 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11954 }
11955
TEST_F(UnicastTest,DisconnectAclBeforeGettingReadResponses)11956 TEST_F(UnicastTest, DisconnectAclBeforeGettingReadResponses) {
11957 uint8_t group_size = 2;
11958 int group_id = 2;
11959
11960 // Report working CSIS
11961 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
11962
11963 const RawAddress test_address0 = GetTestAddress(0);
11964 const RawAddress test_address1 = GetTestAddress(1);
11965
11966 /* Due to imitated problems with GATT read operations (status != GATT_SUCCESS)
11967 * a CONNECTED state should not be propagated together with audio location
11968 */
11969 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11970 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11971 .Times(0);
11972 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11973 OnSinkAudioLocationAvailable(test_address0,
11974 std::make_optional<std::bitset<32>>(
11975 codec_spec_conf::kLeAudioLocationFrontLeft)))
11976 .Times(0);
11977
11978 // First earbud initial connection
11979 SetSampleDatabaseEarbudsValid(1 /* conn_id */, test_address0,
11980 codec_spec_conf::kLeAudioLocationFrontLeft,
11981 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
11982 default_channel_cnt, 0x0004, /* source sample freq 16khz */
11983 true, /*add_csis*/
11984 true, /*add_cas*/
11985 true, /*add_pacs*/
11986 true, /*add_ascs*/
11987 group_size, 1 /* rank */, GATT_INTERNAL_ERROR);
11988 groups[test_address0] = group_id;
11989 // by default indicate link as encrypted
11990 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
11991 .WillByDefault(DoAll(Return(true)));
11992
11993 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11994 .Times(1);
11995 /* When connected it will got to TA */
11996 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
11997 EXPECT_CALL(mock_gatt_interface_,
11998 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11999 .Times(1);
12000
12001 do_in_main_thread(base::BindOnce(&LeAudioClient::Connect, base::Unretained(LeAudioClient::Get()),
12002 test_address0));
12003
12004 SyncOnMainLoop();
12005 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
12006 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
12007 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12008 InjectGroupDeviceAdded(test_address0, group_id);
12009
12010 // Second earbud initial connection
12011 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12012 OnSinkAudioLocationAvailable(test_address1,
12013 std::make_optional<std::bitset<32>>(
12014 codec_spec_conf::kLeAudioLocationFrontRight)))
12015 .Times(1);
12016
12017 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12018 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12019 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12020 true /*connect_through_csis*/);
12021
12022 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
12023
12024 /* for Target announcements AutoConnect is always there, until
12025 * device is removed
12026 */
12027 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false)).Times(0);
12028 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(0);
12029
12030 // Verify grouping information
12031 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
12032 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
12033 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
12034
12035 /* Remove default action on the direct connect */
12036 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
12037
12038 /* Initiate disconnection with timeout reason, the possible reason why GATT
12039 * read attribute operation may be not handled
12040 */
12041 InjectDisconnectedEvent(1, GATT_CONN_TIMEOUT);
12042 SyncOnMainLoop();
12043
12044 /* After reconnection a sink audio location callback with connection state
12045 * should be propagated.
12046 */
12047 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12048 OnConnectionState(ConnectionState::CONNECTED, test_address0))
12049 .Times(1);
12050 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12051 OnSinkAudioLocationAvailable(test_address0,
12052 std::make_optional<std::bitset<32>>(
12053 codec_spec_conf::kLeAudioLocationFrontLeft)))
12054 .Times(1);
12055
12056 /* Prepare valid GATT status responsing attributes */
12057 SetSampleDatabaseEarbudsValid(1 /* conn_id */, test_address0,
12058 codec_spec_conf::kLeAudioLocationFrontLeft,
12059 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
12060 default_channel_cnt, 0x0004, /* source sample freq 16khz */
12061 true, /*add_csis*/
12062 true, /*add_cas*/
12063 true, /*add_pacs*/
12064 true, /*add_ascs*/
12065 group_size, 1 /* rank */);
12066
12067 /* For background connect, test needs to Inject Connected Event */
12068 InjectConnectedEvent(test_address0, 1);
12069 SyncOnMainLoop();
12070 }
12071
TEST_F(UnicastTest,GroupStreamStatus)12072 TEST_F(UnicastTest, GroupStreamStatus) {
12073 int group_id = bluetooth::groups::kGroupUnknown;
12074
12075 InSequence s;
12076
12077 /* Check if all states are properly notified */
12078 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12079 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12080 .Times(1);
12081 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12082
12083 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12084 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12085 .Times(1);
12086 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12087
12088 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12089 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12090 .Times(1);
12091 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::RELEASING);
12092
12093 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12094 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12095 .Times(1);
12096 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12097
12098 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12099 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12100 .Times(1);
12101 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::RELEASING_AUTONOMOUS);
12102
12103 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12104 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12105 .Times(1);
12106 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12107
12108 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12109 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12110 .Times(1);
12111 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::SUSPENDING);
12112
12113 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12114 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12115 .Times(1);
12116 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12117
12118 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12119 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12120 .Times(1);
12121 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::SUSPENDED);
12122
12123 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12124 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12125 .Times(1);
12126 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12127
12128 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12129 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12130 .Times(1);
12131 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::CONFIGURED_AUTONOMOUS);
12132
12133 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12134 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12135 .Times(1);
12136 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12137
12138 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12139 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12140 .Times(1);
12141 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::CONFIGURED_BY_USER);
12142
12143 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12144 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12145 .Times(1);
12146 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12147
12148 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12149 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12150 .Times(1);
12151 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::DESTROYED);
12152
12153 /* Check if there are no resending of the same state */
12154 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::RELEASING);
12155 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::SUSPENDING);
12156 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::SUSPENDED);
12157 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::CONFIGURED_AUTONOMOUS);
12158 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::CONFIGURED_BY_USER);
12159 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12160
12161 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12162 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12163 .Times(1);
12164 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12165 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12166 }
12167
TEST_F(UnicastTest,GroupStreamStatusManyGroups)12168 TEST_F(UnicastTest, GroupStreamStatusManyGroups) {
12169 uint8_t group_size = 2;
12170 int group_id_1 = 1;
12171 int group_id_2 = 2;
12172
12173 // Report working CSIS
12174 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12175
12176 ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Return(group_size));
12177
12178 // First group - First earbud
12179 const RawAddress test_address0 = GetTestAddress(0);
12180 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12181 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12182 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_1,
12183 1 /* rank*/);
12184
12185 // First group - Second earbud
12186 const RawAddress test_address1 = GetTestAddress(1);
12187 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12188 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12189 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id_1,
12190 2 /* rank*/, true /*connect_through_csis*/);
12191
12192 // Second group - First earbud
12193 const RawAddress test_address2 = GetTestAddress(2);
12194 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address2, true)).Times(1);
12195 ConnectCsisDevice(test_address2, 3 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12196 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_2,
12197 1 /* rank*/);
12198
12199 // Second group - Second earbud
12200 const RawAddress test_address3 = GetTestAddress(3);
12201 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address3, true)).Times(1);
12202 ConnectCsisDevice(test_address3, 4 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12203 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id_2,
12204 2 /* rank*/, true /*connect_through_csis*/);
12205
12206 InSequence s;
12207
12208 // Group 1 IDLE
12209 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12210 OnGroupStreamStatus(group_id_1, GroupStreamStatus::IDLE))
12211 .Times(1);
12212 state_machine_callbacks_->StatusReportCb(group_id_1, GroupStreamStatus::IDLE);
12213
12214 // Group 2 IDLE
12215 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12216 OnGroupStreamStatus(group_id_2, GroupStreamStatus::IDLE))
12217 .Times(1);
12218 state_machine_callbacks_->StatusReportCb(group_id_2, GroupStreamStatus::IDLE);
12219
12220 log::info("Group 1 active and start streaming");
12221 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12222 OnGroupStreamStatus(group_id_1, GroupStreamStatus::STREAMING))
12223 .Times(1);
12224 LeAudioClient::Get()->GroupSetActive(group_id_1);
12225 SyncOnMainLoop();
12226 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_1);
12227 SyncOnMainLoop();
12228 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12229
12230 log::info("Group 2 is getting active");
12231 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12232 OnGroupStreamStatus(group_id_1, GroupStreamStatus::IDLE))
12233 .Times(1);
12234 LeAudioClient::Get()->GroupSetActive(group_id_2);
12235 SyncOnMainLoop();
12236 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12237
12238 log::info("Group 2 is starts streaming");
12239 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12240 OnGroupStreamStatus(group_id_2, GroupStreamStatus::STREAMING))
12241 .Times(1);
12242 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_2);
12243 SyncOnMainLoop();
12244 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12245 }
12246
TEST_F(UnicastTest,GroupStreamStatusManyGroups_GettingConfigWhileOtherGroupIsStreaming)12247 TEST_F(UnicastTest, GroupStreamStatusManyGroups_GettingConfigWhileOtherGroupIsStreaming) {
12248 uint8_t group_size = 2;
12249 int group_id_1 = 1;
12250 int group_id_2 = 2;
12251
12252 // Report working CSIS
12253 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12254
12255 ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Return(group_size));
12256
12257 // First group - First earbud
12258 const RawAddress test_address0 = GetTestAddress(0);
12259 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12260 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12261 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_1,
12262 1 /* rank*/);
12263
12264 // First group - Second earbud
12265 const RawAddress test_address1 = GetTestAddress(1);
12266 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12267 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12268 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id_1,
12269 2 /* rank*/, true /*connect_through_csis*/);
12270
12271 // Second group - First earbud
12272 const RawAddress test_address2 = GetTestAddress(2);
12273 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address2, true)).Times(1);
12274 ConnectCsisDevice(test_address2, 3 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12275 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_2,
12276 1 /* rank*/);
12277
12278 // Second group - Second earbud
12279 const RawAddress test_address3 = GetTestAddress(3);
12280 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address3, true)).Times(1);
12281 ConnectCsisDevice(test_address3, 4 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12282 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id_2,
12283 2 /* rank*/, true /*connect_through_csis*/);
12284
12285 InSequence s;
12286
12287 // Group 1 IDLE
12288 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12289 OnGroupStreamStatus(group_id_1, GroupStreamStatus::IDLE))
12290 .Times(1);
12291 state_machine_callbacks_->StatusReportCb(group_id_1, GroupStreamStatus::IDLE);
12292
12293 // Group 2 IDLE
12294 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12295 OnGroupStreamStatus(group_id_2, GroupStreamStatus::IDLE))
12296 .Times(1);
12297 state_machine_callbacks_->StatusReportCb(group_id_2, GroupStreamStatus::IDLE);
12298
12299 log::info("Group 1 active and start streaming");
12300 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12301 OnGroupStreamStatus(group_id_1, GroupStreamStatus::STREAMING))
12302 .Times(1);
12303 LeAudioClient::Get()->GroupSetActive(group_id_1);
12304 SyncOnMainLoop();
12305 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_1);
12306 SyncOnMainLoop();
12307 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12308
12309 log::info("Group 2 is getting active");
12310 stay_at_releasing_stop_stream = true;
12311 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12312 OnGroupStreamStatus(group_id_1, GroupStreamStatus::IDLE))
12313 .Times(1);
12314 LeAudioClient::Get()->GroupSetActive(group_id_2);
12315 SyncOnMainLoop();
12316
12317 log::info("Group 2 is starts streaming");
12318 stay_at_qos_config_in_start_stream = true;
12319 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12320 OnGroupStreamStatus(group_id_2, GroupStreamStatus::STREAMING))
12321 .Times(1);
12322 EXPECT_CALL(*mock_le_audio_source_hal_client_, ConfirmStreamingRequest()).Times(1);
12323
12324 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_2, AUDIO_SOURCE_INVALID,
12325 false, false);
12326
12327 log::info("Group 1 going to IDLE");
12328 do_in_main_thread(base::BindOnce(
12329 [](int group_id,
12330 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks) {
12331 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12332 },
12333 group_id_1, base::Unretained(this->state_machine_callbacks_)));
12334 SyncOnMainLoop();
12335 log::info("Group 2 going to STREAMING");
12336 do_in_main_thread(base::BindOnce(
12337 [](int group_id,
12338 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks) {
12339 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12340 },
12341 group_id_2, base::Unretained(this->state_machine_callbacks_)));
12342 SyncOnMainLoop();
12343 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12344 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12345 }
12346
TEST_F(UnicastTest,GroupStreamStatusResendAfterRemove)12347 TEST_F(UnicastTest, GroupStreamStatusResendAfterRemove) {
12348 uint8_t group_size = 2;
12349 int group_id = 1;
12350
12351 // Report working CSIS
12352 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12353
12354 ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Return(group_size));
12355
12356 // First earbud
12357 const RawAddress test_address0 = GetTestAddress(0);
12358 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12359 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12360 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12361
12362 // Second earbud
12363 const RawAddress test_address1 = GetTestAddress(1);
12364 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12365 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12366 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12367 true /*connect_through_csis*/);
12368
12369 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
12370
12371 InSequence s;
12372
12373 // Activate group, start streaming and immediately stop
12374 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12375 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12376 .Times(1);
12377 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12378 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12379 .Times(1);
12380 LeAudioClient::Get()->GroupSetActive(group_id);
12381 SyncOnMainLoop();
12382 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12383 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12384
12385 // No resend
12386 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12387 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12388 .Times(0);
12389 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12390
12391 // No resend after removing only one device
12392 /*
12393 * StopStream will put calls on main_loop so to keep the correct order
12394 * of operations and to avoid races we put the test command on main_loop as
12395 * well.
12396 */
12397 do_in_main_thread(base::BindOnce(
12398 [](LeAudioClient* client, const RawAddress& test_address0) {
12399 client->RemoveDevice(test_address0);
12400 },
12401 LeAudioClient::Get(), test_address0));
12402 SyncOnMainLoop();
12403 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12404 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12405 .Times(0);
12406 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12407 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12408
12409 // Resend after removing last device
12410 /*
12411 * StopStream will put calls on main_loop so to keep the correct order
12412 * of operations and to avoid races we put the test command on main_loop as
12413 * well.
12414 */
12415 do_in_main_thread(base::BindOnce(
12416 [](LeAudioClient* client, const RawAddress& test_address1) {
12417 client->RemoveDevice(test_address1);
12418 },
12419 LeAudioClient::Get(), test_address1));
12420 SyncOnMainLoop();
12421 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12422 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12423 .Times(1);
12424 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12425 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12426 }
12427
TEST_F(UnicastTestHandoverMode,SetSinkMonitorModeWhileUnicastIsActive)12428 TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsActive) {
12429 uint8_t group_size = 2;
12430 int group_id = 2;
12431
12432 // Report working CSIS
12433 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12434
12435 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
12436 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
12437
12438 // First earbud
12439 const RawAddress test_address0 = GetTestAddress(0);
12440 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12441 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12442 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12443
12444 // Second earbud
12445 const RawAddress test_address1 = GetTestAddress(1);
12446 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12447 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12448 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12449 true /*connect_through_csis*/);
12450
12451 // Start streaming
12452 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12453 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12454 LeAudioClient::Get()->GroupSetActive(group_id);
12455 SyncOnMainLoop();
12456
12457 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12458
12459 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12460
12461 SyncOnMainLoop();
12462 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12463 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12464
12465 // Verify Data transfer on two peer sinks and one source
12466 uint8_t cis_count_out = 2;
12467 uint8_t cis_count_in = 2;
12468 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
12469
12470 // Imitate activation of monitor mode
12471 do_in_main_thread(base::BindOnce(
12472 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12473 bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */));
12474
12475 ASSERT_NE(0lu, streaming_groups.count(group_id));
12476 auto group = streaming_groups.at(group_id);
12477
12478 // Stop streaming and expect Service to be informed about straming suspension
12479 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12480 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12481 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12482 .Times(1);
12483
12484 // Stop
12485 StopStreaming(group_id, true);
12486
12487 if (com::android::bluetooth::flags::leaudio_use_audio_recording_listener()) {
12488 // simulate suspend timeout passed, alarm executing
12489 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
12490 SyncOnMainLoop();
12491 } else {
12492 // Check if cache configuration is still present
12493 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12494 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12495 .size());
12496 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12497 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12498 .size());
12499
12500 // Release, Sink HAL client should remain in monitor mode
12501 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12502 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12503 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
12504 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
12505 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12506 SyncOnMainLoop();
12507
12508 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12509 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12510 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12511
12512 // Re-initialize mock for destroyed hal client
12513 RegisterSourceHalClientMock();
12514
12515 // Setting group inactive, shall not change cached configuration
12516 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12517 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12518 .size());
12519 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12520 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12521 .size());
12522
12523 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12524 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12525 UnicastMonitorModeStatus::STREAMING_REQUESTED))
12526 .Times(1);
12527
12528 // Start streaming to trigger next group going to IDLE state
12529 LocalAudioSinkResume();
12530
12531 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12532 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12533 LeAudioClient::Get()->GroupSetActive(group_id);
12534 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12535 SyncOnMainLoop();
12536
12537 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12538
12539 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12540 SyncOnMainLoop();
12541 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12542
12543 // Stop streaming and expect Service to be informed about straming suspension
12544 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12545 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12546 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12547 .Times(1);
12548
12549 // Stop
12550 StopStreaming(group_id, true);
12551
12552 // Release, Sink HAL client should remain in monitor mode
12553 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12554 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12555 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
12556 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
12557 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12558 SyncOnMainLoop();
12559
12560 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12561 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12562 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12563
12564 // De-activate monitoring mode
12565 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
12566 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
12567 do_in_main_thread(base::BindOnce(
12568 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12569 bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */));
12570 SyncOnMainLoop();
12571 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12572 }
12573 }
12574
TEST_F(UnicastTestHandoverMode,SetSinkMonitorModeWhileUnicastIsInactive)12575 TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsInactive) {
12576 uint8_t group_size = 2;
12577 int group_id = 2;
12578
12579 // Imitate activation of monitor mode
12580 do_in_main_thread(base::BindOnce(
12581 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12582 bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */));
12583
12584 // Report working CSIS
12585 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12586
12587 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
12588 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
12589
12590 // First earbud
12591 const RawAddress test_address0 = GetTestAddress(0);
12592 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12593 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12594 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12595
12596 // Second earbud
12597 const RawAddress test_address1 = GetTestAddress(1);
12598 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12599 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12600 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12601 true /*connect_through_csis*/);
12602
12603 // Start streaming
12604 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12605 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12606 LeAudioClient::Get()->GroupSetActive(group_id);
12607 SyncOnMainLoop();
12608
12609 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12610
12611 // Expect no streaming request on stream resume when group is already active
12612 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12613 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12614 UnicastMonitorModeStatus::STREAMING_REQUESTED))
12615 .Times(0);
12616
12617 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12618
12619 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12620 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12621 SyncOnMainLoop();
12622
12623 // Verify Data transfer on two peer sinks and one source
12624 uint8_t cis_count_out = 2;
12625 uint8_t cis_count_in = 2;
12626 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
12627
12628 ASSERT_NE(0lu, streaming_groups.count(group_id));
12629 auto group = streaming_groups.at(group_id);
12630
12631 // Stop streaming and expect Service to be informed about straming suspension
12632 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12633 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12634 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12635 .Times(1);
12636
12637 // Stop
12638 StopStreaming(group_id, true);
12639
12640 if (com::android::bluetooth::flags::leaudio_use_audio_recording_listener()) {
12641 // simulate suspend timeout passed, alarm executing
12642 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
12643 SyncOnMainLoop();
12644 } else {
12645 // Check if cache configuration is still present
12646 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12647 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12648 .size());
12649 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12650 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12651 .size());
12652
12653 // Release, Sink HAL client should remain in monitor mode
12654 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12655 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12656 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
12657 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
12658 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12659 SyncOnMainLoop();
12660
12661 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12662 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12663 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12664
12665 // Setting group inactive, shall not change cached configuration
12666 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12667 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12668 .size());
12669 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12670 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12671 .size());
12672 }
12673 }
12674
TEST_F(UnicastTestHandoverMode,ClearSinkMonitorModeWhileUnicastIsActive)12675 TEST_F(UnicastTestHandoverMode, ClearSinkMonitorModeWhileUnicastIsActive) {
12676 uint8_t group_size = 2;
12677 int group_id = 2;
12678
12679 // Imitate activation of monitor mode
12680 do_in_main_thread(base::BindOnce(
12681 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12682 bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */));
12683
12684 // Report working CSIS
12685 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12686
12687 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
12688 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
12689
12690 // First earbud
12691 const RawAddress test_address0 = GetTestAddress(0);
12692 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12693 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12694 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12695
12696 // Second earbud
12697 const RawAddress test_address1 = GetTestAddress(1);
12698 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12699 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12700 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12701 true /*connect_through_csis*/);
12702
12703 // Start streaming
12704 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12705 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12706 LeAudioClient::Get()->GroupSetActive(group_id);
12707 SyncOnMainLoop();
12708
12709 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12710
12711 // Expect no streaming request on stream resume when group is already active
12712 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12713 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12714 UnicastMonitorModeStatus::STREAMING_REQUESTED))
12715 .Times(0);
12716
12717 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12718
12719 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12720 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12721 SyncOnMainLoop();
12722
12723 // Verify Data transfer on two peer sinks and one source
12724 uint8_t cis_count_out = 2;
12725 uint8_t cis_count_in = 2;
12726 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
12727
12728 ASSERT_NE(0lu, streaming_groups.count(group_id));
12729 auto group = streaming_groups.at(group_id);
12730
12731 // De-activate monitoring mode
12732 do_in_main_thread(base::BindOnce(
12733 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12734 bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */));
12735
12736 // Stop
12737 StopStreaming(group_id, true);
12738 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12739
12740 // Check if cache configuration is still present
12741 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12742 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12743 .size());
12744 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12745 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12746 .size());
12747
12748 // Release of sink and source hals due to de-activating monitor mode
12749 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12750 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12751 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
12752 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
12753 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12754 SyncOnMainLoop();
12755
12756 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12757 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12758
12759 // Setting group inactive, shall not change cached configuration
12760 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12761 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12762 .size());
12763 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12764 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12765 .size());
12766 }
12767
TEST_F(UnicastTestHandoverMode,SetAndClearSinkMonitorModeWhileUnicastIsInactive)12768 TEST_F(UnicastTestHandoverMode, SetAndClearSinkMonitorModeWhileUnicastIsInactive) {
12769 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(0);
12770 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(0);
12771 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
12772 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(0);
12773 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
12774 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
12775
12776 // Imitate activation of monitor mode
12777 do_in_main_thread(base::BindOnce(
12778 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12779 bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */));
12780 do_in_main_thread(base::BindOnce(
12781 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12782 bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */));
12783
12784 SyncOnMainLoop();
12785
12786 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12787 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12788 }
12789
TEST_F(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsInactive)12790 TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsInactive) {
12791 /* Enabling monitor mode for source while group is not active should result in
12792 * sending STREAMING_SUSPENDED notification.
12793 */
12794 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12795 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12796 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12797 .Times(1);
12798
12799 // Imitate activation of monitor mode
12800 do_in_main_thread(base::BindOnce(
12801 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12802 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12803 SyncOnMainLoop();
12804 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12805 }
12806
TEST_F(UnicastTestHandoverMode,SetTwiceSourceMonitorModeWhileUnicastIsInactive)12807 TEST_F(UnicastTestHandoverMode, SetTwiceSourceMonitorModeWhileUnicastIsInactive) {
12808 /* Enabling monitor mode for source while group is not active should result in
12809 * sending STREAMING_SUSPENDED notification.
12810 */
12811 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12812 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12813 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12814 .Times(1);
12815
12816 // Imitate activation of monitor mode
12817 do_in_main_thread(base::BindOnce(
12818 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12819 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12820 // Imitate second activation of monitor mode - should not be notified
12821 do_in_main_thread(base::BindOnce(
12822 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12823 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12824 SyncOnMainLoop();
12825 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12826 }
12827
TEST_F(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsNotStreaming)12828 TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsNotStreaming) {
12829 int group_id = 2;
12830
12831 LeAudioClient::Get()->GroupSetActive(group_id);
12832
12833 /* Enabling monitor mode for source while group is not active should result in
12834 * sending STREAMING_SUSPENDED notification.
12835 */
12836 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12837 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12838 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12839 .Times(1);
12840
12841 // Imitate activation of monitor mode
12842 do_in_main_thread(base::BindOnce(
12843 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12844 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12845 SyncOnMainLoop();
12846 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12847 }
12848
TEST_F(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsActive)12849 TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsActive) {
12850 uint8_t group_size = 2;
12851 int group_id = 2;
12852
12853 // Report working CSIS
12854 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12855
12856 // First earbud
12857 const RawAddress test_address0 = GetTestAddress(0);
12858 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12859 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12860 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12861
12862 // Second earbud
12863 const RawAddress test_address1 = GetTestAddress(1);
12864 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12865 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12866 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12867 true /*connect_through_csis*/);
12868
12869 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
12870 .WillByDefault(Invoke([&](int /*group_id*/) { return 2; }));
12871
12872 // Start streaming
12873 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12874 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12875 LeAudioClient::Get()->GroupSetActive(group_id);
12876 SyncOnMainLoop();
12877
12878 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12879
12880 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12881 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12882 SyncOnMainLoop();
12883
12884 // Verify Data transfer on two peer sinks and one source
12885 uint8_t cis_count_out = 2;
12886 uint8_t cis_count_in = 2;
12887 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
12888
12889 /* Enabling monitor mode for source while stream is active should result in
12890 * sending STREAMING notification.
12891 */
12892 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12893 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12894 UnicastMonitorModeStatus::STREAMING))
12895 .Times(1);
12896
12897 // Imitate activation of monitor mode
12898 do_in_main_thread(base::BindOnce(
12899 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12900 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12901 SyncOnMainLoop();
12902 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12903
12904 ASSERT_NE(0lu, streaming_groups.count(group_id));
12905 auto group = streaming_groups.at(group_id);
12906
12907 // Stop streaming and expect Service to be informed about straming suspension
12908 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12909 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12910 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12911 .Times(1);
12912
12913 // Stop
12914 StopStreaming(group_id, true);
12915
12916 // Check if cache configuration is still present
12917 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12918 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12919 .size());
12920 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12921 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12922 .size());
12923
12924 // Both Sink and Source HAL clients should be stopped
12925 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12926 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12927 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
12928 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
12929 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12930 SyncOnMainLoop();
12931
12932 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12933 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12934 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12935
12936 // Re-initialize mock for destroyed hal client
12937 RegisterSourceHalClientMock();
12938 RegisterSinkHalClientMock();
12939
12940 // Setting group inactive, shall not change cached configuration
12941 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12942 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12943 .size());
12944 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12945 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12946 .size());
12947
12948 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12949 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12950 UnicastMonitorModeStatus::STREAMING_REQUESTED))
12951 .Times(1);
12952
12953 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12954 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12955 LeAudioClient::Get()->GroupSetActive(group_id);
12956
12957 // Start streaming to trigger next group going to IDLE state
12958 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12959 SyncOnMainLoop();
12960
12961 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12962 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12963 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12964
12965 // Stop streaming and expect Service to be informed about straming suspension
12966 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12967 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12968 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12969 .Times(1);
12970
12971 // Stop
12972 StopStreaming(group_id, true);
12973
12974 // Both Sink and Source HAL clients should be stopped
12975 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12976 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12977 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
12978 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
12979 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12980 SyncOnMainLoop();
12981
12982 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12983 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12984 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12985
12986 // De-activate monitoring mode
12987 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12988 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12989 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12990 .Times(0);
12991
12992 do_in_main_thread(base::BindOnce(
12993 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12994 bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */));
12995 }
12996
TEST_F(UnicastTestHandoverMode,SetAllowedContextMask)12997 TEST_F(UnicastTestHandoverMode, SetAllowedContextMask) {
12998 const RawAddress test_address0 = GetTestAddress(0);
12999 int group_id = bluetooth::groups::kGroupUnknown;
13000
13001 available_snk_context_types_ =
13002 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
13003 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA |
13004 types::LeAudioContextType::SOUNDEFFECTS)
13005 .value();
13006 available_src_context_types_ = available_snk_context_types_;
13007 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
13008 supported_src_context_types_ =
13009 (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED).value();
13010 /* Don't allow SOUNDEFFECTS context type to be streamed */
13011 int allowed_context_types =
13012 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
13013 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
13014 .value();
13015
13016 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
13017 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
13018 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
13019 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
13020 0 /*rank*/);
13021 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13022 OnConnectionState(ConnectionState::CONNECTED, test_address0))
13023 .Times(1);
13024 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13025 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
13026 .WillOnce(DoAll(SaveArg<1>(&group_id)));
13027
13028 ConnectLeAudio(test_address0);
13029 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
13030
13031 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
13032 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, _, _))
13033 .Times(0);
13034
13035 LeAudioClient::Get()->GroupSetActive(group_id);
13036 SyncOnMainLoop();
13037
13038 /* Set the same allowed context mask for sink and source */
13039 LeAudioClient::Get()->SetGroupAllowedContextMask(group_id, allowed_context_types,
13040 allowed_context_types);
13041
13042 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, group_id,
13043 AUDIO_SOURCE_INVALID, false, false);
13044
13045 SyncOnMainLoop();
13046 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
13047 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
13048 }
13049
TEST_F(UnicastTest,NoContextvalidateStreamingRequest)13050 TEST_F(UnicastTest, NoContextvalidateStreamingRequest) {
13051 const RawAddress test_address0 = GetTestAddress(0);
13052 int group_id = bluetooth::groups::kGroupUnknown;
13053
13054 available_snk_context_types_ =
13055 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
13056 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
13057 .value();
13058 available_src_context_types_ = available_snk_context_types_;
13059 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
13060 supported_src_context_types_ =
13061 (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED).value();
13062
13063 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
13064 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
13065 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
13066 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
13067 0 /*rank*/);
13068 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13069 OnConnectionState(ConnectionState::CONNECTED, test_address0))
13070 .Times(1);
13071 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13072 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
13073 .WillOnce(DoAll(SaveArg<1>(&group_id)));
13074
13075 ConnectLeAudio(test_address0);
13076 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
13077
13078 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
13079 types::BidirectionalPair<types::AudioContexts> metadata = {.sink = types::AudioContexts(),
13080 .source = types::AudioContexts()};
13081 EXPECT_CALL(mock_state_machine_,
13082 StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, metadata, _))
13083 .Times(0);
13084
13085 LeAudioClient::Get()->GroupSetActive(group_id);
13086
13087 // Imitate activation of monitor mode
13088 do_in_main_thread(base::BindOnce(
13089 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
13090 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
13091 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
13092 SyncOnMainLoop();
13093
13094 // Stop streaming and expect Service to be informed about streaming suspension
13095 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13096 OnUnicastMonitorModeStatus(
13097 bluetooth::le_audio::types::kLeAudioDirectionSource,
13098 UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE))
13099 .Times(1);
13100
13101 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, group_id,
13102 AUDIO_SOURCE_INVALID, false, false);
13103
13104 SyncOnMainLoop();
13105 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
13106 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
13107 }
13108
TEST_F(UnicastTest,CodecFrameBlocks2)13109 TEST_F(UnicastTest, CodecFrameBlocks2) {
13110 auto const max_codec_frames_per_sdu = 2;
13111 uint32_t data_len = 1920;
13112
13113 // Register a on-the-fly hook for codec interface mock mutation to prepare the
13114 // codec mock for encoding
13115 std::list<MockCodecInterface*> codec_mocks;
13116 MockCodecInterface::RegisterMockInstanceHook([&](MockCodecInterface* mock, bool is_destroyed) {
13117 if (is_destroyed) {
13118 log::debug("Codec Interface Destroyed: {}", std::format_ptr(mock));
13119 codec_mocks.remove(mock);
13120 } else {
13121 log::debug("Codec Interface Created: {}", std::format_ptr(mock));
13122 ON_CALL(*mock, GetNumOfSamplesPerChannel()).WillByDefault(Return(960));
13123 ON_CALL(*mock, GetNumOfBytesPerSample()).WillByDefault(Return(2)); // 16bits samples
13124 ON_CALL(*mock, Encode(_, _, _, _, _))
13125 .WillByDefault(Return(CodecInterface::Status::STATUS_OK));
13126 codec_mocks.push_back(mock);
13127 }
13128 });
13129
13130 // Add a frame block PAC passing provider
13131 bool is_fb2_passed_as_requirement = false;
13132 ON_CALL(*mock_codec_manager_, GetCodecConfig)
13133 .WillByDefault(Invoke(
13134 [&](const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements&
13135 requirements,
13136 bluetooth::le_audio::CodecManager::UnicastConfigurationProvider provider) {
13137 auto filtered = *bluetooth::le_audio::AudioSetConfigurationProvider::Get()
13138 ->GetConfigurations(requirements.audio_context_type);
13139 // Filter out the dual bidir SWB configurations
13140 if (!bluetooth::le_audio::CodecManager::GetInstance()
13141 ->IsDualBiDirSwbSupported()) {
13142 filtered.erase(
13143 std::remove_if(filtered.begin(), filtered.end(),
13144 [](auto const& el) {
13145 if (el->confs.source.empty()) {
13146 return false;
13147 }
13148 return AudioSetConfigurationProvider::Get()
13149 ->CheckConfigurationIsDualBiDirSwb(*el);
13150 }),
13151 filtered.end());
13152 }
13153 auto cfg = provider(requirements, &filtered);
13154 if (cfg == nullptr) {
13155 return std::unique_ptr<bluetooth::le_audio::types::AudioSetConfiguration>(
13156 nullptr);
13157 }
13158
13159 if (requirements.sink_pacs.has_value()) {
13160 for (auto const& rec : requirements.sink_pacs.value()) {
13161 auto caps = rec.codec_spec_caps.GetAsCoreCodecCapabilities();
13162 if (caps.HasSupportedMaxCodecFramesPerSdu()) {
13163 if (caps.supported_max_codec_frames_per_sdu.value() ==
13164 max_codec_frames_per_sdu) {
13165 // Inject the proper Codec Frames Per SDU as the json
13166 // configs are conservative and will always give us 1
13167 for (auto& entry : cfg->confs.sink) {
13168 entry.codec.params.Add(
13169 codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
13170 (uint8_t)max_codec_frames_per_sdu);
13171 }
13172 is_fb2_passed_as_requirement = true;
13173 }
13174 }
13175 }
13176 }
13177 return cfg;
13178 }));
13179
13180 types::BidirectionalPair<stream_parameters> codec_manager_stream_params;
13181 ON_CALL(*mock_codec_manager_, UpdateActiveAudioConfig)
13182 .WillByDefault(
13183 Invoke([&](const types::BidirectionalPair<stream_parameters>& stream_params,
13184 std::function<void(const stream_config& config, uint8_t direction)>
13185 /*updater*/,
13186 uint8_t /*directions_to_update*/) {
13187 codec_manager_stream_params = stream_params;
13188 }));
13189
13190 const RawAddress test_address0 = GetTestAddress(0);
13191 int group_id = bluetooth::groups::kGroupUnknown;
13192
13193 SampleDatabaseParameters remote_params{
13194 .conn_id = 1,
13195 .addr = test_address0,
13196 .sink_audio_allocation = codec_spec_conf::kLeAudioLocationStereo,
13197 .source_audio_allocation = codec_spec_conf::kLeAudioLocationStereo,
13198 .sink_channel_cnt = default_channel_cnt,
13199 .source_channel_cnt = default_channel_cnt,
13200 .sample_freq_mask = le_audio::codec_spec_caps::kLeAudioSamplingFreq32000Hz,
13201 .add_csis = false,
13202 .add_cas = true,
13203 .add_pacs = true,
13204 .add_ascs_cnt = 1,
13205 .set_size = 0,
13206 .rank = 0,
13207 .gatt_status = GATT_SUCCESS,
13208 .max_supported_codec_frames_per_sdu = 2,
13209 };
13210 SetSampleDatabaseEarbudsValid(remote_params);
13211
13212 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13213 OnConnectionState(ConnectionState::CONNECTED, test_address0))
13214 .Times(1);
13215 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13216 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
13217 .WillOnce(DoAll(SaveArg<1>(&group_id)));
13218
13219 ConnectLeAudio(test_address0);
13220 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
13221
13222 constexpr int gmcs_ccid = 1;
13223 constexpr int gtbs_ccid = 2;
13224
13225 // Audio sessions are started only when device gets active
13226 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
13227 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
13228 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
13229 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
13230 LeAudioClient::Get()->GroupSetActive(group_id);
13231 SyncOnMainLoop();
13232
13233 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
13234 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
13235
13236 stay_at_qos_config_in_start_stream = true;
13237
13238 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
13239 LocalAudioSourceResume(false);
13240
13241 SyncOnMainLoop();
13242 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
13243 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
13244 ASSERT_TRUE(is_fb2_passed_as_requirement);
13245
13246 // Verify codec fram blocks per SDU has been applied to the device
13247 ASSERT_NE(0lu, streaming_groups.count(group_id));
13248 uint8_t device_configured_codec_frame_blocks_per_sdu = 0;
13249 auto group = streaming_groups.at(group_id);
13250 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
13251 device = group->GetNextDevice(device)) {
13252 for (auto& ase : device->ases_) {
13253 if (ase.active) {
13254 auto cfg = ase.codec_config.params.GetAsCoreCodecConfig();
13255 ASSERT_TRUE(cfg.codec_frames_blocks_per_sdu.has_value());
13256 device_configured_codec_frame_blocks_per_sdu = cfg.codec_frames_blocks_per_sdu.value();
13257 }
13258 }
13259 }
13260
13261 // Verify the configured codec frame blocks per SDU
13262 ASSERT_EQ(device_configured_codec_frame_blocks_per_sdu,
13263 remote_params.max_supported_codec_frames_per_sdu);
13264
13265 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
13266 do_in_main_thread(base::BindOnce(
13267 [](int group_id,
13268 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks) {
13269 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
13270 },
13271 group_id, base::Unretained(state_machine_callbacks_)));
13272 SyncOnMainLoop();
13273 Mock::VerifyAndClearExpectations(&mock_state_machine_);
13274
13275 // Verify Data transfer on one audio source cis
13276 constexpr uint8_t cis_count_out = 1;
13277 constexpr uint8_t cis_count_in = 0;
13278 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in,
13279 data_len * device_configured_codec_frame_blocks_per_sdu);
13280
13281 ASSERT_NE(codec_mocks.size(), 0ul);
13282
13283 // Verify that the initially started session was updated with the new params
13284 ASSERT_EQ(codec_manager_stream_params.sink.stream_config.codec_frames_blocks_per_sdu,
13285 max_codec_frames_per_sdu);
13286 }
13287
TEST_F(UnicastTestHandoverMode,UpdateMetadataToNotAllowedContexts)13288 TEST_F(UnicastTestHandoverMode, UpdateMetadataToNotAllowedContexts) {
13289 com::android::bluetooth::flags::provider_->leaudio_stop_updated_to_not_available_context_stream(
13290 true);
13291 const RawAddress test_address0 = GetTestAddress(0);
13292 int group_id = bluetooth::groups::kGroupUnknown;
13293
13294 available_snk_context_types_ =
13295 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
13296 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA |
13297 types::LeAudioContextType::SOUNDEFFECTS)
13298 .value();
13299 available_src_context_types_ = available_snk_context_types_;
13300 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
13301 supported_src_context_types_ =
13302 (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED).value();
13303 /* Don't allow SOUNDEFFECTS context type to be streamed */
13304 int allowed_context_types =
13305 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
13306 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
13307 .value();
13308
13309 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
13310 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
13311 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
13312 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
13313 0 /*rank*/);
13314 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13315 OnConnectionState(ConnectionState::CONNECTED, test_address0))
13316 .Times(1);
13317 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13318 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
13319 .WillOnce(DoAll(SaveArg<1>(&group_id)));
13320
13321 ConnectLeAudio(test_address0);
13322 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
13323
13324 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
13325 types::BidirectionalPair<types::AudioContexts> metadata = {.sink = types::AudioContexts(),
13326 .source = types::AudioContexts()};
13327 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::MEDIA, _, _)).Times(1);
13328
13329 LeAudioClient::Get()->GroupSetActive(group_id);
13330 SyncOnMainLoop();
13331
13332 /* Set the same allowed context mask for sink and source */
13333 LeAudioClient::Get()->SetGroupAllowedContextMask(group_id, allowed_context_types,
13334 allowed_context_types);
13335
13336 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID,
13337 false, false);
13338
13339 SyncOnMainLoop();
13340 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
13341 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
13342
13343 /* Expect stream to be stopped when not allowed context would be updated in metadata */
13344 EXPECT_CALL(mock_state_machine_, StopStream(_));
13345
13346 UpdateLocalSourceMetadata(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, true);
13347 }
13348
TEST_F(UnicastTestHandoverMode,UpdateMetadataToNotAllowedContextsInCallMode)13349 TEST_F(UnicastTestHandoverMode, UpdateMetadataToNotAllowedContextsInCallMode) {
13350 com::android::bluetooth::flags::provider_->leaudio_stop_updated_to_not_available_context_stream(
13351 true);
13352 const RawAddress test_address0 = GetTestAddress(0);
13353 int group_id = bluetooth::groups::kGroupUnknown;
13354
13355 available_snk_context_types_ =
13356 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
13357 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA |
13358 types::LeAudioContextType::SOUNDEFFECTS)
13359 .value();
13360 available_src_context_types_ = available_snk_context_types_;
13361 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
13362 supported_src_context_types_ =
13363 (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED).value();
13364
13365 /* Don't allow SOUNDEFFECTS context type to be streamed */
13366 int allowed_context_types =
13367 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
13368 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
13369 .value();
13370
13371 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
13372 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
13373 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
13374 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
13375 0 /*rank*/);
13376 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13377 OnConnectionState(ConnectionState::CONNECTED, test_address0))
13378 .Times(1);
13379 EXPECT_CALL(mock_audio_hal_client_callbacks_,
13380 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
13381 .WillOnce(DoAll(SaveArg<1>(&group_id)));
13382
13383 ConnectLeAudio(test_address0);
13384 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
13385
13386 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
13387 types::BidirectionalPair<types::AudioContexts> metadata = {.sink = types::AudioContexts(),
13388 .source = types::AudioContexts()};
13389 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, _))
13390 .Times(1);
13391
13392 LeAudioClient::Get()->GroupSetActive(group_id);
13393 SyncOnMainLoop();
13394
13395 /* Set the same allowed context mask for sink and source */
13396 LeAudioClient::Get()->SetGroupAllowedContextMask(group_id, allowed_context_types,
13397 allowed_context_types);
13398
13399 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_SONIFICATION,
13400 group_id, AUDIO_SOURCE_INVALID, false, false);
13401
13402 SyncOnMainLoop();
13403 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
13404 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
13405
13406 /* Expect stream to not be stopped when not allowed context would be updated in metadata and
13407 * inCall mode is set */
13408 LeAudioClient::Get()->SetInCall(true);
13409 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
13410
13411 /* Expect no reconfiguration while being in call mode */
13412 UpdateLocalSourceMetadata(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION,
13413 false);
13414
13415 SyncOnMainLoop();
13416
13417 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
13418 Mock::VerifyAndClearExpectations(&mock_state_machine_);
13419
13420 /* Expect stream to be stopped when not allowed context is set and inCall mode is not set */
13421 EXPECT_CALL(mock_state_machine_, StopStream(_));
13422 LeAudioClient::Get()->SetInCall(false);
13423 }
13424 } // namespace bluetooth::le_audio
13425