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/mock_core_callbacks.h"
34 #include "btif_storage_mock.h"
35 #include "btm_api_mock.h"
36 #include "btm_iso_api.h"
37 #include "common/message_loop_thread.h"
38 #include "fake_osi.h"
39 #include "gatt/database_builder.h"
40 #include "hardware/bt_gatt_types.h"
41 #include "hardware/bt_le_audio.h"
42 #include "hci/controller_interface_mock.h"
43 #include "internal_include/stack_config.h"
44 #include "le_audio/codec_manager.h"
45 #include "le_audio/mock_codec_interface.h"
46 #include "le_audio_health_status.h"
47 #include "le_audio_set_configuration_provider.h"
48 #include "le_audio_types.h"
49 #include "mock_codec_manager.h"
50 #include "mock_csis_client.h"
51 #include "mock_device_groups.h"
52 #include "mock_state_machine.h"
53 #include "stack/include/btm_status.h"
54 #include "test/common/mock_functions.h"
55 #include "test/mock/mock_main_shim_entry.h"
56 #include "test/mock/mock_stack_btm_iso.h"
57
58 #define TEST_BT com::android::bluetooth::flags
59
60 // TODO(b/369381361) Enfore -Wmissing-prototypes
61 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
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 void osi_property_set_bool(const char* key, bool value);
108
109 // Disables most likely false-positives from base::SplitString()
__asan_default_options()110 extern "C" const char* __asan_default_options() { return "detect_container_overflow=0"; }
111
112 std::atomic<int> num_async_tasks;
113 static base::MessageLoop* message_loop_;
114 bluetooth::common::MessageLoopThread message_loop_thread("test message loop");
get_main_thread()115 bluetooth::common::MessageLoopThread* get_main_thread() { return &message_loop_thread; }
116
do_in_main_thread(base::OnceClosure task)117 bt_status_t do_in_main_thread(base::OnceClosure task) {
118 if (!message_loop_) {
119 return BT_STATUS_FAIL;
120 }
121
122 // Wrap the task with task counter so we could later know if there are
123 // any callbacks scheduled and we should wait before performing some actions
124 if (!message_loop_thread.DoInThread(
125 FROM_HERE, base::BindOnce(
126 [](base::OnceClosure task, std::atomic<int>& num_async_tasks) {
127 std::move(task).Run();
128 num_async_tasks--;
129 },
130 std::move(task), std::ref(num_async_tasks)))) {
131 bluetooth::log::error("failed to post task to task runner!");
132 return BT_STATUS_FAIL;
133 }
134 num_async_tasks++;
135 return BT_STATUS_SUCCESS;
136 }
137
do_in_main_thread_delayed(base::OnceClosure task,std::chrono::microseconds)138 bt_status_t do_in_main_thread_delayed(base::OnceClosure task, std::chrono::microseconds /*delay*/) {
139 /* For testing purpose it is ok to just skip delay */
140 return do_in_main_thread(std::move(task));
141 }
142
get_main_message_loop()143 base::MessageLoop* get_main_message_loop() { return message_loop_; }
144
init_message_loop_thread()145 static void init_message_loop_thread() {
146 num_async_tasks = 0;
147 message_loop_thread.StartUp();
148 if (!message_loop_thread.IsRunning()) {
149 FAIL() << "unable to create message loop thread.";
150 }
151
152 if (!message_loop_thread.EnableRealTimeScheduling()) {
153 bluetooth::log::error("Unable to set real time scheduling");
154 }
155
156 message_loop_ = message_loop_thread.message_loop();
157 if (message_loop_ == nullptr) {
158 FAIL() << "unable to get message loop.";
159 }
160 }
161
cleanup_message_loop_thread()162 static void cleanup_message_loop_thread() {
163 message_loop_ = nullptr;
164 message_loop_thread.ShutDown();
165 }
166
invoke_switch_codec_cb(bool)167 void invoke_switch_codec_cb(bool /*is_low_latency_buffer_size*/) {}
invoke_switch_buffer_size_cb(bool)168 void invoke_switch_buffer_size_cb(bool /*is_low_latency_buffer_size*/) {}
169
170 const std::string kSmpOptions("mock smp options");
get_pts_avrcp_test(void)171 bool get_pts_avrcp_test(void) { return false; }
get_pts_secure_only_mode(void)172 bool get_pts_secure_only_mode(void) { return false; }
get_pts_conn_updates_disabled(void)173 bool get_pts_conn_updates_disabled(void) { return false; }
get_pts_crosskey_sdp_disable(void)174 bool get_pts_crosskey_sdp_disable(void) { return false; }
get_pts_smp_options(void)175 const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
get_pts_smp_failure_case(void)176 int get_pts_smp_failure_case(void) { return 123; }
get_pts_force_eatt_for_notifications(void)177 bool get_pts_force_eatt_for_notifications(void) { return false; }
get_pts_connect_eatt_unconditionally(void)178 bool get_pts_connect_eatt_unconditionally(void) { return false; }
get_pts_connect_eatt_before_encryption(void)179 bool get_pts_connect_eatt_before_encryption(void) { return false; }
get_pts_unencrypt_broadcast(void)180 bool get_pts_unencrypt_broadcast(void) { return false; }
get_pts_eatt_peripheral_collision_support(void)181 bool get_pts_eatt_peripheral_collision_support(void) { return false; }
get_pts_force_le_audio_multiple_contexts_metadata(void)182 bool get_pts_force_le_audio_multiple_contexts_metadata(void) { return false; }
get_pts_le_audio_disable_ases_before_stopping(void)183 bool get_pts_le_audio_disable_ases_before_stopping(void) { return false; }
get_all(void)184 config_t* get_all(void) { return nullptr; }
185
186 stack_config_t mock_stack_config{
187 .get_pts_avrcp_test = get_pts_avrcp_test,
188 .get_pts_secure_only_mode = get_pts_secure_only_mode,
189 .get_pts_conn_updates_disabled = get_pts_conn_updates_disabled,
190 .get_pts_crosskey_sdp_disable = get_pts_crosskey_sdp_disable,
191 .get_pts_smp_options = get_pts_smp_options,
192 .get_pts_smp_failure_case = get_pts_smp_failure_case,
193 .get_pts_force_eatt_for_notifications = get_pts_force_eatt_for_notifications,
194 .get_pts_connect_eatt_unconditionally = get_pts_connect_eatt_unconditionally,
195 .get_pts_connect_eatt_before_encryption = get_pts_connect_eatt_before_encryption,
196 .get_pts_unencrypt_broadcast = get_pts_unencrypt_broadcast,
197 .get_pts_eatt_peripheral_collision_support = get_pts_eatt_peripheral_collision_support,
198 .get_pts_force_le_audio_multiple_contexts_metadata =
199 get_pts_force_le_audio_multiple_contexts_metadata,
200 .get_pts_le_audio_disable_ases_before_stopping =
201 get_pts_le_audio_disable_ases_before_stopping,
202 .get_all = get_all,
203 };
stack_config_get_interface(void)204 const stack_config_t* stack_config_get_interface(void) { return &mock_stack_config; }
205
IsLeAudioBroadcasterRunning()206 bool LeAudioBroadcaster::IsLeAudioBroadcasterRunning() { return false; }
207
208 namespace bluetooth::le_audio {
209 class MockLeAudioSourceHalClient;
210 MockLeAudioSourceHalClient* mock_le_audio_source_hal_client_;
211 std::unique_ptr<LeAudioSourceAudioHalClient> owned_mock_le_audio_source_hal_client_;
212 bool is_audio_unicast_source_acquired;
213
AcquireUnicast()214 std::unique_ptr<LeAudioSourceAudioHalClient> LeAudioSourceAudioHalClient::AcquireUnicast() {
215 if (is_audio_unicast_source_acquired) {
216 return nullptr;
217 }
218 is_audio_unicast_source_acquired = true;
219 return std::move(owned_mock_le_audio_source_hal_client_);
220 }
221
DebugDump(int)222 void LeAudioSourceAudioHalClient::DebugDump(int /*fd*/) {}
223
224 class MockLeAudioSinkHalClient;
225 MockLeAudioSinkHalClient* mock_le_audio_sink_hal_client_;
226 std::unique_ptr<LeAudioSinkAudioHalClient> owned_mock_le_audio_sink_hal_client_;
227 bool is_audio_unicast_sink_acquired;
228
AcquireUnicast()229 std::unique_ptr<LeAudioSinkAudioHalClient> LeAudioSinkAudioHalClient::AcquireUnicast() {
230 if (is_audio_unicast_sink_acquired) {
231 return nullptr;
232 }
233 is_audio_unicast_sink_acquired = true;
234 return std::move(owned_mock_le_audio_sink_hal_client_);
235 }
236
DebugDump(int)237 void LeAudioSinkAudioHalClient::DebugDump(int /*fd*/) {}
238
GetTestAddress(uint8_t index)239 RawAddress GetTestAddress(uint8_t index) {
240 EXPECT_LT(index, UINT8_MAX);
241 RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}};
242 return result;
243 }
244
245 class MockAudioHalClientCallbacks : public bluetooth::le_audio::LeAudioClientCallbacks {
246 public:
247 MOCK_METHOD((void), OnInitialized, (), (override));
248 MOCK_METHOD((void), OnConnectionState, (ConnectionState state, const RawAddress& address),
249 (override));
250 MOCK_METHOD((void), OnGroupStatus, (int group_id, GroupStatus group_status), (override));
251 MOCK_METHOD((void), OnGroupStreamStatus, (int group_id, GroupStreamStatus group_stream_status),
252 (override));
253 MOCK_METHOD((void), OnGroupNodeStatus,
254 (const RawAddress& bd_addr, int group_id, GroupNodeStatus node_status), (override));
255 MOCK_METHOD((void), OnAudioConf,
256 (uint8_t direction, int group_id, uint32_t snk_audio_location,
257 uint32_t src_audio_location, uint16_t avail_cont),
258 (override));
259 MOCK_METHOD((void), OnSinkAudioLocationAvailable,
260 (const RawAddress& bd_addr, uint32_t snk_audio_location), (override));
261 MOCK_METHOD((void), OnAudioLocalCodecCapabilities,
262 (std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
263 std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf),
264 (override));
265 MOCK_METHOD((void), OnAudioGroupCurrentCodecConf,
266 (int group_id, btle_audio_codec_config_t input_codec_conf,
267 btle_audio_codec_config_t output_codec_conf),
268 (override));
269 MOCK_METHOD((void), OnAudioGroupSelectableCodecConf,
270 (int group_id, std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
271 std::vector<btle_audio_codec_config_t> output_selectable_codec_conf),
272 (override));
273 MOCK_METHOD((void), OnHealthBasedRecommendationAction,
274 (const RawAddress& address, LeAudioHealthBasedAction action), (override));
275 MOCK_METHOD((void), OnHealthBasedGroupRecommendationAction,
276 (int group_id, LeAudioHealthBasedAction action), (override));
277 MOCK_METHOD((void), OnUnicastMonitorModeStatus,
278 (uint8_t direction, UnicastMonitorModeStatus status));
279 };
280
281 class MockLeAudioSinkHalClient : public LeAudioSinkAudioHalClient {
282 public:
283 MockLeAudioSinkHalClient() = default;
284 MOCK_METHOD((bool), Start,
285 (const LeAudioCodecConfiguration& codecConfiguration,
286 LeAudioSinkAudioHalClient::Callbacks* audioReceiver, DsaModes dsa_modes),
287 (override));
288 MOCK_METHOD((void), Stop, (), (override));
289 MOCK_METHOD((size_t), SendData, (uint8_t* data, uint16_t size), (override));
290 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
291 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
292 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
293 MOCK_METHOD((void), UpdateAudioConfigToHal, (const ::bluetooth::le_audio::offload_config&),
294 (override));
295 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
296 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
297
298 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSinkHalClient()299 virtual ~MockLeAudioSinkHalClient() override { OnDestroyed(); }
300 };
301
302 class MockLeAudioSourceHalClient : public LeAudioSourceAudioHalClient {
303 public:
304 MockLeAudioSourceHalClient() = default;
305 MOCK_METHOD((bool), Start,
306 (const LeAudioCodecConfiguration& codecConfiguration,
307 LeAudioSourceAudioHalClient::Callbacks* audioReceiver, DsaModes dsa_modes),
308 (override));
309 MOCK_METHOD((void), Stop, (), (override));
310 MOCK_METHOD((void), ConfirmStreamingRequest, (), (override));
311 MOCK_METHOD((void), CancelStreamingRequest, (), (override));
312 MOCK_METHOD((void), UpdateRemoteDelay, (uint16_t delay), (override));
313 MOCK_METHOD((void), UpdateAudioConfigToHal, (const ::bluetooth::le_audio::offload_config&),
314 (override));
315 MOCK_METHOD((std::optional<broadcaster::BroadcastConfiguration>), GetBroadcastConfig,
316 ((const std::vector<std::pair<types::LeAudioContextType, uint8_t>>&),
317 (const std::optional<std::vector<::bluetooth::le_audio::types::acs_ac_record>>&)),
318 (const override));
319 MOCK_METHOD((std::optional<::bluetooth::le_audio::set_configurations::AudioSetConfiguration>),
320 GetUnicastConfig, (const CodecManager::UnicastConfigurationRequirements&),
321 (const override));
322 MOCK_METHOD((void), UpdateBroadcastAudioConfigToHal,
323 (const ::bluetooth::le_audio::broadcast_offload_config&), (override));
324 MOCK_METHOD((void), SuspendedForReconfiguration, (), (override));
325 MOCK_METHOD((void), ReconfigurationComplete, (), (override));
326
327 MOCK_METHOD((void), OnDestroyed, ());
~MockLeAudioSourceHalClient()328 virtual ~MockLeAudioSourceHalClient() override { OnDestroyed(); }
329 };
330
331 class UnicastTestNoInit : public Test {
332 public:
333 bool use_handover_mode = false;
334
335 protected:
RegisterSourceHalClientMock()336 void RegisterSourceHalClientMock() {
337 owned_mock_le_audio_source_hal_client_.reset(new NiceMock<MockLeAudioSourceHalClient>());
338 mock_le_audio_source_hal_client_ =
339 (MockLeAudioSourceHalClient*)owned_mock_le_audio_source_hal_client_.get();
340
341 is_audio_unicast_source_acquired = false;
342 ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _))
343 .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/,
344 LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
345 DsaModes /*dsa_modes*/) {
346 unicast_source_hal_cb_ = audioReceiver;
347 return true;
348 });
349 ON_CALL(*mock_le_audio_source_hal_client_, OnDestroyed).WillByDefault([]() {
350 mock_le_audio_source_hal_client_ = nullptr;
351 is_audio_unicast_source_acquired = false;
352 });
353 }
354
RegisterSinkHalClientMock()355 void RegisterSinkHalClientMock() {
356 owned_mock_le_audio_sink_hal_client_.reset(new NiceMock<MockLeAudioSinkHalClient>());
357 mock_le_audio_sink_hal_client_ =
358 (MockLeAudioSinkHalClient*)owned_mock_le_audio_sink_hal_client_.get();
359
360 is_audio_unicast_sink_acquired = false;
361 ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _))
362 .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/,
363 LeAudioSinkAudioHalClient::Callbacks* audioReceiver,
364 DsaModes /*dsa_modes*/) {
365 unicast_sink_hal_cb_ = audioReceiver;
366 return true;
367 });
368 ON_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed).WillByDefault([]() {
369 mock_le_audio_sink_hal_client_ = nullptr;
370 is_audio_unicast_sink_acquired = false;
371 });
372 }
373
SetUpMockAudioHal()374 void SetUpMockAudioHal() {
375 /* Since these are returned by the Acquire() methods as unique_ptrs, we
376 * will not free them manually.
377 */
378 RegisterSourceHalClientMock();
379
380 owned_mock_le_audio_sink_hal_client_.reset(new NiceMock<MockLeAudioSinkHalClient>());
381 mock_le_audio_sink_hal_client_ =
382 (MockLeAudioSinkHalClient*)owned_mock_le_audio_sink_hal_client_.get();
383
384 owned_mock_le_audio_source_hal_client_.reset(new NiceMock<MockLeAudioSourceHalClient>());
385 mock_le_audio_source_hal_client_ =
386 (MockLeAudioSourceHalClient*)owned_mock_le_audio_source_hal_client_.get();
387
388 is_audio_unicast_source_acquired = false;
389 ON_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _))
390 .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/,
391 LeAudioSourceAudioHalClient::Callbacks* audioReceiver,
392 DsaModes /*dsa_modes*/) {
393 unicast_source_hal_cb_ = audioReceiver;
394 return true;
395 });
396 ON_CALL(*mock_le_audio_source_hal_client_, OnDestroyed).WillByDefault([]() {
397 mock_le_audio_source_hal_client_ = nullptr;
398 is_audio_unicast_source_acquired = false;
399 });
400
401 is_audio_unicast_sink_acquired = false;
402 ON_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _))
403 .WillByDefault([this](const LeAudioCodecConfiguration& /*codec_configuration*/,
404 LeAudioSinkAudioHalClient::Callbacks* audioReceiver,
405 DsaModes /*dsa_modes*/) {
406 unicast_sink_hal_cb_ = audioReceiver;
407 return true;
408 });
409 ON_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed).WillByDefault([]() {
410 mock_le_audio_sink_hal_client_ = nullptr;
411 is_audio_unicast_sink_acquired = false;
412 });
413
414 ON_CALL(*mock_le_audio_sink_hal_client_, SendData)
415 .WillByDefault([](uint8_t* /*data*/, uint16_t size) { return size; });
416
417 // HAL
418 ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool { return true; });
419 }
420
InjectGroupDeviceRemoved(const RawAddress & address,int group_id)421 void InjectGroupDeviceRemoved(const RawAddress& address, int group_id) {
422 group_callbacks_->OnGroupMemberRemoved(address, group_id);
423 }
424
InjectGroupDeviceAdded(const RawAddress & address,int group_id)425 void InjectGroupDeviceAdded(const RawAddress& address, int group_id) {
426 bluetooth::Uuid uuid = bluetooth::le_audio::uuid::kCapServiceUuid;
427
428 int group_members_num = 0;
429 for (const auto& [addr, id] : groups) {
430 if (id == group_id) {
431 group_members_num++;
432 }
433 }
434
435 bool first_device = (group_members_num == 1);
436 do_in_main_thread(base::BindOnce(
437 [](const RawAddress& addr, int group_id, bluetooth::Uuid uuid,
438 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks, bool first_device) {
439 if (first_device) {
440 group_callbacks->OnGroupAdded(addr, uuid, group_id);
441 } else {
442 group_callbacks->OnGroupMemberAdded(addr, group_id);
443 }
444 },
445 address, group_id, uuid, base::Unretained(this->group_callbacks_), first_device));
446 }
447
InjectServiceChangedEvent(const RawAddress & address,uint16_t conn_id)448 void InjectServiceChangedEvent(const RawAddress& address, uint16_t conn_id) {
449 tBTA_GATTC_SERVICE_CHANGED event_data = {.remote_bda = address, .conn_id = conn_id};
450
451 do_in_main_thread(base::BindOnce(
452 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_SERVICE_CHANGED event_data) {
453 gatt_callback(BTA_GATTC_SRVC_CHG_EVT, (tBTA_GATTC*)&event_data);
454 },
455 base::Unretained(this->gatt_callback), event_data));
456 }
457
InjectConnectedEvent(const RawAddress & address,uint16_t conn_id,tGATT_STATUS status=GATT_SUCCESS)458 void InjectConnectedEvent(const RawAddress& address, uint16_t conn_id,
459 tGATT_STATUS status = GATT_SUCCESS) {
460 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
461 tBTA_GATTC_OPEN event_data = {
462 .status = status,
463 .conn_id = conn_id,
464 .client_if = gatt_if,
465 .remote_bda = address,
466 .transport = BT_TRANSPORT_LE,
467 .mtu = 240,
468 };
469
470 if (status == GATT_SUCCESS) {
471 ASSERT_NE(peer_devices.count(conn_id), 0u);
472 peer_devices.at(conn_id)->connected = true;
473 }
474
475 do_in_main_thread(base::BindOnce(
476 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_OPEN event_data) {
477 gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
478 },
479 base::Unretained(this->gatt_callback), event_data));
480 }
481
InjectEncryptionChangedEvent(const RawAddress & address)482 void InjectEncryptionChangedEvent(const RawAddress& address) {
483 tBTA_GATTC_ENC_CMPL_CB event_data = {
484 .client_if = gatt_if,
485 .remote_bda = address,
486 };
487
488 do_in_main_thread(base::BindOnce(
489 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_ENC_CMPL_CB event_data) {
490 gatt_callback(BTA_GATTC_ENC_CMPL_CB_EVT, (tBTA_GATTC*)&event_data);
491 },
492 base::Unretained(this->gatt_callback), event_data));
493 }
494
TriggerDisconnectionFromApp(const RawAddress & address)495 void TriggerDisconnectionFromApp(const RawAddress& address) {
496 do_in_main_thread(base::BindOnce(
497 [](LeAudioClient* client, const RawAddress& address) { client->Disconnect(address); },
498 LeAudioClient::Get(), address));
499 }
500
InjectDisconnectedEvent(uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST)501 void InjectDisconnectedEvent(uint16_t conn_id,
502 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) {
503 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
504 ASSERT_NE(peer_devices.count(conn_id), 0u);
505
506 tBTA_GATTC_CLOSE event_data = {
507 .conn_id = conn_id,
508 .status = GATT_SUCCESS,
509 .client_if = gatt_if,
510 .remote_bda = peer_devices.at(conn_id)->addr,
511 .reason = reason,
512 };
513
514 peer_devices.at(conn_id)->connected = false;
515 do_in_main_thread(base::BindOnce(
516 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_CLOSE event_data) {
517 gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
518 },
519 base::Unretained(this->gatt_callback), event_data));
520 }
521
InjectPhyChangedEvent(uint16_t conn_id,uint8_t tx_phy,uint8_t rx_phy,tGATT_STATUS status)522 void InjectPhyChangedEvent(uint16_t conn_id, uint8_t tx_phy, uint8_t rx_phy,
523 tGATT_STATUS status) {
524 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
525 tBTA_GATTC_PHY_UPDATE event_data = {
526 .conn_id = conn_id,
527 .tx_phy = tx_phy,
528 .rx_phy = rx_phy,
529 .status = status,
530 };
531
532 do_in_main_thread(base::BindOnce(
533 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_PHY_UPDATE event_data) {
534 gatt_callback(BTA_GATTC_PHY_UPDATE_EVT, (tBTA_GATTC*)&event_data);
535 },
536 base::Unretained(this->gatt_callback), event_data));
537 }
538
InjectSearchCompleteEvent(uint16_t conn_id)539 void InjectSearchCompleteEvent(uint16_t conn_id) {
540 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
541 tBTA_GATTC_SEARCH_CMPL event_data = {
542 .conn_id = conn_id,
543 .status = GATT_SUCCESS,
544 };
545
546 do_in_main_thread(base::BindOnce(
547 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_SEARCH_CMPL event_data) {
548 gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT, (tBTA_GATTC*)&event_data);
549 },
550 base::Unretained(this->gatt_callback), event_data));
551 }
552
InjectNotificationEvent(const RawAddress & test_address,uint16_t conn_id,uint16_t handle,std::vector<uint8_t> value)553 void InjectNotificationEvent(const RawAddress& test_address, uint16_t conn_id, uint16_t handle,
554 std::vector<uint8_t> value) {
555 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
556 tBTA_GATTC_NOTIFY event_data = {
557 .conn_id = conn_id,
558 .bda = test_address,
559 .handle = handle,
560 .len = (uint8_t)value.size(),
561 .is_notify = true,
562 };
563
564 std::copy(value.begin(), value.end(), event_data.value);
565 do_in_main_thread(base::BindOnce(
566 [](tBTA_GATTC_CBACK* gatt_callback, tBTA_GATTC_NOTIFY event_data) {
567 gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
568 },
569 base::Unretained(this->gatt_callback), event_data));
570 }
571
InjectContextTypes(const RawAddress & test_address,uint16_t conn_id,uint16_t handle,AudioContexts sink_ctxs,AudioContexts source_ctxs)572 void InjectContextTypes(const RawAddress& test_address, uint16_t conn_id, uint16_t handle,
573 AudioContexts sink_ctxs, AudioContexts source_ctxs) {
574 std::vector<uint8_t> contexts = {
575 (uint8_t)(sink_ctxs.value()), (uint8_t)(sink_ctxs.value() >> 8),
576 (uint8_t)(source_ctxs.value()), (uint8_t)(source_ctxs.value() >> 8)};
577
578 InjectNotificationEvent(test_address, conn_id, handle, contexts);
579 }
580
InjectSupportedContextTypes(const RawAddress & test_address,uint16_t conn_id,AudioContexts sink_ctxs,AudioContexts source_ctxs)581 void InjectSupportedContextTypes(const RawAddress& test_address, uint16_t conn_id,
582 AudioContexts sink_ctxs, AudioContexts source_ctxs) {
583 /* 0x0077 pacs->supp_contexts_char + 1 */
584 InjectContextTypes(test_address, conn_id, 0x0077, sink_ctxs, source_ctxs);
585 SyncOnMainLoop();
586 }
587
InjectAvailableContextTypes(const RawAddress & test_address,uint16_t conn_id,AudioContexts sink_ctxs,AudioContexts source_ctxs,bool sync_on_mainloop=true)588 void InjectAvailableContextTypes(const RawAddress& test_address, uint16_t conn_id,
589 AudioContexts sink_ctxs, AudioContexts source_ctxs,
590 bool sync_on_mainloop = true) {
591 /* 0x0074 is pacs->avail_contexts_char + 1 */
592 InjectContextTypes(test_address, conn_id, 0x0074, sink_ctxs, source_ctxs);
593 if (sync_on_mainloop) {
594 SyncOnMainLoop();
595 }
596 }
597
SetUpMockGatt()598 void SetUpMockGatt() {
599 // default action for GetCharacteristic function call
600 ON_CALL(mock_gatt_interface_, GetCharacteristic(_, _))
601 .WillByDefault(
602 Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Characteristic* {
603 std::list<gatt::Service>& services = peer_devices.at(conn_id)->services;
604 for (auto const& service : services) {
605 for (auto const& characteristic : service.characteristics) {
606 if (characteristic.value_handle == handle) {
607 return &characteristic;
608 }
609 }
610 }
611
612 return nullptr;
613 }));
614
615 // default action for GetOwningService function call
616 ON_CALL(mock_gatt_interface_, GetOwningService(_, _))
617 .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Service* {
618 std::list<gatt::Service>& services = peer_devices.at(conn_id)->services;
619 for (auto const& service : services) {
620 if (service.handle <= handle && service.end_handle >= handle) {
621 return &service;
622 }
623 }
624
625 return nullptr;
626 }));
627
628 // default action for ServiceSearchRequest function call
629 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _))
630 .WillByDefault(WithArg<0>(
631 Invoke([&](uint16_t conn_id) { InjectSearchCompleteEvent(conn_id); })));
632
633 // default action for GetServices function call
634 ON_CALL(mock_gatt_interface_, GetServices(_))
635 .WillByDefault(WithArg<0>(Invoke([&](uint16_t conn_id) -> std::list<gatt::Service>* {
636 return &peer_devices.at(conn_id)->services;
637 })));
638
639 // default action for RegisterForNotifications function call
640 ON_CALL(mock_gatt_interface_, RegisterForNotifications(gatt_if, _, _))
641 .WillByDefault(Return(GATT_SUCCESS));
642
643 // default action for DeregisterForNotifications function call
644 ON_CALL(mock_gatt_interface_, DeregisterForNotifications(gatt_if, _, _))
645 .WillByDefault(Return(GATT_SUCCESS));
646
647 // default action for WriteDescriptor function call
648 ON_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _))
649 .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle,
650 std::vector<uint8_t> value,
651 tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb,
652 void* cb_data) -> void {
653 auto& ascs = peer_devices.at(conn_id)->ascs;
654 uint8_t idx;
655
656 if (handle == ascs->ctp_ccc) {
657 value = UINT16_TO_VEC_UINT8(ascs->ctp_ccc_val);
658 } else {
659 for (idx = 0; idx < max_num_of_ases; idx++) {
660 if (handle == ascs->sink_ase_ccc[idx] + 1) {
661 value = UINT16_TO_VEC_UINT8(ascs->sink_ase_ccc_val[idx]);
662 break;
663 }
664 if (handle == ascs->source_ase_char[idx] + 1) {
665 value = UINT16_TO_VEC_UINT8(ascs->source_ase_ccc_val[idx]);
666 break;
667 }
668 }
669 }
670
671 if (cb) {
672 do_in_main_thread(base::BindOnce(
673 [](GATT_WRITE_OP_CB cb, uint16_t conn_id, uint16_t handle, uint16_t len,
674 uint8_t* value, void* cb_data) {
675 cb(conn_id, GATT_SUCCESS, handle, len, value, cb_data);
676 },
677 cb, conn_id, handle, value.size(), value.data(), cb_data));
678 }
679 }));
680
681 global_conn_id = 1;
682 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
683 .WillByDefault(Invoke([&](tGATT_IF /*client_if*/, const RawAddress& remote_bda,
684 bool /*is_direct*/, bool /*opportunistic*/) {
685 InjectConnectedEvent(remote_bda, global_conn_id++);
686 }));
687
688 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(Invoke([&](uint16_t conn_id) {
689 ASSERT_NE(conn_id, GATT_INVALID_CONN_ID);
690 InjectDisconnectedEvent(conn_id);
691 }));
692
693 // default Characteristic read handler dispatches requests to service mocks
694 ON_CALL(mock_gatt_queue_, ReadCharacteristic(_, _, _, _))
695 .WillByDefault(Invoke([&](uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
696 void* cb_data) {
697 do_in_main_thread(base::BindOnce(
698 [](std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>>*
699 peer_devices,
700 uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
701 void* cb_data) -> void {
702 if (peer_devices->count(conn_id)) {
703 auto& device = peer_devices->at(conn_id);
704 auto svc = std::find_if(device->services.begin(), device->services.end(),
705 [handle](const gatt::Service& svc) {
706 return (handle >= svc.handle) &&
707 (handle <= svc.end_handle);
708 });
709 if (svc == device->services.end()) {
710 return;
711 }
712
713 GattStatus status;
714 std::vector<uint8_t> value;
715 // Dispatch to mockable handler functions
716 if (svc->handle == device->csis->start) {
717 std::tie(status, value) =
718 device->csis->OnGetCharacteristicValue(handle);
719 } else if (svc->handle == device->cas->start) {
720 std::tie(status, value) = device->cas->OnGetCharacteristicValue(handle);
721 } else if (svc->handle == device->ascs->start) {
722 std::tie(status, value) =
723 device->ascs->OnGetCharacteristicValue(handle);
724 } else if (svc->handle == device->pacs->start) {
725 std::tie(status, value) =
726 device->pacs->OnGetCharacteristicValue(handle);
727 } else {
728 return;
729 }
730
731 cb(conn_id, status, handle, value.size(), value.data(), cb_data);
732 }
733 },
734 &peer_devices, conn_id, handle, cb, cb_data));
735 }));
736
737 // default multiple Characteristic read handler dispatches requests to service mocks
738 ON_CALL(mock_gatt_queue_, ReadMultiCharacteristic(_, _, _, _))
739 .WillByDefault(Invoke([&](uint16_t conn_id, tBTA_GATTC_MULTI& handles,
740 GATT_READ_MULTI_OP_CB cb, void* cb_data) {
741 do_in_main_thread(base::BindOnce(
742 [](std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>>*
743 peer_devices,
744 uint16_t conn_id, tBTA_GATTC_MULTI handles, GATT_READ_MULTI_OP_CB cb,
745 void* cb_data) -> void {
746 if (!peer_devices->count(conn_id)) {
747 return;
748 }
749 auto& device = peer_devices->at(conn_id);
750
751 auto get_char_value_helper = [&](NiceMock<MockDeviceWrapper>& device,
752 uint16_t handle) {
753 auto svc = std::find_if(device.services.begin(), device.services.end(),
754 [handle](const gatt::Service& svc) {
755 return (handle >= svc.handle) &&
756 (handle <= svc.end_handle);
757 });
758 if (svc == device.services.end()) {
759 return std::make_pair(GATT_ERROR, std::vector<uint8_t>());
760 }
761
762 // Dispatch to mockable handler functions
763 if (svc->handle == device.csis->start) {
764 return device.csis->OnGetCharacteristicValue(handle);
765 } else if (svc->handle == device.cas->start) {
766 return device.cas->OnGetCharacteristicValue(handle);
767 } else if (svc->handle == device.ascs->start) {
768 return device.ascs->OnGetCharacteristicValue(handle);
769 } else if (svc->handle == device.pacs->start) {
770 return device.pacs->OnGetCharacteristicValue(handle);
771 } else {
772 return std::make_pair(GATT_ERROR, std::vector<uint8_t>());
773 };
774 };
775 std::array<uint8_t, GATT_MAX_ATTR_LEN> value;
776 uint16_t value_end = 0;
777 for (int i = 0; i < handles.num_attr; i++) {
778 GattStatus status;
779 std::vector<uint8_t> curr_val;
780 std::tie(status, curr_val) =
781 get_char_value_helper(*device, handles.handles[i]);
782
783 if (status != GATT_SUCCESS) {
784 cb(conn_id, status, handles, 0, value.data(), cb_data);
785 return;
786 }
787
788 value[value_end] = (curr_val.size() & 0x00ff);
789 value[value_end + 1] = (curr_val.size() & 0xff00) >> 8;
790 value_end += 2;
791
792 // concatenate all read values together
793 std::copy(curr_val.begin(), curr_val.end(), value.data() + value_end);
794 value_end += curr_val.size();
795 }
796 cb(conn_id, GATT_SUCCESS, handles, value_end, value.data(), cb_data);
797 },
798 &peer_devices, conn_id, handles, cb, cb_data));
799 }));
800 }
801
SetUpMockGroups()802 void SetUpMockGroups() {
803 MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
804 MockDeviceGroups::SetMockInstanceForTesting(&mock_groups_module_);
805 MockLeAudioGroupStateMachine::SetMockInstanceForTesting(&mock_state_machine_);
806
807 ON_CALL(mock_csis_client_module_, Get()).WillByDefault(Return(&mock_csis_client_module_));
808
809 // Store group callbacks so that we could inject grouping events
810 group_callbacks_ = nullptr;
811 ON_CALL(mock_groups_module_, Initialize(_)).WillByDefault(SaveArg<0>(&group_callbacks_));
812
813 ON_CALL(mock_groups_module_, GetGroupId(_, _))
814 .WillByDefault([this](const RawAddress& addr, bluetooth::Uuid /*uuid*/) {
815 if (groups.find(addr) != groups.end()) {
816 return groups.at(addr);
817 }
818 return bluetooth::groups::kGroupUnknown;
819 });
820
821 ON_CALL(mock_groups_module_, RemoveDevice(_, _))
822 .WillByDefault([this](const RawAddress& addr, int /*group_id*/) {
823 int group_id = -1;
824 if (groups.find(addr) != groups.end()) {
825 group_id = groups[addr];
826 groups.erase(addr);
827 }
828 if (group_id < 0) {
829 return;
830 }
831
832 do_in_main_thread(base::BindOnce(
833 [](const RawAddress& address, int group_id,
834 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks) {
835 group_callbacks->OnGroupMemberRemoved(address, group_id);
836 },
837 addr, group_id, base::Unretained(group_callbacks_)));
838 });
839
840 // Our test devices have unique LSB - use it for unique grouping when
841 // devices added with a non-CIS context and no grouping info
842 ON_CALL(mock_groups_module_, AddDevice(_, bluetooth::le_audio::uuid::kCapServiceUuid, _))
843 .WillByDefault(
844 [this](const RawAddress& addr,
845 bluetooth::Uuid /*uuid*/ = bluetooth::le_audio::uuid::kCapServiceUuid,
846 int group_id = bluetooth::groups::kGroupUnknown) -> int {
847 if (group_id == bluetooth::groups::kGroupUnknown) {
848 /* Generate group id from address */
849 groups[addr] = addr.address[RawAddress::kLength - 1];
850 group_id = groups[addr];
851 } else {
852 groups[addr] = group_id;
853 }
854
855 InjectGroupDeviceAdded(addr, groups[addr]);
856 return addr.address[RawAddress::kLength - 1];
857 });
858
859 ON_CALL(mock_state_machine_, Initialize(_))
860 .WillByDefault(SaveArg<0>(&state_machine_callbacks_));
861
862 ON_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _))
863 .WillByDefault([this](LeAudioDeviceGroup* group, types::LeAudioContextType context_type,
864 types::BidirectionalPair<types::AudioContexts>
865 metadata_context_types,
866 types::BidirectionalPair<std::vector<uint8_t>> ccid_lists,
867 bool configure_qos) {
868 auto group_state = group->GetState();
869 bool isReconfiguration = group->IsPendingConfiguration();
870
871 log::info(
872 "ConfigureStream: group {} state {}, context type {} sink metadata_ctx {}, "
873 "source metadata_ctx {}, ccid_sink size {}, ccid_source_size {}, "
874 "isReconfiguration {}",
875 group->group_id_, bluetooth::common::ToString(group_state),
876 bluetooth::common::ToString(context_type),
877 bluetooth::common::ToString(metadata_context_types.sink),
878 bluetooth::common::ToString(metadata_context_types.source),
879 ccid_lists.sink.size(), ccid_lists.source.size(), isReconfiguration);
880
881 /* Do what ReleaseCisIds(group) does: start */
882 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
883 while (leAudioDevice != nullptr) {
884 for (auto& ase : leAudioDevice->ases_) {
885 ase.cis_id = bluetooth::le_audio::kInvalidCisId;
886 }
887 leAudioDevice = group->GetNextDevice(leAudioDevice);
888 }
889 group->ClearAllCises();
890 /* end */
891
892 if (!group->Configure(context_type, metadata_context_types, ccid_lists)) {
893 log::error("ConfigureStream: Could not configure ASEs for group {} content type {}",
894 group->group_id_, int(context_type));
895
896 return false;
897 }
898
899 group->cig.GenerateCisIds(context_type);
900
901 types::AseState config_state =
902 types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
903
904 if (configure_qos) {
905 // Make sure CIG is created
906 config_state = types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED;
907 group->cig.SetState(types::CigState::CREATED);
908 }
909
910 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
911 device = group->GetNextDevice(device)) {
912 if (!group->cig.AssignCisIds(device)) {
913 continue;
914 }
915
916 if (group->cig.GetState() == types::CigState::CREATED) {
917 group->AssignCisConnHandlesToAses(device);
918 }
919
920 for (auto& ase : device->ases_) {
921 if (!ase.active) {
922 continue;
923 }
924
925 ase.cis_state = types::CisState::IDLE;
926 ase.data_path_state = types::DataPathState::IDLE;
927 ase.state = config_state;
928 }
929 }
930
931 // Inject the state
932 group->SetTargetState(config_state);
933 group->SetState(group->GetTargetState());
934 group->ClearPendingConfiguration();
935 do_in_main_thread(base::BindOnce(
936 [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
937 state_machine_callbacks) {
938 state_machine_callbacks->StatusReportCb(
939 group_id, GroupStreamStatus::CONFIGURED_BY_USER);
940 },
941 group->group_id_, base::Unretained(this->state_machine_callbacks_)));
942 return true;
943 });
944
945 ON_CALL(mock_state_machine_, AttachToStream(_, _, _))
946 .WillByDefault([this](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
947 types::BidirectionalPair<std::vector<uint8_t>> ccids) {
948 log::info(
949 "AttachToStream: group_id {}, address {}, current_state {}, target_state {}",
950 group->group_id_, leAudioDevice->address_,
951 bluetooth::common::ToString(group->GetState()),
952 bluetooth::common::ToString(group->GetTargetState()));
953
954 if (group->GetState() != types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
955 if (group->GetTargetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
956 attach_to_stream_scheduled = true;
957 }
958
959 return false;
960 }
961
962 group->Configure(group->GetConfigurationContextType(), group->GetMetadataContexts(),
963 ccids);
964 if (!group->cig.AssignCisIds(leAudioDevice)) {
965 return false;
966 }
967 group->AssignCisConnHandlesToAses(leAudioDevice);
968
969 auto* stream_conf = &group->stream_conf;
970
971 for (auto& ase : leAudioDevice->ases_) {
972 if (!ase.active) {
973 continue;
974 }
975
976 // And also skip the ase establishment procedure which should
977 // be tested as part of the state machine unit tests
978 ase.cis_state = types::CisState::CONNECTED;
979 ase.data_path_state = types::DataPathState::CONFIGURED;
980 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
981
982 uint16_t cis_conn_hdl = ase.cis_conn_hdl;
983 auto core_config = ase.codec_config.GetAsCoreCodecConfig();
984
985 /* Copied from state_machine.cc ProcessHciNotifSetupIsoDataPath */
986 if (ase.direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
987 auto iter = std::find_if(
988 stream_conf->stream_params.source.stream_locations.begin(),
989 stream_conf->stream_params.source.stream_locations.end(),
990 [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });
991
992 if (iter == stream_conf->stream_params.source.stream_locations.end()) {
993 stream_conf->stream_params.source.stream_locations.emplace_back(std::make_pair(
994 ase.cis_conn_hdl, *core_config.audio_channel_allocation));
995
996 stream_conf->stream_params.source.num_of_devices++;
997 stream_conf->stream_params.source.num_of_channels += ase.channel_count;
998
999 log::info(
1000 "AttachToStream: Added Source Stream Configuration. CIS Connection "
1001 "Handle: "
1002 "{}, Audio Channel Allocation: {}, Source Number Of "
1003 "Devices: {}, Source Number Of Channels: {}",
1004 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1005 stream_conf->stream_params.source.num_of_devices,
1006 stream_conf->stream_params.source.num_of_channels);
1007 }
1008 } else {
1009 auto iter = std::find_if(
1010 stream_conf->stream_params.sink.stream_locations.begin(),
1011 stream_conf->stream_params.sink.stream_locations.end(),
1012 [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });
1013
1014 if (iter == stream_conf->stream_params.sink.stream_locations.end()) {
1015 stream_conf->stream_params.sink.stream_locations.emplace_back(std::make_pair(
1016 ase.cis_conn_hdl, *core_config.audio_channel_allocation));
1017
1018 stream_conf->stream_params.sink.num_of_devices++;
1019 stream_conf->stream_params.sink.num_of_channels += ase.channel_count;
1020
1021 log::info(
1022 "AttachToStream: Added Sink Stream Configuration. CIS Connection "
1023 "Handle: "
1024 "{}, Audio Channel Allocation: {}, Sink Number Of Devices: "
1025 "{}, Sink Number Of Channels: {}",
1026 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1027 stream_conf->stream_params.sink.num_of_devices,
1028 stream_conf->stream_params.sink.num_of_channels);
1029 }
1030 }
1031 }
1032
1033 return true;
1034 });
1035
1036 ON_CALL(mock_state_machine_, StartStream(_, _, _, _))
1037 .WillByDefault([this](LeAudioDeviceGroup* group, types::LeAudioContextType context_type,
1038 types::BidirectionalPair<types::AudioContexts>
1039 metadata_context_types,
1040 types::BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
1041 auto group_state = group->GetState();
1042 log::info(
1043 "StartStream: group {} state {}, context type {} sink metadata_ctx {}, "
1044 "source metadata_ctx {}, ccid_sink size {}, ccid_source_size {}",
1045 group->group_id_, bluetooth::common::ToString(group_state),
1046 bluetooth::common::ToString(context_type),
1047 bluetooth::common::ToString(metadata_context_types.sink),
1048 bluetooth::common::ToString(metadata_context_types.source),
1049 ccid_lists.sink.size(), ccid_lists.source.size());
1050
1051 /* Do nothing if already streaming - the implementation would
1052 * probably update the metadata.
1053 */
1054 if (group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
1055 return true;
1056 }
1057
1058 // Inject the state
1059 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1060
1061 if (group_state != types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) {
1062 /* Do what ReleaseCisIds(group) does: start */
1063 LeAudioDevice* leAudioDevice = group->GetFirstDevice();
1064 while (leAudioDevice != nullptr) {
1065 for (auto& ase : leAudioDevice->ases_) {
1066 ase.cis_id = bluetooth::le_audio::kInvalidCisId;
1067 }
1068 leAudioDevice = group->GetNextDevice(leAudioDevice);
1069 }
1070 group->ClearAllCises();
1071 /* end */
1072
1073 if (!group->Configure(context_type, metadata_context_types, ccid_lists)) {
1074 log::error("StartStream: failed to set ASE configuration");
1075 return false;
1076 }
1077
1078 if (group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE ||
1079 group_state == types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) {
1080 group->cig.GenerateCisIds(context_type);
1081
1082 std::vector<uint16_t> conn_handles;
1083 for (uint8_t i = 0; i < (uint8_t)(group->cig.cises.size()); i++) {
1084 conn_handles.push_back(iso_con_counter_++);
1085 }
1086 group->cig.AssignCisConnHandles(conn_handles);
1087 for (LeAudioDevice* device = group->GetFirstActiveDevice(); device != nullptr;
1088 device = group->GetNextActiveDevice(device)) {
1089 if (!group->cig.AssignCisIds(device)) {
1090 return false;
1091 }
1092 group->AssignCisConnHandlesToAses(device);
1093 }
1094 }
1095 }
1096
1097 auto* stream_conf = &group->stream_conf;
1098
1099 // Fake ASE configuration
1100 for (LeAudioDevice* device = group->GetFirstActiveDevice(); device != nullptr;
1101 device = group->GetNextActiveDevice(device)) {
1102 for (auto& ase : device->ases_) {
1103 if (!ase.active) {
1104 continue;
1105 }
1106
1107 // And also skip the ase establishment procedure which should
1108 // be tested as part of the state machine unit tests
1109 ase.cis_state = types::CisState::CONNECTED;
1110 ase.data_path_state = types::DataPathState::CONFIGURED;
1111 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
1112 ase.qos_preferences.pres_delay_min = 2500;
1113 ase.qos_preferences.pres_delay_max = 2500;
1114 ase.qos_preferences.preferred_pres_delay_min = 2500;
1115 ase.qos_preferences.preferred_pres_delay_max = 2500;
1116 auto core_config = ase.codec_config.GetAsCoreCodecConfig();
1117
1118 uint16_t cis_conn_hdl = ase.cis_conn_hdl;
1119
1120 /* Copied from state_machine.cc ProcessHciNotifSetupIsoDataPath */
1121 if (ase.direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
1122 auto iter = std::find_if(
1123 stream_conf->stream_params.source.stream_locations.begin(),
1124 stream_conf->stream_params.source.stream_locations.end(),
1125 [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });
1126
1127 if (iter == stream_conf->stream_params.source.stream_locations.end()) {
1128 stream_conf->stream_params.source.stream_locations.emplace_back(
1129 std::make_pair(ase.cis_conn_hdl,
1130 *core_config.audio_channel_allocation));
1131
1132 stream_conf->stream_params.source.num_of_devices++;
1133 stream_conf->stream_params.source.num_of_channels += ase.channel_count;
1134 stream_conf->stream_params.source.audio_channel_allocation |=
1135 *core_config.audio_channel_allocation;
1136
1137 if (stream_conf->stream_params.source.sample_frequency_hz == 0) {
1138 stream_conf->stream_params.source.sample_frequency_hz =
1139 core_config.GetSamplingFrequencyHz();
1140 } else {
1141 log::assert_that(stream_conf->stream_params.source.sample_frequency_hz ==
1142 core_config.GetSamplingFrequencyHz(),
1143 "StartStream: sample freq mismatch: {}!={}",
1144 stream_conf->stream_params.source.sample_frequency_hz,
1145 core_config.GetSamplingFrequencyHz());
1146 }
1147
1148 if (stream_conf->stream_params.source.octets_per_codec_frame == 0) {
1149 stream_conf->stream_params.source.octets_per_codec_frame =
1150 *core_config.octets_per_codec_frame;
1151 } else {
1152 log::assert_that(stream_conf->stream_params.source.octets_per_codec_frame ==
1153 *core_config.octets_per_codec_frame,
1154 "StartStream: octets per frame mismatch: {}!={}",
1155 stream_conf->stream_params.source.octets_per_codec_frame,
1156 *core_config.octets_per_codec_frame);
1157 }
1158
1159 if (stream_conf->stream_params.source.codec_frames_blocks_per_sdu == 0) {
1160 stream_conf->stream_params.source.codec_frames_blocks_per_sdu =
1161 *core_config.codec_frames_blocks_per_sdu;
1162 stream_conf->stream_params.source.frame_duration_us =
1163 core_config.GetFrameDurationUs();
1164 } else {
1165 log::assert_that(
1166 stream_conf->stream_params.source.codec_frames_blocks_per_sdu ==
1167 *core_config.codec_frames_blocks_per_sdu,
1168 "StartStream: codec_frames_blocks_per_sdu: {}!={}",
1169 stream_conf->stream_params.source.codec_frames_blocks_per_sdu,
1170 *core_config.codec_frames_blocks_per_sdu);
1171 }
1172
1173 log::info(
1174 "StartStream: Added Source Stream Configuration. CIS Connection "
1175 "Handle: {}, Audio Channel Allocation: {}, Source Number "
1176 "Of Devices: {}, Source Number Of Channels: {}",
1177 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1178 stream_conf->stream_params.source.num_of_devices,
1179 stream_conf->stream_params.source.num_of_channels);
1180 }
1181 } else {
1182 auto iter = std::find_if(
1183 stream_conf->stream_params.sink.stream_locations.begin(),
1184 stream_conf->stream_params.sink.stream_locations.end(),
1185 [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });
1186
1187 if (iter == stream_conf->stream_params.sink.stream_locations.end()) {
1188 stream_conf->stream_params.sink.stream_locations.emplace_back(std::make_pair(
1189 ase.cis_conn_hdl, *core_config.audio_channel_allocation));
1190
1191 stream_conf->stream_params.sink.num_of_devices++;
1192 stream_conf->stream_params.sink.num_of_channels += ase.channel_count;
1193
1194 stream_conf->stream_params.sink.audio_channel_allocation |=
1195 *core_config.audio_channel_allocation;
1196
1197 if (stream_conf->stream_params.sink.sample_frequency_hz == 0) {
1198 stream_conf->stream_params.sink.sample_frequency_hz =
1199 core_config.GetSamplingFrequencyHz();
1200 } else {
1201 log::assert_that(stream_conf->stream_params.sink.sample_frequency_hz ==
1202 core_config.GetSamplingFrequencyHz(),
1203 "StartStream: sample freq mismatch: {}!={}",
1204 stream_conf->stream_params.sink.sample_frequency_hz,
1205 core_config.GetSamplingFrequencyHz());
1206 }
1207
1208 if (stream_conf->stream_params.sink.octets_per_codec_frame == 0) {
1209 stream_conf->stream_params.sink.octets_per_codec_frame =
1210 *core_config.octets_per_codec_frame;
1211 } else {
1212 log::assert_that(stream_conf->stream_params.sink.octets_per_codec_frame ==
1213 *core_config.octets_per_codec_frame,
1214 "StartStream: octets per frame mismatch: {}!={}",
1215 stream_conf->stream_params.sink.octets_per_codec_frame,
1216 *core_config.octets_per_codec_frame);
1217 }
1218
1219 if (stream_conf->stream_params.sink.codec_frames_blocks_per_sdu == 0) {
1220 stream_conf->stream_params.sink.codec_frames_blocks_per_sdu =
1221 *core_config.codec_frames_blocks_per_sdu;
1222 stream_conf->stream_params.sink.frame_duration_us =
1223 core_config.GetFrameDurationUs();
1224 } else {
1225 log::assert_that(
1226 stream_conf->stream_params.sink.codec_frames_blocks_per_sdu ==
1227 *core_config.codec_frames_blocks_per_sdu,
1228 "StartStream: codec_frames_blocks_per_sdu: {}!={}",
1229 stream_conf->stream_params.sink.codec_frames_blocks_per_sdu,
1230 *core_config.codec_frames_blocks_per_sdu);
1231 }
1232
1233 log::info(
1234 "StartStream: Added Sink Stream Configuration. CIS Connection "
1235 "Handle: "
1236 "{}, Audio Channel Allocation: {}, Sink Number Of "
1237 "Devices: {}, Sink Number Of Channels: {}",
1238 ase.cis_conn_hdl, *core_config.audio_channel_allocation,
1239 stream_conf->stream_params.sink.num_of_devices,
1240 stream_conf->stream_params.sink.num_of_channels);
1241 }
1242 }
1243 }
1244 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1245 /* Assume CIG is created */
1246 group->cig.SetState(bluetooth::le_audio::types::CigState::CREATED);
1247 }
1248
1249 streaming_groups[group->group_id_] = group;
1250
1251 if (stay_at_qos_config_in_start_stream) {
1252 return true;
1253 }
1254
1255 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1256 do_in_main_thread(base::BindOnce(
1257 [](int group_id, bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
1258 state_machine_callbacks) {
1259 state_machine_callbacks->StatusReportCb(group_id,
1260 GroupStreamStatus::STREAMING);
1261 },
1262 group->group_id_, base::Unretained(this->state_machine_callbacks_)));
1263 return true;
1264 });
1265
1266 ON_CALL(mock_state_machine_, SuspendStream(_)).WillByDefault([this](LeAudioDeviceGroup* group) {
1267 // Fake ASE state
1268 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
1269 device = group->GetNextDevice(device)) {
1270 for (auto& ase : device->ases_) {
1271 ase.cis_state = types::CisState::CONNECTED;
1272 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED;
1273 }
1274 }
1275
1276 // Inject the state
1277 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1278 group->SetState(group->GetTargetState());
1279 state_machine_callbacks_->StatusReportCb(group->group_id_, GroupStreamStatus::SUSPENDED);
1280 });
1281
1282 ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
1283 .WillByDefault([this](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) {
1284 if (!group) {
1285 return;
1286 }
1287
1288 for (auto& ase : leAudioDevice->ases_) {
1289 group->RemoveCisFromStreamIfNeeded(leAudioDevice, ase.cis_conn_hdl);
1290 }
1291
1292 if (group->IsEmpty()) {
1293 group->cig.SetState(bluetooth::le_audio::types::CigState::NONE);
1294 InjectCigRemoved(group->group_id_);
1295 }
1296 });
1297
1298 ON_CALL(mock_state_machine_, ProcessHciNotifCisDisconnected(_, _, _))
1299 .WillByDefault([](LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
1300 const bluetooth::hci::iso_manager::cis_disconnected_evt* event) {
1301 if (!group) {
1302 return;
1303 }
1304 auto ases_pair = leAudioDevice->GetAsesByCisConnHdl(event->cis_conn_hdl);
1305 if (ases_pair.sink) {
1306 ases_pair.sink->cis_state = types::CisState::ASSIGNED;
1307 ases_pair.sink->active = false;
1308 }
1309 if (ases_pair.source) {
1310 ases_pair.source->active = false;
1311 ases_pair.source->cis_state = types::CisState::ASSIGNED;
1312 }
1313 /* Invalidate stream configuration if needed */
1314 auto* stream_conf = &group->stream_conf;
1315 if (!stream_conf->stream_params.sink.stream_locations.empty() ||
1316 !stream_conf->stream_params.source.stream_locations.empty()) {
1317 stream_conf->stream_params.sink.stream_locations.erase(
1318 std::remove_if(
1319 stream_conf->stream_params.sink.stream_locations.begin(),
1320 stream_conf->stream_params.sink.stream_locations.end(),
1321 [leAudioDevice, &stream_conf](auto& pair) {
1322 auto ases = leAudioDevice->GetAsesByCisConnHdl(pair.first);
1323
1324 log::info(
1325 ", sink ase to delete. Cis handle: {}, ase pointer: "
1326 "{}",
1327 (int)(pair.first), std::format_ptr(+ases.sink));
1328 if (ases.sink) {
1329 stream_conf->stream_params.sink.num_of_devices--;
1330 stream_conf->stream_params.sink.num_of_channels -=
1331 ases.sink->channel_count;
1332
1333 log::info(
1334 "Sink Number Of Devices: {}, Sink Number Of "
1335 "Channels: {}",
1336 stream_conf->stream_params.sink.num_of_devices,
1337 stream_conf->stream_params.sink.num_of_channels);
1338 }
1339 return ases.sink;
1340 }),
1341 stream_conf->stream_params.sink.stream_locations.end());
1342
1343 stream_conf->stream_params.source.stream_locations.erase(
1344 std::remove_if(
1345 stream_conf->stream_params.source.stream_locations.begin(),
1346 stream_conf->stream_params.source.stream_locations.end(),
1347 [leAudioDevice, &stream_conf](auto& pair) {
1348 auto ases = leAudioDevice->GetAsesByCisConnHdl(pair.first);
1349
1350 log::info(", source to delete. Cis handle: {}, ase pointer: {}",
1351 (int)(pair.first), std::format_ptr(ases.source));
1352 if (ases.source) {
1353 stream_conf->stream_params.source.num_of_devices--;
1354 stream_conf->stream_params.source.num_of_channels -=
1355 ases.source->channel_count;
1356
1357 log::info(
1358 ", Source Number Of Devices: {}, Source Number Of "
1359 "Channels: {}",
1360 stream_conf->stream_params.source.num_of_devices,
1361 stream_conf->stream_params.source.num_of_channels);
1362 }
1363 return ases.source;
1364 }),
1365 stream_conf->stream_params.source.stream_locations.end());
1366 }
1367
1368 group->cig.UnassignCis(leAudioDevice, event->cis_conn_hdl);
1369 });
1370
1371 ON_CALL(mock_state_machine_, StopStream(_)).WillByDefault([this](LeAudioDeviceGroup* group) {
1372 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
1373 device = group->GetNextDevice(device)) {
1374 /* Invalidate stream configuration if needed */
1375 auto* stream_conf = &group->stream_conf;
1376 if (!stream_conf->stream_params.sink.stream_locations.empty() ||
1377 !stream_conf->stream_params.source.stream_locations.empty()) {
1378 stream_conf->stream_params.sink.stream_locations.erase(
1379 std::remove_if(stream_conf->stream_params.sink.stream_locations.begin(),
1380 stream_conf->stream_params.sink.stream_locations.end(),
1381 [device, &stream_conf](auto& pair) {
1382 auto ases = device->GetAsesByCisConnHdl(pair.first);
1383
1384 log::info(
1385 ", sink ase to delete. Cis handle: {}, ase "
1386 "pointer: {}",
1387 (int)(pair.first), std::format_ptr(+ases.sink));
1388 if (ases.sink) {
1389 stream_conf->stream_params.sink.num_of_devices--;
1390 stream_conf->stream_params.sink.num_of_channels -=
1391 ases.sink->channel_count;
1392
1393 log::info(
1394 "Sink Number Of Devices: {}, Sink Number Of "
1395 "Channels: {}",
1396 stream_conf->stream_params.sink.num_of_devices,
1397 stream_conf->stream_params.sink.num_of_channels);
1398 }
1399 return ases.sink;
1400 }),
1401 stream_conf->stream_params.sink.stream_locations.end());
1402
1403 stream_conf->stream_params.source.stream_locations.erase(
1404 std::remove_if(stream_conf->stream_params.source.stream_locations.begin(),
1405 stream_conf->stream_params.source.stream_locations.end(),
1406 [device, &stream_conf](auto& pair) {
1407 auto ases = device->GetAsesByCisConnHdl(pair.first);
1408
1409 log::info(
1410 ", source to delete. Cis handle: {}, ase pointer: "
1411 "{}",
1412 (int)(pair.first), std::format_ptr(+ases.source));
1413 if (ases.source) {
1414 stream_conf->stream_params.source.num_of_devices--;
1415 stream_conf->stream_params.source.num_of_channels -=
1416 ases.source->channel_count;
1417
1418 log::info(
1419 ", Source Number Of Devices: {}, Source Number "
1420 "Of Channels: {}",
1421 stream_conf->stream_params.source.num_of_devices,
1422 stream_conf->stream_params.source.num_of_channels);
1423 }
1424 return ases.source;
1425 }),
1426 stream_conf->stream_params.source.stream_locations.end());
1427 }
1428
1429 for (auto& ase : device->ases_) {
1430 group->cig.UnassignCis(device, ase.cis_conn_hdl);
1431
1432 ase.cis_state = types::CisState::IDLE;
1433 ase.data_path_state = types::DataPathState::IDLE;
1434 ase.active = false;
1435 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
1436 ase.cis_id = 0;
1437 ase.cis_conn_hdl = bluetooth::le_audio::kInvalidCisConnHandle;
1438 }
1439 }
1440
1441 // Inject the state
1442 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
1443 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING);
1444 state_machine_callbacks_->StatusReportCb(group->group_id_, GroupStreamStatus::RELEASING);
1445
1446 if (stay_at_releasing_stop_stream) {
1447 log::info("StopStream {} -> stay in Releasing state", group->group_id_);
1448 return;
1449 }
1450 group->SetState(group->GetTargetState());
1451
1452 do_in_main_thread(base::BindOnce(
1453 [](bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* cb, int group_id) {
1454 cb->StatusReportCb(group_id, GroupStreamStatus::IDLE);
1455 },
1456 state_machine_callbacks_, group->group_id_));
1457 });
1458 }
1459
SetUp()1460 void SetUp() override {
1461 __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
1462 init_message_loop_thread();
1463 reset_mock_function_count_map();
1464 ON_CALL(controller_, SupportsBleConnectedIsochronousStreamCentral).WillByDefault(Return(true));
1465 ON_CALL(controller_, SupportsBleConnectedIsochronousStreamPeripheral)
1466 .WillByDefault(Return(true));
1467 ON_CALL(controller_, SupportsBle2mPhy).WillByDefault(Return(true));
1468 bluetooth::hci::testing::mock_controller_ = &controller_;
1469 bluetooth::manager::SetMockBtmInterface(&mock_btm_interface_);
1470 gatt::SetMockBtaGattInterface(&mock_gatt_interface_);
1471 gatt::SetMockBtaGattQueue(&mock_gatt_queue_);
1472 bluetooth::storage::SetMockBtifStorageInterface(&mock_btif_storage_);
1473
1474 iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
1475 ASSERT_NE(iso_manager_, nullptr);
1476 iso_manager_->Start();
1477
1478 mock_iso_manager_ = MockIsoManager::GetInstance();
1479 ON_CALL(*mock_iso_manager_, RegisterCigCallbacks(_)).WillByDefault(SaveArg<0>(&cig_callbacks_));
1480
1481 ON_CALL(mock_btm_interface_, IsLinkKeyKnown(_, _)).WillByDefault(DoAll(Return(true)));
1482
1483 // Required since we call OnAudioDataReady()
1484 const auto codec_location = ::bluetooth::le_audio::types::CodecLocation::HOST;
1485
1486 SetUpMockAudioHal();
1487 SetUpMockGroups();
1488 SetUpMockGatt();
1489 SetUpMockCodecManager(codec_location);
1490
1491 stay_at_qos_config_in_start_stream = false;
1492 stay_at_releasing_stop_stream = false;
1493
1494 available_snk_context_types_ = 0xffff;
1495 available_src_context_types_ = 0xffff;
1496 supported_snk_context_types_ = 0xffff;
1497 supported_src_context_types_ = 0xffff;
1498
1499 empty_source_pack_ = false;
1500 empty_sink_pack_ = false;
1501
1502 bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(codec_location);
1503 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
1504 }
1505
SetUpMockCodecManager(types::CodecLocation location)1506 void SetUpMockCodecManager(types::CodecLocation location) {
1507 codec_manager_ = bluetooth::le_audio::CodecManager::GetInstance();
1508 ASSERT_NE(codec_manager_, nullptr);
1509 std::vector<bluetooth::le_audio::btle_audio_codec_config_t> mock_offloading_preference(0);
1510 codec_manager_->Start(mock_offloading_preference);
1511 mock_codec_manager_ = MockCodecManager::GetInstance();
1512 ASSERT_NE((void*)mock_codec_manager_, (void*)codec_manager_);
1513 ASSERT_NE(mock_codec_manager_, nullptr);
1514 ON_CALL(*mock_codec_manager_, GetCodecLocation()).WillByDefault(Return(location));
1515 ON_CALL(*mock_codec_manager_, UpdateActiveUnicastAudioHalClient(_, _, _))
1516 .WillByDefault(Return(true));
1517 ON_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(_, _))
1518 .WillByDefault(Return(true));
1519 // Turn on the dual bidir SWB support
1520 ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(true));
1521 // Regardless of the codec location, return all the possible configurations
1522 ON_CALL(*mock_codec_manager_, GetCodecConfig)
1523 .WillByDefault(Invoke([](const CodecManager::UnicastConfigurationRequirements&
1524 requirements,
1525 CodecManager::UnicastConfigurationProvider provider) {
1526 auto filtered = *le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
1527 requirements.audio_context_type);
1528 // Filter out the dual bidir SWB configurations
1529 if (!bluetooth::le_audio::CodecManager::GetInstance()->IsDualBiDirSwbSupported()) {
1530 filtered.erase(std::remove_if(filtered.begin(), filtered.end(),
1531 [](auto const& el) {
1532 if (el->confs.source.empty()) {
1533 return false;
1534 }
1535 return AudioSetConfigurationProvider::Get()
1536 ->CheckConfigurationIsDualBiDirSwb(*el);
1537 }),
1538 filtered.end());
1539 }
1540 return provider(requirements, &filtered);
1541 }));
1542 }
1543
TearDown()1544 void TearDown() override {
1545 com::android::bluetooth::flags::provider_->reset_flags();
1546
1547 if (is_audio_unicast_source_acquired) {
1548 if (unicast_source_hal_cb_ != nullptr) {
1549 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(1);
1550 }
1551 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
1552 }
1553
1554 if (is_audio_unicast_sink_acquired) {
1555 if (unicast_sink_hal_cb_ != nullptr) {
1556 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop).Times(1);
1557 }
1558 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
1559 }
1560
1561 // Message loop cleanup should wait for all the 'till now' scheduled calls
1562 // so it should be called right at the very begginning of teardown.
1563 cleanup_message_loop_thread();
1564
1565 // This is required since Stop() and Cleanup() may trigger some callbacks or
1566 // drop unique pointers to mocks we have raw pointer for and we want to
1567 // verify them all.
1568 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1569
1570 if (LeAudioClient::IsLeAudioClientRunning()) {
1571 EXPECT_CALL(mock_gatt_interface_, AppDeregister(gatt_if)).Times(1);
1572 LeAudioClient::Cleanup();
1573 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
1574 }
1575
1576 owned_mock_le_audio_sink_hal_client_.reset();
1577 owned_mock_le_audio_source_hal_client_.reset();
1578
1579 if (bluetooth::le_audio::AudioSetConfigurationProvider::Get()) {
1580 bluetooth::le_audio::AudioSetConfigurationProvider::Cleanup();
1581 }
1582
1583 iso_manager_->Stop();
1584 bluetooth::hci::testing::mock_controller_ = nullptr;
1585 }
1586
1587 protected:
1588 class MockDeviceWrapper {
1589 class IGattHandlers {
1590 public:
1591 // IGattHandlers() = default;
1592 virtual ~IGattHandlers() = default;
1593 virtual std::pair<GattStatus, std::vector<uint8_t>> OnGetCharacteristicValue(
1594 uint16_t handle) = 0;
1595 virtual void OnWriteCharacteristic(uint16_t handle, std::vector<uint8_t> value,
1596 tGATT_WRITE_TYPE write_type, GATT_WRITE_OP_CB cb,
1597 void* cb_data) = 0;
1598 };
1599
1600 public:
1601 struct csis_mock : public IGattHandlers {
1602 uint16_t start = 0;
1603 uint16_t end = 0;
1604 uint16_t sirk_char = 0;
1605 uint16_t sirk_ccc = 0;
1606 uint16_t size_char = 0;
1607 uint16_t size_ccc = 0;
1608 uint16_t lock_char = 0;
1609 uint16_t lock_ccc = 0;
1610 uint16_t rank_char = 0;
1611
1612 int rank = 0;
1613 int size = 0;
1614
1615 MOCK_METHOD((std::pair<GattStatus, std::vector<uint8_t>>), OnGetCharacteristicValue,
1616 (uint16_t handle), (override));
1617 MOCK_METHOD((void), OnWriteCharacteristic,
1618 (uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
1619 GATT_WRITE_OP_CB cb, void* cb_data),
1620 (override));
1621 };
1622
1623 struct cas_mock : public IGattHandlers {
1624 uint16_t start = 0;
1625 uint16_t end = 0;
1626 uint16_t csis_include = 0;
1627
1628 MOCK_METHOD((std::pair<GattStatus, std::vector<uint8_t>>), OnGetCharacteristicValue,
1629 (uint16_t handle), (override));
1630 MOCK_METHOD((void), OnWriteCharacteristic,
1631 (uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
1632 GATT_WRITE_OP_CB cb, void* cb_data),
1633 (override));
1634 };
1635
1636 struct pacs_mock : public IGattHandlers {
1637 uint16_t start = 0;
1638 uint16_t sink_pac_char = 0;
1639 uint16_t sink_pac_ccc = 0;
1640 uint16_t sink_audio_loc_char = 0;
1641 uint16_t sink_audio_loc_ccc = 0;
1642 uint16_t source_pac_char = 0;
1643 uint16_t source_pac_ccc = 0;
1644 uint16_t source_audio_loc_char = 0;
1645 uint16_t source_audio_loc_ccc = 0;
1646 uint16_t avail_contexts_char = 0;
1647 uint16_t avail_contexts_ccc = 0;
1648 uint16_t supp_contexts_char = 0;
1649 uint16_t supp_contexts_ccc = 0;
1650 uint16_t end = 0;
1651
1652 MOCK_METHOD((std::pair<GattStatus, std::vector<uint8_t>>), OnGetCharacteristicValue,
1653 (uint16_t handle), (override));
1654 MOCK_METHOD((void), OnWriteCharacteristic,
1655 (uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
1656 GATT_WRITE_OP_CB cb, void* cb_data),
1657 (override));
1658 };
1659
1660 struct ascs_mock : public IGattHandlers {
1661 uint16_t start = 0;
1662 uint16_t sink_ase_char[max_num_of_ases] = {0};
1663 uint16_t sink_ase_ccc[max_num_of_ases] = {0};
1664 uint16_t sink_ase_ccc_val[max_num_of_ases] = {0};
1665 uint16_t source_ase_char[max_num_of_ases] = {0};
1666 uint16_t source_ase_ccc[max_num_of_ases] = {0};
1667 uint16_t source_ase_ccc_val[max_num_of_ases] = {0};
1668 uint16_t ctp_char = 0;
1669 uint16_t ctp_ccc = 0;
1670 uint16_t ctp_ccc_val = 0;
1671 uint16_t end = 0;
1672
1673 MOCK_METHOD((std::pair<GattStatus, std::vector<uint8_t>>), OnGetCharacteristicValue,
1674 (uint16_t handle), (override));
1675 MOCK_METHOD((void), OnWriteCharacteristic,
1676 (uint16_t handle, std::vector<uint8_t> value, tGATT_WRITE_TYPE write_type,
1677 GATT_WRITE_OP_CB cb, void* cb_data),
1678 (override));
1679 };
1680
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)1681 MockDeviceWrapper(RawAddress addr, const std::list<gatt::Service>& services,
1682 std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,
1683 std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,
1684 std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,
1685 std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs)
1686 : addr(addr) {
1687 this->services = services;
1688 this->csis = std::move(csis);
1689 this->cas = std::move(cas);
1690 this->ascs = std::move(ascs);
1691 this->pacs = std::move(pacs);
1692 }
1693
~MockDeviceWrapper()1694 ~MockDeviceWrapper() {
1695 Mock::VerifyAndClearExpectations(csis.get());
1696 Mock::VerifyAndClearExpectations(cas.get());
1697 Mock::VerifyAndClearExpectations(ascs.get());
1698 Mock::VerifyAndClearExpectations(pacs.get());
1699 }
1700
1701 RawAddress addr;
1702 bool connected = false;
1703
1704 // A list of services and their useful params
1705 std::list<gatt::Service> services;
1706 std::unique_ptr<csis_mock> csis;
1707 std::unique_ptr<cas_mock> cas;
1708 std::unique_ptr<ascs_mock> ascs;
1709 std::unique_ptr<pacs_mock> pacs;
1710 };
1711
SyncOnMainLoop()1712 void SyncOnMainLoop() {
1713 // Wait for the main loop to flush
1714 // WARNING: Not tested with Timers pushing periodic tasks to the main loop
1715 while (num_async_tasks > 0) {
1716 }
1717 }
1718
ConnectLeAudio(const RawAddress & address,bool isEncrypted=true,bool expect_connected_event=true)1719 void ConnectLeAudio(const RawAddress& address, bool isEncrypted = true,
1720 bool expect_connected_event = true) {
1721 // by default indicate link as encrypted
1722 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(address, _))
1723 .WillByDefault(DoAll(Return(isEncrypted)));
1724
1725 ON_CALL(mock_btm_interface_, IsLinkKeyKnown(address, _)).WillByDefault(DoAll(Return(true)));
1726
1727 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, _))
1728 .Times(1);
1729
1730 /* If connected event is not expected to arrive, don't test those two below
1731 */
1732 if (expect_connected_event) {
1733 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, address, false));
1734 EXPECT_CALL(mock_gatt_interface_,
1735 Open(gatt_if, address, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
1736 .Times(1);
1737 }
1738
1739 do_in_main_thread(base::BindOnce(&LeAudioClient::Connect,
1740 base::Unretained(LeAudioClient::Get()), address));
1741
1742 SyncOnMainLoop();
1743 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1744 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1745 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1746 }
1747
DisconnectLeAudioWithGattClose(const RawAddress & address,uint16_t conn_id,tGATT_DISCONN_REASON=GATT_CONN_TERMINATE_LOCAL_HOST)1748 void DisconnectLeAudioWithGattClose(
1749 const RawAddress& address, uint16_t conn_id,
1750 tGATT_DISCONN_REASON /*reason*/ = GATT_CONN_TERMINATE_LOCAL_HOST) {
1751 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1752 OnConnectionState(ConnectionState::DISCONNECTED, address))
1753 .Times(1);
1754
1755 // For test purpose use the acl handle same as conn_id
1756 ON_CALL(mock_btm_interface_, GetHCIConnHandle(address, _))
1757 .WillByDefault([conn_id](RawAddress const& /*bd_addr*/, tBT_TRANSPORT /*transport*/) {
1758 return conn_id;
1759 });
1760 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(0);
1761 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
1762
1763 do_in_main_thread(base::Bind(&LeAudioClient::Disconnect, base::Unretained(LeAudioClient::Get()),
1764 address));
1765 SyncOnMainLoop();
1766 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1767 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1768 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1769 }
1770
DisconnectLeAudioWithAclClose(const RawAddress & address,uint16_t conn_id,tGATT_DISCONN_REASON reason=GATT_CONN_TERMINATE_LOCAL_HOST)1771 void DisconnectLeAudioWithAclClose(const RawAddress& address, uint16_t conn_id,
1772 tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST) {
1773 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1774 OnConnectionState(ConnectionState::DISCONNECTED, address))
1775 .Times(1);
1776
1777 // For test purpose use the acl handle same as conn_id
1778 ON_CALL(mock_btm_interface_, GetHCIConnHandle(address, _))
1779 .WillByDefault([conn_id](RawAddress const& /*bd_addr*/, tBT_TRANSPORT /*transport*/) {
1780 return conn_id;
1781 });
1782 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _))
1783 .WillOnce([this, &reason](uint16_t handle, tHCI_STATUS /*rs*/) {
1784 InjectDisconnectedEvent(handle, reason);
1785 });
1786 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(0);
1787
1788 do_in_main_thread(base::Bind(&LeAudioClient::Disconnect, base::Unretained(LeAudioClient::Get()),
1789 address));
1790 SyncOnMainLoop();
1791 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1792 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1793 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
1794 }
1795
DisconnectLeAudioNoDisconnectedEvtExpected(const RawAddress & address,uint16_t conn_id)1796 void DisconnectLeAudioNoDisconnectedEvtExpected(const RawAddress& address, uint16_t conn_id) {
1797 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(0);
1798 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(1);
1799 do_in_main_thread(base::BindOnce(&LeAudioClient::Disconnect,
1800 base::Unretained(LeAudioClient::Get()), address));
1801 SyncOnMainLoop();
1802 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
1803 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
1804 }
1805
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)1806 void ConnectCsisDevice(const RawAddress& addr, uint16_t conn_id, uint32_t sink_audio_allocation,
1807 uint32_t source_audio_allocation, uint8_t group_size, int group_id,
1808 uint8_t rank, bool connect_through_csis = false, bool new_device = true) {
1809 SetSampleDatabaseEarbudsValid(conn_id, addr, sink_audio_allocation, source_audio_allocation,
1810 default_channel_cnt, default_channel_cnt,
1811 0x0034, /* source sample freq 16/24k/32hz */
1812 true, /*add_csis*/
1813 true, /*add_cas*/
1814 true, /*add_pacs*/
1815 true, /*add_ascs*/
1816 group_size, rank);
1817 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1818 OnConnectionState(ConnectionState::CONNECTED, addr))
1819 .Times(1);
1820
1821 if (new_device) {
1822 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1823 OnGroupNodeStatus(addr, group_id, GroupNodeStatus::ADDED))
1824 .Times(1);
1825 }
1826
1827 if (connect_through_csis) {
1828 // Add it the way CSIS would do: add to group and then connect
1829 do_in_main_thread(base::BindOnce(&LeAudioClient::GroupAddNode,
1830 base::Unretained(LeAudioClient::Get()), group_id, addr));
1831 ConnectLeAudio(addr);
1832 } else {
1833 // The usual connect
1834 // Since device has CSIS, lets add it here to groups already now
1835 groups[addr] = group_id;
1836 ConnectLeAudio(addr);
1837 InjectGroupDeviceAdded(addr, group_id);
1838 }
1839 }
1840
ConnectNonCsisDevice(const RawAddress & addr,uint16_t conn_id,uint32_t sink_audio_allocation,uint32_t source_audio_allocation)1841 void ConnectNonCsisDevice(const RawAddress& addr, uint16_t conn_id,
1842 uint32_t sink_audio_allocation, uint32_t source_audio_allocation) {
1843 SetSampleDatabaseEarbudsValid(conn_id, addr, sink_audio_allocation, source_audio_allocation,
1844 default_channel_cnt, default_channel_cnt, 0x0004,
1845 /* source sample freq 16khz */ false, /*add_csis*/
1846 true, /*add_cas*/
1847 true, /*add_pacs*/
1848 true, /*add_ascs*/
1849 0, 0);
1850 EXPECT_CALL(mock_audio_hal_client_callbacks_,
1851 OnConnectionState(ConnectionState::CONNECTED, addr))
1852 .Times(1);
1853
1854 ConnectLeAudio(addr);
1855 }
1856
UpdateLocalSourceMetadata(std::vector<struct playback_track_metadata> tracks,bool reconfigure_existing_stream=false)1857 void UpdateLocalSourceMetadata(std::vector<struct playback_track_metadata> tracks,
1858 bool reconfigure_existing_stream = false) {
1859 std::vector<playback_track_metadata_v7> tracks_vec;
1860 tracks_vec.reserve(tracks.size());
1861 for (const auto& track : tracks) {
1862 playback_track_metadata_v7 desc_track = {
1863 .base =
1864 {
1865 .usage = static_cast<audio_usage_t>(track.usage),
1866 .content_type = static_cast<audio_content_type_t>(track.content_type),
1867 .gain = track.gain,
1868 },
1869 };
1870 if (test_tags_ptr_) {
1871 memcpy(desc_track.tags, test_tags_ptr_, strlen(test_tags_ptr_));
1872 }
1873
1874 tracks_vec.push_back(desc_track);
1875 }
1876
1877 ASSERT_NE(nullptr, mock_le_audio_source_hal_client_);
1878 /* Local Source may reconfigure once the metadata is updated */
1879 if (reconfigure_existing_stream) {
1880 Expectation reconfigure =
1881 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration())
1882 .Times(1);
1883 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
1884 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
1885 .Times(1)
1886 .After(reconfigure);
1887 } else {
1888 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(0);
1889 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0);
1890 }
1891
1892 ASSERT_NE(unicast_source_hal_cb_, nullptr);
1893 unicast_source_hal_cb_->OnAudioMetadataUpdate(std::move(tracks_vec), DsaMode::DISABLED);
1894 }
1895
UpdateLocalSourceMetadata(audio_usage_t usage,audio_content_type_t content_type,bool reconfigure_existing_stream=false)1896 void UpdateLocalSourceMetadata(audio_usage_t usage, audio_content_type_t content_type,
1897 bool reconfigure_existing_stream = false) {
1898 std::vector<struct playback_track_metadata> tracks = {
1899 {{AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0},
1900 {AUDIO_USAGE_UNKNOWN, AUDIO_CONTENT_TYPE_UNKNOWN, 0}}};
1901
1902 tracks[0].usage = usage;
1903 tracks[0].content_type = content_type;
1904 UpdateLocalSourceMetadata(tracks, reconfigure_existing_stream);
1905 }
1906
UpdateLocalSinkMetadata(audio_source_t audio_source)1907 void UpdateLocalSinkMetadata(audio_source_t audio_source) {
1908 std::vector<struct record_track_metadata> tracks = {
1909 {{AUDIO_SOURCE_INVALID, 0.5, AUDIO_DEVICE_NONE, "00:11:22:33:44:55"},
1910 {AUDIO_SOURCE_MIC, 0.7, AUDIO_DEVICE_OUT_BLE_HEADSET, "AA:BB:CC:DD:EE:FF"}}};
1911
1912 tracks[1].source = audio_source;
1913
1914 std::vector<record_track_metadata_v7> tracks_vec;
1915 tracks_vec.reserve(tracks.size());
1916 for (const auto& track : tracks) {
1917 record_track_metadata_v7 desc_track = {
1918 .base =
1919 {
1920 .source = static_cast<audio_source_t>(track.source),
1921 .gain = track.gain,
1922 .dest_device = static_cast<audio_devices_t>(track.dest_device),
1923 },
1924 };
1925
1926 strcpy(desc_track.base.dest_device_address, track.dest_device_address);
1927 tracks_vec.push_back(desc_track);
1928 }
1929
1930 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
1931 unicast_sink_hal_cb_->OnAudioMetadataUpdate(std::move(tracks_vec));
1932 }
1933
LocalAudioSourceSuspend(void)1934 void LocalAudioSourceSuspend(void) {
1935 ASSERT_NE(unicast_source_hal_cb_, nullptr);
1936 unicast_source_hal_cb_->OnAudioSuspend();
1937 SyncOnMainLoop();
1938 }
1939
LocalAudioSourceResume(bool expected_confirmation=true,bool expected_cancel=false)1940 void LocalAudioSourceResume(bool expected_confirmation = true, bool expected_cancel = false) {
1941 ASSERT_NE(nullptr, mock_le_audio_source_hal_client_);
1942 if (expected_confirmation) {
1943 EXPECT_CALL(*mock_le_audio_source_hal_client_, ConfirmStreamingRequest()).Times(1);
1944 }
1945
1946 if (expected_cancel) {
1947 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
1948 }
1949
1950 do_in_main_thread(base::BindOnce(
1951 [](LeAudioSourceAudioHalClient::Callbacks* cb) {
1952 if (cb) {
1953 cb->OnAudioResume();
1954 }
1955 },
1956 unicast_source_hal_cb_));
1957
1958 SyncOnMainLoop();
1959 Mock::VerifyAndClearExpectations(&*mock_le_audio_source_hal_client_);
1960 }
1961
LocalAudioSinkSuspend(void)1962 void LocalAudioSinkSuspend(void) {
1963 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
1964 unicast_sink_hal_cb_->OnAudioSuspend();
1965 SyncOnMainLoop();
1966 }
1967
LocalAudioSinkResume(void)1968 void LocalAudioSinkResume(void) {
1969 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
1970 do_in_main_thread(
1971 base::BindOnce([](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
1972 unicast_sink_hal_cb_));
1973
1974 SyncOnMainLoop();
1975 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
1976 }
1977
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)1978 void StartStreaming(audio_usage_t usage, audio_content_type_t content_type, int /*group_id*/,
1979 audio_source_t audio_source = AUDIO_SOURCE_INVALID,
1980 bool reconfigure_existing_stream = false,
1981 bool expected_resume_confirmation = true) {
1982 ASSERT_NE(unicast_source_hal_cb_, nullptr);
1983
1984 UpdateLocalSourceMetadata(usage, content_type, reconfigure_existing_stream);
1985 if (audio_source != AUDIO_SOURCE_INVALID) {
1986 UpdateLocalSinkMetadata(audio_source);
1987 }
1988
1989 /* Stream has been automatically restarted on UpdateLocalSourceMetadata */
1990 if (reconfigure_existing_stream) {
1991 return;
1992 }
1993
1994 LocalAudioSourceResume(expected_resume_confirmation);
1995 SyncOnMainLoop();
1996 Mock::VerifyAndClearExpectations(&mock_state_machine_);
1997
1998 if (usage == AUDIO_USAGE_VOICE_COMMUNICATION || audio_source != AUDIO_SOURCE_INVALID) {
1999 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2000 do_in_main_thread(
2001 base::BindOnce([](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
2002 unicast_sink_hal_cb_));
2003 }
2004 SyncOnMainLoop();
2005 }
2006
StopStreaming(int,bool suspend_source=false)2007 void StopStreaming(int /*group_id*/, bool suspend_source = false) {
2008 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2009
2010 /* TODO We should have a way to confirm Stop() otherwise, audio framework
2011 * might have different state that it is in the le_audio code - as tearing
2012 * down CISes might take some time
2013 */
2014 /* It's enough to call only one resume even if it'll be bi-directional
2015 * streaming. First suspend will trigger GroupStop.
2016 *
2017 * There is no - 'only source receiver' scenario (e.g. single microphone).
2018 * If there will be such test oriented scenario, such resume choose logic
2019 * should be applied.
2020 */
2021 unicast_source_hal_cb_->OnAudioSuspend();
2022
2023 if (suspend_source) {
2024 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2025 unicast_sink_hal_cb_->OnAudioSuspend();
2026 }
2027 SyncOnMainLoop();
2028 }
2029
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)2030 void set_sample_database(uint16_t conn_id, RawAddress addr,
2031 std::unique_ptr<NiceMock<MockDeviceWrapper::csis_mock>> csis,
2032 std::unique_ptr<NiceMock<MockDeviceWrapper::cas_mock>> cas,
2033 std::unique_ptr<NiceMock<MockDeviceWrapper::ascs_mock>> ascs,
2034 std::unique_ptr<NiceMock<MockDeviceWrapper::pacs_mock>> pacs) {
2035 gatt::DatabaseBuilder bob;
2036
2037 /* Generic Access Service */
2038 bob.AddService(0x0001, 0x0003, Uuid::From16Bit(0x1800), true);
2039 /* Device Name Char. */
2040 bob.AddCharacteristic(0x0002, 0x0003, Uuid::From16Bit(0x2a00), GATT_CHAR_PROP_BIT_READ);
2041
2042 if (csis->start) {
2043 bool is_primary = true;
2044 bob.AddService(csis->start, csis->end, bluetooth::csis::kCsisServiceUuid, is_primary);
2045 if (csis->sirk_char) {
2046 bob.AddCharacteristic(csis->sirk_char, csis->sirk_char + 1, bluetooth::csis::kCsisSirkUuid,
2047 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
2048 if (csis->sirk_ccc) {
2049 bob.AddDescriptor(csis->sirk_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2050 }
2051 }
2052
2053 if (csis->size_char) {
2054 bob.AddCharacteristic(csis->size_char, csis->size_char + 1, bluetooth::csis::kCsisSizeUuid,
2055 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
2056 if (csis->size_ccc) {
2057 bob.AddDescriptor(csis->size_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2058 }
2059 }
2060
2061 if (csis->lock_char) {
2062 bob.AddCharacteristic(
2063 csis->lock_char, csis->lock_char + 1, bluetooth::csis::kCsisLockUuid,
2064 GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY | GATT_CHAR_PROP_BIT_WRITE);
2065 if (csis->lock_ccc) {
2066 bob.AddDescriptor(csis->lock_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2067 }
2068 }
2069
2070 if (csis->rank_char) {
2071 bob.AddCharacteristic(csis->rank_char, csis->rank_char + 1, bluetooth::csis::kCsisRankUuid,
2072 GATT_CHAR_PROP_BIT_READ);
2073 }
2074 }
2075
2076 if (cas->start) {
2077 bool is_primary = true;
2078 bob.AddService(cas->start, cas->end, bluetooth::le_audio::uuid::kCapServiceUuid, is_primary);
2079 // Include CSIS service inside
2080 if (cas->csis_include) {
2081 bob.AddIncludedService(cas->csis_include, bluetooth::csis::kCsisServiceUuid, csis->start,
2082 csis->end);
2083 }
2084 }
2085
2086 if (pacs->start) {
2087 bool is_primary = true;
2088 bob.AddService(pacs->start, pacs->end,
2089 bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid, is_primary);
2090
2091 if (pacs->sink_pac_char) {
2092 bob.AddCharacteristic(
2093 pacs->sink_pac_char, pacs->sink_pac_char + 1,
2094 bluetooth::le_audio::uuid::kSinkPublishedAudioCapabilityCharacteristicUuid,
2095 GATT_CHAR_PROP_BIT_READ);
2096 if (pacs->sink_pac_ccc) {
2097 bob.AddDescriptor(pacs->sink_pac_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2098 }
2099 }
2100
2101 if (pacs->sink_audio_loc_char) {
2102 bob.AddCharacteristic(pacs->sink_audio_loc_char, pacs->sink_audio_loc_char + 1,
2103 bluetooth::le_audio::uuid::kSinkAudioLocationCharacteristicUuid,
2104 GATT_CHAR_PROP_BIT_READ);
2105 if (pacs->sink_audio_loc_ccc) {
2106 bob.AddDescriptor(pacs->sink_audio_loc_ccc,
2107 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2108 }
2109 }
2110
2111 if (pacs->source_pac_char) {
2112 bob.AddCharacteristic(
2113 pacs->source_pac_char, pacs->source_pac_char + 1,
2114 bluetooth::le_audio::uuid::kSourcePublishedAudioCapabilityCharacteristicUuid,
2115 GATT_CHAR_PROP_BIT_READ);
2116 if (pacs->source_pac_ccc) {
2117 bob.AddDescriptor(pacs->source_pac_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2118 }
2119 }
2120
2121 if (pacs->source_audio_loc_char) {
2122 bob.AddCharacteristic(pacs->source_audio_loc_char, pacs->source_audio_loc_char + 1,
2123 bluetooth::le_audio::uuid::kSourceAudioLocationCharacteristicUuid,
2124 GATT_CHAR_PROP_BIT_READ);
2125 if (pacs->source_audio_loc_ccc) {
2126 bob.AddDescriptor(pacs->source_audio_loc_ccc,
2127 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2128 }
2129 }
2130
2131 if (pacs->avail_contexts_char) {
2132 bob.AddCharacteristic(
2133 pacs->avail_contexts_char, pacs->avail_contexts_char + 1,
2134 bluetooth::le_audio::uuid::kAudioContextAvailabilityCharacteristicUuid,
2135 GATT_CHAR_PROP_BIT_READ);
2136 if (pacs->avail_contexts_ccc) {
2137 bob.AddDescriptor(pacs->avail_contexts_ccc,
2138 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2139 }
2140 }
2141
2142 if (pacs->supp_contexts_char) {
2143 bob.AddCharacteristic(pacs->supp_contexts_char, pacs->supp_contexts_char + 1,
2144 bluetooth::le_audio::uuid::kAudioSupportedContextCharacteristicUuid,
2145 GATT_CHAR_PROP_BIT_READ);
2146 if (pacs->supp_contexts_ccc) {
2147 bob.AddDescriptor(pacs->supp_contexts_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2148 }
2149 }
2150 }
2151
2152 if (ascs->start) {
2153 bool is_primary = true;
2154 bob.AddService(ascs->start, ascs->end,
2155 bluetooth::le_audio::uuid::kAudioStreamControlServiceUuid, is_primary);
2156 for (int i = 0; i < max_num_of_ases; i++) {
2157 if (ascs->sink_ase_char[i]) {
2158 bob.AddCharacteristic(ascs->sink_ase_char[i], ascs->sink_ase_char[i] + 1,
2159 bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid,
2160 GATT_CHAR_PROP_BIT_READ);
2161 if (ascs->sink_ase_ccc[i]) {
2162 bob.AddDescriptor(ascs->sink_ase_ccc[i], Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2163 }
2164 }
2165 if (ascs->source_ase_char[i]) {
2166 bob.AddCharacteristic(ascs->source_ase_char[i], ascs->source_ase_char[i] + 1,
2167 bluetooth::le_audio::uuid::kSourceAudioStreamEndpointUuid,
2168 GATT_CHAR_PROP_BIT_READ);
2169 if (ascs->source_ase_ccc[i]) {
2170 bob.AddDescriptor(ascs->source_ase_ccc[i],
2171 Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2172 }
2173 }
2174 }
2175 if (ascs->ctp_char) {
2176 bob.AddCharacteristic(
2177 ascs->ctp_char, ascs->ctp_char + 1,
2178 bluetooth::le_audio::uuid::kAudioStreamEndpointControlPointCharacteristicUuid,
2179 GATT_CHAR_PROP_BIT_READ);
2180 if (ascs->ctp_ccc) {
2181 bob.AddDescriptor(ascs->ctp_ccc, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
2182 }
2183 }
2184 }
2185
2186 // Assign conn_id to a certain device - this does not mean it is connected
2187 auto dev_wrapper = std::make_unique<NiceMock<MockDeviceWrapper>>(
2188 addr, bob.Build().Services(), std::move(csis), std::move(cas), std::move(ascs),
2189 std::move(pacs));
2190 peer_devices.emplace(conn_id, std::move(dev_wrapper));
2191 }
2192
SetSampleDatabaseEmpty(uint16_t conn_id,RawAddress addr)2193 void SetSampleDatabaseEmpty(uint16_t conn_id, RawAddress addr) {
2194 auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
2195 auto cas = std::make_unique<NiceMock<MockDeviceWrapper::cas_mock>>();
2196 auto pacs = std::make_unique<NiceMock<MockDeviceWrapper::pacs_mock>>();
2197 auto ascs = std::make_unique<NiceMock<MockDeviceWrapper::ascs_mock>>();
2198 set_sample_database(conn_id, addr, std::move(csis), std::move(cas), std::move(ascs),
2199 std::move(pacs));
2200 }
2201
2202 struct SampleDatabaseParameters {
2203 uint16_t conn_id;
2204 RawAddress addr;
2205
2206 uint32_t sink_audio_allocation = codec_spec_conf::kLeAudioLocationStereo;
2207 uint32_t source_audio_allocation = codec_spec_conf::kLeAudioLocationStereo;
2208 uint8_t sink_channel_cnt = 0x03;
2209 uint8_t source_channel_cnt = 0x03;
2210 uint16_t sample_freq_mask = 0x0004;
2211 bool add_csis = true;
2212 bool add_cas = true;
2213 bool add_pacs = true;
2214 int add_ascs_cnt = 1;
2215 uint8_t set_size = 2;
2216 uint8_t rank = 1;
2217 GattStatus gatt_status = GATT_SUCCESS;
2218 uint8_t max_supported_codec_frames_per_sdu = 1;
2219 };
2220
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)2221 void SetSampleDatabaseEarbudsValid(
2222 uint16_t conn_id, RawAddress addr, uint32_t sink_audio_allocation,
2223 uint32_t source_audio_allocation, uint8_t sink_channel_cnt = 0x03,
2224 uint8_t source_channel_cnt = 0x03, uint16_t sample_freq_mask = 0x0004,
2225 bool add_csis = true, bool add_cas = true, bool add_pacs = true, int add_ascs_cnt = 1,
2226 uint8_t set_size = 2, uint8_t rank = 1, GattStatus gatt_status = GATT_SUCCESS) {
2227 SetSampleDatabaseEarbudsValid(SampleDatabaseParameters{
2228 .conn_id = conn_id,
2229 .addr = addr,
2230 .sink_audio_allocation = sink_audio_allocation,
2231 .source_audio_allocation = source_audio_allocation,
2232 .sink_channel_cnt = sink_channel_cnt,
2233 .source_channel_cnt = source_channel_cnt,
2234 .sample_freq_mask = sample_freq_mask,
2235 .add_csis = add_csis,
2236 .add_cas = add_cas,
2237 .add_pacs = add_pacs,
2238 .add_ascs_cnt = add_ascs_cnt,
2239 .set_size = set_size,
2240 .rank = rank,
2241 .gatt_status = gatt_status,
2242 .max_supported_codec_frames_per_sdu = 1,
2243 });
2244 }
2245
SetSampleDatabaseEarbudsValid(const SampleDatabaseParameters & params)2246 void SetSampleDatabaseEarbudsValid(const SampleDatabaseParameters& params) {
2247 auto conn_id = params.conn_id;
2248 auto addr = params.addr;
2249 auto sink_audio_allocation = params.sink_audio_allocation;
2250 auto source_audio_allocation = params.source_audio_allocation;
2251 auto sink_channel_cnt = params.sink_channel_cnt;
2252 auto source_channel_cnt = params.source_channel_cnt;
2253 auto sample_freq_mask = params.sample_freq_mask;
2254 auto add_csis = params.add_csis;
2255 auto add_cas = params.add_cas;
2256 auto add_pacs = params.add_pacs;
2257 auto add_ascs_cnt = params.add_ascs_cnt;
2258 auto set_size = params.set_size;
2259 auto rank = params.rank;
2260 auto gatt_status = params.gatt_status;
2261 auto max_supported_codec_frames_per_sdu = params.max_supported_codec_frames_per_sdu;
2262
2263 auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
2264 if (add_csis) {
2265 // attribute handles
2266 csis->start = 0x0010;
2267 csis->sirk_char = 0x0020;
2268 csis->sirk_ccc = 0x0022;
2269 csis->size_char = 0x0023;
2270 csis->size_ccc = 0x0025;
2271 csis->lock_char = 0x0026;
2272 csis->lock_ccc = 0x0028;
2273 csis->rank_char = 0x0029;
2274 csis->end = 0x0030;
2275 // other params
2276 csis->size = set_size;
2277 csis->rank = rank;
2278 }
2279
2280 auto cas = std::make_unique<NiceMock<MockDeviceWrapper::cas_mock>>();
2281 if (add_cas) {
2282 // attribute handles
2283 cas->start = 0x0040;
2284 if (add_csis) {
2285 cas->csis_include = 0x0041;
2286 }
2287 cas->end = 0x0050;
2288 // other params
2289 }
2290
2291 auto pacs = std::make_unique<NiceMock<MockDeviceWrapper::pacs_mock>>();
2292 if (add_pacs) {
2293 // attribute handles
2294 pacs->start = 0x0060;
2295 pacs->sink_pac_char = 0x0061;
2296 pacs->sink_pac_ccc = 0x0063;
2297 pacs->sink_audio_loc_char = 0x0064;
2298 pacs->sink_audio_loc_ccc = 0x0066;
2299 pacs->source_pac_char = 0x0067;
2300 pacs->source_pac_ccc = 0x0069;
2301 pacs->source_audio_loc_char = 0x0070;
2302 pacs->source_audio_loc_ccc = 0x0072;
2303 pacs->avail_contexts_char = 0x0073;
2304 pacs->avail_contexts_ccc = 0x0075;
2305 pacs->supp_contexts_char = 0x0076;
2306 pacs->supp_contexts_ccc = 0x0078;
2307 pacs->end = 0x0080;
2308 // other params
2309 }
2310
2311 auto ascs = std::make_unique<NiceMock<MockDeviceWrapper::ascs_mock>>();
2312 if (add_ascs_cnt > 0) {
2313 // attribute handles
2314 ascs->start = 0x0090;
2315 uint16_t handle = 0x0091;
2316 for (int i = 0; i < add_ascs_cnt; i++) {
2317 if (sink_audio_allocation != 0) {
2318 ascs->sink_ase_char[i] = handle;
2319 handle += 2;
2320 ascs->sink_ase_ccc[i] = handle;
2321 handle++;
2322 }
2323
2324 if (source_audio_allocation != 0) {
2325 ascs->source_ase_char[i] = handle;
2326 handle += 2;
2327 ascs->source_ase_ccc[i] = handle;
2328 handle++;
2329 }
2330 }
2331 ascs->ctp_char = handle;
2332 handle += 2;
2333 ascs->ctp_ccc = handle;
2334 handle++;
2335 ascs->end = handle;
2336 // other params
2337 }
2338
2339 set_sample_database(conn_id, addr, std::move(csis), std::move(cas), std::move(ascs),
2340 std::move(pacs));
2341
2342 if (add_pacs) {
2343 uint8_t snk_allocation[4];
2344 uint8_t src_allocation[4];
2345
2346 snk_allocation[0] = (uint8_t)(sink_audio_allocation);
2347 snk_allocation[1] = (uint8_t)(sink_audio_allocation >> 8);
2348 snk_allocation[2] = (uint8_t)(sink_audio_allocation >> 16);
2349 snk_allocation[3] = (uint8_t)(sink_audio_allocation >> 24);
2350
2351 src_allocation[0] = (uint8_t)(source_audio_allocation);
2352 src_allocation[1] = (uint8_t)(source_audio_allocation >> 8);
2353 src_allocation[2] = (uint8_t)(source_audio_allocation >> 16);
2354 src_allocation[3] = (uint8_t)(source_audio_allocation >> 24);
2355
2356 uint8_t sample_freq[2];
2357 sample_freq[0] = (uint8_t)(sample_freq_mask);
2358 sample_freq[1] = (uint8_t)(sample_freq_mask >> 8);
2359
2360 // Set pacs default read values
2361 ON_CALL(*peer_devices.at(conn_id)->pacs, OnGetCharacteristicValue(_))
2362 .WillByDefault([=, this](uint16_t handle) {
2363 auto& pacs = peer_devices.at(conn_id)->pacs;
2364 std::vector<uint8_t> value;
2365 if (gatt_status == GATT_SUCCESS) {
2366 if (handle == pacs->sink_pac_char + 1) {
2367 if (empty_sink_pack_) {
2368 value = {0x00};
2369 } else {
2370 value = {
2371 // Num records
2372 0x02,
2373 // Codec_ID
2374 0x06,
2375 0x00,
2376 0x00,
2377 0x00,
2378 0x00,
2379 // Codec Spec. Caps. Len
2380 0x10,
2381 0x03, /* sample freq */
2382 0x01,
2383 sample_freq[0],
2384 sample_freq[1],
2385 0x02,
2386 0x02, /* frame duration */
2387 0x03,
2388 0x02, /* channel count */
2389 0x03,
2390 sink_channel_cnt,
2391 0x05,
2392 0x04,
2393 0x1E,
2394 0x00,
2395 0x78,
2396 0x00,
2397 // Metadata Length
2398 0x00,
2399 // Codec_ID
2400 0x06,
2401 0x00,
2402 0x00,
2403 0x00,
2404 0x00,
2405 // Codec Spec. Caps. Len
2406 0x13,
2407 0x03, /* sample freq */
2408 0x01,
2409 0x80, /* 48kHz */
2410 0x00,
2411 0x02, /* frame duration */
2412 0x02,
2413 0x03,
2414 0x02, /* channel count */
2415 0x03,
2416 sink_channel_cnt,
2417 0x05, /* octects per frame */
2418 0x04,
2419 0x78,
2420 0x00,
2421 0x78,
2422 0x00,
2423 0x02, /* Max supported codec frames per SDU */
2424 0x05,
2425 max_supported_codec_frames_per_sdu,
2426 // Metadata Length
2427 0x00,
2428 };
2429 }
2430 } else if (handle == pacs->sink_audio_loc_char + 1) {
2431 value = {
2432 // Audio Locations
2433 snk_allocation[0],
2434 snk_allocation[1],
2435 snk_allocation[2],
2436 snk_allocation[3],
2437 };
2438 } else if (handle == pacs->source_pac_char + 1) {
2439 if (empty_source_pack_) {
2440 value = {0x00};
2441 } else {
2442 value = {
2443 // Num records
2444 0x02,
2445 // Codec_ID
2446 0x06,
2447 0x00,
2448 0x00,
2449 0x00,
2450 0x00,
2451 // Codec Spec. Caps. Len
2452 0x10,
2453 0x03,
2454 0x01,
2455 sample_freq[0],
2456 sample_freq[1],
2457 0x02,
2458 0x02,
2459 0x03,
2460 0x02,
2461 0x03,
2462 source_channel_cnt,
2463 0x05,
2464 0x04,
2465 0x1E,
2466 0x00,
2467 0x78,
2468 0x00,
2469 // Metadata Length
2470 0x00,
2471 // Codec_ID
2472 0x06,
2473 0x00,
2474 0x00,
2475 0x00,
2476 0x00,
2477 // Codec Spec. Caps. Len
2478 0x10,
2479 0x03,
2480 0x01,
2481 0x24,
2482 0x00,
2483 0x02,
2484 0x02,
2485 0x03,
2486 0x02,
2487 0x03,
2488 source_channel_cnt,
2489 0x05,
2490 0x04,
2491 0x1E,
2492 0x00,
2493 0x50,
2494 0x00,
2495 // Metadata Length
2496 0x00,
2497 };
2498 }
2499 } else if (handle == pacs->source_audio_loc_char + 1) {
2500 value = {
2501 // Audio Locations
2502 src_allocation[0],
2503 src_allocation[1],
2504 src_allocation[2],
2505 src_allocation[3],
2506 };
2507 } else if (handle == pacs->avail_contexts_char + 1) {
2508 value = {
2509 // Sink Avail Contexts
2510 (uint8_t)(available_snk_context_types_),
2511 (uint8_t)(available_snk_context_types_ >> 8),
2512 // Source Avail Contexts
2513 (uint8_t)(available_src_context_types_),
2514 (uint8_t)(available_src_context_types_ >> 8),
2515 };
2516 } else if (handle == pacs->supp_contexts_char + 1) {
2517 value = {
2518 // Sink Supp Contexts
2519 (uint8_t)(supported_snk_context_types_),
2520 (uint8_t)(supported_snk_context_types_ >> 8),
2521 // Source Supp Contexts
2522 (uint8_t)(supported_src_context_types_),
2523 (uint8_t)(supported_src_context_types_ >> 8),
2524 };
2525 }
2526 }
2527 return std::make_pair(gatt_status, value);
2528 });
2529 }
2530
2531 if (add_ascs_cnt > 0) {
2532 // Set ascs default read values
2533 ON_CALL(*peer_devices.at(conn_id)->ascs, OnGetCharacteristicValue(_))
2534 .WillByDefault([this, conn_id, gatt_status](uint16_t handle) {
2535 auto& ascs = peer_devices.at(conn_id)->ascs;
2536 std::vector<uint8_t> value;
2537 bool is_ase_sink_request = false;
2538 bool is_ase_src_request = false;
2539 uint8_t idx;
2540
2541 if (handle == ascs->ctp_ccc && ccc_stored_byte_val_.has_value()) {
2542 value = {*ccc_stored_byte_val_, 00};
2543 return std::make_pair(gatt_read_ctp_ccc_status_, value);
2544 }
2545
2546 if (gatt_status == GATT_SUCCESS) {
2547 if (handle == ascs->ctp_ccc) {
2548 value = UINT16_TO_VEC_UINT8(ascs->ctp_ccc_val);
2549 } else {
2550 for (idx = 0; idx < max_num_of_ases; idx++) {
2551 if (handle == ascs->sink_ase_ccc[idx] + 1) {
2552 value = UINT16_TO_VEC_UINT8(ascs->sink_ase_ccc_val[idx]);
2553 break;
2554 }
2555 if (handle == ascs->source_ase_char[idx] + 1) {
2556 value = UINT16_TO_VEC_UINT8(ascs->source_ase_ccc_val[idx]);
2557 break;
2558 }
2559 }
2560 }
2561
2562 for (idx = 0; idx < max_num_of_ases; idx++) {
2563 if (handle == ascs->sink_ase_char[idx] + 1) {
2564 is_ase_sink_request = true;
2565 break;
2566 }
2567 if (handle == ascs->source_ase_char[idx] + 1) {
2568 is_ase_src_request = true;
2569 break;
2570 }
2571 }
2572
2573 if (is_ase_sink_request) {
2574 value = {
2575 // ASE ID
2576 static_cast<uint8_t>(idx + 1),
2577 // State
2578 static_cast<uint8_t>(bluetooth::le_audio::types::AseState::
2579 BTA_LE_AUDIO_ASE_STATE_IDLE),
2580 // No Additional ASE params for IDLE state
2581 };
2582 } else if (is_ase_src_request) {
2583 value = {
2584 // ASE ID
2585 static_cast<uint8_t>(idx + 6),
2586 // State
2587 static_cast<uint8_t>(bluetooth::le_audio::types::AseState::
2588 BTA_LE_AUDIO_ASE_STATE_IDLE),
2589 // No Additional ASE params for IDLE state
2590 };
2591 }
2592 }
2593 return std::make_pair(gatt_status, value);
2594 });
2595 }
2596 }
2597
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)2598 void TestAudioDataTransfer(int group_id, uint8_t cis_count_out, uint8_t cis_count_in,
2599 int data_len, int in_data_len = 40, uint16_t decoded_in_data_len = 0) {
2600 ASSERT_NE(unicast_source_hal_cb_, nullptr);
2601 ASSERT_NE(mock_le_audio_sink_hal_client_, nullptr);
2602
2603 // Expect two channels ISO Data to be sent
2604 std::vector<uint16_t> handles;
2605 if (cis_count_out) {
2606 EXPECT_CALL(*mock_iso_manager_, SendIsoData(_, _, _))
2607 .Times(cis_count_out)
2608 .WillRepeatedly([&handles](uint16_t iso_handle, const uint8_t* /*data*/,
2609 uint16_t /*data_len*/) { handles.push_back(iso_handle); });
2610 }
2611 std::vector<uint8_t> data(data_len);
2612 unicast_source_hal_cb_->OnAudioDataReady(data);
2613
2614 // Inject microphone data from group (2 CISes - pass stereo data in 1 call)
2615 if (decoded_in_data_len) {
2616 EXPECT_CALL(*mock_le_audio_sink_hal_client_, SendData(_, decoded_in_data_len))
2617 .Times(cis_count_in > 0 ? 1 : 0);
2618 } else {
2619 EXPECT_CALL(*mock_le_audio_sink_hal_client_, SendData(_, _)).Times(cis_count_in > 0 ? 1 : 0);
2620 }
2621 ASSERT_EQ(streaming_groups.count(group_id), 1u);
2622
2623 if (cis_count_in) {
2624 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
2625
2626 ASSERT_NE(0lu, streaming_groups.count(group_id));
2627 auto group = streaming_groups.at(group_id);
2628 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
2629 device = group->GetNextDevice(device)) {
2630 for (auto& ase : device->ases_) {
2631 if (ase.direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
2632 InjectIncomingIsoData(group_id, ase.cis_conn_hdl, in_data_len);
2633 --cis_count_in;
2634 if (!cis_count_in) {
2635 break;
2636 }
2637 }
2638 }
2639 if (!cis_count_in) {
2640 break;
2641 }
2642 }
2643 }
2644
2645 SyncOnMainLoop();
2646 std::sort(handles.begin(), handles.end());
2647 ASSERT_EQ(cis_count_in, 0);
2648 handles.clear();
2649
2650 Mock::VerifyAndClearExpectations(mock_iso_manager_);
2651 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
2652 }
2653
InjectIncomingIsoData(uint16_t cig_id,uint16_t cis_con_hdl,size_t payload_size)2654 void InjectIncomingIsoData(uint16_t cig_id, uint16_t cis_con_hdl, size_t payload_size) {
2655 BT_HDR* bt_hdr = (BT_HDR*)malloc(sizeof(BT_HDR) + payload_size);
2656
2657 bt_hdr->offset = 0;
2658 bt_hdr->len = payload_size;
2659
2660 bluetooth::hci::iso_manager::cis_data_evt cis_evt;
2661 cis_evt.cig_id = cig_id;
2662 cis_evt.cis_conn_hdl = cis_con_hdl;
2663 cis_evt.ts = 0;
2664 cis_evt.evt_lost = 0;
2665 cis_evt.p_msg = bt_hdr;
2666
2667 ASSERT_NE(cig_callbacks_, nullptr);
2668 cig_callbacks_->OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDataAvailable, &cis_evt);
2669 free(bt_hdr);
2670 }
2671
InjectCisDisconnected(uint16_t cig_id,uint16_t cis_con_hdl,uint8_t reason=0)2672 void InjectCisDisconnected(uint16_t cig_id, uint16_t cis_con_hdl, uint8_t reason = 0) {
2673 bluetooth::hci::iso_manager::cis_disconnected_evt cis_evt;
2674 cis_evt.cig_id = cig_id;
2675 cis_evt.cis_conn_hdl = cis_con_hdl;
2676 cis_evt.reason = reason;
2677
2678 ASSERT_NE(cig_callbacks_, nullptr);
2679 cig_callbacks_->OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCisDisconnected, &cis_evt);
2680 }
2681
InjectCigRemoved(uint8_t cig_id)2682 void InjectCigRemoved(uint8_t cig_id) {
2683 bluetooth::hci::iso_manager::cig_remove_cmpl_evt evt;
2684 evt.status = 0;
2685 evt.cig_id = cig_id;
2686
2687 ASSERT_NE(cig_callbacks_, nullptr);
2688 cig_callbacks_->OnCisEvent(bluetooth::hci::iso_manager::kIsoEventCigOnRemoveCmpl, &evt);
2689 }
2690
2691 NiceMock<MockAudioHalClientCallbacks> mock_audio_hal_client_callbacks_;
2692 LeAudioSourceAudioHalClient::Callbacks* unicast_source_hal_cb_ = nullptr;
2693 LeAudioSinkAudioHalClient::Callbacks* unicast_sink_hal_cb_ = nullptr;
2694
2695 uint8_t default_channel_cnt = 0x03;
2696 uint8_t default_ase_cnt = 1;
2697
2698 NiceMock<MockCsisClient> mock_csis_client_module_;
2699 NiceMock<MockDeviceGroups> mock_groups_module_;
2700 bluetooth::groups::DeviceGroupsCallbacks* group_callbacks_;
2701 NiceMock<MockLeAudioGroupStateMachine> mock_state_machine_;
2702
2703 NiceMock<MockFunction<void()>> mock_storage_load;
2704 NiceMock<MockFunction<bool()>> mock_hal_2_1_verifier;
2705
2706 NiceMock<bluetooth::manager::MockBtmInterface> mock_btm_interface_;
2707 NiceMock<gatt::MockBtaGattInterface> mock_gatt_interface_;
2708 NiceMock<gatt::MockBtaGattQueue> mock_gatt_queue_;
2709 tBTA_GATTC_CBACK* gatt_callback;
2710 const uint8_t gatt_if = 0xfe;
2711 uint16_t global_conn_id = 1;
2712 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks_;
2713 std::map<int, LeAudioDeviceGroup*> streaming_groups;
2714 bool stay_at_qos_config_in_start_stream = false;
2715 bool stay_at_releasing_stop_stream = false;
2716
2717 bool attach_to_stream_scheduled = false;
2718
2719 bluetooth::hci::IsoManager* iso_manager_;
2720 MockIsoManager* mock_iso_manager_;
2721 bluetooth::hci::iso_manager::CigCallbacks* cig_callbacks_ = nullptr;
2722 uint16_t iso_con_counter_ = 1;
2723
2724 bluetooth::le_audio::CodecManager* codec_manager_;
2725 MockCodecManager* mock_codec_manager_;
2726
2727 uint16_t available_snk_context_types_ = 0xffff;
2728 uint16_t available_src_context_types_ = 0xffff;
2729 uint16_t supported_snk_context_types_ = 0xffff;
2730 uint16_t supported_src_context_types_ = 0xffff;
2731
2732 bool empty_source_pack_;
2733 bool empty_sink_pack_;
2734
2735 NiceMock<bluetooth::storage::MockBtifStorageInterface> mock_btif_storage_;
2736
2737 std::map<uint16_t, std::unique_ptr<NiceMock<MockDeviceWrapper>>> peer_devices;
2738 std::list<int> group_locks;
2739 std::map<RawAddress, int> groups;
2740
2741 /* CCC descriptor data */
2742 tGATT_STATUS gatt_read_ctp_ccc_status_ = GATT_SUCCESS;
2743 std::optional<uint8_t> ccc_stored_byte_val_ = std::nullopt;
2744
2745 /* Audio track metadata */
2746 char* test_tags_ptr_ = nullptr;
2747 NiceMock<bluetooth::hci::testing::MockControllerInterface> controller_;
2748 };
2749
2750 class UnicastTest : public UnicastTestNoInit {
2751 protected:
SetUp()2752 void SetUp() override {
2753 UnicastTestNoInit::SetUp();
2754
2755 EXPECT_CALL(mock_hal_2_1_verifier, Call()).Times(1);
2756 EXPECT_CALL(mock_storage_load, Call()).Times(1);
2757
2758 ON_CALL(mock_btm_interface_, GetHCIConnHandle(_, _))
2759 .WillByDefault(
2760 [this](RawAddress const& bd_addr, tBT_TRANSPORT /*transport*/) -> uint16_t {
2761 for (auto const& [conn_id, dev_wrapper] : peer_devices) {
2762 if (dev_wrapper->addr == bd_addr) {
2763 return conn_id;
2764 }
2765 }
2766 log::error("GetHCIConnHandle Mock: not a valid test device!");
2767 return 0x00FE;
2768 });
2769 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
2770 .WillByDefault([this](uint16_t handle, tHCI_STATUS /*rs*/) {
2771 ASSERT_NE(handle, GATT_INVALID_CONN_ID);
2772 InjectDisconnectedEvent(handle, GATT_CONN_TERMINATE_LOCAL_HOST);
2773 });
2774
2775 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
2776 BtaAppRegisterCallback app_register_callback;
2777 EXPECT_CALL(mock_gatt_interface_, AppRegister(_, _, _))
2778 .WillOnce(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
2779 LeAudioClient::Initialize(
2780 &mock_audio_hal_client_callbacks_,
2781 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
2782 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2783 &mock_hal_2_1_verifier),
2784 framework_encode_preference);
2785
2786 SyncOnMainLoop();
2787 ASSERT_TRUE(gatt_callback);
2788 ASSERT_TRUE(group_callbacks_);
2789 ASSERT_TRUE(app_register_callback);
2790 app_register_callback.Run(gatt_if, GATT_SUCCESS);
2791 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
2792 }
2793
TearDown()2794 void TearDown() override {
2795 MockCodecInterface::ClearMockInstanceHookList();
2796
2797 // Clear the default actions before the parent class teardown is called
2798 Mock::VerifyAndClear(&mock_btm_interface_);
2799 Mock::VerifyAndClear(&mock_gatt_interface_);
2800 Mock::VerifyAndClear(&mock_audio_hal_client_callbacks_);
2801 groups.clear();
2802 UnicastTestNoInit::TearDown();
2803 }
2804
TestSetupRemoteDevices(int group_id)2805 void TestSetupRemoteDevices(int group_id) {
2806 uint8_t group_size = 2;
2807
2808 // Report working CSIS
2809 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
2810
2811 // First earbud
2812 const RawAddress test_address0 = GetTestAddress(0);
2813 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
2814 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
2815 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id,
2816 1 /* rank*/);
2817
2818 // Second earbud
2819 const RawAddress test_address1 = GetTestAddress(1);
2820 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
2821 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
2822 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id,
2823 2 /* rank*/, true /*connect_through_csis*/);
2824
2825 constexpr int gmcs_ccid = 1;
2826 constexpr int gtbs_ccid = 2;
2827 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
2828 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
2829 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid,
2830 static_cast<int>(LeAudioContextType::MEDIA));
2831 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid,
2832 static_cast<int>(LeAudioContextType::CONVERSATIONAL));
2833 LeAudioClient::Get()->GroupSetActive(group_id);
2834 }
2835
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)2836 void TestSetCodecPreference(
2837 const btle_audio_codec_config_t* preferred_codec_config_before_streaming,
2838 const btle_audio_codec_config_t* preferred_codec_config_during_streaming,
2839 LeAudioContextType context_type, int group_id, bool set_before_streaming,
2840 bool set_while_streaming, bool is_using_set_before_streaming_codec_during_streaming,
2841 bool is_using_set_while_streaming_codec_during_streaming, bool is_reconfig) {
2842 auto config_before_streaming_str = preferred_codec_config_before_streaming
2843 ? preferred_codec_config_before_streaming->ToString()
2844 : "null";
2845 auto config_during_streaming_str = preferred_codec_config_during_streaming
2846 ? preferred_codec_config_during_streaming->ToString()
2847 : "null";
2848 log::debug(
2849 "preferred_codec_config_before_streaming: {}, "
2850 "preferred_codec_config_during_streaming: {}, context_type: {}, "
2851 "group_id: {}, set_before_streaming: {}, "
2852 "set_while_streaming: {}, "
2853 "is_using_set_before_streaming_codec_during_streaming: "
2854 "{},is_using_set_while_streaming_codec_during_streaming:{}, "
2855 "is_reconfig: {}",
2856 config_before_streaming_str, config_during_streaming_str,
2857 bluetooth::common::ToString(context_type), group_id, set_before_streaming,
2858 set_while_streaming, is_using_set_before_streaming_codec_during_streaming,
2859 is_using_set_while_streaming_codec_during_streaming, is_reconfig);
2860
2861 if (context_type != LeAudioContextType::MEDIA &&
2862 context_type != LeAudioContextType::CONVERSATIONAL) {
2863 return;
2864 }
2865
2866 if (set_before_streaming) {
2867 do_in_main_thread(base::BindOnce(&LeAudioClient::SetCodecConfigPreference,
2868 base::Unretained(LeAudioClient::Get()), group_id,
2869 *preferred_codec_config_before_streaming,
2870 *preferred_codec_config_before_streaming));
2871 SyncOnMainLoop();
2872 }
2873
2874 types::BidirectionalPair<std::vector<uint8_t>> ccids;
2875 constexpr int gmcs_ccid = 1;
2876 constexpr int gtbs_ccid = 2;
2877 if (context_type == LeAudioContextType::MEDIA) {
2878 ccids = types::BidirectionalPair<std::vector<uint8_t>>{{gmcs_ccid}, {}};
2879 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
2880 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
2881 } else {
2882 ccids = types::BidirectionalPair<std::vector<uint8_t>>{{gtbs_ccid}, {gtbs_ccid}};
2883 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
2884 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
2885 }
2886 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
2887 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
2888
2889 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(group_id,
2890 static_cast<int>(context_type)),
2891 is_using_set_before_streaming_codec_during_streaming);
2892
2893 uint8_t cis_count_out = 2;
2894 uint8_t cis_count_in = context_type == LeAudioContextType::MEDIA ? 0 : 2;
2895 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
2896
2897 if (set_while_streaming) {
2898 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(is_reconfig);
2899 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(is_reconfig);
2900
2901 do_in_main_thread(base::BindOnce(&LeAudioClient::SetCodecConfigPreference,
2902 base::Unretained(LeAudioClient::Get()), group_id,
2903 *preferred_codec_config_during_streaming,
2904 *preferred_codec_config_during_streaming));
2905 SyncOnMainLoop();
2906 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(group_id,
2907 static_cast<int>(context_type)),
2908 is_using_set_while_streaming_codec_during_streaming);
2909
2910 if (context_type == LeAudioContextType::MEDIA) {
2911 ccids = types::BidirectionalPair<std::vector<uint8_t>>{{gmcs_ccid}, {}};
2912 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
2913 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
2914 } else {
2915 ccids = types::BidirectionalPair<std::vector<uint8_t>>{{gtbs_ccid}, {gtbs_ccid}};
2916 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
2917 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
2918 }
2919 }
2920
2921 StopStreaming(group_id, context_type == LeAudioContextType::CONVERSATIONAL);
2922 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
2923 Mock::VerifyAndClearExpectations(&mock_state_machine_);
2924 }
2925 };
2926
2927 class UnicastTestHealthStatus : public UnicastTest {
2928 protected:
SetUp()2929 void SetUp() override {
2930 UnicastTest::SetUp();
2931 group_ = new LeAudioDeviceGroup(group_id_);
2932 }
2933
TearDown()2934 void TearDown() override {
2935 delete group_;
2936 UnicastTest::TearDown();
2937 }
2938
2939 const int group_id_ = 0;
2940 LeAudioDeviceGroup* group_ = nullptr;
2941 };
2942
2943 class UnicastTestHandoverMode : public UnicastTest {
2944 protected:
SetUp()2945 void SetUp() override {
2946 use_handover_mode = true;
2947 UnicastTest::SetUp();
2948 group_ = new LeAudioDeviceGroup(group_id_);
2949 }
2950
TearDown()2951 void TearDown() override {
2952 delete group_;
2953 UnicastTest::TearDown();
2954 }
2955
2956 const int group_id_ = 0;
2957 LeAudioDeviceGroup* group_ = nullptr;
2958 };
2959
TEST_F(UnicastTest,Initialize)2960 TEST_F(UnicastTest, Initialize) {
2961 ASSERT_NE(LeAudioClient::Get(), nullptr);
2962 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
2963 }
2964
TEST_F(UnicastTestNoInit,InitializeNoHal_2_1)2965 TEST_F(UnicastTestNoInit, InitializeNoHal_2_1) {
2966 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
2967
2968 // Report False when asked for Audio HAL 2.1 support
2969 ON_CALL(mock_hal_2_1_verifier, Call()).WillByDefault([]() -> bool { return false; });
2970
2971 BtaAppRegisterCallback app_register_callback;
2972 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
2973 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
2974 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
2975
2976 EXPECT_DEATH(
2977 LeAudioClient::Initialize(
2978 &mock_audio_hal_client_callbacks_,
2979 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
2980 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); },
2981 &mock_hal_2_1_verifier),
2982 framework_encode_preference),
2983 "LE Audio Client requires Bluetooth Audio HAL V2.1 at least. Either "
2984 "disable LE Audio Profile, or update your HAL");
2985 }
2986
TEST_F(UnicastTest,CleanupWhenUserConnecting)2987 TEST_F(UnicastTest, CleanupWhenUserConnecting) {
2988 const RawAddress test_address0 = GetTestAddress(0);
2989 uint16_t conn_id = 1;
2990 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
2991 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
2992 default_channel_cnt, 0x0004,
2993 /* source sample freq 16khz */ true, /*add_csis*/
2994 true, /*add_cas*/
2995 true, /*add_pacs*/
2996 default_ase_cnt /*add_ascs*/);
2997
2998 /* Remove default action on the direct connect */
2999 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
3000 ConnectLeAudio(test_address0, false, false);
3001
3002 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
3003 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
3004 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(0);
3005 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
3006
3007 LeAudioClient::Cleanup();
3008 SyncOnMainLoop();
3009
3010 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3011 }
3012
TEST_F(UnicastTest,CleanupWhenAutoConnecting)3013 TEST_F(UnicastTest, CleanupWhenAutoConnecting) {
3014 const RawAddress test_address0 = GetTestAddress(0);
3015 uint16_t conn_id = 1;
3016 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3017 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3018 default_channel_cnt, 0x0004,
3019 /* source sample freq 16khz */ true, /*add_csis*/
3020 true, /*add_cas*/
3021 true, /*add_pacs*/
3022 default_ase_cnt /*add_ascs*/);
3023
3024 log::info("Connect device");
3025 ConnectLeAudio(test_address0);
3026
3027 /* Remove default action on the autoconnect */
3028 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3029 .WillByDefault(Return());
3030
3031 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3032 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3033 .Times(1);
3034 /* Make sure when remote device disconnects us, TA is used */
3035 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
3036 EXPECT_CALL(mock_gatt_interface_,
3037 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3038 .Times(1);
3039
3040 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
3041 SyncOnMainLoop();
3042
3043 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3044
3045 log::info("Device is in auto connect");
3046
3047 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
3048 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(0);
3049 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(0);
3050 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
3051
3052 LeAudioClient::Cleanup();
3053 SyncOnMainLoop();
3054
3055 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3056 }
3057
TEST_F(UnicastTest,CleanupWhenConnected)3058 TEST_F(UnicastTest, CleanupWhenConnected) {
3059 const RawAddress test_address0 = GetTestAddress(0);
3060 uint16_t conn_id = 1;
3061 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3062 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3063 default_channel_cnt, 0x0004,
3064 /* source sample freq 16khz */ true, /*add_csis*/
3065 true, /*add_cas*/
3066 true, /*add_pacs*/
3067 default_ase_cnt /*add_ascs*/);
3068
3069 log::info("Connect device");
3070 ConnectLeAudio(test_address0);
3071
3072 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
3073 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(0);
3074 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(conn_id, _)).Times(1);
3075 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3076
3077 LeAudioClient::Cleanup();
3078 SyncOnMainLoop();
3079
3080 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3081 }
3082
TEST_F(UnicastTest,ConnectAndSetupPhy)3083 TEST_F(UnicastTest, ConnectAndSetupPhy) {
3084 const RawAddress test_address0 = GetTestAddress(0);
3085 uint16_t conn_id = 1;
3086 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3087 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3088 default_channel_cnt, 0x0004,
3089 /* source sample freq 16khz */ true, /*add_csis*/
3090 true, /*add_cas*/
3091 true, /*add_pacs*/
3092 default_ase_cnt /*add_ascs*/);
3093
3094 EXPECT_CALL(mock_btm_interface_, BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0)).Times(1);
3095 ConnectLeAudio(test_address0, false);
3096 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3097
3098 EXPECT_CALL(mock_btm_interface_, BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0)).Times(1);
3099 InjectPhyChangedEvent(conn_id, 0, 0, GATT_REQ_NOT_SUPPORTED);
3100 SyncOnMainLoop();
3101 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3102 .WillByDefault(DoAll(Return(true)));
3103 InjectEncryptionChangedEvent(test_address0);
3104 SyncOnMainLoop();
3105 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3106
3107 /* Make sure flag `acl_phy_update_done_` is cleared after disconnect.
3108 * Just repeat previous steps after reconnection
3109 */
3110 InjectDisconnectedEvent(conn_id);
3111 SyncOnMainLoop();
3112
3113 EXPECT_CALL(mock_btm_interface_, BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0)).Times(1);
3114
3115 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3116 .WillByDefault(DoAll(Return(false)));
3117 InjectConnectedEvent(test_address0, 1);
3118 SyncOnMainLoop();
3119 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3120
3121 EXPECT_CALL(mock_btm_interface_, BleSetPhy(test_address0, PHY_LE_2M, PHY_LE_2M, 0)).Times(1);
3122 InjectPhyChangedEvent(conn_id, 0, 0, GATT_REQ_NOT_SUPPORTED);
3123 SyncOnMainLoop();
3124 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3125 .WillByDefault(DoAll(Return(true)));
3126 InjectEncryptionChangedEvent(test_address0);
3127 SyncOnMainLoop();
3128 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3129 }
3130
TEST_F(UnicastTest,ConnectOneEarbudEmpty)3131 TEST_F(UnicastTest, ConnectOneEarbudEmpty) {
3132 const RawAddress test_address0 = GetTestAddress(0);
3133 SetSampleDatabaseEmpty(1, test_address0);
3134 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3135 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3136 .Times(1);
3137 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3138 ConnectLeAudio(test_address0);
3139 }
3140
TEST_F(UnicastTest,ConnectOneEarbudNoPacs)3141 TEST_F(UnicastTest, ConnectOneEarbudNoPacs) {
3142 const RawAddress test_address0 = GetTestAddress(0);
3143 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3144 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3145 default_channel_cnt, 0x0004,
3146 /* source sample freq 16khz */ true, /*add_csis*/
3147 true, /*add_cas*/
3148 false, /*add_pacs*/
3149 default_ase_cnt /*add_ascs*/);
3150 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3151 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3152 .Times(1);
3153 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3154 ConnectLeAudio(test_address0);
3155 }
3156
TEST_F(UnicastTest,ConnectOneEarbudNoAscs)3157 TEST_F(UnicastTest, ConnectOneEarbudNoAscs) {
3158 const RawAddress test_address0 = GetTestAddress(0);
3159 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3160 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3161 default_channel_cnt, 0x0004,
3162 /* source sample freq 16khz */ true, /*add_csis*/
3163 true, /*add_cas*/
3164 true, /*add_pacs*/
3165 0 /*add_ascs*/);
3166 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3167 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3168 .Times(1);
3169 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3170 ConnectLeAudio(test_address0);
3171 }
3172
TEST_F(UnicastTest,ConnectOneEarbudNoCas)3173 TEST_F(UnicastTest, ConnectOneEarbudNoCas) {
3174 const RawAddress test_address0 = GetTestAddress(0);
3175 uint16_t conn_id = 1;
3176 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3177 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3178 default_channel_cnt, 0x0004,
3179 /* source sample freq 16khz */ true, /*add_csis*/
3180 false, /*add_cas*/
3181 true, /*add_pacs*/
3182 default_ase_cnt /*add_ascs*/);
3183
3184 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3185 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3186 .Times(1);
3187 ConnectLeAudio(test_address0);
3188 }
3189
TEST_F(UnicastTest,ConnectOneEarbudNoCsis)3190 TEST_F(UnicastTest, ConnectOneEarbudNoCsis) {
3191 const RawAddress test_address0 = GetTestAddress(0);
3192 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3193 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3194 default_channel_cnt, 0x0004,
3195 /* source sample freq 16khz */ false, /*add_csis*/
3196 true, /*add_cas*/
3197 true, /*add_pacs*/
3198 default_ase_cnt /*add_ascs*/);
3199 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3200 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3201 .Times(1);
3202 ConnectLeAudio(test_address0);
3203 }
3204
TEST_F(UnicastTest,ConnectOneEarbudWithInvalidCsis)3205 TEST_F(UnicastTest, ConnectOneEarbudWithInvalidCsis) {
3206 const RawAddress test_address0 = GetTestAddress(0);
3207 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3208 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3209 default_channel_cnt, 0x0004,
3210 /* source sample freq 16khz */ true, /*add_csis*/
3211 true, /*add_cas*/
3212 true, /*add_pacs*/
3213 default_ase_cnt /*add_ascs*/);
3214 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3215 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3216 .Times(1);
3217 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3218
3219 // Report working CSIS
3220 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
3221
3222 /* Make sure Group has not knowledge about the device */
3223 ON_CALL(mock_groups_module_, GetGroupId(_, _))
3224 .WillByDefault([](const RawAddress& /*addr*/, bluetooth::Uuid /*uuid*/) {
3225 return bluetooth::groups::kGroupUnknown;
3226 });
3227
3228 ConnectLeAudio(test_address0);
3229 SyncOnMainLoop();
3230 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3231 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3232 }
3233
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudEmpty_withHealthStatus)3234 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudEmpty_withHealthStatus) {
3235 const RawAddress test_address0 = GetTestAddress(0);
3236 SetSampleDatabaseEmpty(1, test_address0);
3237 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3238 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3239 .Times(1);
3240 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3241 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3242 .Times(1);
3243 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3244 ConnectLeAudio(test_address0);
3245 SyncOnMainLoop();
3246 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3247 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3248
3249 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3250 }
3251
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoPacs_withHealthStatus)3252 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoPacs_withHealthStatus) {
3253 const RawAddress test_address0 = GetTestAddress(0);
3254 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3255 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3256 default_channel_cnt, 0x0004,
3257 /* source sample freq 16khz */ true, /*add_csis*/
3258 true, /*add_cas*/
3259 false, /*add_pacs*/
3260 default_ase_cnt /*add_ascs*/);
3261 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3262 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3263 .Times(1);
3264 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3265 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3266 .Times(1);
3267 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3268 ConnectLeAudio(test_address0);
3269 SyncOnMainLoop();
3270 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3271 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3272
3273 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3274 }
3275
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoAscs_withHealthStatus)3276 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoAscs_withHealthStatus) {
3277 const RawAddress test_address0 = GetTestAddress(0);
3278 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3279 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3280 default_channel_cnt, 0x0004,
3281 /* source sample freq 16khz */ true, /*add_csis*/
3282 true, /*add_cas*/
3283 true, /*add_pacs*/
3284 0 /*add_ascs*/);
3285 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3286 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3287 .Times(1);
3288 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3289 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3290 .Times(1);
3291 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3292 ConnectLeAudio(test_address0);
3293 SyncOnMainLoop();
3294 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3295 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3296
3297 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3298 }
3299
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoCas_withHealthStatus)3300 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoCas_withHealthStatus) {
3301 const RawAddress test_address0 = GetTestAddress(0);
3302 uint16_t conn_id = 1;
3303 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3304 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3305 default_channel_cnt, 0x0004,
3306 /* source sample freq 16khz */ true, /*add_csis*/
3307 false, /*add_cas*/
3308 true, /*add_pacs*/
3309 default_ase_cnt /*add_ascs*/);
3310
3311 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3312 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3313 .Times(0);
3314 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3315 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3316 .Times(1);
3317 ConnectLeAudio(test_address0);
3318 SyncOnMainLoop();
3319 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3320
3321 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3322 }
3323
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudNoCsis_withHealthStatus)3324 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudNoCsis_withHealthStatus) {
3325 const RawAddress test_address0 = GetTestAddress(0);
3326 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3327 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3328 default_channel_cnt, 0x0004,
3329 /* source sample freq 16khz */ false, /*add_csis*/
3330 true, /*add_cas*/
3331 true, /*add_pacs*/
3332 default_ase_cnt /*add_ascs*/);
3333 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3334 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3335 .Times(0);
3336 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3337 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3338 .Times(1);
3339 ConnectLeAudio(test_address0);
3340 SyncOnMainLoop();
3341 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3342
3343 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3344 }
3345
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudWithInvalidCsis_withHealthStatus)3346 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudWithInvalidCsis_withHealthStatus) {
3347 const RawAddress test_address0 = GetTestAddress(0);
3348 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3349 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3350 default_channel_cnt, 0x0004,
3351 /* source sample freq 16khz */ true, /*add_csis*/
3352 true, /*add_cas*/
3353 true, /*add_pacs*/
3354 default_ase_cnt /*add_ascs*/);
3355 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3356 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3357 .Times(1);
3358 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3359 OnHealthBasedRecommendationAction(test_address0, LeAudioHealthBasedAction::DISABLE))
3360 .Times(1);
3361
3362 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(1);
3363
3364 // Report working CSIS
3365 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
3366
3367 /* Make sure Group has not knowledge about the device */
3368 ON_CALL(mock_groups_module_, GetGroupId(_, _))
3369 .WillByDefault([](const RawAddress& /*addr*/, bluetooth::Uuid /*uuid*/) {
3370 return bluetooth::groups::kGroupUnknown;
3371 });
3372
3373 ConnectLeAudio(test_address0);
3374 SyncOnMainLoop();
3375 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3376 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3377
3378 LeAudioHealthStatus::Get()->RemoveStatistics(test_address0, bluetooth::groups::kGroupUnknown);
3379 }
3380
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudDisable_withHealthStatus)3381 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudDisable_withHealthStatus) {
3382 const RawAddress test_address0 = GetTestAddress(0);
3383 int conn_id = 1;
3384
3385 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3386 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3387 default_channel_cnt, 0x0004, false);
3388 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3389 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3390 .Times(1);
3391
3392 ConnectLeAudio(test_address0);
3393 SyncOnMainLoop();
3394 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3395
3396 LeAudioClient::Get()->GroupSetActive(group_id_);
3397 auto device = std::make_shared<LeAudioDevice>(test_address0, DeviceConnectState::DISCONNECTED);
3398 group_->AddNode(device);
3399 SyncOnMainLoop();
3400
3401 auto health_status = LeAudioHealthStatus::Get();
3402
3403 /* Inject stream error */
3404 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3405 OnHealthBasedGroupRecommendationAction(group_id_, LeAudioHealthBasedAction::DISABLE))
3406 .Times(1);
3407 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3408 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3409
3410 /* Do not act on disconnect */
3411 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
3412 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).WillByDefault(DoAll(Return()));
3413
3414 state_machine_callbacks_->OnStateTransitionTimeout(group_id_);
3415 SyncOnMainLoop();
3416 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3417
3418 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3419 OnHealthBasedGroupRecommendationAction(group_id_, LeAudioHealthBasedAction::DISABLE))
3420 .Times(0);
3421 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3422 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3423 SyncOnMainLoop();
3424 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3425 }
3426
TEST_F(UnicastTestHealthStatus,ConnectOneEarbudConsiderDisabling_withHealthStatus)3427 TEST_F(UnicastTestHealthStatus, ConnectOneEarbudConsiderDisabling_withHealthStatus) {
3428 const RawAddress test_address0 = GetTestAddress(0);
3429 int conn_id = 1;
3430
3431 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3432 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
3433 default_channel_cnt, 0x0004, false);
3434 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3435 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3436 .Times(1);
3437
3438 ConnectLeAudio(test_address0);
3439 SyncOnMainLoop();
3440 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3441
3442 LeAudioClient::Get()->GroupSetActive(group_id_);
3443 auto device = std::make_shared<LeAudioDevice>(test_address0, DeviceConnectState::DISCONNECTED);
3444 group_->AddNode(device);
3445 SyncOnMainLoop();
3446
3447 auto health_status = LeAudioHealthStatus::Get();
3448
3449 /* Inject stream success and error */
3450 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3451 OnHealthBasedGroupRecommendationAction(group_id_,
3452 LeAudioHealthBasedAction::CONSIDER_DISABLING))
3453 .Times(1);
3454 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
3455 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3456 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3457
3458 /* Do not act on disconnect */
3459 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
3460 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).WillByDefault(DoAll(Return()));
3461
3462 state_machine_callbacks_->OnStateTransitionTimeout(group_id_);
3463 SyncOnMainLoop();
3464 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3465
3466 EXPECT_CALL(
3467 mock_audio_hal_client_callbacks_,
3468 OnHealthBasedGroupRecommendationAction(1, LeAudioHealthBasedAction::CONSIDER_DISABLING))
3469 .Times(0);
3470 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3471 health_status->AddStatisticForGroup(group_, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
3472 SyncOnMainLoop();
3473 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3474 }
3475
TEST_F(UnicastTest,ConnectDisconnectOneEarbud)3476 TEST_F(UnicastTest, ConnectDisconnectOneEarbud) {
3477 const RawAddress test_address0 = GetTestAddress(0);
3478 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3479 codec_spec_conf::kLeAudioLocationStereo);
3480 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3481 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3482 .Times(1);
3483 ConnectLeAudio(test_address0);
3484 DisconnectLeAudioWithAclClose(test_address0, 1);
3485 }
3486
TEST_F(UnicastTest,ConnectRemoteServiceDiscoveryCompleteBeforeEncryption)3487 TEST_F(UnicastTest, ConnectRemoteServiceDiscoveryCompleteBeforeEncryption) {
3488 const RawAddress test_address0 = GetTestAddress(0);
3489 uint16_t conn_id = 1;
3490 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3491 codec_spec_conf::kLeAudioLocationStereo);
3492 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3493 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3494 .Times(0);
3495 ConnectLeAudio(test_address0, false);
3496 InjectSearchCompleteEvent(conn_id);
3497
3498 SyncOnMainLoop();
3499 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3500
3501 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3502 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3503 .Times(1);
3504 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3505 .WillByDefault(DoAll(Return(true)));
3506 InjectEncryptionChangedEvent(test_address0);
3507 SyncOnMainLoop();
3508 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
3509 }
3510
TEST_F(UnicastTest,DisconnectWhenLinkKeyIsGone)3511 TEST_F(UnicastTest, DisconnectWhenLinkKeyIsGone) {
3512 const RawAddress test_address0 = GetTestAddress(0);
3513 uint16_t conn_id = 1;
3514 SetSampleDatabaseEarbudsValid(conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3515 codec_spec_conf::kLeAudioLocationStereo);
3516 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3517 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3518 .Times(1);
3519
3520 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3521 .WillByDefault(DoAll(Return(false)));
3522
3523 ON_CALL(mock_btm_interface_, SetEncryption(test_address0, _, _, _, _))
3524 .WillByDefault(Return(tBTM_STATUS::BTM_ERR_KEY_MISSING));
3525
3526 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
3527 do_in_main_thread(base::BindOnce(&LeAudioClient::Connect, base::Unretained(LeAudioClient::Get()),
3528 test_address0));
3529
3530 SyncOnMainLoop();
3531 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
3532 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3533 }
3534
3535 /* same as above case except the disconnect is initiated by remote */
TEST_F(UnicastTest,ConnectRemoteDisconnectOneEarbud)3536 TEST_F(UnicastTest, ConnectRemoteDisconnectOneEarbud) {
3537 const RawAddress test_address0 = GetTestAddress(0);
3538 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3539 codec_spec_conf::kLeAudioLocationStereo);
3540 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3541 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3542 .Times(1);
3543 ConnectLeAudio(test_address0);
3544 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3545
3546 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3547 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3548 .Times(1);
3549 /* Make sure when remote device disconnects us, TA is used */
3550 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
3551 EXPECT_CALL(mock_gatt_interface_,
3552 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3553 .Times(1);
3554
3555 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
3556 SyncOnMainLoop();
3557
3558 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3559
3560 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3561 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3562 .Times(1);
3563
3564 /* When reconnected, we always remove background connect, as we do not track
3565 * which type (allow list or TA) was used and then make sure the TA is used.
3566 */
3567 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
3568 EXPECT_CALL(mock_gatt_interface_,
3569 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3570 .Times(1);
3571
3572 /* For background connect, test needs to Inject Connected Event */
3573 InjectConnectedEvent(test_address0, 1);
3574 SyncOnMainLoop();
3575 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3576 }
3577
3578 /* same as above case except the disconnect is initiated by remote */
TEST_F(UnicastTest,ConnectRemoteDisconnectOnTimeoutOneEarbud)3579 TEST_F(UnicastTest, ConnectRemoteDisconnectOnTimeoutOneEarbud) {
3580 const RawAddress test_address0 = GetTestAddress(0);
3581 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
3582 codec_spec_conf::kLeAudioLocationStereo);
3583 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3584 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3585 .Times(1);
3586 ConnectLeAudio(test_address0);
3587 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3588 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
3589 .Times(1);
3590
3591 /* Remove default action on the direct connect */
3592 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
3593
3594 /* For remote disconnection, expect stack to try background re-connect */
3595 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3596 .Times(1);
3597
3598 InjectDisconnectedEvent(1, GATT_CONN_TIMEOUT);
3599 SyncOnMainLoop();
3600
3601 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3602
3603 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3604 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3605 .Times(1);
3606
3607 /* For background connect, test needs to Inject Connected Event */
3608 InjectConnectedEvent(test_address0, 1);
3609 SyncOnMainLoop();
3610 }
3611
TEST_F(UnicastTest,ConnectTwoEarbudsCsisGrouped)3612 TEST_F(UnicastTest, ConnectTwoEarbudsCsisGrouped) {
3613 uint8_t group_size = 2;
3614 int group_id = 2;
3615
3616 // Report working CSIS
3617 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
3618
3619 // First earbud
3620 const RawAddress test_address0 = GetTestAddress(0);
3621 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
3622 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
3623 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
3624
3625 // Second earbud
3626 const RawAddress test_address1 = GetTestAddress(1);
3627 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
3628 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
3629 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
3630 true /*connect_through_csis*/);
3631
3632 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3633
3634 /* for Target announcements AutoConnect is always there, until
3635 * device is removed
3636 */
3637 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false)).Times(0);
3638 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(0);
3639
3640 // Verify grouping information
3641 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
3642 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3643 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3644
3645 DisconnectLeAudioWithAclClose(test_address0, 1);
3646 DisconnectLeAudioWithAclClose(test_address1, 2);
3647 }
3648
TEST_F(UnicastTest,ConnectTwoEarbudsCsisGroupUnknownAtConnect)3649 TEST_F(UnicastTest, ConnectTwoEarbudsCsisGroupUnknownAtConnect) {
3650 uint8_t group_size = 2;
3651 uint8_t group_id = 2;
3652
3653 // Report working CSIS
3654 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
3655
3656 // First earbud connects without known grouping
3657 const RawAddress test_address0 = GetTestAddress(0);
3658 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
3659 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
3660 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
3661
3662 // Second earbud
3663 const RawAddress test_address1 = GetTestAddress(1);
3664 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
3665 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
3666 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
3667 true /*connect_through_csis*/);
3668
3669 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
3670
3671 // Verify grouping information
3672 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
3673 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3674 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3675
3676 /* for Target announcements AutoConnect is always there, until
3677 * device is removed
3678 */
3679 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false)).Times(0);
3680 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(0);
3681 DisconnectLeAudioWithAclClose(test_address0, 1);
3682 DisconnectLeAudioWithAclClose(test_address1, 2);
3683 }
3684
TEST_F(UnicastTestNoInit,ConnectFailedDueToInvalidParameters)3685 TEST_F(UnicastTestNoInit, ConnectFailedDueToInvalidParameters) {
3686 // Prepare two devices
3687 uint8_t group_size = 2;
3688 uint8_t group_id = 2;
3689
3690 /* Prepare mock to not inject connect event so the device can stay in
3691 * CONNECTING state*/
3692 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3693 .WillByDefault(DoAll(Return()));
3694
3695 const RawAddress test_address0 = GetTestAddress(0);
3696 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3697 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3698 default_channel_cnt, 0x0004,
3699 /* source sample freq 16khz */ true, /*add_csis*/
3700 true, /*add_cas*/
3701 true, /*add_pacs*/
3702 default_ase_cnt, /*add_ascs_cnt*/
3703 group_size, 1);
3704
3705 const RawAddress test_address1 = GetTestAddress(1);
3706 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
3707 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
3708 default_channel_cnt, 0x0004,
3709 /* source sample freq 16khz */ true, /*add_csis*/
3710 true, /*add_cas*/
3711 true, /*add_pacs*/
3712 default_ase_cnt, /*add_ascs_cnt*/
3713 group_size, 2);
3714
3715 // Load devices from the storage when storage API is called
3716 bool autoconnect = true;
3717
3718 /* Common storage values */
3719 std::vector<uint8_t> handles;
3720 LeAudioClient::GetHandlesForStorage(test_address0, handles);
3721
3722 std::vector<uint8_t> ases;
3723 LeAudioClient::GetAsesForStorage(test_address0, ases);
3724
3725 std::vector<uint8_t> src_pacs;
3726 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
3727
3728 std::vector<uint8_t> snk_pacs;
3729 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
3730
3731 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
3732 do_in_main_thread(base::Bind(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
3733 codec_spec_conf::kLeAudioLocationFrontLeft,
3734 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
3735 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
3736 std::move(ases)));
3737 do_in_main_thread(base::Bind(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
3738 codec_spec_conf::kLeAudioLocationFrontRight,
3739 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
3740 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
3741 std::move(ases)));
3742 });
3743
3744 // Expect stored device0 to connect automatically (first directed connection )
3745 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3746 .Times(1);
3747
3748 // Expect stored device1 to connect automatically (first direct connection)
3749 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
3750 .Times(1);
3751
3752 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
3753 .WillByDefault(DoAll(Return(true)));
3754 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3755 .WillByDefault(DoAll(Return(true)));
3756
3757 ON_CALL(mock_groups_module_, GetGroupId(_, _)).WillByDefault(DoAll(Return(group_id)));
3758
3759 ON_CALL(mock_btm_interface_, GetSecurityFlagsByTransport(test_address0, NotNull(), _))
3760 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
3761
3762 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
3763
3764 // Initialize
3765 BtaAppRegisterCallback app_register_callback;
3766 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
3767 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
3768 LeAudioClient::Initialize(
3769 &mock_audio_hal_client_callbacks_,
3770 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
3771 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
3772 framework_encode_preference);
3773 if (app_register_callback) {
3774 app_register_callback.Run(gatt_if, GATT_SUCCESS);
3775 }
3776
3777 // We need to wait for the storage callback before verifying stuff
3778 SyncOnMainLoop();
3779 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
3780 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3781
3782 // Simulate connect parameters are invalid and phone does not fallback
3783 // to background connect.
3784 EXPECT_CALL(mock_gatt_interface_,
3785 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3786 .Times(0);
3787
3788 EXPECT_CALL(mock_gatt_interface_,
3789 Open(gatt_if, test_address1, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3790 .Times(0);
3791
3792 // Devices not found
3793 InjectConnectedEvent(test_address0, 0, GATT_ILLEGAL_PARAMETER);
3794 InjectConnectedEvent(test_address1, 0, GATT_ILLEGAL_PARAMETER);
3795
3796 SyncOnMainLoop();
3797 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3798 }
3799
TEST_F(UnicastTestNoInit,LoadStoredEarbudsBroakenStorage)3800 TEST_F(UnicastTestNoInit, LoadStoredEarbudsBroakenStorage) {
3801 // Prepare two devices
3802 uint8_t group_size = 2;
3803 uint8_t group_id = 2;
3804 /* If the storage has been broken, make sure device will be rediscovered after
3805 * reconnection
3806 */
3807
3808 /* Prepare mock to not inject connect event so the device can stay in
3809 * CONNECTING state*/
3810 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3811 .WillByDefault(DoAll(Return()));
3812
3813 const RawAddress test_address0 = GetTestAddress(0);
3814 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3815 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3816 default_channel_cnt, 0x0004,
3817 /* source sample freq 16khz */ true, /*add_csis*/
3818 true, /*add_cas*/
3819 true, /*add_pacs*/
3820 default_ase_cnt, /*add_ascs_cnt*/
3821 group_size, 1);
3822
3823 const RawAddress test_address1 = GetTestAddress(1);
3824 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
3825 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
3826 default_channel_cnt, 0x0004,
3827 /* source sample freq 16khz */ true, /*add_csis*/
3828 true, /*add_cas*/
3829 true, /*add_pacs*/
3830 default_ase_cnt, /*add_ascs_cnt*/
3831 group_size, 2);
3832
3833 // Load devices from the storage when storage API is called
3834 bool autoconnect = true;
3835 std::vector<uint8_t> empty_buf;
3836
3837 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
3838 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
3839 codec_spec_conf::kLeAudioLocationFrontLeft,
3840 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
3841 std::move(empty_buf), std::move(empty_buf),
3842 std::move(empty_buf), std::move(empty_buf)));
3843 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
3844 codec_spec_conf::kLeAudioLocationFrontRight,
3845 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
3846 std::move(empty_buf), std::move(empty_buf),
3847 std::move(empty_buf), std::move(empty_buf)));
3848 SyncOnMainLoop();
3849 });
3850
3851 // Expect stored device0 to connect automatically (first directed connection )
3852 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3853 .Times(1);
3854
3855 // Expect stored device1 to connect automatically (first direct connection)
3856 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
3857 .Times(1);
3858
3859 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
3860 .WillByDefault(DoAll(Return(true)));
3861 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
3862 .WillByDefault(DoAll(Return(true)));
3863
3864 ON_CALL(mock_groups_module_, GetGroupId(_, _)).WillByDefault(DoAll(Return(group_id)));
3865
3866 ON_CALL(mock_btm_interface_, GetSecurityFlagsByTransport(test_address0, NotNull(), _))
3867 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
3868
3869 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
3870
3871 // Initialize
3872 BtaAppRegisterCallback app_register_callback;
3873 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
3874 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
3875 LeAudioClient::Initialize(
3876 &mock_audio_hal_client_callbacks_,
3877 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
3878 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
3879 framework_encode_preference);
3880 if (app_register_callback) {
3881 app_register_callback.Run(gatt_if, GATT_SUCCESS);
3882 }
3883
3884 // We need to wait for the storage callback before verifying stuff
3885 SyncOnMainLoop();
3886 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
3887 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3888
3889 // Simulate devices are not there and phone fallbacks to targeted
3890 // announcements
3891 EXPECT_CALL(mock_gatt_interface_,
3892 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3893 .Times(1);
3894
3895 EXPECT_CALL(mock_gatt_interface_,
3896 Open(gatt_if, test_address1, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
3897 .Times(1);
3898
3899 // Devices not found
3900 InjectConnectedEvent(test_address0, 0, GATT_ERROR);
3901 InjectConnectedEvent(test_address1, 0, GATT_ERROR);
3902
3903 SyncOnMainLoop();
3904 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
3905
3906 /* Stack should rediscover services as storage is broken */
3907 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(2, _)).Times(1);
3908 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(1, _)).Times(1);
3909
3910 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3911 OnConnectionState(ConnectionState::CONNECTED, test_address0))
3912 .Times(1);
3913
3914 EXPECT_CALL(mock_audio_hal_client_callbacks_,
3915 OnConnectionState(ConnectionState::CONNECTED, test_address1))
3916 .Times(1);
3917
3918 /* For background connect, test needs to Inject Connected Event */
3919 InjectConnectedEvent(test_address0, 1);
3920 InjectConnectedEvent(test_address1, 2);
3921 SyncOnMainLoop();
3922
3923 // Verify if all went well and we got the proper group
3924 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
3925 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
3926 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
3927
3928 DisconnectLeAudioWithAclClose(test_address0, 1);
3929 DisconnectLeAudioWithAclClose(test_address1, 2);
3930 }
3931
TEST_F(UnicastTestNoInit,LoadStoredEarbudsCsisGrouped)3932 TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) {
3933 // Prepare two devices
3934 uint8_t group_size = 2;
3935 uint8_t group_id = 2;
3936
3937 /* Prepare mock to not inject connect event so the device can stay in
3938 * CONNECTING state*/
3939 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
3940 .WillByDefault(DoAll(Return()));
3941
3942 const RawAddress test_address0 = GetTestAddress(0);
3943 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
3944 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
3945 default_channel_cnt, 0x0004,
3946 /* source sample freq 16khz */ true, /*add_csis*/
3947 true, /*add_cas*/
3948 true, /*add_pacs*/
3949 default_ase_cnt, /*add_ascs_cnt*/
3950 group_size, 1);
3951
3952 const RawAddress test_address1 = GetTestAddress(1);
3953 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
3954 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
3955 default_channel_cnt, 0x0004,
3956 /* source sample freq 16khz */ true, /*add_csis*/
3957 true, /*add_cas*/
3958 true, /*add_pacs*/
3959 default_ase_cnt, /*add_ascs_cnt*/
3960 group_size, 2);
3961
3962 // Load devices from the storage when storage API is called
3963 bool autoconnect = true;
3964
3965 /* Common storage values */
3966 std::vector<uint8_t> handles;
3967 LeAudioClient::GetHandlesForStorage(test_address0, handles);
3968
3969 std::vector<uint8_t> ases;
3970 LeAudioClient::GetAsesForStorage(test_address0, ases);
3971
3972 std::vector<uint8_t> src_pacs;
3973 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
3974
3975 std::vector<uint8_t> snk_pacs;
3976 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
3977
3978 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
3979 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
3980 codec_spec_conf::kLeAudioLocationFrontLeft,
3981 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
3982 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
3983 std::move(ases)));
3984 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
3985 codec_spec_conf::kLeAudioLocationFrontRight,
3986 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
3987 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
3988 std::move(ases)));
3989 SyncOnMainLoop();
3990 });
3991
3992 // Expect stored device0 to connect automatically (first directed connection )
3993 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
3994 .Times(1);
3995
3996 // Expect stored device1 to connect automatically (first direct connection)
3997 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
3998 .Times(1);
3999
4000 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4001 .WillByDefault(DoAll(Return(true)));
4002 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4003 .WillByDefault(DoAll(Return(true)));
4004
4005 ON_CALL(mock_groups_module_, GetGroupId(_, _)).WillByDefault(DoAll(Return(group_id)));
4006
4007 ON_CALL(mock_btm_interface_, GetSecurityFlagsByTransport(test_address0, NotNull(), _))
4008 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
4009
4010 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
4011
4012 // Initialize
4013 BtaAppRegisterCallback app_register_callback;
4014 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
4015 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
4016 LeAudioClient::Initialize(
4017 &mock_audio_hal_client_callbacks_,
4018 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
4019 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
4020 framework_encode_preference);
4021 if (app_register_callback) {
4022 app_register_callback.Run(gatt_if, GATT_SUCCESS);
4023 }
4024
4025 // We need to wait for the storage callback before verifying stuff
4026 SyncOnMainLoop();
4027 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4028 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4029
4030 // Simulate devices are not there and phone fallbacks to targeted
4031 // announcements
4032 EXPECT_CALL(mock_gatt_interface_,
4033 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4034 .Times(1);
4035
4036 EXPECT_CALL(mock_gatt_interface_,
4037 Open(gatt_if, test_address1, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4038 .Times(1);
4039
4040 // Devices not found
4041 InjectConnectedEvent(test_address0, 0, GATT_ERROR);
4042 InjectConnectedEvent(test_address1, 0, GATT_ERROR);
4043
4044 SyncOnMainLoop();
4045 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4046
4047 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4048 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4049 .Times(1);
4050
4051 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4052 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4053 .Times(1);
4054
4055 /* For background connect, test needs to Inject Connected Event */
4056 InjectConnectedEvent(test_address0, 1);
4057 InjectConnectedEvent(test_address1, 2);
4058 SyncOnMainLoop();
4059
4060 // Verify if all went well and we got the proper group
4061 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
4062 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4063 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4064
4065 DisconnectLeAudioWithAclClose(test_address0, 1);
4066 DisconnectLeAudioWithAclClose(test_address1, 2);
4067 }
4068
TEST_F(UnicastTest,LoadStoredBandedHeadphones)4069 TEST_F(UnicastTest, LoadStoredBandedHeadphones) {
4070 const RawAddress test_address0 = GetTestAddress(0);
4071 uint16_t conn_id = 1;
4072
4073 SetSampleDatabaseEarbudsValid(
4074 conn_id, test_address0,
4075 codec_spec_conf::kLeAudioLocationFrontLeft | codec_spec_conf::kLeAudioLocationFrontRight,
4076 codec_spec_conf::kLeAudioLocationMonoAudio, 2, 1, 0x0004,
4077 /* source sample freq 16khz */ false, /*add_csis*/
4078 true, /*add_cas*/
4079 true, /*add_pacs*/
4080 true, /*add_ascs*/
4081 0, 0);
4082 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4083 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4084 .Times(1);
4085
4086 /* Connect and fill the device storage */
4087 ConnectLeAudio(test_address0);
4088
4089 std::vector<uint8_t> handles;
4090 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4091
4092 std::vector<uint8_t> ases;
4093 LeAudioClient::GetAsesForStorage(test_address0, ases);
4094
4095 std::vector<uint8_t> src_pacs;
4096 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4097
4098 std::vector<uint8_t> snk_pacs;
4099 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4100
4101 /* Disconnect & Cleanup */
4102 DisconnectLeAudioWithAclClose(test_address0, conn_id);
4103 if (LeAudioClient::IsLeAudioClientRunning()) {
4104 LeAudioClient::Cleanup();
4105 ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
4106 }
4107
4108 Mock::VerifyAndClearExpectations(&mock_hal_2_1_verifier);
4109 Mock::VerifyAndClearExpectations(&mock_storage_load);
4110
4111 // Load devices from the storage when storage API is called
4112 bool autoconnect = true;
4113 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4114 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
4115 codec_spec_conf::kLeAudioLocationFrontLeft |
4116 codec_spec_conf::kLeAudioLocationFrontRight,
4117 codec_spec_conf::kLeAudioLocationMonoAudio, 0xff, 0xff,
4118 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4119 std::move(ases)));
4120 SyncOnMainLoop();
4121 });
4122
4123 /* Prepare mock to not inject connect event so the device can stay in
4124 * CONNECTING state*/
4125 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
4126 .WillByDefault(DoAll(Return()));
4127
4128 // Re-Initialize & load from storage
4129 BtaAppRegisterCallback app_register_callback;
4130 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
4131 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
4132 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
4133 LeAudioClient::Initialize(
4134 &mock_audio_hal_client_callbacks_,
4135 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
4136 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
4137 framework_encode_preference);
4138 if (app_register_callback) {
4139 app_register_callback.Run(gatt_if, GATT_SUCCESS);
4140 }
4141
4142 InjectConnectedEvent(test_address0, conn_id);
4143 SyncOnMainLoop();
4144 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4145
4146 // Verify if all went well and we got the proper group
4147 auto group_id = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
4148 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
4149 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4150
4151 SetUpMockCodecManager(::bluetooth::le_audio::types::CodecLocation::HOST);
4152
4153 // Start streaming
4154 LeAudioClient::Get()->GroupSetActive(group_id);
4155 SyncOnMainLoop();
4156
4157 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4158 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _))
4159 .Times(1);
4160 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
4161
4162 SyncOnMainLoop();
4163 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4164 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4165
4166 ASSERT_NE(0lu, streaming_groups.count(group_id));
4167 auto group = streaming_groups.at(group_id);
4168 ASSERT_NE(group, nullptr);
4169
4170 auto device = group->GetFirstDevice();
4171 ASSERT_NE(device, nullptr);
4172 ASSERT_EQ(device->audio_directions_, bluetooth::le_audio::types::kLeAudioDirectionSink |
4173 bluetooth::le_audio::types::kLeAudioDirectionSource);
4174
4175 DisconnectLeAudioWithAclClose(test_address0, conn_id);
4176 }
4177
TEST_F(UnicastTestNoInit,ServiceChangedBeforeServiceIsConnected)4178 TEST_F(UnicastTestNoInit, ServiceChangedBeforeServiceIsConnected) {
4179 // Prepare two devices
4180 uint8_t group_size = 2;
4181 uint8_t group_id = 2;
4182
4183 /* Prepare mock to not inject connect event so the device can stay in
4184 * CONNECTING state*/
4185 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, false))
4186 .WillByDefault(DoAll(Return()));
4187
4188 const RawAddress test_address0 = GetTestAddress(0);
4189 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
4190 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
4191 default_channel_cnt, 0x0004,
4192 /* source sample freq 16khz */ true, /*add_csis*/
4193 true, /*add_cas*/
4194 true, /*add_pacs*/
4195 default_ase_cnt, /*add_ascs_cnt*/
4196 group_size, 1);
4197
4198 const RawAddress test_address1 = GetTestAddress(1);
4199 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
4200 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
4201 default_channel_cnt, 0x0004,
4202 /* source sample freq 16khz */ true, /*add_csis*/
4203 true, /*add_cas*/
4204 true, /*add_pacs*/
4205 default_ase_cnt, /*add_ascs_cnt*/
4206 group_size, 2);
4207
4208 // Load devices from the storage when storage API is called
4209 bool autoconnect = true;
4210
4211 /* Common storage values */
4212 std::vector<uint8_t> handles;
4213 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4214
4215 std::vector<uint8_t> ases;
4216 LeAudioClient::GetAsesForStorage(test_address0, ases);
4217
4218 std::vector<uint8_t> src_pacs;
4219 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4220
4221 std::vector<uint8_t> snk_pacs;
4222 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4223
4224 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4225 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect,
4226 codec_spec_conf::kLeAudioLocationFrontLeft,
4227 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
4228 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4229 std::move(ases)));
4230 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect,
4231 codec_spec_conf::kLeAudioLocationFrontRight,
4232 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
4233 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4234 std::move(ases)));
4235 SyncOnMainLoop();
4236 });
4237
4238 // Expect stored device0 to connect automatically (first directed connection )
4239 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
4240 .Times(1);
4241
4242 // Expect stored device1 to connect automatically (first direct connection)
4243 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
4244 .Times(1);
4245
4246 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4247 .WillByDefault(DoAll(Return(true)));
4248 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4249 .WillByDefault(DoAll(Return(true)));
4250
4251 ON_CALL(mock_groups_module_, GetGroupId(_, _)).WillByDefault(DoAll(Return(group_id)));
4252
4253 ON_CALL(mock_btm_interface_, GetSecurityFlagsByTransport(test_address0, NotNull(), _))
4254 .WillByDefault(DoAll(SetArgPointee<1>(BTM_SEC_FLAG_ENCRYPTED), Return(true)));
4255
4256 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
4257
4258 // Initialize
4259 BtaAppRegisterCallback app_register_callback;
4260 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
4261 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
4262 LeAudioClient::Initialize(
4263 &mock_audio_hal_client_callbacks_,
4264 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
4265 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
4266 framework_encode_preference);
4267 if (app_register_callback) {
4268 app_register_callback.Run(gatt_if, GATT_SUCCESS);
4269 }
4270
4271 // We need to wait for the storage callback before verifying stuff
4272 SyncOnMainLoop();
4273 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4274 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4275
4276 /* Inject Service Changed */
4277 InjectServiceChangedEvent(test_address1, 0xffff);
4278 SyncOnMainLoop();
4279 InjectServiceChangedEvent(test_address0, 0xffff);
4280 SyncOnMainLoop();
4281 /* Stack should rediscover services as storage is broken */
4282 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(2, _)).Times(1);
4283 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(1, _)).Times(1);
4284
4285 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4286 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4287 .Times(1);
4288
4289 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4290 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4291 .Times(1);
4292
4293 /* For background connect, test needs to Inject Connected Event */
4294 InjectConnectedEvent(test_address0, 1);
4295 InjectConnectedEvent(test_address1, 2);
4296 SyncOnMainLoop();
4297
4298 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4299 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4300 }
4301
TEST_F(UnicastTestNoInit,LoadStoredEarbudsCsisGroupedDifferently)4302 TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGroupedDifferently) {
4303 // Prepare two devices
4304 uint8_t group_size = 1;
4305
4306 // Device 0
4307 uint8_t group_id0 = 2;
4308 bool autoconnect0 = true;
4309 const RawAddress test_address0 = GetTestAddress(0);
4310 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeft,
4311 codec_spec_conf::kLeAudioLocationFrontLeft, 0x0004,
4312 /* source sample freq 16khz */ true, /*add_csis*/
4313 true, /*add_cas*/
4314 true, /*add_pacs*/
4315 true, /*add_ascs*/
4316 group_size, 1);
4317
4318 ON_CALL(mock_groups_module_, GetGroupId(test_address0, _))
4319 .WillByDefault(DoAll(Return(group_id0)));
4320
4321 // Device 1
4322 uint8_t group_id1 = 3;
4323 bool autoconnect1 = false;
4324 const RawAddress test_address1 = GetTestAddress(1);
4325 SetSampleDatabaseEarbudsValid(2, test_address1, codec_spec_conf::kLeAudioLocationFrontRight,
4326 codec_spec_conf::kLeAudioLocationFrontRight, default_channel_cnt,
4327 default_channel_cnt, 0x0004,
4328 /* source sample freq 16khz */ true, /*add_csis*/
4329 true, /*add_cas*/
4330 true, /*add_pacs*/
4331 default_ase_cnt, /*add_ascs_cnt*/
4332 group_size, 2);
4333
4334 ON_CALL(mock_groups_module_, GetGroupId(test_address1, _))
4335 .WillByDefault(DoAll(Return(group_id1)));
4336
4337 /* Commont storage values */
4338 std::vector<uint8_t> handles;
4339 LeAudioClient::GetHandlesForStorage(test_address0, handles);
4340
4341 std::vector<uint8_t> ases;
4342 LeAudioClient::GetAsesForStorage(test_address0, ases);
4343
4344 std::vector<uint8_t> src_pacs;
4345 LeAudioClient::GetSourcePacsForStorage(test_address0, src_pacs);
4346
4347 std::vector<uint8_t> snk_pacs;
4348 LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs);
4349
4350 // Load devices from the storage when storage API is called
4351 EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() {
4352 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect0,
4353 codec_spec_conf::kLeAudioLocationFrontLeft,
4354 codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff,
4355 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4356 std::move(ases)));
4357 do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect1,
4358 codec_spec_conf::kLeAudioLocationFrontRight,
4359 codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff,
4360 std::move(handles), std::move(snk_pacs), std::move(src_pacs),
4361 std::move(ases)));
4362 });
4363
4364 // Expect stored device0 to connect automatically
4365 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4366 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4367 .Times(1);
4368 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4369 .WillByDefault(DoAll(Return(true)));
4370
4371 // First device will got connected
4372 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
4373 .Times(1);
4374 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
4375 EXPECT_CALL(mock_gatt_interface_,
4376 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4377 .Times(1);
4378
4379 // Expect stored device1 to NOT connect automatically
4380 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4381 OnConnectionState(ConnectionState::CONNECTED, test_address1))
4382 .Times(0);
4383 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address1, _))
4384 .WillByDefault(DoAll(Return(true)));
4385
4386 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
4387 .Times(0);
4388
4389 // Initialize
4390 BtaAppRegisterCallback app_register_callback;
4391 ON_CALL(mock_gatt_interface_, AppRegister(_, _, _))
4392 .WillByDefault(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
4393 std::vector<::bluetooth::le_audio::btle_audio_codec_config_t> framework_encode_preference;
4394 LeAudioClient::Initialize(
4395 &mock_audio_hal_client_callbacks_,
4396 base::Bind([](MockFunction<void()>* foo) { foo->Call(); }, &mock_storage_load),
4397 base::Bind([](MockFunction<bool()>* foo) { return foo->Call(); }, &mock_hal_2_1_verifier),
4398 framework_encode_preference);
4399 if (app_register_callback) {
4400 app_register_callback.Run(gatt_if, GATT_SUCCESS);
4401 }
4402
4403 // We need to wait for the storage callback before verifying stuff
4404 SyncOnMainLoop();
4405 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4406 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4407 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4408
4409 // Simulate device is not there and phone fallbacks to targeted announcements
4410 EXPECT_CALL(mock_gatt_interface_,
4411 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4412 .Times(1);
4413
4414 // Devices 0 is connected. Disconnect it
4415 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
4416
4417 SyncOnMainLoop();
4418 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4419
4420 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
4421 EXPECT_CALL(mock_gatt_interface_,
4422 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
4423 .Times(1);
4424
4425 /* Keep device in Getting Ready state */
4426 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
4427 .WillByDefault(DoAll(Return(false)));
4428 ON_CALL(mock_btm_interface_, SetEncryption(test_address0, _, _, _, _))
4429 .WillByDefault(Return(tBTM_STATUS::BTM_SUCCESS));
4430
4431 /* For background connect, test needs to Inject Connected Event */
4432 InjectConnectedEvent(test_address0, 1);
4433
4434 // We need to wait for the storage callback before verifying stuff
4435 SyncOnMainLoop();
4436 ASSERT_TRUE(LeAudioClient::IsLeAudioClientRunning());
4437 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
4438
4439 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id0);
4440 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4441 ASSERT_EQ(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4442
4443 devs = LeAudioClient::Get()->GetGroupDevices(group_id1);
4444 ASSERT_EQ(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4445 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4446
4447 /* Disconnects while being in getting ready state */
4448 DisconnectLeAudioWithGattClose(test_address0, 1);
4449 }
4450
TEST_F(UnicastTest,GroupingAddRemove)4451 TEST_F(UnicastTest, GroupingAddRemove) {
4452 // Earbud connects without known grouping
4453 uint8_t group_id0 = bluetooth::groups::kGroupUnknown;
4454 const RawAddress test_address0 = GetTestAddress(0);
4455
4456 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
4457 ConnectNonCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
4458 codec_spec_conf::kLeAudioLocationFrontLeft);
4459
4460 group_id0 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
4461
4462 // Earbud connects without known grouping
4463 uint8_t group_id1 = bluetooth::groups::kGroupUnknown;
4464 const RawAddress test_address1 = GetTestAddress(1);
4465 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
4466 ConnectNonCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
4467 codec_spec_conf::kLeAudioLocationFrontRight);
4468
4469 group_id1 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
4470
4471 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
4472
4473 // Verify individual groups
4474 ASSERT_NE(group_id0, bluetooth::groups::kGroupUnknown);
4475 ASSERT_NE(group_id1, bluetooth::groups::kGroupUnknown);
4476 ASSERT_NE(group_id0, group_id1);
4477 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 1u);
4478 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 1u);
4479
4480 // Expectations on reassigning second earbud to the first group
4481 int dev1_storage_group = bluetooth::groups::kGroupUnknown;
4482 int dev1_new_group = bluetooth::groups::kGroupUnknown;
4483
4484 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4485 OnGroupNodeStatus(test_address1, group_id1, GroupNodeStatus::REMOVED))
4486 .Times(AtLeast(1));
4487 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4488 OnGroupNodeStatus(test_address1, _, GroupNodeStatus::ADDED))
4489 .WillRepeatedly(SaveArg<1>(&dev1_new_group));
4490 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id1)).Times(AtLeast(1));
4491 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, _)).Times(AnyNumber());
4492
4493 LeAudioClient::Get()->GroupRemoveNode(group_id1, test_address1);
4494 SyncOnMainLoop();
4495
4496 Mock::VerifyAndClearExpectations(&mock_groups_module_);
4497 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
4498
4499 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, group_id0)).Times(1);
4500
4501 LeAudioClient::Get()->GroupAddNode(group_id0, test_address1);
4502 SyncOnMainLoop();
4503 Mock::VerifyAndClearExpectations(&mock_groups_module_);
4504
4505 dev1_storage_group = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
4506
4507 // Verify regrouping results
4508 EXPECT_EQ(dev1_new_group, group_id0);
4509 EXPECT_EQ(dev1_new_group, dev1_storage_group);
4510 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 0u);
4511 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 2u);
4512 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id0);
4513 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
4514 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
4515 }
4516
TEST_F(UnicastTest,DoubleResumeFromAF)4517 TEST_F(UnicastTest, DoubleResumeFromAF) {
4518 const RawAddress test_address0 = GetTestAddress(0);
4519 int group_id = bluetooth::groups::kGroupUnknown;
4520
4521 SetSampleDatabaseEarbudsValid(
4522 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4523 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4524 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4525 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4526 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4527 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4528 .Times(1);
4529 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4530 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4531 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4532
4533 ConnectLeAudio(test_address0);
4534 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4535
4536 constexpr int gmcs_ccid = 1;
4537 constexpr int gtbs_ccid = 2;
4538
4539 // Audio sessions are started only when device gets active
4540 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4541 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4542 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
4543 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
4544 LeAudioClient::Get()->GroupSetActive(group_id);
4545 SyncOnMainLoop();
4546
4547 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
4548 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
4549
4550 stay_at_qos_config_in_start_stream = true;
4551
4552 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
4553 LocalAudioSourceResume(false);
4554
4555 SyncOnMainLoop();
4556 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4557 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4558
4559 // Additional resume shall be ignored.
4560 LocalAudioSourceResume(false, false);
4561
4562 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
4563
4564 do_in_main_thread(base::BindOnce(
4565 [](int group_id,
4566 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks) {
4567 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
4568 },
4569 group_id, base::Unretained(state_machine_callbacks_)));
4570 SyncOnMainLoop();
4571 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4572
4573 // Verify Data transfer on one audio source cis
4574 constexpr uint8_t cis_count_out = 1;
4575 constexpr uint8_t cis_count_in = 0;
4576 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
4577 }
4578
TEST_F(UnicastTest,DoubleResumeFromAFOnLocalSink)4579 TEST_F(UnicastTest, DoubleResumeFromAFOnLocalSink) {
4580 const RawAddress test_address0 = GetTestAddress(0);
4581 int group_id = bluetooth::groups::kGroupUnknown;
4582
4583 default_channel_cnt = 1;
4584
4585 SetSampleDatabaseEarbudsValid(
4586 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4587 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4588 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4589 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4590 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4591 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4592 .Times(1);
4593 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4594 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4595 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4596
4597 ConnectLeAudio(test_address0);
4598 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4599
4600 // Audio sessions are started only when device gets active
4601 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4602 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4603 LeAudioClient::Get()->GroupSetActive(group_id);
4604 SyncOnMainLoop();
4605
4606 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4607
4608 stay_at_qos_config_in_start_stream = true;
4609
4610 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
4611 LocalAudioSinkResume();
4612
4613 SyncOnMainLoop();
4614 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4615 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4616
4617 EXPECT_CALL(*mock_le_audio_sink_hal_client_, CancelStreamingRequest()).Times(0);
4618
4619 // Actuall test here: send additional resume which shall be ignored.
4620 LocalAudioSinkResume();
4621
4622 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
4623
4624 do_in_main_thread(base::BindOnce(
4625 [](int group_id,
4626 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks) {
4627 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
4628 },
4629 group_id, base::Unretained(state_machine_callbacks_)));
4630 SyncOnMainLoop();
4631 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4632
4633 // Verify Data transfer on local audio sink which is started
4634 constexpr uint8_t cis_count_out = 0;
4635 constexpr uint8_t cis_count_in = 1;
4636 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
4637 }
4638
TEST_F(UnicastTest,HandleResumeWithoutMetadataUpdateOnLocalSink)4639 TEST_F(UnicastTest, HandleResumeWithoutMetadataUpdateOnLocalSink) {
4640 const RawAddress test_address0 = GetTestAddress(0);
4641 int group_id = bluetooth::groups::kGroupUnknown;
4642
4643 /**
4644 * In this test we want to make sure that if MetadataUpdate is
4645 * not called before Resume, but the context type is supported,
4646 * stream should be created
4647 */
4648
4649 default_channel_cnt = 1;
4650
4651 SetSampleDatabaseEarbudsValid(
4652 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4653 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4654 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4655 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4656 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4657 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4658 .Times(1);
4659 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4660 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4661 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4662
4663 ConnectLeAudio(test_address0);
4664 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4665
4666 // Audio sessions are started only when device gets active
4667 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4668 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4669 LeAudioClient::Get()->GroupSetActive(group_id);
4670 SyncOnMainLoop();
4671
4672 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4673
4674 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
4675 LocalAudioSinkResume();
4676
4677 SyncOnMainLoop();
4678 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4679 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4680 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4681
4682 // Verify Data transfer on local audio sink which is started
4683 constexpr uint8_t cis_count_out = 0;
4684 constexpr uint8_t cis_count_in = 1;
4685 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
4686
4687 SyncOnMainLoop();
4688 /* Clear cache by changing context types, this is required for the test
4689 * as setting active device actually generate cache
4690 */
4691 auto sink_available_context = types::kLeAudioContextAllRemoteSinkOnly;
4692 auto source_available_context = types::kLeAudioContextAllRemoteSource;
4693 InjectAvailableContextTypes(test_address0, 1, sink_available_context, source_available_context);
4694
4695 StopStreaming(group_id, true);
4696 SyncOnMainLoop();
4697
4698 // simulate suspend timeout passed, alarm executing
4699 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
4700 SyncOnMainLoop();
4701
4702 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4703
4704 // Resume without metadata update while cached configuration is cleared
4705 LocalAudioSinkResume();
4706 SyncOnMainLoop();
4707 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4708 }
4709
TEST_F(UnicastTest,GroupSetActiveNonConnectedGroup)4710 TEST_F(UnicastTest, GroupSetActiveNonConnectedGroup) {
4711 const RawAddress test_address0 = GetTestAddress(0);
4712 int group_id = bluetooth::groups::kGroupUnknown;
4713
4714 /**
4715 * In this test we want to make sure that Available context change reach Java
4716 * when group is in Configured state
4717 */
4718
4719 default_channel_cnt = 1;
4720 int conn_id = 1;
4721 SetSampleDatabaseEarbudsValid(
4722 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4723 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4724 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4725 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4726 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4727 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4728 .Times(1);
4729 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4730 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4731 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4732
4733 ConnectLeAudio(test_address0);
4734 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4735
4736 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4737
4738 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, GroupStatus::INACTIVE))
4739 .Times(1);
4740
4741 InjectDisconnectedEvent(conn_id);
4742 SyncOnMainLoop();
4743
4744 // Audio sessions are started only when device gets active
4745 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupSelectableCodecConf(group_id, _, _))
4746 .Times(0);
4747 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _))
4748 .Times(0);
4749 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(0);
4750 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(0);
4751
4752 // try to set active group on non connected group
4753
4754 LeAudioClient::Get()->GroupSetActive(group_id);
4755 SyncOnMainLoop();
4756 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4757 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4758 }
4759
TEST_F(UnicastTest,GroupSetActive_CurrentCodecSentOfActive)4760 TEST_F(UnicastTest, GroupSetActive_CurrentCodecSentOfActive) {
4761 com::android::bluetooth::flags::provider_->leaudio_codec_config_callback_order_fix(true);
4762 const RawAddress test_address0 = GetTestAddress(0);
4763 int group_id = bluetooth::groups::kGroupUnknown;
4764
4765 /**
4766 * In this test we want to make sure that Available context change reach Java
4767 * when group is in Configured state
4768 */
4769
4770 default_channel_cnt = 1;
4771
4772 SetSampleDatabaseEarbudsValid(
4773 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4774 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4775 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4776 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4777 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4778 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4779 .Times(1);
4780 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4781 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4782 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4783
4784 ConnectLeAudio(test_address0);
4785 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4786
4787 // Audio sessions are started only when device gets active
4788 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupSelectableCodecConf(group_id, _, _))
4789 .Times(1);
4790 btle_audio_codec_config_t empty_conf{};
4791 btle_audio_codec_config_t output_config = {
4792 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
4793 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
4794 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
4795 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
4796 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
4797 .octets_per_frame = 120};
4798
4799 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4800 OnAudioGroupCurrentCodecConf(group_id, empty_conf, output_config))
4801 .Times(1);
4802
4803 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4804 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4805 LeAudioClient::Get()->GroupSetActive(group_id);
4806 SyncOnMainLoop();
4807 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4808 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4809 }
4810
TEST_F(UnicastTest,GroupSetActive)4811 TEST_F(UnicastTest, GroupSetActive) {
4812 const RawAddress test_address0 = GetTestAddress(0);
4813 int group_id = bluetooth::groups::kGroupUnknown;
4814
4815 /**
4816 * In this test we want to make sure that Available context change reach Java
4817 * when group is in Configured state
4818 */
4819
4820 default_channel_cnt = 1;
4821
4822 SetSampleDatabaseEarbudsValid(
4823 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4824 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4825 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4826 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4827 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4828 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4829 .Times(1);
4830 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4831 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4832 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4833
4834 ConnectLeAudio(test_address0);
4835 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4836
4837 // Audio sessions are started only when device gets active
4838 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupSelectableCodecConf(group_id, _, _))
4839 .Times(1);
4840 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, GroupStatus::ACTIVE))
4841 .Times(1);
4842 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(_, GroupStatus::INACTIVE)).Times(0);
4843 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4844 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4845
4846 EXPECT_CALL(*mock_codec_manager_,
4847 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
4848 mock_le_audio_sink_hal_client_, true))
4849 .Times(1);
4850
4851 LeAudioClient::Get()->GroupSetActive(group_id);
4852 SyncOnMainLoop();
4853 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4854 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4855 Mock::VerifyAndClearExpectations(mock_codec_manager_);
4856 }
4857
TEST_F(UnicastTest,GroupSetActive_SinkPacksEmpty)4858 TEST_F(UnicastTest, GroupSetActive_SinkPacksEmpty) {
4859 const RawAddress test_address0 = GetTestAddress(0);
4860 int group_id = bluetooth::groups::kGroupUnknown;
4861 empty_sink_pack_ = true;
4862
4863 /**
4864 * In this test we want to make sure that Available context change reach Java
4865 * when group is in Configured state
4866 */
4867
4868 default_channel_cnt = 1;
4869
4870 SetSampleDatabaseEarbudsValid(
4871 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4872 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4873 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4874 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4875 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4876 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4877 .Times(1);
4878 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4879 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4880 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4881
4882 ConnectLeAudio(test_address0);
4883 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4884
4885 // Audio sessions are started only when device gets active
4886 std::vector<btle_audio_codec_config_t> empty_confs;
4887
4888 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4889 OnAudioGroupSelectableCodecConf(group_id, _, empty_confs))
4890 .Times(1);
4891 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4892 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4893
4894 EXPECT_CALL(*mock_codec_manager_,
4895 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
4896 mock_le_audio_sink_hal_client_, true))
4897 .Times(1);
4898
4899 LeAudioClient::Get()->GroupSetActive(group_id);
4900 SyncOnMainLoop();
4901 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4902 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4903 Mock::VerifyAndClearExpectations(mock_codec_manager_);
4904 }
4905
TEST_F(UnicastTest,GroupSetActive_SourcePacksEmpty)4906 TEST_F(UnicastTest, GroupSetActive_SourcePacksEmpty) {
4907 const RawAddress test_address0 = GetTestAddress(0);
4908 int group_id = bluetooth::groups::kGroupUnknown;
4909 empty_source_pack_ = true;
4910
4911 /**
4912 * In this test we want to make sure that Available context change reach Java
4913 * when group is in Configured state
4914 */
4915
4916 default_channel_cnt = 1;
4917
4918 SetSampleDatabaseEarbudsValid(
4919 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4920 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4921 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4922 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4923 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4924 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4925 .Times(1);
4926 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4927 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4928 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4929
4930 ConnectLeAudio(test_address0);
4931 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4932
4933 // Audio sessions are started only when device gets active
4934 std::vector<btle_audio_codec_config_t> empty_confs;
4935
4936 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4937 OnAudioGroupSelectableCodecConf(group_id, empty_confs, _))
4938 .Times(1);
4939 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
4940 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
4941 LeAudioClient::Get()->GroupSetActive(group_id);
4942 SyncOnMainLoop();
4943 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
4944 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
4945 }
4946
TEST_F(UnicastTest,GroupSetActive_and_InactiveDuringStreamConfiguration)4947 TEST_F(UnicastTest, GroupSetActive_and_InactiveDuringStreamConfiguration) {
4948 const RawAddress test_address0 = GetTestAddress(0);
4949 int group_id = bluetooth::groups::kGroupUnknown;
4950 empty_source_pack_ = true;
4951
4952 /**
4953 * In this test we want to make sure that StopStream is called when group is set to inactive
4954 * while being between IDLE and CONFIGURED state
4955 */
4956
4957 default_channel_cnt = 1;
4958
4959 SetSampleDatabaseEarbudsValid(
4960 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
4961 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
4962 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
4963 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
4964 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4965 OnConnectionState(ConnectionState::CONNECTED, test_address0))
4966 .Times(1);
4967 EXPECT_CALL(mock_audio_hal_client_callbacks_,
4968 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
4969 .WillOnce(DoAll(SaveArg<1>(&group_id)));
4970
4971 ConnectLeAudio(test_address0);
4972 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
4973
4974 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
4975
4976 stay_at_qos_config_in_start_stream = true;
4977
4978 LeAudioClient::Get()->GroupSetActive(group_id);
4979 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID, false,
4980 false);
4981
4982 SyncOnMainLoop();
4983
4984 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
4985 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
4986
4987 SyncOnMainLoop();
4988 Mock::VerifyAndClearExpectations(&mock_state_machine_);
4989 }
4990
TEST_F(UnicastTest,GroupSetActive_and_GroupSetInactive_DuringPhoneCall)4991 TEST_F(UnicastTest, GroupSetActive_and_GroupSetInactive_DuringPhoneCall) {
4992 com::android::bluetooth::flags::provider_->leaudio_improve_switch_during_phone_call(true);
4993 const RawAddress test_address0 = GetTestAddress(0);
4994 int group_id = bluetooth::groups::kGroupUnknown;
4995
4996 /**
4997 * Scenario:
4998 * 1. Call is started
4999 * 2. Group is set active - it is expected the state machine to be instructed to Configure to Qos
5000 * 3. Group is set to inactive - it is expected that state machine is instructed to stop *
5001 */
5002
5003 default_channel_cnt = 1;
5004
5005 SetSampleDatabaseEarbudsValid(
5006 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5007 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5008 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5009 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5010 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5011 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5012 .Times(1);
5013 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5014 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5015 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5016
5017 ConnectLeAudio(test_address0);
5018 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5019
5020 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
5021 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, true)).Times(1);
5022
5023 log::info("Call is started and group is getting Active");
5024 LeAudioClient::Get()->SetInCall(true);
5025 LeAudioClient::Get()->GroupSetActive(group_id);
5026
5027 SyncOnMainLoop();
5028 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5029
5030 log::info("Group is getting inctive");
5031 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5032 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
5033
5034 SyncOnMainLoop();
5035 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5036 }
5037
TEST_F(UnicastTest,GroupSetActive_DuringPhoneCall_ThenResume)5038 TEST_F(UnicastTest, GroupSetActive_DuringPhoneCall_ThenResume) {
5039 com::android::bluetooth::flags::provider_->leaudio_improve_switch_during_phone_call(true);
5040 const RawAddress test_address0 = GetTestAddress(0);
5041 int group_id = bluetooth::groups::kGroupUnknown;
5042
5043 /**
5044 * Scenario:
5045 * 1. Call is started
5046 * 2. Group is set active - it is expected the state machine to be instructed to Configure to Qos
5047 * 3. Audio Framework callse Resume - expect stream is started.
5048 * 4. Group is set to inactive - it is expected that state machine is instructed to stop *
5049 */
5050
5051 default_channel_cnt = 1;
5052
5053 SetSampleDatabaseEarbudsValid(
5054 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5055 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5056 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5057 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5058 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5059 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5060 .Times(1);
5061 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5062 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5063 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5064
5065 ConnectLeAudio(test_address0);
5066 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5067
5068 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
5069 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, true)).Times(1);
5070
5071 log::info("Call is started and group is getting Active");
5072 LeAudioClient::Get()->SetInCall(true);
5073 LeAudioClient::Get()->GroupSetActive(group_id);
5074
5075 SyncOnMainLoop();
5076 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5077
5078 log::info("AF resumes the stream");
5079 /* Simulate resume and expect StartStream to be called.
5080 * Do not expect confirmation on resume, as this part is not mocked on the state machine
5081 */
5082 EXPECT_CALL(mock_state_machine_, StartStream(_, LeAudioContextType::CONVERSATIONAL, _, _))
5083 .Times(1);
5084 LocalAudioSourceResume(true, false);
5085 SyncOnMainLoop();
5086 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5087
5088 log::info("Group is getting inactive");
5089 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5090 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
5091
5092 SyncOnMainLoop();
5093 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5094 }
5095
TEST_F(UnicastTest,ChangeAvailableContextTypeWhenInCodecConfigured)5096 TEST_F(UnicastTest, ChangeAvailableContextTypeWhenInCodecConfigured) {
5097 const RawAddress test_address0 = GetTestAddress(0);
5098 int group_id = bluetooth::groups::kGroupUnknown;
5099
5100 /**
5101 * In this test we want to make sure that Available context change reach Java
5102 * when group is in Configured state
5103 */
5104
5105 default_channel_cnt = 1;
5106
5107 SetSampleDatabaseEarbudsValid(
5108 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5109 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5110 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5111 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5112 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5113 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5114 .Times(1);
5115 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5116 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5117 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5118
5119 ConnectLeAudio(test_address0);
5120 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5121
5122 // Audio sessions are started only when device gets active
5123 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5124 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5125 LeAudioClient::Get()->GroupSetActive(group_id);
5126 SyncOnMainLoop();
5127
5128 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5129
5130 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
5131 LocalAudioSinkResume();
5132
5133 SyncOnMainLoop();
5134 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5135 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5136 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5137
5138 // Verify Data transfer on local audio sink which is started
5139 constexpr uint8_t cis_count_out = 0;
5140 constexpr uint8_t cis_count_in = 1;
5141 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
5142
5143 // Remember group to set the state after stopping the stream
5144 ASSERT_NE(0lu, streaming_groups.count(group_id));
5145 auto group = streaming_groups.at(group_id);
5146
5147 SyncOnMainLoop();
5148 StopStreaming(group_id, true);
5149 SyncOnMainLoop();
5150
5151 // simulate suspend timeout passed, alarm executing
5152 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
5153 SyncOnMainLoop();
5154
5155 // Simulate state Configured
5156 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
5157
5158 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioConf(_, _, _, _, _));
5159
5160 /* Check if available context will be sent to Java */
5161 auto sink_available_context = types::kLeAudioContextAllRemoteSinkOnly;
5162 auto source_available_context = types::kLeAudioContextAllRemoteSource;
5163
5164 InjectAvailableContextTypes(test_address0, 1, sink_available_context, source_available_context);
5165
5166 SyncOnMainLoop();
5167 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5168 }
5169
TEST_F(UnicastTest,TestUpdateConfigurationCallbackWhileStreaming)5170 TEST_F(UnicastTest, TestUpdateConfigurationCallbackWhileStreaming) {
5171 const RawAddress test_address0 = GetTestAddress(0);
5172 int group_id = bluetooth::groups::kGroupUnknown;
5173
5174 SetSampleDatabaseEarbudsValid(
5175 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5176 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5177 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5178 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5179 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5180 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5181 .Times(1);
5182 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5183 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5184 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5185
5186 ConnectLeAudio(test_address0);
5187 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5188
5189 // Start streaming
5190 LeAudioClient::Get()->GroupSetActive(group_id);
5191 SyncOnMainLoop();
5192
5193 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5194 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _))
5195 .Times(1);
5196 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5197
5198 SyncOnMainLoop();
5199 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5200 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5201 SyncOnMainLoop();
5202
5203 // When metadata update happen, there should be no configuration change
5204 // callback sent
5205 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnAudioGroupCurrentCodecConf(group_id, _, _))
5206 .Times(0);
5207
5208 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
5209 UpdateLocalSourceMetadata(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN);
5210
5211 // Inject STREAMING Status from state machine.
5212 auto group = streaming_groups.at(group_id);
5213 do_in_main_thread(base::BindOnce(
5214 [](int group_id,
5215 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
5216 LeAudioDeviceGroup* /*group*/) {
5217 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
5218 },
5219 group_id, base::Unretained(this->state_machine_callbacks_), std::move(group)));
5220
5221 SyncOnMainLoop();
5222 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5223 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5224 }
5225
TEST_F(UnicastTest,TestDeactivateWhileStartingStream)5226 TEST_F(UnicastTest, TestDeactivateWhileStartingStream) {
5227 const RawAddress test_address0 = GetTestAddress(0);
5228 int group_id = bluetooth::groups::kGroupUnknown;
5229
5230 SetSampleDatabaseEarbudsValid(
5231 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5232 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5233 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5234 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5235 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5236 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5237 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5238
5239 ConnectLeAudio(test_address0);
5240 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5241
5242 // Start streaming
5243 LeAudioClient::Get()->GroupSetActive(group_id);
5244 SyncOnMainLoop();
5245 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5246
5247 // Deactivate while starting to stream
5248 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
5249
5250 // Inject STREAMING Status from state machine.
5251 auto group = streaming_groups.at(group_id);
5252 do_in_main_thread(base::BindOnce(
5253 [](int group_id,
5254 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
5255 LeAudioDeviceGroup* /*group*/) {
5256 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
5257 },
5258 group_id, base::Unretained(this->state_machine_callbacks_), std::move(group)));
5259 SyncOnMainLoop();
5260 }
5261
TEST_F(UnicastTest,RemoveNodeWhileStreaming)5262 TEST_F(UnicastTest, RemoveNodeWhileStreaming) {
5263 const RawAddress test_address0 = GetTestAddress(0);
5264 int group_id = bluetooth::groups::kGroupUnknown;
5265
5266 SetSampleDatabaseEarbudsValid(
5267 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5268 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5269 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5270 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5271 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5272 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5273 .Times(1);
5274 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5275 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5276 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5277
5278 ConnectLeAudio(test_address0);
5279 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5280
5281 // Start streaming
5282 constexpr uint8_t cis_count_out = 1;
5283 constexpr uint8_t cis_count_in = 0;
5284
5285 constexpr int gmcs_ccid = 1;
5286 constexpr int gtbs_ccid = 2;
5287
5288 // Audio sessions are started only when device gets active
5289 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5290 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5291 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5292 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5293 LeAudioClient::Get()->GroupSetActive(group_id);
5294 SyncOnMainLoop();
5295
5296 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
5297 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5298
5299 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5300
5301 SyncOnMainLoop();
5302 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5303 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5304 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5305 SyncOnMainLoop();
5306
5307 // Verify Data transfer on one audio source cis
5308 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5309
5310 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id)).Times(1);
5311 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
5312 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _)).Times(1);
5313 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5314 OnGroupNodeStatus(test_address0, group_id, GroupNodeStatus::REMOVED));
5315 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5316 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5317 .Times(1);
5318
5319 LeAudioClient::Get()->GroupRemoveNode(group_id, test_address0);
5320
5321 SyncOnMainLoop();
5322 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5323 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5324 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5325 }
5326
TEST_F(UnicastTest,InactiveDeviceOnInternalStateMachineError)5327 TEST_F(UnicastTest, InactiveDeviceOnInternalStateMachineError) {
5328 const RawAddress test_address0 = GetTestAddress(0);
5329 int group_id = bluetooth::groups::kGroupUnknown;
5330
5331 SetSampleDatabaseEarbudsValid(
5332 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5333 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5334 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5335 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5336 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5337 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5338 .Times(1);
5339 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5340 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5341 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5342
5343 ConnectLeAudio(test_address0);
5344 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5345
5346 // Start streaming
5347 constexpr uint8_t cis_count_out = 1;
5348 constexpr uint8_t cis_count_in = 0;
5349
5350 constexpr int gmcs_ccid = 1;
5351 constexpr int gtbs_ccid = 2;
5352
5353 // Audio sessions are started only when device gets active
5354 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5355 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5356 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5357 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5358 LeAudioClient::Get()->GroupSetActive(group_id);
5359 SyncOnMainLoop();
5360
5361 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
5362 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5363
5364 btle_audio_codec_config_t empty_conf{};
5365 btle_audio_codec_config_t output_config = {
5366 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
5367 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
5368 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
5369 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_2,
5370 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
5371 .octets_per_frame = 120};
5372
5373 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5374 OnAudioGroupCurrentCodecConf(group_id, empty_conf, output_config))
5375 .Times(1);
5376
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_le_audio_source_hal_client_);
5382 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
5383 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5384 SyncOnMainLoop();
5385
5386 // Verify Data transfer on one audio source cis
5387 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5388
5389 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
5390 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
5391
5392 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, GroupStatus::INACTIVE))
5393 .Times(1);
5394
5395 /* This is internal error of the state machine */
5396 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::RELEASING);
5397
5398 SyncOnMainLoop();
5399 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5400 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5401 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
5402 }
5403
TEST_F(UnicastTest,GroupingAddTwiceNoRemove)5404 TEST_F(UnicastTest, GroupingAddTwiceNoRemove) {
5405 // Earbud connects without known grouping
5406 uint8_t group_id0 = bluetooth::groups::kGroupUnknown;
5407 const RawAddress test_address0 = GetTestAddress(0);
5408 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
5409 .WillOnce(Return())
5410 .RetiresOnSaturation();
5411 ConnectNonCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
5412 codec_spec_conf::kLeAudioLocationFrontLeft);
5413
5414 group_id0 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address0);
5415
5416 // Earbud connects without known grouping
5417 uint8_t group_id1 = bluetooth::groups::kGroupUnknown;
5418 const RawAddress test_address1 = GetTestAddress(1);
5419 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
5420 .WillOnce(Return())
5421 .RetiresOnSaturation();
5422 ConnectNonCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
5423 codec_spec_conf::kLeAudioLocationFrontRight);
5424
5425 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5426
5427 group_id1 = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
5428 // Verify individual groups
5429 ASSERT_NE(group_id0, bluetooth::groups::kGroupUnknown);
5430 ASSERT_NE(group_id1, bluetooth::groups::kGroupUnknown);
5431 ASSERT_NE(group_id0, group_id1);
5432 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 1u);
5433 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 1u);
5434
5435 // Expectations on reassigning second earbud to the first group
5436 int dev1_storage_group = bluetooth::groups::kGroupUnknown;
5437 int dev1_new_group = bluetooth::groups::kGroupUnknown;
5438
5439 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5440 OnGroupNodeStatus(test_address1, group_id1, GroupNodeStatus::REMOVED))
5441 .Times(AtLeast(1));
5442 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5443 OnGroupNodeStatus(test_address1, _, GroupNodeStatus::ADDED))
5444 .WillRepeatedly(SaveArg<1>(&dev1_new_group));
5445
5446 // FIXME: We should expect removal with group_id context. No such API exists.
5447 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id1)).Times(AtLeast(1));
5448 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, _)).Times(AnyNumber());
5449 EXPECT_CALL(mock_groups_module_, AddDevice(test_address1, _, group_id0)).Times(1);
5450
5451 // Regroup device: assign new group without removing it from the first one
5452 LeAudioClient::Get()->GroupAddNode(group_id0, test_address1);
5453 SyncOnMainLoop();
5454 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5455
5456 dev1_storage_group = MockDeviceGroups::DeviceGroups::Get()->GetGroupId(test_address1);
5457
5458 // Verify regrouping results
5459 EXPECT_EQ(dev1_new_group, group_id0);
5460 EXPECT_EQ(dev1_new_group, dev1_storage_group);
5461 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id1).size(), 0u);
5462 ASSERT_EQ(LeAudioClient::Get()->GetGroupDevices(group_id0).size(), 2u);
5463 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id0);
5464 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
5465 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
5466 }
5467
TEST_F(UnicastTest,RemoveTwoEarbudsCsisGrouped)5468 TEST_F(UnicastTest, RemoveTwoEarbudsCsisGrouped) {
5469 uint8_t group_size = 2;
5470 int group_id0 = 2;
5471 int group_id1 = 3;
5472
5473 // Report working CSIS
5474 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
5475
5476 // First group - First earbud
5477 const RawAddress test_address0 = GetTestAddress(0);
5478 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
5479 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
5480 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id0, 1 /* rank*/);
5481
5482 // First group - Second earbud
5483 const RawAddress test_address1 = GetTestAddress(1);
5484 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
5485 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
5486 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id0, 2 /* rank*/,
5487 true /*connect_through_csis*/);
5488
5489 // Second group - First earbud
5490 const RawAddress test_address2 = GetTestAddress(2);
5491 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address2, true)).Times(1);
5492 ConnectCsisDevice(test_address2, 3 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
5493 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id1, 1 /* rank*/);
5494
5495 // Second group - Second earbud
5496 const RawAddress test_address3 = GetTestAddress(3);
5497 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address3, true)).Times(1);
5498 ConnectCsisDevice(test_address3, 4 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
5499 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id1, 2 /* rank*/,
5500 true /*connect_through_csis*/);
5501
5502 // First group - verify grouping information
5503 std::vector<RawAddress> group0_devs = LeAudioClient::Get()->GetGroupDevices(group_id0);
5504 ASSERT_NE(std::find(group0_devs.begin(), group0_devs.end(), test_address0), group0_devs.end());
5505 ASSERT_NE(std::find(group0_devs.begin(), group0_devs.end(), test_address1), group0_devs.end());
5506
5507 // Second group - verify grouping information
5508 std::vector<RawAddress> group1_devs = LeAudioClient::Get()->GetGroupDevices(group_id1);
5509 ASSERT_NE(std::find(group1_devs.begin(), group1_devs.end(), test_address2), group1_devs.end());
5510 ASSERT_NE(std::find(group1_devs.begin(), group1_devs.end(), test_address3), group1_devs.end());
5511 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5512
5513 // Expect one of the groups to be dropped and devices to be disconnected
5514 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id0)).Times(1);
5515 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address1, group_id0)).Times(1);
5516 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5517 OnGroupNodeStatus(test_address0, group_id0, GroupNodeStatus::REMOVED));
5518 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5519 OnGroupNodeStatus(test_address1, group_id0, GroupNodeStatus::REMOVED));
5520 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5521 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5522 .Times(1);
5523 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5524 OnConnectionState(ConnectionState::DISCONNECTED, test_address1))
5525 .Times(1);
5526
5527 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
5528 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(2, _)).Times(1);
5529
5530 // Expect the other groups to be left as is
5531 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id1, _)).Times(0);
5532 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5533 OnConnectionState(ConnectionState::DISCONNECTED, test_address2))
5534 .Times(0);
5535 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5536 OnConnectionState(ConnectionState::DISCONNECTED, test_address3))
5537 .Times(0);
5538
5539 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(3, _)).Times(0);
5540 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(4, _)).Times(0);
5541
5542 do_in_main_thread(base::BindOnce(&LeAudioClient::GroupDestroy,
5543 base::Unretained(LeAudioClient::Get()), group_id0));
5544
5545 SyncOnMainLoop();
5546 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5547 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
5548 }
5549
TEST_F(UnicastTest,ConnectAfterRemove)5550 TEST_F(UnicastTest, ConnectAfterRemove) {
5551 const RawAddress test_address0 = GetTestAddress(0);
5552 int group_id = bluetooth::groups::kGroupUnknown;
5553 uint16_t conn_id = 1;
5554
5555 SetSampleDatabaseEarbudsValid(
5556 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5557 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5558 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5559 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5560 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5561 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5562 .Times(1);
5563
5564 /* RemoveDevice */
5565 do_in_main_thread(base::BindOnce(
5566 [](LeAudioClient* client, const RawAddress& test_address0) {
5567 client->RemoveDevice(test_address0);
5568 },
5569 LeAudioClient::Get(), test_address0));
5570 SyncOnMainLoop();
5571
5572 ON_CALL(mock_btm_interface_, IsLinkKeyKnown(_, _)).WillByDefault(DoAll(Return(false)));
5573
5574 do_in_main_thread(base::BindOnce(&LeAudioClient::Connect, base::Unretained(LeAudioClient::Get()),
5575 test_address0));
5576 SyncOnMainLoop();
5577
5578 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5579 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5580 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5581 }
5582
TEST_F(UnicastTest,RemoveDeviceWhenConnected)5583 TEST_F(UnicastTest, RemoveDeviceWhenConnected) {
5584 const RawAddress test_address0 = GetTestAddress(0);
5585 int group_id = bluetooth::groups::kGroupUnknown;
5586 uint16_t conn_id = 1;
5587
5588 SetSampleDatabaseEarbudsValid(
5589 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5590 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5591 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5592 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5593 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5594 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5595 .Times(1);
5596 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5597 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5598 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5599 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
5600 ConnectLeAudio(test_address0);
5601 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5602
5603 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5604 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5605
5606 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(1);
5607 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5608 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
5609
5610 /*
5611 * StopStream will put calls on main_loop so to keep the correct order
5612 * of operations and to avoid races we put the test command on main_loop as
5613 * well.
5614 */
5615 do_in_main_thread(base::BindOnce(
5616 [](LeAudioClient* client, const RawAddress& test_address0) {
5617 client->RemoveDevice(test_address0);
5618 },
5619 LeAudioClient::Get(), test_address0));
5620 SyncOnMainLoop();
5621
5622 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5623 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5624 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5625 }
5626
TEST_F(UnicastTest,RemoveDeviceWhenUserConnecting)5627 TEST_F(UnicastTest, RemoveDeviceWhenUserConnecting) {
5628 const RawAddress test_address0 = GetTestAddress(0);
5629 uint16_t conn_id = 1;
5630
5631 /* Prepare mock to not inject connect event so the device can stay in
5632 * CONNECTING state*/
5633 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
5634 .WillByDefault(DoAll(Return()));
5635
5636 SetSampleDatabaseEarbudsValid(
5637 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5638 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5639 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5640 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5641 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5642 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5643 .Times(0);
5644 ConnectLeAudio(test_address0, true, false);
5645
5646 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5647
5648 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
5649 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
5650 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5651
5652 /*
5653 * StopStream will put calls on main_loop so to keep the correct order
5654 * of operations and to avoid races we put the test command on main_loop as
5655 * well.
5656 */
5657 do_in_main_thread(base::BindOnce(
5658 [](LeAudioClient* client, const RawAddress& test_address0) {
5659 client->RemoveDevice(test_address0);
5660 },
5661 LeAudioClient::Get(), test_address0));
5662
5663 SyncOnMainLoop();
5664
5665 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5666 }
5667
TEST_F(UnicastTest,RemoveDeviceWhenAutoConnectingWithTargetedAnnouncements)5668 TEST_F(UnicastTest, RemoveDeviceWhenAutoConnectingWithTargetedAnnouncements) {
5669 const RawAddress test_address0 = GetTestAddress(0);
5670 uint16_t conn_id = 1;
5671
5672 /* Scenario
5673 * 1. Connect device
5674 * 2. Disconnect by remote device -> this shall start Reconnection Using TA
5675 * 3. Remove device
5676 */
5677 SetSampleDatabaseEarbudsValid(
5678 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5679 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5680 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5681 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5682
5683 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5684 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5685 .Times(1);
5686 ConnectLeAudio(test_address0, true);
5687
5688 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5689 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5690
5691 EXPECT_CALL(mock_gatt_interface_,
5692 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
5693 .Times(1);
5694
5695 // Inject disconnected event, Reconnect with TA shall start
5696 InjectDisconnectedEvent(conn_id);
5697 SyncOnMainLoop();
5698 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5699
5700 // Remove device when being in auto connect state.
5701 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
5702 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
5703 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5704
5705 do_in_main_thread(base::BindOnce(
5706 [](LeAudioClient* client, const RawAddress& test_address0) {
5707 client->RemoveDevice(test_address0);
5708 },
5709 LeAudioClient::Get(), test_address0));
5710
5711 SyncOnMainLoop();
5712
5713 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5714 }
5715
TEST_F(UnicastTest,RemoveDeviceWhenAutoConnectingAfterConnectionTimeout)5716 TEST_F(UnicastTest, RemoveDeviceWhenAutoConnectingAfterConnectionTimeout) {
5717 const RawAddress test_address0 = GetTestAddress(0);
5718 uint16_t conn_id = 1;
5719
5720 /* Scenario
5721 * 1. Connect device
5722 * 2. Disconnect remote device with connection timeout -> this shall start direct connect
5723 * 3. Remove device
5724 */
5725 SetSampleDatabaseEarbudsValid(
5726 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5727 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5728 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5729 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5730
5731 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5732 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5733 .Times(1);
5734 ConnectLeAudio(test_address0, true);
5735
5736 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5737 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5738
5739 // Prepare mock for direct connect and inject connection timeout
5740 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
5741 .WillByDefault(DoAll(Return()));
5742 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
5743 .Times(1);
5744
5745 InjectDisconnectedEvent(conn_id, GATT_CONN_TIMEOUT);
5746 SyncOnMainLoop();
5747 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5748
5749 // Remove device when being in auto connect state after connection timeout
5750 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
5751 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
5752 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5753
5754 do_in_main_thread(base::BindOnce(
5755 [](LeAudioClient* client, const RawAddress& test_address0) {
5756 client->RemoveDevice(test_address0);
5757 },
5758 LeAudioClient::Get(), test_address0));
5759
5760 SyncOnMainLoop();
5761
5762 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5763 }
5764
TEST_F(UnicastTest,RemoveDeviceWhenGettingConnectionReady)5765 TEST_F(UnicastTest, RemoveDeviceWhenGettingConnectionReady) {
5766 const RawAddress test_address0 = GetTestAddress(0);
5767 uint16_t conn_id = 1;
5768
5769 /* Prepare mock to not inject Service Search Complete*/
5770 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _)).WillByDefault(DoAll(Return()));
5771
5772 SetSampleDatabaseEarbudsValid(
5773 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5774 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5775 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5776 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5777 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5778 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5779 .Times(0);
5780 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(0);
5781 ConnectLeAudio(test_address0);
5782
5783 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5784 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5785
5786 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5787 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
5788
5789 /* Cancel should be called in RemoveDevice */
5790 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
5791 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5792
5793 /*
5794 * StopStream will put calls on main_loop so to keep the correct order
5795 * of operations and to avoid races we put the test command on main_loop as
5796 * well.
5797 */
5798 do_in_main_thread(base::BindOnce(
5799 [](LeAudioClient* client, const RawAddress& test_address0) {
5800 client->RemoveDevice(test_address0);
5801 },
5802 LeAudioClient::Get(), test_address0));
5803
5804 SyncOnMainLoop();
5805
5806 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5807 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5808 }
5809
TEST_F(UnicastTest,DisconnectDeviceWhenConnected)5810 TEST_F(UnicastTest, DisconnectDeviceWhenConnected) {
5811 const RawAddress test_address0 = GetTestAddress(0);
5812 int group_id = bluetooth::groups::kGroupUnknown;
5813 uint16_t conn_id = 1;
5814
5815 SetSampleDatabaseEarbudsValid(
5816 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5817 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5818 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5819 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5820 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5821 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5822 .Times(1);
5823 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5824 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5825 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5826 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
5827 ConnectLeAudio(test_address0);
5828 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5829
5830 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5831 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5832
5833 /* for Target announcements AutoConnect is always there, until
5834 * device is removed
5835 */
5836 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(0);
5837 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5838 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(1, _)).Times(1);
5839
5840 LeAudioClient::Get()->Disconnect(test_address0);
5841 SyncOnMainLoop();
5842
5843 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
5844 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5845 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5846 }
5847
TEST_F(UnicastTest,DisconnectDeviceWhenConnecting)5848 TEST_F(UnicastTest, DisconnectDeviceWhenConnecting) {
5849 const RawAddress test_address0 = GetTestAddress(0);
5850 uint16_t conn_id = 1;
5851
5852 /* Prepare mock to not inject connect event so the device can stay in
5853 * CONNECTING state*/
5854 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _))
5855 .WillByDefault(DoAll(Return()));
5856
5857 SetSampleDatabaseEarbudsValid(
5858 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5859 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5860 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5861 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5862 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5863 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5864 .Times(0);
5865 ConnectLeAudio(test_address0, true, false);
5866
5867 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5868
5869 /* Prepare on call mock on Close - to not trigger Inject Disconnection, as it
5870 * is done in default mock.
5871 */
5872 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
5873 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, true)).Times(1);
5874 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5875
5876 LeAudioClient::Get()->Disconnect(test_address0);
5877 SyncOnMainLoop();
5878
5879 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5880 }
5881
TEST_F(UnicastTest,DisconnectDeviceWhenGettingConnectionReady)5882 TEST_F(UnicastTest, DisconnectDeviceWhenGettingConnectionReady) {
5883 const RawAddress test_address0 = GetTestAddress(0);
5884 uint16_t conn_id = global_conn_id;
5885
5886 /* Prepare mock to not inject Service Search Complete*/
5887 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _)).WillByDefault(DoAll(Return()));
5888
5889 SetSampleDatabaseEarbudsValid(
5890 conn_id, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5891 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5892 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5893 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5894 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5895 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5896 .Times(0);
5897 ConnectLeAudio(test_address0);
5898
5899 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5900 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5901
5902 /* TA reconnect is enabled in ConnectLeAudio. Make sure this is not removed */
5903 EXPECT_CALL(mock_gatt_queue_, Clean(conn_id)).Times(AtLeast(1));
5904 EXPECT_CALL(mock_gatt_interface_, Close(conn_id)).Times(1);
5905 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(0);
5906 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, _, _)).Times(0);
5907
5908 LeAudioClient::Get()->Disconnect(test_address0);
5909 SyncOnMainLoop();
5910
5911 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
5912 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
5913 }
5914
TEST_F(UnicastTest,RemoveWhileStreaming)5915 TEST_F(UnicastTest, RemoveWhileStreaming) {
5916 const RawAddress test_address0 = GetTestAddress(0);
5917 int group_id = bluetooth::groups::kGroupUnknown;
5918
5919 SetSampleDatabaseEarbudsValid(
5920 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
5921 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
5922 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
5923 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
5924 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5925 OnConnectionState(ConnectionState::CONNECTED, test_address0))
5926 .Times(1);
5927 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5928 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
5929 .WillOnce(DoAll(SaveArg<1>(&group_id)));
5930
5931 ConnectLeAudio(test_address0);
5932 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
5933
5934 // Start streaming
5935 constexpr uint8_t cis_count_out = 1;
5936 constexpr uint8_t cis_count_in = 0;
5937
5938 constexpr int gmcs_ccid = 1;
5939 constexpr int gtbs_ccid = 2;
5940
5941 // Audio sessions are started only when device gets active
5942 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
5943 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
5944 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
5945 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
5946 LeAudioClient::Get()->GroupSetActive(group_id);
5947 SyncOnMainLoop();
5948
5949 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
5950 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
5951
5952 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
5953
5954 SyncOnMainLoop();
5955 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5956 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
5957 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5958 SyncOnMainLoop();
5959
5960 // Verify Data transfer on one audio source cis
5961 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
5962
5963 EXPECT_CALL(mock_groups_module_, RemoveDevice(test_address0, group_id)).Times(1);
5964
5965 LeAudioDeviceGroup* group = nullptr;
5966 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
5967 .WillOnce(DoAll(SaveArg<0>(&group)));
5968 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5969 OnGroupNodeStatus(test_address0, group_id, GroupNodeStatus::REMOVED));
5970
5971 EXPECT_CALL(mock_audio_hal_client_callbacks_,
5972 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
5973 .Times(1);
5974
5975 /*
5976 * StopStream will put calls on main_loop so to keep the correct order
5977 * of operations and to avoid races we put the test command on main_loop as
5978 * well.
5979 */
5980 do_in_main_thread(base::BindOnce(
5981 [](LeAudioClient* client, const RawAddress& test_address0) {
5982 client->RemoveDevice(test_address0);
5983 },
5984 LeAudioClient::Get(), test_address0));
5985
5986 SyncOnMainLoop();
5987 Mock::VerifyAndClearExpectations(&mock_groups_module_);
5988 Mock::VerifyAndClearExpectations(&mock_state_machine_);
5989 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
5990
5991 ASSERT_EQ(group, nullptr);
5992 }
5993
TEST_F(UnicastTest,DisconnecteWhileAlmostStreaming)5994 TEST_F(UnicastTest, DisconnecteWhileAlmostStreaming) {
5995 const RawAddress test_address0 = GetTestAddress(0);
5996 int group_id = bluetooth::groups::kGroupUnknown;
5997
5998 SetSampleDatabaseEarbudsValid(
5999 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6000 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6001 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6002 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6003 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6004 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6005 .Times(1);
6006 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6007 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6008 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6009
6010 ConnectLeAudio(test_address0);
6011 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6012
6013 constexpr int gmcs_ccid = 1;
6014 constexpr int gtbs_ccid = 2;
6015
6016 // Audio sessions are started only when device gets active
6017 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6018 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6019 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
6020 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
6021 LeAudioClient::Get()->GroupSetActive(group_id);
6022 SyncOnMainLoop();
6023
6024 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
6025 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
6026
6027 /* We want here to CIS be established but device not being yet in streaming
6028 * state
6029 */
6030 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6031
6032 SyncOnMainLoop();
6033 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6034 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6035 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6036 SyncOnMainLoop();
6037
6038 /* This is test code, which will change the group state to the one which
6039 * is required by test
6040 */
6041 ASSERT_NE(0lu, streaming_groups.count(group_id));
6042 auto group_inject = streaming_groups.at(group_id);
6043 group_inject->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING);
6044
6045 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
6046
6047 LeAudioDeviceGroup* group = nullptr;
6048 EXPECT_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
6049 .WillOnce(DoAll(SaveArg<0>(&group)));
6050
6051 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6052 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
6053 .Times(1);
6054
6055 /*
6056 * StopStream will put calls on main_loop so to keep the correct order
6057 * of operations and to avoid races we put the test command on main_loop as
6058 * well.
6059 */
6060 do_in_main_thread(
6061 base::BindOnce([](LeAudioClient* client,
6062 const RawAddress& test_address0) { client->Disconnect(test_address0); },
6063 LeAudioClient::Get(), test_address0));
6064
6065 SyncOnMainLoop();
6066 Mock::VerifyAndClearExpectations(&mock_groups_module_);
6067 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6068 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6069
6070 ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
6071 }
6072
TEST_F(UnicastTest,DisconnecteWhileAlmostStreaming_twoDevices)6073 TEST_F(UnicastTest, DisconnecteWhileAlmostStreaming_twoDevices) {
6074 const RawAddress test_address0 = GetTestAddress(0);
6075 const RawAddress test_address1 = GetTestAddress(1);
6076 int group_id = 5;
6077
6078 TestSetupRemoteDevices(group_id);
6079 SyncOnMainLoop();
6080
6081 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(1);
6082
6083 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6084
6085 SyncOnMainLoop();
6086 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6087 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6088 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6089 SyncOnMainLoop();
6090
6091 ASSERT_NE(0lu, streaming_groups.count(group_id));
6092 auto group_inject = streaming_groups.at(group_id);
6093
6094 // This shall be called once only when first device from the group is disconnecting.
6095 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
6096
6097 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnConnectionState(ConnectionState::DISCONNECTED, _))
6098 .Times(0);
6099
6100 // Do not got to IDLE state imidiatelly.
6101 stay_at_releasing_stop_stream = true;
6102
6103 log::info("First of all disconnect: {}", test_address0);
6104 TriggerDisconnectionFromApp(test_address0);
6105 SyncOnMainLoop();
6106
6107 log::info("Secondly disconnect: {}", test_address1);
6108 TriggerDisconnectionFromApp(test_address1);
6109 SyncOnMainLoop();
6110
6111 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6112 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6113
6114 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6115 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
6116 .Times(1);
6117 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6118 OnConnectionState(ConnectionState::DISCONNECTED, test_address1))
6119 .Times(1);
6120
6121 do_in_main_thread(base::BindOnce(
6122 [](bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* cb, int group_id) {
6123 cb->StatusReportCb(group_id, GroupStreamStatus::IDLE);
6124 },
6125 state_machine_callbacks_, group_id));
6126 SyncOnMainLoop();
6127 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6128 }
6129
TEST_F(UnicastTest,EarbudsTwsStyleStreaming)6130 TEST_F(UnicastTest, EarbudsTwsStyleStreaming) {
6131 const RawAddress test_address0 = GetTestAddress(0);
6132 int group_id = bluetooth::groups::kGroupUnknown;
6133
6134 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6135 codec_spec_conf::kLeAudioLocationStereo, 0x01, 0x01,
6136 codec_spec_caps::kLeAudioSamplingFreq16000Hz, false /*add_csis*/,
6137 true /*add_cas*/, true /*add_pacs*/, 2 /*add_asc_cnt*/,
6138 1 /*set_size*/, 0 /*rank*/);
6139 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6140 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6141 .Times(1);
6142 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6143 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6144 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6145
6146 log::info("Connect device");
6147 ConnectLeAudio(test_address0);
6148 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6149
6150 // Expected CIS count on streaming
6151 uint8_t cis_count_out = 2;
6152 uint8_t cis_count_in = 0;
6153
6154 log::info("Group is getting Active");
6155 // Audio sessions are started only when device gets active
6156 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6157 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6158 LeAudioClient::Get()->GroupSetActive(group_id);
6159 SyncOnMainLoop();
6160
6161 log::info("Start stream");
6162 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6163
6164 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6165 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6166 SyncOnMainLoop();
6167
6168 log::info("Verify Data transfer on one audio source cis");
6169 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6170
6171 log::info("Suspend");
6172 EXPECT_CALL(mock_state_machine_, SuspendStream(_)).Times(1);
6173 LeAudioClient::Get()->GroupSuspend(group_id);
6174 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6175 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6176
6177 log::info("Resume");
6178 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6179 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6180 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6181
6182 log::info("Stop");
6183 StopStreaming(group_id);
6184 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6185
6186 // Release
6187 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6188 EXPECT_CALL(*mock_codec_manager_,
6189 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6190 mock_le_audio_sink_hal_client_, false))
6191 .Times(1);
6192
6193 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6194 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6195 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6196 SyncOnMainLoop();
6197 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6198 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6199 }
6200
TEST_F(UnicastTest,SpeakerFailedConversationalStreaming)6201 TEST_F(UnicastTest, SpeakerFailedConversationalStreaming) {
6202 const RawAddress test_address0 = GetTestAddress(0);
6203 int group_id = bluetooth::groups::kGroupUnknown;
6204
6205 available_src_context_types_ = 0;
6206 supported_src_context_types_ =
6207 available_src_context_types_ |
6208 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
6209 available_snk_context_types_ = 0x0004;
6210 supported_snk_context_types_ =
6211 available_snk_context_types_ |
6212 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
6213
6214 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo, 0,
6215 default_channel_cnt, default_channel_cnt, 0x0004,
6216 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
6217 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
6218 0 /*rank*/);
6219 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6220 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6221 .Times(1);
6222 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6223 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6224 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6225
6226 ConnectLeAudio(test_address0);
6227 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6228
6229 // Audio sessions are started only when device gets active
6230 LeAudioClient::Get()->GroupSetActive(group_id);
6231 SyncOnMainLoop();
6232
6233 /* Nothing to do - expect no crash */
6234 }
6235
TEST_F(UnicastTest,SpeakerStreaming)6236 TEST_F(UnicastTest, SpeakerStreaming) {
6237 const RawAddress test_address0 = GetTestAddress(0);
6238 int group_id = bluetooth::groups::kGroupUnknown;
6239
6240 SetSampleDatabaseEarbudsValid(
6241 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6242 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6243 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6244 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6245 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6246 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6247 .Times(1);
6248 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6249 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6250 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6251
6252 ConnectLeAudio(test_address0);
6253 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6254
6255 // Start streaming
6256 uint8_t cis_count_out = 1;
6257 uint8_t cis_count_in = 0;
6258
6259 // Audio sessions are started only when device gets active
6260 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6261 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6262 LeAudioClient::Get()->GroupSetActive(group_id);
6263 SyncOnMainLoop();
6264
6265 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6266
6267 SyncOnMainLoop();
6268 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6269 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6270
6271 // Verify Data transfer on one audio source cis
6272 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6273
6274 // Suspend
6275 /*TODO Need a way to verify STOP */
6276 LeAudioClient::Get()->GroupSuspend(group_id);
6277 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6278 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6279
6280 // Resume
6281 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6282 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6283 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6284
6285 // Stop
6286 StopStreaming(group_id);
6287 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6288
6289 // Release
6290 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6291
6292 EXPECT_CALL(*mock_codec_manager_,
6293 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6294 mock_le_audio_sink_hal_client_, false))
6295 .Times(1);
6296
6297 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6298 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6299 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6300 SyncOnMainLoop();
6301 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6302 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6303 }
6304
TEST_F(UnicastTest,SpeakerStreamingNonDefault)6305 TEST_F(UnicastTest, SpeakerStreamingNonDefault) {
6306 const RawAddress test_address0 = GetTestAddress(0);
6307 int group_id = bluetooth::groups::kGroupUnknown;
6308
6309 /**
6310 * Scenario test steps
6311 * 1. Set group active and stream VOICEASSISTANT
6312 * 2. Suspend group and resume with VOICEASSISTANT
6313 * 3. Stop Stream and make group inactive
6314 * 4. Start stream without setting metadata.
6315 * 5. Verify that UNSPECIFIED context type is used.
6316 */
6317
6318 available_snk_context_types_ =
6319 (types::LeAudioContextType::VOICEASSISTANTS | types::LeAudioContextType::MEDIA |
6320 types::LeAudioContextType::UNSPECIFIED)
6321 .value();
6322 supported_snk_context_types_ = available_snk_context_types_;
6323
6324 SetSampleDatabaseEarbudsValid(
6325 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6326 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6327 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6328 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6329 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6330 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6331 .Times(1);
6332 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6333 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6334 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6335
6336 ConnectLeAudio(test_address0);
6337 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6338
6339 // Start streaming
6340 uint8_t cis_count_out = 1;
6341 uint8_t cis_count_in = 0;
6342
6343 // Audio sessions are started only when device gets active
6344 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6345 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6346 LeAudioClient::Get()->GroupSetActive(group_id);
6347 SyncOnMainLoop();
6348
6349 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6350
6351 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6352 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6353 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6354 SyncOnMainLoop();
6355
6356 // Verify Data transfer on one audio source cis
6357 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6358
6359 // Suspend
6360 /*TODO Need a way to verify STOP */
6361 LeAudioClient::Get()->GroupSuspend(group_id);
6362 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6363 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6364
6365 // Resume
6366 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6367 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6368 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6369
6370 // Stop
6371 StopStreaming(group_id);
6372 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6373
6374 // Release
6375 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6376 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6377 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6378 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6379 SyncOnMainLoop();
6380 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6381
6382 /* When session is closed, the hal client mocks are freed - get new ones */
6383 SetUpMockAudioHal();
6384 /* Expect the previous release to clear the old audio session metadata */
6385 LeAudioClient::Get()->GroupSetActive(group_id);
6386 SyncOnMainLoop();
6387 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, _, _))
6388 .Times(0);
6389 EXPECT_CALL(mock_state_machine_, StartStream(_, kLeAudioDefaultConfigurationContext, _, _))
6390 .Times(1);
6391 LocalAudioSourceResume();
6392 }
6393
TEST_F(UnicastTest,TestUnidirectionalGameAndLiveRecording)6394 TEST_F(UnicastTest, TestUnidirectionalGameAndLiveRecording) {
6395 com::android::bluetooth::flags::provider_->le_audio_support_unidirectional_voice_assistant(true);
6396 const RawAddress test_address0 = GetTestAddress(0);
6397 int group_id = bluetooth::groups::kGroupUnknown;
6398
6399 /**
6400 * Scenario test steps
6401 * 1. Configure group to support GAME only on SINK
6402 * 2. Configure group to support LIVE
6403 * 3. Start recording with LIVE
6404 * 4. Update context type with GAME
6405 * 5. Verify that Configuration did not changed.
6406 */
6407
6408 available_snk_context_types_ =
6409 (types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA |
6410 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::LIVE)
6411 .value();
6412 supported_snk_context_types_ = available_snk_context_types_;
6413
6414 available_src_context_types_ =
6415 (types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED).value();
6416 supported_src_context_types_ = available_src_context_types_;
6417
6418 default_channel_cnt = 1;
6419
6420 SetSampleDatabaseEarbudsValid(
6421 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6422 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6423 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6424 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6425 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6426 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6427 .Times(1);
6428 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6429 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6430 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6431
6432 types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
6433 .sink = types::AudioContexts(types::LeAudioContextType::LIVE),
6434 .source = types::AudioContexts(types::LeAudioContextType::LIVE)};
6435 EXPECT_CALL(mock_state_machine_,
6436 StartStream(_, types::LeAudioContextType::LIVE, metadata_contexts, _))
6437 .Times(1);
6438
6439 log::info("Connecting LeAudio to {}", test_address0);
6440 ConnectLeAudio(test_address0);
6441 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6442
6443 // Audio sessions are started only when device gets active
6444 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6445 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6446
6447 EXPECT_CALL(*mock_codec_manager_,
6448 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6449 mock_le_audio_sink_hal_client_, true))
6450 .Times(1);
6451
6452 LeAudioClient::Get()->GroupSetActive(group_id);
6453 SyncOnMainLoop();
6454
6455 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
6456 LocalAudioSinkResume();
6457 SyncOnMainLoop();
6458
6459 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6460 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6461 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6462 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6463 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6464 SyncOnMainLoop();
6465
6466 // We do expect only unidirectional CIS
6467 uint8_t cis_count_out = 0;
6468 uint8_t cis_count_in = 1;
6469
6470 // Verify Data transfer on one local audio source cis
6471 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 0, 40);
6472 SyncOnMainLoop();
6473
6474 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
6475 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN);
6476 LocalAudioSourceResume();
6477 SyncOnMainLoop();
6478 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6479 }
6480
TEST_F(UnicastTest,TestUnidirectionalVoiceAssistant_Sink)6481 TEST_F(UnicastTest, TestUnidirectionalVoiceAssistant_Sink) {
6482 com::android::bluetooth::flags::provider_->le_audio_support_unidirectional_voice_assistant(true);
6483 const RawAddress test_address0 = GetTestAddress(0);
6484 int group_id = bluetooth::groups::kGroupUnknown;
6485
6486 /**
6487 * Scenario test steps
6488 * 1. Configure group to support VOICEASSISTANT only on SINK
6489 * 2. Start stream
6490 * 5. Verify that Unidirectional VOICEASSISTANT has been created
6491 */
6492
6493 available_snk_context_types_ =
6494 (types::LeAudioContextType::VOICEASSISTANTS | types::LeAudioContextType::MEDIA |
6495 types::LeAudioContextType::UNSPECIFIED)
6496 .value();
6497 supported_snk_context_types_ = available_snk_context_types_;
6498
6499 available_src_context_types_ =
6500 (types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED).value();
6501 supported_src_context_types_ = available_src_context_types_;
6502
6503 SetSampleDatabaseEarbudsValid(
6504 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6505 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6506 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6507 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6508 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6509 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6510 .Times(1);
6511 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6512 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6513 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6514
6515 types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
6516 .sink = types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS),
6517 .source = types::AudioContexts()};
6518 EXPECT_CALL(mock_state_machine_,
6519 StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, metadata_contexts, _))
6520 .Times(1);
6521
6522 log::info("Connecting LeAudio to {}", test_address0);
6523 ConnectLeAudio(test_address0);
6524 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6525
6526 // We do expect only unidirectional CIS
6527 uint8_t cis_count_out = 1;
6528 uint8_t cis_count_in = 0;
6529
6530 // Audio sessions are started only when device gets active
6531 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6532 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6533
6534 EXPECT_CALL(*mock_codec_manager_,
6535 UpdateActiveUnicastAudioHalClient(mock_le_audio_source_hal_client_,
6536 mock_le_audio_sink_hal_client_, true))
6537 .Times(1);
6538
6539 LeAudioClient::Get()->GroupSetActive(group_id);
6540 SyncOnMainLoop();
6541
6542 StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
6543
6544 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6545 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6546 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
6547 Mock::VerifyAndClearExpectations(mock_codec_manager_);
6548 SyncOnMainLoop();
6549
6550 // Verify Data transfer on one local audio source cis
6551 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6552 SyncOnMainLoop();
6553 }
6554
TEST_F(UnicastTest,TestUnidirectionalVoiceAssistant_Source)6555 TEST_F(UnicastTest, TestUnidirectionalVoiceAssistant_Source) {
6556 com::android::bluetooth::flags::provider_->le_audio_support_unidirectional_voice_assistant(true);
6557 const RawAddress test_address0 = GetTestAddress(0);
6558 int group_id = bluetooth::groups::kGroupUnknown;
6559
6560 /**
6561 * Scenario test steps
6562 * 1. Configure group to support VOICEASSISTANT only on SOURCE
6563 * 2. Start stream
6564 * 5. Verify that uni-direction VOICEASSISTANT has been created
6565 */
6566
6567 available_snk_context_types_ =
6568 (types::LeAudioContextType::MEDIA | types::LeAudioContextType::UNSPECIFIED).value();
6569 supported_snk_context_types_ = available_snk_context_types_;
6570
6571 available_src_context_types_ =
6572 (types::LeAudioContextType::VOICEASSISTANTS | types::LeAudioContextType::LIVE |
6573 types::LeAudioContextType::UNSPECIFIED)
6574 .value();
6575 supported_src_context_types_ = available_src_context_types_;
6576
6577 SetSampleDatabaseEarbudsValid(
6578 1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeftOfCenter,
6579 codec_spec_conf::kLeAudioLocationFrontLeftOfCenter, default_channel_cnt,
6580 default_channel_cnt, 0x0004,
6581 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6582 default_ase_cnt /*add_ascs_cnt*/, 2 /*set_size*/, 1 /*rank*/);
6583 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6584 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6585 .Times(1);
6586 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6587 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6588 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6589
6590 types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
6591 .sink = types::AudioContexts(),
6592 .source = types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS)};
6593 EXPECT_CALL(mock_state_machine_,
6594 StartStream(_, types::LeAudioContextType::VOICEASSISTANTS, metadata_contexts, _))
6595 .Times(1);
6596
6597 log::info("Connecting LeAudio device {}", test_address0);
6598
6599 ConnectLeAudio(test_address0);
6600 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6601
6602 // Expected only unidirectional CIS
6603 uint8_t cis_count_out = 0;
6604 uint8_t cis_count_in = 1;
6605
6606 // Audio sessions are started only when device gets active
6607 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6608 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6609 LeAudioClient::Get()->GroupSetActive(group_id);
6610 SyncOnMainLoop();
6611
6612 UpdateLocalSinkMetadata(AUDIO_SOURCE_VOICE_RECOGNITION);
6613 LocalAudioSinkResume();
6614
6615 // Verify Data transfer on one local audio source cis
6616 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
6617
6618 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6619 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6620 SyncOnMainLoop();
6621 }
6622
TEST_F(UnicastTest,SpeakerStreamingAutonomousRelease)6623 TEST_F(UnicastTest, SpeakerStreamingAutonomousRelease) {
6624 const RawAddress test_address0 = GetTestAddress(0);
6625 int group_id = bluetooth::groups::kGroupUnknown;
6626
6627 SetSampleDatabaseEarbudsValid(
6628 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
6629 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
6630 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
6631 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
6632 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6633 OnConnectionState(ConnectionState::CONNECTED, test_address0))
6634 .Times(1);
6635 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6636 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
6637 .WillOnce(DoAll(SaveArg<1>(&group_id)));
6638
6639 ConnectLeAudio(test_address0);
6640 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
6641
6642 // Start streaming
6643 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6644 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6645 LeAudioClient::Get()->GroupSetActive(group_id);
6646 SyncOnMainLoop();
6647
6648 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6649
6650 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6651 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6652 SyncOnMainLoop();
6653
6654 // Verify Data transfer on one audio source cis
6655 TestAudioDataTransfer(group_id, 1 /* cis_count_out */, 0 /* cis_count_in */, 1920);
6656
6657 // Inject the IDLE state as if an autonomous release happened
6658 ASSERT_NE(0lu, streaming_groups.count(group_id));
6659 auto group = streaming_groups.at(group_id);
6660 ASSERT_NE(group, nullptr);
6661 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
6662 device = group->GetNextDevice(device)) {
6663 for (auto& ase : device->ases_) {
6664 ase.cis_state = types::CisState::IDLE;
6665 ase.data_path_state = types::DataPathState::IDLE;
6666 ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
6667 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
6668 }
6669 }
6670
6671 // Verify no Data transfer after the autonomous release
6672 TestAudioDataTransfer(group_id, 0 /* cis_count_out */, 0 /* cis_count_in */, 1920);
6673 }
6674
TEST_F(UnicastTest,TwoEarbudsStreaming)6675 TEST_F(UnicastTest, TwoEarbudsStreaming) {
6676 uint8_t group_size = 2;
6677 int group_id = 2;
6678
6679 // Report working CSIS
6680 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
6681 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
6682 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
6683
6684 // First earbud
6685 const RawAddress test_address0 = GetTestAddress(0);
6686 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
6687 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
6688 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
6689
6690 // Second earbud
6691 const RawAddress test_address1 = GetTestAddress(1);
6692 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
6693 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
6694 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
6695 true /*connect_through_csis*/);
6696
6697 // Start streaming
6698 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
6699 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
6700 LeAudioClient::Get()->GroupSetActive(group_id);
6701 SyncOnMainLoop();
6702
6703 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6704
6705 /* Make sure configurations are non empty */
6706 btle_audio_codec_config_t call_config = {.codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6707 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
6708 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
6709 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
6710 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
6711 .octets_per_frame = 80};
6712
6713 EXPECT_CALL(mock_audio_hal_client_callbacks_,
6714 OnAudioGroupCurrentCodecConf(group_id, call_config, call_config))
6715 .Times(1);
6716
6717 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
6718
6719 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6720 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6721 SyncOnMainLoop();
6722
6723 // Verify Data transfer on two peer sinks and one source
6724 uint8_t cis_count_out = 2;
6725 uint8_t cis_count_in = 2;
6726 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
6727
6728 // Suspend
6729 LeAudioClient::Get()->GroupSuspend(group_id);
6730 SyncOnMainLoop();
6731
6732 // Resume
6733 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
6734 SyncOnMainLoop();
6735 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6736
6737 // Verify Data transfer still works
6738 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
6739
6740 ASSERT_NE(0lu, streaming_groups.count(group_id));
6741 auto group = streaming_groups.at(group_id);
6742
6743 // Stop
6744 StopStreaming(group_id, true);
6745 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6746
6747 // Check if cache configuration is still present
6748 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
6749 ->confs.get(le_audio::types::kLeAudioDirectionSink)
6750 .size());
6751 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
6752 ->confs.get(le_audio::types::kLeAudioDirectionSource)
6753 .size());
6754
6755 // Release
6756 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
6757 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
6758 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
6759 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
6760 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6761 SyncOnMainLoop();
6762
6763 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6764
6765 // Setting group inactive, shall not change cached configuration
6766 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
6767 ->confs.get(le_audio::types::kLeAudioDirectionSink)
6768 .size());
6769 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
6770 ->confs.get(le_audio::types::kLeAudioDirectionSource)
6771 .size());
6772 }
6773
TEST_F(UnicastTest,TestSetValidSingleOutputPreferredCodecConfig)6774 TEST_F(UnicastTest, TestSetValidSingleOutputPreferredCodecConfig) {
6775 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
6776
6777 btle_audio_codec_config_t preferred_output_codec_config = {
6778 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6779 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
6780 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
6781 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
6782 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
6783 .octets_per_frame = 60};
6784 // We did not set input preferred codec config
6785 btle_audio_codec_config_t empty_input_codec_config;
6786
6787 int group_id = 2;
6788 TestSetupRemoteDevices(group_id);
6789 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6790 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
6791 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6792
6793 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
6794 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
6795 false);
6796 do_in_main_thread(base::BindOnce(&LeAudioClient::SetCodecConfigPreference,
6797 base::Unretained(LeAudioClient::Get()), group_id,
6798 empty_input_codec_config, preferred_output_codec_config));
6799 SyncOnMainLoop();
6800 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
6801 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
6802 true);
6803 // We only set output preferred codec config so bidirectional context would
6804 // use default config
6805 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
6806 group_id, static_cast<int>(types::LeAudioContextType::CONVERSATIONAL)),
6807 false);
6808 }
6809
TEST_F(UnicastTest,TestSetPreferredCodecConfigToNonActiveGroup)6810 TEST_F(UnicastTest, TestSetPreferredCodecConfigToNonActiveGroup) {
6811 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
6812
6813 int group_id = 2;
6814 TestSetupRemoteDevices(group_id);
6815 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6816 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
6817 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
6818 false);
6819
6820 // Inactivate group 2
6821 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
6822
6823 btle_audio_codec_config_t preferred_codec_config = {
6824 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6825 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
6826 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
6827 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
6828 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
6829 .octets_per_frame = 40};
6830
6831 // Re-initialize mock for destroyed hal client
6832 RegisterSourceHalClientMock();
6833 RegisterSinkHalClientMock();
6834
6835 // Reconfiguration not needed as set preferred config to non active group
6836 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
6837 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0);
6838
6839 do_in_main_thread(base::BindOnce(&LeAudioClient::SetCodecConfigPreference,
6840 base::Unretained(LeAudioClient::Get()), group_id,
6841 preferred_codec_config, preferred_codec_config));
6842 SyncOnMainLoop();
6843
6844 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
6845 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
6846 true);
6847 Mock::VerifyAndClearExpectations(&mock_state_machine_);
6848 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
6849
6850 // Activate group 2 again
6851 do_in_main_thread(base::BindOnce(&LeAudioClient::GroupSetActive,
6852 base::Unretained(LeAudioClient::Get()), group_id));
6853 SyncOnMainLoop();
6854
6855 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
6856 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
6857 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
6858 true);
6859 }
6860
TEST_F(UnicastTest,TwoEarbudsClearPreferenceBeforeMedia)6861 TEST_F(UnicastTest, TwoEarbudsClearPreferenceBeforeMedia) {
6862 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
6863
6864 int group_id = 2;
6865 TestSetupRemoteDevices(group_id);
6866
6867 btle_audio_codec_config_t preferred_codec_config_before_media = {.codec_priority = -1};
6868
6869 bool set_before_media = true;
6870 bool set_while_media = false;
6871 bool is_using_set_before_media_codec_during_media = false;
6872 bool is_using_set_while_media_codec_during_media = false;
6873 // Use legacy codec and should not reconfig while streaming
6874 bool is_reconfig = false;
6875 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
6876 group_id, set_before_media, set_while_media,
6877 is_using_set_before_media_codec_during_media,
6878 is_using_set_while_media_codec_during_media, is_reconfig);
6879 }
6880
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessBeforeMedia)6881 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessBeforeMedia) {
6882 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
6883
6884 int group_id = 2;
6885 TestSetupRemoteDevices(group_id);
6886
6887 // This codec can be used by media
6888 btle_audio_codec_config_t preferred_codec_config_before_media = {
6889 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6890 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
6891 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
6892 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
6893 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
6894 .octets_per_frame = 40};
6895
6896 bool set_before_media = true;
6897 bool set_while_media = false;
6898 bool is_using_set_before_media_codec_during_media = true;
6899 bool is_using_set_while_media_codec_during_media = false;
6900 // Use preferred codec and should not reconfig while streaming
6901 bool is_reconfig = false;
6902 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
6903 group_id, set_before_media, set_while_media,
6904 is_using_set_before_media_codec_during_media,
6905 is_using_set_while_media_codec_during_media, is_reconfig);
6906 }
6907
TEST_F(UnicastTest,TwoEarbudsSetPreferenceFailBeforeMedia)6908 TEST_F(UnicastTest, TwoEarbudsSetPreferenceFailBeforeMedia) {
6909 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
6910
6911 int group_id = 2;
6912 TestSetupRemoteDevices(group_id);
6913
6914 // This codec can not be used by media
6915 btle_audio_codec_config_t preferred_codec_config_before_media = {
6916 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6917 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
6918 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
6919 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
6920 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
6921 .octets_per_frame = 70};
6922
6923 bool set_before_media = true;
6924 bool set_while_media = false;
6925 bool is_using_set_before_media_codec_during_media = false;
6926 bool is_using_set_while_media_codec_during_media = false;
6927 // Use legacy codec and should not reconfig while streaming
6928 bool is_reconfig = false;
6929 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
6930 group_id, set_before_media, set_while_media,
6931 is_using_set_before_media_codec_during_media,
6932 is_using_set_while_media_codec_during_media, is_reconfig);
6933 }
6934
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessDuringMediaWithReconfig)6935 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessDuringMediaWithReconfig) {
6936 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
6937
6938 int group_id = 2;
6939 TestSetupRemoteDevices(group_id);
6940
6941 // This codec can be used by media
6942 btle_audio_codec_config_t preferred_codec_config_during_media = {
6943 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6944 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
6945 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
6946 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
6947 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
6948 .octets_per_frame = 60};
6949
6950 bool set_before_media = false;
6951 bool set_while_media = true;
6952 bool is_using_set_before_media_codec_during_media = false;
6953 bool is_using_set_while_media_codec_during_media = true;
6954 // Should reconfig and use preferred codec while streaming
6955 bool is_reconfig = true;
6956 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
6957 group_id, set_before_media, set_while_media,
6958 is_using_set_before_media_codec_during_media,
6959 is_using_set_while_media_codec_during_media, is_reconfig);
6960 }
6961
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessDuringMediaWithoutReconfig)6962 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessDuringMediaWithoutReconfig) {
6963 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
6964
6965 int group_id = 2;
6966 TestSetupRemoteDevices(group_id);
6967
6968 // This codec can be used by media
6969 btle_audio_codec_config_t preferred_codec_config_during_media = {
6970 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6971 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ,
6972 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
6973 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
6974 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
6975 .octets_per_frame = 120};
6976
6977 bool set_before_media = false;
6978 bool set_while_media = true;
6979 bool is_using_set_before_media_codec_during_media = false;
6980 bool is_using_set_while_media_codec_during_media = true;
6981 // Use preferred codec but not reconfig while streaming since same codec with
6982 // original
6983 bool is_reconfig = false;
6984 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
6985 group_id, set_before_media, set_while_media,
6986 is_using_set_before_media_codec_during_media,
6987 is_using_set_while_media_codec_during_media, is_reconfig);
6988 }
6989
TEST_F(UnicastTest,TwoEarbudsSetPreferenceFailDuringMediaWithoutReconfig)6990 TEST_F(UnicastTest, TwoEarbudsSetPreferenceFailDuringMediaWithoutReconfig) {
6991 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
6992
6993 int group_id = 2;
6994 TestSetupRemoteDevices(group_id);
6995
6996 // This codec can not be used by media
6997 btle_audio_codec_config_t preferred_codec_config_during_media = {
6998 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
6999 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7000 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7001 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7002 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7003 .octets_per_frame = 70};
7004
7005 bool set_before_media = false;
7006 bool set_while_media = true;
7007 bool is_using_set_before_media_codec_during_media = false;
7008 bool is_using_set_while_media_codec_during_media = false;
7009 // Use original codec and should not reconfig while streaming
7010 bool is_reconfig = false;
7011 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
7012 group_id, set_before_media, set_while_media,
7013 is_using_set_before_media_codec_during_media,
7014 is_using_set_while_media_codec_during_media, is_reconfig);
7015 }
7016
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeMediaClearPreferenceDuringMediaWithReconfig)7017 TEST_F(UnicastTest,
7018 TwoEarbudsSetPreferenceSucessBeforeMediaClearPreferenceDuringMediaWithReconfig) {
7019 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7020
7021 int group_id = 2;
7022 TestSetupRemoteDevices(group_id);
7023
7024 // This codec can be used by media
7025 btle_audio_codec_config_t preferred_codec_config_before_media = {
7026 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7027 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7028 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7029 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7030 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7031 .octets_per_frame = 40};
7032 btle_audio_codec_config_t preferred_codec_config_during_media = {.codec_priority = -1};
7033
7034 bool set_before_media = true;
7035 bool set_while_media = true;
7036 bool is_using_set_before_media_codec_during_media = true;
7037 bool is_using_set_while_media_codec_during_media = false;
7038 // Should reconfig to legacy codec while streaming as we clear preferred codec
7039 bool is_reconfig = true;
7040 TestSetCodecPreference(&preferred_codec_config_before_media, &preferred_codec_config_during_media,
7041 LeAudioContextType::MEDIA, group_id, set_before_media, set_while_media,
7042 is_using_set_before_media_codec_during_media,
7043 is_using_set_while_media_codec_during_media, is_reconfig);
7044 }
7045
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceSuccessDuringMediaWithReconfig)7046 TEST_F(UnicastTest,
7047 TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceSuccessDuringMediaWithReconfig) {
7048 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7049
7050 int group_id = 2;
7051 TestSetupRemoteDevices(group_id);
7052
7053 // This codec can be used by media
7054 btle_audio_codec_config_t preferred_codec_config_before_media = {
7055 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7056 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7057 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7058 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7059 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7060 .octets_per_frame = 40};
7061 // This codec can be used by media
7062 btle_audio_codec_config_t preferred_codec_config_during_media = {
7063 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7064 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7065 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7066 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7067 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7068 .octets_per_frame = 60};
7069
7070 bool set_before_media = true;
7071 bool set_while_media = true;
7072 bool is_using_set_before_media_codec_during_media = true;
7073 bool is_using_set_while_media_codec_during_media = true;
7074 // Should reconfig to new preferred codec from old preferred codec while streaming
7075 bool is_reconfig = true;
7076 TestSetCodecPreference(&preferred_codec_config_before_media, &preferred_codec_config_during_media,
7077 LeAudioContextType::MEDIA, group_id, set_before_media, set_while_media,
7078 is_using_set_before_media_codec_during_media,
7079 is_using_set_while_media_codec_during_media, is_reconfig);
7080 }
7081
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceSuccessDuringMediaWithoutReconfig)7082 TEST_F(UnicastTest,
7083 TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceSuccessDuringMediaWithoutReconfig) {
7084 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7085
7086 int group_id = 2;
7087 TestSetupRemoteDevices(group_id);
7088
7089 // This codec can be used by media
7090 btle_audio_codec_config_t preferred_codec_config_before_media = {
7091 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7092 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7093 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7094 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7095 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7096 .octets_per_frame = 40};
7097 // This codec can be used by media
7098 btle_audio_codec_config_t preferred_codec_config_during_media = {
7099 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7100 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7101 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7102 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7103 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7104 .octets_per_frame = 40};
7105
7106 bool set_before_media = true;
7107 bool set_while_media = true;
7108 bool is_using_set_before_media_codec_during_media = true;
7109 bool is_using_set_while_media_codec_during_media = true;
7110 // Should not reconfig while streaming because same as previous preferred codec
7111 bool is_reconfig = false;
7112 TestSetCodecPreference(&preferred_codec_config_before_media, &preferred_codec_config_during_media,
7113 LeAudioContextType::MEDIA, group_id, set_before_media, set_while_media,
7114 is_using_set_before_media_codec_during_media,
7115 is_using_set_while_media_codec_during_media, is_reconfig);
7116 }
7117
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceFailDuringMediaWithReconfig)7118 TEST_F(UnicastTest,
7119 TwoEarbudsSetPreferenceSucessBeforeMediaSetPreferenceFailDuringMediaWithReconfig) {
7120 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7121
7122 int group_id = 2;
7123 TestSetupRemoteDevices(group_id);
7124
7125 // This codec can be used by media
7126 btle_audio_codec_config_t preferred_codec_config_before_media = {
7127 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7128 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7129 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7130 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7131 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7132 .octets_per_frame = 40};
7133 // This codec can not be used by media
7134 btle_audio_codec_config_t preferred_codec_config_during_media = {
7135 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7136 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7137 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7138 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7139 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7140 .octets_per_frame = 70};
7141
7142 bool set_before_media = true;
7143 bool set_while_media = true;
7144 bool is_using_set_before_media_codec_during_media = true;
7145 bool is_using_set_while_media_codec_during_media = false;
7146 // Should reconfig to legacy codec while streaming because invalid preferred codec
7147 bool is_reconfig = true;
7148 TestSetCodecPreference(&preferred_codec_config_before_media, &preferred_codec_config_during_media,
7149 LeAudioContextType::MEDIA, group_id, set_before_media, set_while_media,
7150 is_using_set_before_media_codec_during_media,
7151 is_using_set_while_media_codec_during_media, is_reconfig);
7152 }
7153
TEST_F(UnicastTest,TwoEarbudsClearPreferenceBeforeConv)7154 TEST_F(UnicastTest, TwoEarbudsClearPreferenceBeforeConv) {
7155 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7156
7157 int group_id = 2;
7158 TestSetupRemoteDevices(group_id);
7159
7160 btle_audio_codec_config_t preferred_codec_config_before_conv = {.codec_priority = -1};
7161
7162 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7163 LeAudioClient::Get()->SetInCall(true);
7164
7165 bool set_before_conv = true;
7166 bool set_while_conv = false;
7167 bool is_using_set_before_conv_codec_during_conv = false;
7168 bool is_using_set_while_conv_codec_during_conv = false;
7169 // Use legacy codec and should not reconfig while streaming
7170 bool is_reconfig = false;
7171 TestSetCodecPreference(&preferred_codec_config_before_conv, nullptr,
7172 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7173 set_while_conv, is_using_set_before_conv_codec_during_conv,
7174 is_using_set_while_conv_codec_during_conv, is_reconfig);
7175 LeAudioClient::Get()->SetInCall(false);
7176 }
7177
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessBeforeConv)7178 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessBeforeConv) {
7179 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7180
7181 int group_id = 2;
7182 TestSetupRemoteDevices(group_id);
7183
7184 // This codec can be used by conv
7185 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7186 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7187 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7188 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7189 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7190 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7191 .octets_per_frame = 40};
7192
7193 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7194 LeAudioClient::Get()->SetInCall(true);
7195
7196 bool set_before_conv = true;
7197 bool set_while_conv = false;
7198 bool is_using_set_before_conv_codec_during_conv = true;
7199 bool is_using_set_while_conv_codec_during_conv = false;
7200 // Use preferred codec and should not reconfig while streaming
7201 bool is_reconfig = false;
7202 TestSetCodecPreference(&preferred_codec_config_before_conv, nullptr,
7203 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7204 set_while_conv, is_using_set_before_conv_codec_during_conv,
7205 is_using_set_while_conv_codec_during_conv, is_reconfig);
7206 LeAudioClient::Get()->SetInCall(false);
7207 }
7208
TEST_F(UnicastTest,TwoEarbudsSetPreferenceFailBeforeConv)7209 TEST_F(UnicastTest, TwoEarbudsSetPreferenceFailBeforeConv) {
7210 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7211
7212 int group_id = 2;
7213 TestSetupRemoteDevices(group_id);
7214
7215 // This codec can not be used by conv
7216 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7217 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7218 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7219 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7220 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7221 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7222 .octets_per_frame = 70};
7223
7224 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7225 LeAudioClient::Get()->SetInCall(true);
7226
7227 bool set_before_conv = true;
7228 bool set_while_conv = false;
7229 bool is_using_set_before_conv_codec_during_conv = false;
7230 bool is_using_set_while_conv_codec_during_conv = false;
7231 // Use legacy codec and should not reconfig while streaming
7232 bool is_reconfig = false;
7233 TestSetCodecPreference(&preferred_codec_config_before_conv, nullptr,
7234 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7235 set_while_conv, is_using_set_before_conv_codec_during_conv,
7236 is_using_set_while_conv_codec_during_conv, is_reconfig);
7237 LeAudioClient::Get()->SetInCall(false);
7238 }
7239
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessDuringConvWithReconfig)7240 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessDuringConvWithReconfig) {
7241 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7242
7243 int group_id = 2;
7244 TestSetupRemoteDevices(group_id);
7245
7246 // This codec can be used by conv
7247 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7248 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7249 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7250 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7251 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7252 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7253 .octets_per_frame = 40};
7254
7255 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7256 LeAudioClient::Get()->SetInCall(true);
7257
7258 bool set_before_conv = false;
7259 bool set_while_conv = true;
7260 bool is_using_set_before_conv_codec_during_conv = false;
7261 bool is_using_set_while_conv_codec_during_conv = true;
7262 // Should reconfig and use preferred codec while streaming
7263 bool is_reconfig = true;
7264 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
7265 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7266 set_while_conv, is_using_set_before_conv_codec_during_conv,
7267 is_using_set_while_conv_codec_during_conv, is_reconfig);
7268 LeAudioClient::Get()->SetInCall(false);
7269 }
7270
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSuccessDuringConvWithoutReconfig)7271 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSuccessDuringConvWithoutReconfig) {
7272 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7273
7274 int group_id = 2;
7275 TestSetupRemoteDevices(group_id);
7276
7277 // This codec can be used by conv
7278 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7279 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7280 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
7281 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7282 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7283 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7284 .octets_per_frame = 80};
7285
7286 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7287 LeAudioClient::Get()->SetInCall(true);
7288
7289 bool set_before_conv = false;
7290 bool set_while_conv = true;
7291 bool is_using_set_before_conv_codec_during_conv = false;
7292 bool is_using_set_while_conv_codec_during_conv = true;
7293 // Use preferred codec but not reconfig while streaming since same codec with
7294 // original
7295 bool is_reconfig = false;
7296 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
7297 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7298 set_while_conv, is_using_set_before_conv_codec_during_conv,
7299 is_using_set_while_conv_codec_during_conv, is_reconfig);
7300 LeAudioClient::Get()->SetInCall(false);
7301 }
7302
TEST_F(UnicastTest,TwoEarbudsSetPreferenceFailDuringConvWithoutReconfig)7303 TEST_F(UnicastTest, TwoEarbudsSetPreferenceFailDuringConvWithoutReconfig) {
7304 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7305
7306 int group_id = 2;
7307 TestSetupRemoteDevices(group_id);
7308
7309 // This codec can not be used by conv
7310 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7311 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7312 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7313 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7314 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7315 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7316 .octets_per_frame = 70};
7317
7318 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7319 LeAudioClient::Get()->SetInCall(true);
7320
7321 bool set_before_conv = false;
7322 bool set_while_conv = true;
7323 bool is_using_set_before_conv_codec_during_conv = false;
7324 bool is_using_set_while_conv_codec_during_conv = false;
7325 // Use original codec and should not reconfig while streaming
7326 bool is_reconfig = false;
7327 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
7328 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7329 set_while_conv, is_using_set_before_conv_codec_during_conv,
7330 is_using_set_while_conv_codec_during_conv, is_reconfig);
7331 LeAudioClient::Get()->SetInCall(false);
7332 }
7333
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeConvClearPreferenceDuringConvWithReconfig)7334 TEST_F(UnicastTest, TwoEarbudsSetPreferenceSucessBeforeConvClearPreferenceDuringConvWithReconfig) {
7335 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7336
7337 int group_id = 2;
7338 TestSetupRemoteDevices(group_id);
7339
7340 // This codec can be used by conv
7341 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7342 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7343 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7344 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7345 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7346 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7347 .octets_per_frame = 40};
7348 btle_audio_codec_config_t preferred_codec_config_during_conv = {.codec_priority = -1};
7349
7350 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7351 LeAudioClient::Get()->SetInCall(true);
7352
7353 bool set_before_conv = true;
7354 bool set_while_conv = true;
7355 bool is_using_set_before_conv_codec_during_conv = true;
7356 bool is_using_set_while_conv_codec_during_conv = false;
7357 // Should reconfig to legacy codec while streaming as we clear preferred codec
7358 bool is_reconfig = true;
7359 TestSetCodecPreference(&preferred_codec_config_before_conv, &preferred_codec_config_during_conv,
7360 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7361 set_while_conv, is_using_set_before_conv_codec_during_conv,
7362 is_using_set_while_conv_codec_during_conv, is_reconfig);
7363 LeAudioClient::Get()->SetInCall(false);
7364 }
7365
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceSuccessDuringConvWithReconfig)7366 TEST_F(UnicastTest,
7367 TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceSuccessDuringConvWithReconfig) {
7368 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7369
7370 int group_id = 2;
7371 TestSetupRemoteDevices(group_id);
7372
7373 // This codec can be used by conv
7374 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7375 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7376 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7377 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7378 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7379 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7380 .octets_per_frame = 40};
7381 // This codec can be used by conv
7382 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7383 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7384 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
7385 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7386 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7387 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7388 .octets_per_frame = 80};
7389
7390 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7391 LeAudioClient::Get()->SetInCall(true);
7392
7393 bool set_before_conv = true;
7394 bool set_while_conv = true;
7395 bool is_using_set_before_conv_codec_during_conv = true;
7396 bool is_using_set_while_conv_codec_during_conv = true;
7397 // Should reconfig to new preferred codec from old preferred codec while
7398 // streaming
7399 bool is_reconfig = true;
7400 TestSetCodecPreference(&preferred_codec_config_before_conv, &preferred_codec_config_during_conv,
7401 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7402 set_while_conv, is_using_set_before_conv_codec_during_conv,
7403 is_using_set_while_conv_codec_during_conv, is_reconfig);
7404 LeAudioClient::Get()->SetInCall(false);
7405 }
7406
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceSuccessDuringConvWithoutReconfig)7407 TEST_F(UnicastTest,
7408 TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceSuccessDuringConvWithoutReconfig) {
7409 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7410
7411 int group_id = 2;
7412 TestSetupRemoteDevices(group_id);
7413
7414 // This codec can be used by conv
7415 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7416 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7417 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7418 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7419 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7420 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7421 .octets_per_frame = 40};
7422 // This codec can be used by conv
7423 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7424 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7425 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7426 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7427 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7428 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7429 .octets_per_frame = 40};
7430
7431 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7432 LeAudioClient::Get()->SetInCall(true);
7433
7434 bool set_before_conv = true;
7435 bool set_while_conv = true;
7436 bool is_using_set_before_conv_codec_during_conv = true;
7437 bool is_using_set_while_conv_codec_during_conv = true;
7438 // Should not reconfig while streaming because same as previous preferred
7439 // codec
7440 bool is_reconfig = false;
7441 TestSetCodecPreference(&preferred_codec_config_before_conv, &preferred_codec_config_during_conv,
7442 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7443 set_while_conv, is_using_set_before_conv_codec_during_conv,
7444 is_using_set_while_conv_codec_during_conv, is_reconfig);
7445 LeAudioClient::Get()->SetInCall(false);
7446 }
7447
TEST_F(UnicastTest,TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceFailDuringConvWithReconfig)7448 TEST_F(UnicastTest,
7449 TwoEarbudsSetPreferenceSucessBeforeConvSetPreferenceFailDuringConvWithReconfig) {
7450 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7451
7452 int group_id = 2;
7453 TestSetupRemoteDevices(group_id);
7454
7455 // This codec can be used by conv
7456 btle_audio_codec_config_t preferred_codec_config_before_conv = {
7457 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7458 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7459 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7460 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7461 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7462 .octets_per_frame = 40};
7463 // This codec can not be used by conv
7464 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7465 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7466 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7467 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7468 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7469 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7470 .octets_per_frame = 70};
7471
7472 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7473 LeAudioClient::Get()->SetInCall(true);
7474
7475 bool set_before_conv = true;
7476 bool set_while_conv = true;
7477 bool is_using_set_before_conv_codec_during_conv = true;
7478 bool is_using_set_while_conv_codec_during_conv = false;
7479 // Should reconfig to legacy codec while streaming because invalid preferred
7480 // codec
7481 bool is_reconfig = true;
7482 TestSetCodecPreference(&preferred_codec_config_before_conv, &preferred_codec_config_during_conv,
7483 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7484 set_while_conv, is_using_set_before_conv_codec_during_conv,
7485 is_using_set_while_conv_codec_during_conv, is_reconfig);
7486 LeAudioClient::Get()->SetInCall(false);
7487 }
7488
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenIdleForBothMediaAndConv)7489 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenIdleForBothMediaAndConv) {
7490 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7491
7492 int group_id = 2;
7493 TestSetupRemoteDevices(group_id);
7494
7495 // This codec can be used by media and conv
7496 btle_audio_codec_config_t preferred_codec_config_before_media = {
7497 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7498 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7499 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7500 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7501 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7502 .octets_per_frame = 40};
7503
7504 bool set_before_media = true;
7505 bool set_while_media = false;
7506 bool is_using_set_before_media_codec_during_media = true;
7507 bool is_using_set_while_media_codec_during_media = false;
7508 bool is_reconfig = false;
7509 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7510 group_id, set_before_media, set_while_media,
7511 is_using_set_before_media_codec_during_media,
7512 is_using_set_while_media_codec_during_media, is_reconfig);
7513
7514 // simulate suspend timeout passed, alarm executing
7515 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7516 SyncOnMainLoop();
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 = false;
7522 bool set_while_conv = false;
7523 bool is_using_set_before_conv_codec_during_conv = true;
7524 bool is_using_set_while_conv_codec_during_conv = false;
7525 is_reconfig = false;
7526 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7527 set_before_conv, set_while_conv,
7528 is_using_set_before_conv_codec_during_conv,
7529 is_using_set_while_conv_codec_during_conv, is_reconfig);
7530 LeAudioClient::Get()->SetInCall(false);
7531
7532 // should use preferred codec when switching back to media
7533 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7534 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7535 true);
7536 }
7537
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenIdleForMediaNotForConv)7538 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenIdleForMediaNotForConv) {
7539 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7540
7541 int group_id = 2;
7542 TestSetupRemoteDevices(group_id);
7543
7544 // This codec can be used by media but not by conv
7545 btle_audio_codec_config_t preferred_codec_config_before_media = {
7546 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7547 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7548 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7549 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7550 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7551 .octets_per_frame = 60};
7552
7553 bool set_before_media = true;
7554 bool set_while_media = false;
7555 bool is_using_set_before_media_codec_during_media = true;
7556 bool is_using_set_while_media_codec_during_media = false;
7557 bool is_reconfig = false;
7558 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7559 group_id, set_before_media, set_while_media,
7560 is_using_set_before_media_codec_during_media,
7561 is_using_set_while_media_codec_during_media, is_reconfig);
7562
7563 // simulate suspend timeout passed, alarm executing
7564 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7565 SyncOnMainLoop();
7566
7567 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7568 LeAudioClient::Get()->SetInCall(true);
7569
7570 bool set_before_conv = false;
7571 bool set_while_conv = false;
7572 bool is_using_set_before_conv_codec_during_conv = false;
7573 bool is_using_set_while_conv_codec_during_conv = false;
7574 is_reconfig = false;
7575 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7576 set_before_conv, set_while_conv,
7577 is_using_set_before_conv_codec_during_conv,
7578 is_using_set_while_conv_codec_during_conv, is_reconfig);
7579 LeAudioClient::Get()->SetInCall(false);
7580
7581 // should use preferred codec when switching back to media
7582 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7583 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7584 true);
7585 }
7586
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenIdleNotForMediaForConv)7587 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenIdleNotForMediaForConv) {
7588 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7589
7590 int group_id = 2;
7591 TestSetupRemoteDevices(group_id);
7592
7593 // This codec can not be used by media but by conv
7594 btle_audio_codec_config_t preferred_codec_config_before_media = {
7595 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7596 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
7597 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7598 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7599 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7600 .octets_per_frame = 80};
7601
7602 bool set_before_media = true;
7603 bool set_while_media = false;
7604 bool is_using_set_before_media_codec_during_media = false;
7605 bool is_using_set_while_media_codec_during_media = false;
7606 bool is_reconfig = false;
7607 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7608 group_id, set_before_media, set_while_media,
7609 is_using_set_before_media_codec_during_media,
7610 is_using_set_while_media_codec_during_media, is_reconfig);
7611
7612 // simulate suspend timeout passed, alarm executing
7613 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7614 SyncOnMainLoop();
7615
7616 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7617 LeAudioClient::Get()->SetInCall(true);
7618
7619 bool set_before_conv = false;
7620 bool set_while_conv = false;
7621 bool is_using_set_before_conv_codec_during_conv = true;
7622 bool is_using_set_while_conv_codec_during_conv = false;
7623 is_reconfig = false;
7624 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7625 set_before_conv, set_while_conv,
7626 is_using_set_before_conv_codec_during_conv,
7627 is_using_set_while_conv_codec_during_conv, is_reconfig);
7628 LeAudioClient::Get()->SetInCall(false);
7629
7630 // should use legacy codec when switching back to media
7631 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7632 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7633 false);
7634 }
7635
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenIdleNotForBothMediaAndConv)7636 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenIdleNotForBothMediaAndConv) {
7637 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7638
7639 int group_id = 2;
7640 TestSetupRemoteDevices(group_id);
7641
7642 // This codec can not be used by media and conv
7643 btle_audio_codec_config_t preferred_codec_config_before_media = {
7644 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7645 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7646 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7647 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7648 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7649 .octets_per_frame = 10};
7650
7651 bool set_before_media = true;
7652 bool set_while_media = false;
7653 bool is_using_set_before_media_codec_during_media = false;
7654 bool is_using_set_while_media_codec_during_media = false;
7655 bool is_reconfig = false;
7656 TestSetCodecPreference(&preferred_codec_config_before_media, nullptr, LeAudioContextType::MEDIA,
7657 group_id, set_before_media, set_while_media,
7658 is_using_set_before_media_codec_during_media,
7659 is_using_set_while_media_codec_during_media, is_reconfig);
7660
7661 // simulate suspend timeout passed, alarm executing
7662 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7663 SyncOnMainLoop();
7664
7665 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7666 LeAudioClient::Get()->SetInCall(true);
7667
7668 bool set_before_conv = false;
7669 bool set_while_conv = false;
7670 bool is_using_set_before_conv_codec_during_conv = false;
7671 bool is_using_set_while_conv_codec_during_conv = false;
7672 is_reconfig = false;
7673 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7674 set_before_conv, set_while_conv,
7675 is_using_set_before_conv_codec_during_conv,
7676 is_using_set_while_conv_codec_during_conv, is_reconfig);
7677 LeAudioClient::Get()->SetInCall(false);
7678
7679 // should use legacy codec when switching back to media
7680 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7681 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7682 false);
7683 }
7684
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenMediaForBothMediaAndConv)7685 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaForBothMediaAndConv) {
7686 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7687
7688 int group_id = 2;
7689 TestSetupRemoteDevices(group_id);
7690
7691 // This codec can be used by media and conv
7692 btle_audio_codec_config_t preferred_codec_config_during_media = {
7693 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7694 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7695 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7696 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7697 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7698 .octets_per_frame = 40};
7699
7700 bool set_before_media = false;
7701 bool set_while_media = true;
7702 bool is_using_set_before_media_codec_during_media = false;
7703 bool is_using_set_while_media_codec_during_media = true;
7704 // should use preferred codec and reconfig
7705 bool is_reconfig = true;
7706 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
7707 group_id, set_before_media, set_while_media,
7708 is_using_set_before_media_codec_during_media,
7709 is_using_set_while_media_codec_during_media, is_reconfig);
7710
7711 log::info("simulate suspend timeout passed, alarm executing");
7712 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7713 SyncOnMainLoop();
7714
7715 log::info("SetInCall is used by GTBS - and only then we can expect CCID to be set.");
7716 LeAudioClient::Get()->SetInCall(true);
7717
7718 bool set_before_conv = false;
7719 bool set_while_conv = false;
7720 bool is_using_set_before_conv_codec_during_conv = true;
7721 bool is_using_set_while_conv_codec_during_conv = false;
7722 is_reconfig = false;
7723 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7724 set_before_conv, set_while_conv,
7725 is_using_set_before_conv_codec_during_conv,
7726 is_using_set_while_conv_codec_during_conv, is_reconfig);
7727 LeAudioClient::Get()->SetInCall(false);
7728
7729 log::info("should use preferred codec when switching back to media");
7730 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7731 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7732 true);
7733 }
7734
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenMediaForMediaNotForConv)7735 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaForMediaNotForConv) {
7736 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7737
7738 int group_id = 2;
7739 TestSetupRemoteDevices(group_id);
7740
7741 // This codec can be used by media but not by conv
7742 btle_audio_codec_config_t preferred_codec_config_during_media = {
7743 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7744 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7745 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7746 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7747 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7748 .octets_per_frame = 60};
7749
7750 bool set_before_media = false;
7751 bool set_while_media = true;
7752 bool is_using_set_before_media_codec_during_media = false;
7753 bool is_using_set_while_media_codec_during_media = true;
7754 // should use preferred codec and reconfig
7755 bool is_reconfig = true;
7756 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
7757 group_id, set_before_media, set_while_media,
7758 is_using_set_before_media_codec_during_media,
7759 is_using_set_while_media_codec_during_media, is_reconfig);
7760
7761 // simulate suspend timeout passed, alarm executing
7762 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7763 SyncOnMainLoop();
7764
7765 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7766 LeAudioClient::Get()->SetInCall(true);
7767
7768 bool set_before_conv = false;
7769 bool set_while_conv = false;
7770 bool is_using_set_before_conv_codec_during_conv = false;
7771 bool is_using_set_while_conv_codec_during_conv = false;
7772 is_reconfig = false;
7773 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7774 set_before_conv, set_while_conv,
7775 is_using_set_before_conv_codec_during_conv,
7776 is_using_set_while_conv_codec_during_conv, is_reconfig);
7777 LeAudioClient::Get()->SetInCall(false);
7778
7779 // should use preferred codec when switching back to media
7780 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7781 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7782 true);
7783 }
7784
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenMediaNotForMediaForConv)7785 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaNotForMediaForConv) {
7786 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7787
7788 int group_id = 2;
7789 TestSetupRemoteDevices(group_id);
7790
7791 // This codec can not be used by media and but by conv
7792 btle_audio_codec_config_t preferred_codec_config_during_media = {
7793 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7794 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
7795 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7796 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7797 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7798 .octets_per_frame = 80};
7799
7800 bool set_before_media = false;
7801 bool set_while_media = true;
7802 bool is_using_set_before_media_codec_during_media = false;
7803 bool is_using_set_while_media_codec_during_media = false;
7804 // should use legacy codec
7805 bool is_reconfig = false;
7806 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
7807 group_id, set_before_media, set_while_media,
7808 is_using_set_before_media_codec_during_media,
7809 is_using_set_while_media_codec_during_media, is_reconfig);
7810
7811 // simulate suspend timeout passed, alarm executing
7812 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7813 SyncOnMainLoop();
7814
7815 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7816 LeAudioClient::Get()->SetInCall(true);
7817
7818 bool set_before_conv = false;
7819 bool set_while_conv = false;
7820 bool is_using_set_before_conv_codec_during_conv = true;
7821 bool is_using_set_while_conv_codec_during_conv = false;
7822 is_reconfig = false;
7823 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7824 set_before_conv, set_while_conv,
7825 is_using_set_before_conv_codec_during_conv,
7826 is_using_set_while_conv_codec_during_conv, is_reconfig);
7827 LeAudioClient::Get()->SetInCall(false);
7828
7829 // should use legacy codec when switching back to media
7830 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7831 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7832 false);
7833 }
7834
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenMediaNotForBothMediaAndConv)7835 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenMediaNotForBothMediaAndConv) {
7836 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7837
7838 int group_id = 2;
7839 TestSetupRemoteDevices(group_id);
7840
7841 // This codec can not be used by media and conv
7842 btle_audio_codec_config_t preferred_codec_config_during_media = {
7843 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7844 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7845 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7846 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7847 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7848 .octets_per_frame = 70};
7849
7850 bool set_before_media = false;
7851 bool set_while_media = true;
7852 bool is_using_set_before_media_codec_during_media = false;
7853 bool is_using_set_while_media_codec_during_media = false;
7854 // should use legacy codec
7855 bool is_reconfig = false;
7856 TestSetCodecPreference(nullptr, &preferred_codec_config_during_media, LeAudioContextType::MEDIA,
7857 group_id, set_before_media, set_while_media,
7858 is_using_set_before_media_codec_during_media,
7859 is_using_set_while_media_codec_during_media, is_reconfig);
7860
7861 // simulate suspend timeout passed, alarm executing
7862 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7863 SyncOnMainLoop();
7864
7865 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7866 LeAudioClient::Get()->SetInCall(true);
7867
7868 bool set_before_conv = false;
7869 bool set_while_conv = false;
7870 bool is_using_set_before_conv_codec_during_conv = false;
7871 bool is_using_set_while_conv_codec_during_conv = false;
7872 is_reconfig = false;
7873 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::CONVERSATIONAL, group_id,
7874 set_before_conv, set_while_conv,
7875 is_using_set_before_conv_codec_during_conv,
7876 is_using_set_while_conv_codec_during_conv, is_reconfig);
7877 LeAudioClient::Get()->SetInCall(false);
7878
7879 // should use legacy codec when switching back to media
7880 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7881 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7882 false);
7883 }
7884
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenConvForBothMediaAndConv)7885 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenConvForBothMediaAndConv) {
7886 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7887
7888 int group_id = 2;
7889 TestSetupRemoteDevices(group_id);
7890
7891 bool set_before_media = false;
7892 bool set_while_media = false;
7893 bool is_using_set_before_media_codec_during_media = false;
7894 bool is_using_set_while_media_codec_during_media = false;
7895 bool is_reconfig = false;
7896 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::MEDIA, group_id, set_before_media,
7897 set_while_media, is_using_set_before_media_codec_during_media,
7898 is_using_set_while_media_codec_during_media, is_reconfig);
7899
7900 // simulate suspend timeout passed, alarm executing
7901 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7902 SyncOnMainLoop();
7903
7904 // This codec can be used by media and conv
7905 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7906 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7907 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ,
7908 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7909 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7910 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7911 .octets_per_frame = 40};
7912
7913 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7914 LeAudioClient::Get()->SetInCall(true);
7915
7916 bool set_before_conv = false;
7917 bool set_while_conv = true;
7918 bool is_using_set_before_conv_codec_during_conv = false;
7919 bool is_using_set_while_conv_codec_during_conv = true;
7920 // should use preferred codec and reconfig
7921 is_reconfig = true;
7922 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
7923 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7924 set_while_conv, is_using_set_before_conv_codec_during_conv,
7925 is_using_set_while_conv_codec_during_conv, is_reconfig);
7926 LeAudioClient::Get()->SetInCall(false);
7927
7928 // should use preferred codec when switching back to media
7929 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7930 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7931 true);
7932 }
7933
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenConvForMediaNotForConv)7934 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenConvForMediaNotForConv) {
7935 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7936
7937 int group_id = 2;
7938 TestSetupRemoteDevices(group_id);
7939
7940 bool set_before_media = false;
7941 bool set_while_media = false;
7942 bool is_using_set_before_media_codec_during_media = false;
7943 bool is_using_set_while_media_codec_during_media = false;
7944 bool is_reconfig = false;
7945 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::MEDIA, group_id, set_before_media,
7946 set_while_media, is_using_set_before_media_codec_during_media,
7947 is_using_set_while_media_codec_during_media, is_reconfig);
7948
7949 // simulate suspend timeout passed, alarm executing
7950 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
7951 SyncOnMainLoop();
7952
7953 // This codec can be used by media but not by conv
7954 btle_audio_codec_config_t preferred_codec_config_during_conv = {
7955 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
7956 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
7957 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
7958 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
7959 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
7960 .octets_per_frame = 60};
7961
7962 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
7963 LeAudioClient::Get()->SetInCall(true);
7964
7965 bool set_before_conv = false;
7966 bool set_while_conv = true;
7967 bool is_using_set_before_conv_codec_during_conv = false;
7968 bool is_using_set_while_conv_codec_during_conv = false;
7969 // should use legacy codec
7970 is_reconfig = false;
7971 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
7972 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
7973 set_while_conv, is_using_set_before_conv_codec_during_conv,
7974 is_using_set_while_conv_codec_during_conv, is_reconfig);
7975 LeAudioClient::Get()->SetInCall(false);
7976
7977 // should use preferred codec when switching back to media
7978 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
7979 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
7980 true);
7981 }
7982
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenConvNotForMediaForConv)7983 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenConvNotForMediaForConv) {
7984 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
7985
7986 int group_id = 2;
7987 TestSetupRemoteDevices(group_id);
7988
7989 bool set_before_media = false;
7990 bool set_while_media = false;
7991 bool is_using_set_before_media_codec_during_media = false;
7992 bool is_using_set_while_media_codec_during_media = false;
7993 bool is_reconfig = false;
7994 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::MEDIA, group_id, set_before_media,
7995 set_while_media, is_using_set_before_media_codec_during_media,
7996 is_using_set_while_media_codec_during_media, is_reconfig);
7997
7998 // simulate suspend timeout passed, alarm executing
7999 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8000 SyncOnMainLoop();
8001
8002 // This codec can not be used by media but by conv
8003 btle_audio_codec_config_t preferred_codec_config_during_conv = {
8004 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8005 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ,
8006 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8007 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8008 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8009 .octets_per_frame = 80};
8010
8011 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8012 LeAudioClient::Get()->SetInCall(true);
8013
8014 bool set_before_conv = false;
8015 bool set_while_conv = true;
8016 bool is_using_set_before_conv_codec_during_conv = false;
8017 bool is_using_set_while_conv_codec_during_conv = true;
8018 // should use preferred codec but not reconfig
8019 is_reconfig = false;
8020 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
8021 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
8022 set_while_conv, is_using_set_before_conv_codec_during_conv,
8023 is_using_set_while_conv_codec_during_conv, is_reconfig);
8024 LeAudioClient::Get()->SetInCall(false);
8025
8026 // should use legacy codec when switching back to media
8027 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8028 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8029 false);
8030 }
8031
TEST_F(UnicastTest,TwoEarbudsSetPreferenceWhenConvNotForBothMediaAndConv)8032 TEST_F(UnicastTest, TwoEarbudsSetPreferenceWhenConvNotForBothMediaAndConv) {
8033 com::android::bluetooth::flags::provider_->leaudio_set_codec_config_preference(true);
8034
8035 int group_id = 2;
8036 TestSetupRemoteDevices(group_id);
8037
8038 bool set_before_media = false;
8039 bool set_while_media = false;
8040 bool is_using_set_before_media_codec_during_media = false;
8041 bool is_using_set_while_media_codec_during_media = false;
8042 bool is_reconfig = false;
8043 TestSetCodecPreference(nullptr, nullptr, LeAudioContextType::MEDIA, group_id, set_before_media,
8044 set_while_media, is_using_set_before_media_codec_during_media,
8045 is_using_set_while_media_codec_during_media, is_reconfig);
8046
8047 // simulate suspend timeout passed, alarm executing
8048 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8049 SyncOnMainLoop();
8050
8051 // This codec can not be used by media and conv
8052 btle_audio_codec_config_t preferred_codec_config_during_conv = {
8053 .codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_LC3,
8054 .sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ,
8055 .bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_16,
8056 .channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_1,
8057 .frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_10000US,
8058 .octets_per_frame = 70};
8059
8060 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8061 LeAudioClient::Get()->SetInCall(true);
8062
8063 bool set_before_conv = false;
8064 bool set_while_conv = true;
8065 bool is_using_set_before_conv_codec_during_conv = false;
8066 bool is_using_set_while_conv_codec_during_conv = false;
8067 // should use legacy codec
8068 is_reconfig = false;
8069 TestSetCodecPreference(nullptr, &preferred_codec_config_during_conv,
8070 LeAudioContextType::CONVERSATIONAL, group_id, set_before_conv,
8071 set_while_conv, is_using_set_before_conv_codec_during_conv,
8072 is_using_set_while_conv_codec_during_conv, is_reconfig);
8073 LeAudioClient::Get()->SetInCall(false);
8074
8075 // should use legacy codec when switching back to media
8076 ASSERT_EQ(LeAudioClient::Get()->IsUsingPreferredCodecConfig(
8077 group_id, static_cast<int>(types::LeAudioContextType::MEDIA)),
8078 false);
8079 }
8080
TEST_F(UnicastTest,StreamingVxAospSampleSound)8081 TEST_F(UnicastTest, StreamingVxAospSampleSound) {
8082 uint8_t group_size = 2;
8083 int group_id = 2;
8084
8085 /* Test to verify that tag VX_AOSP_SAMPLESOUND is always mapped to
8086 * LeAudioContextType::SOUNDEFFECTS
8087 */
8088
8089 // Report working CSIS
8090 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8091
8092 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8093 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8094
8095 // First earbud
8096 const RawAddress test_address0 = GetTestAddress(0);
8097 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8098 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8099 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8100
8101 // Second earbud
8102 const RawAddress test_address1 = GetTestAddress(1);
8103 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8104 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8105 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8106 true /*connect_through_csis*/);
8107
8108 // Start streaming
8109 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8110 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8111 LeAudioClient::Get()->GroupSetActive(group_id);
8112 SyncOnMainLoop();
8113
8114 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8115
8116 // Set a test TAG
8117 char test_tag[] = "TEST_TAG2;VX_AOSP_SAMPLESOUND;TEST_TAG1";
8118
8119 test_tags_ptr_ = test_tag;
8120
8121 auto initial_context = types::LeAudioContextType::SOUNDEFFECTS;
8122 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {}, .source = {}};
8123 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, _, ccids)).Times(1);
8124 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8125
8126 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8127 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8128 SyncOnMainLoop();
8129
8130 // Verify Data transfer on two peer sinks and one source
8131 uint8_t cis_count_out = 2;
8132 uint8_t cis_count_in = 0;
8133 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 0);
8134 }
8135
TEST_F(UnicastTest,UpdateActiveAudioConfigForLocalSinkSource)8136 TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSinkSource) {
8137 uint8_t group_size = 2;
8138 int group_id = 2;
8139
8140 // Report working CSIS
8141 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8142
8143 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8144 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8145
8146 // First earbud
8147 const RawAddress test_address0 = GetTestAddress(0);
8148 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8149 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8150 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8151
8152 // Second earbud
8153 const RawAddress test_address1 = GetTestAddress(1);
8154 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8155 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8156 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8157 true /*connect_through_csis*/);
8158
8159 // Set group as active
8160 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8161 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8162 LeAudioClient::Get()->GroupSetActive(group_id);
8163 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8164
8165 // Start streaming
8166 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8167 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8168 EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
8169 .Times(1)
8170 .WillOnce([](const types::BidirectionalPair<stream_parameters>& /*stream_params*/,
8171 types::BidirectionalPair<uint16_t> delays_ms,
8172 std::function<void(const offload_config& config, uint8_t direction)>
8173 update_receiver) {
8174 bluetooth::le_audio::offload_config unicast_cfg;
8175 if (delays_ms.sink != 0) {
8176 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSink);
8177 }
8178 if (delays_ms.source != 0) {
8179 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSource);
8180 }
8181 });
8182 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8183
8184 SyncOnMainLoop();
8185 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
8186 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8187 Mock::VerifyAndClearExpectations(&mock_codec_manager_);
8188
8189 // Verify Data transfer on two peer sinks and two sources
8190 uint8_t cis_count_out = 2;
8191 uint8_t cis_count_in = 2;
8192 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8193
8194 // Suspend
8195 LeAudioClient::Get()->GroupSuspend(group_id);
8196 SyncOnMainLoop();
8197 }
8198
TEST_F(UnicastTest,UpdateActiveAudioConfigForLocalSource)8199 TEST_F(UnicastTest, UpdateActiveAudioConfigForLocalSource) {
8200 uint8_t group_size = 2;
8201 int group_id = 2;
8202
8203 // Report working CSIS
8204 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8205
8206 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8207 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8208
8209 // First earbud
8210 const RawAddress test_address0 = GetTestAddress(0);
8211 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8212 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8213 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8214
8215 // Second earbud
8216 const RawAddress test_address1 = GetTestAddress(1);
8217 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8218 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8219 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8220 true /*connect_through_csis*/);
8221
8222 // Set group as active
8223 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8224 LeAudioClient::Get()->GroupSetActive(group_id);
8225 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8226
8227 // Start streaming
8228 EXPECT_CALL(*mock_le_audio_source_hal_client_, UpdateAudioConfigToHal(_)).Times(1);
8229 EXPECT_CALL(*mock_le_audio_sink_hal_client_, UpdateAudioConfigToHal(_)).Times(0);
8230 EXPECT_CALL(*mock_codec_manager_, UpdateActiveAudioConfig(_, _, _))
8231 .Times(1)
8232 .WillOnce([](const types::BidirectionalPair<stream_parameters>& /*stream_params*/,
8233 types::BidirectionalPair<uint16_t> delays_ms,
8234 std::function<void(const offload_config& config, uint8_t direction)>
8235 update_receiver) {
8236 bluetooth::le_audio::offload_config unicast_cfg;
8237 if (delays_ms.sink != 0) {
8238 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSink);
8239 }
8240 if (delays_ms.source != 0) {
8241 update_receiver(unicast_cfg, bluetooth::le_audio::types::kLeAudioDirectionSource);
8242 }
8243 });
8244 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8245
8246 SyncOnMainLoop();
8247 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8248 Mock::VerifyAndClearExpectations(&mock_codec_manager_);
8249
8250 // Verify Data transfer on two peer sinks and no source
8251 uint8_t cis_count_out = 2;
8252 uint8_t cis_count_in = 0;
8253 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8254
8255 // Suspend
8256 LeAudioClient::Get()->GroupSuspend(group_id);
8257 SyncOnMainLoop();
8258 }
8259
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchNoReconfigure)8260 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) {
8261 uint8_t group_size = 2;
8262 int group_id = 2;
8263
8264 // Report working CSIS
8265 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8266
8267 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8268 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8269
8270 // First earbud
8271 const RawAddress test_address0 = GetTestAddress(0);
8272 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8273 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8274 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8275
8276 // Second earbud
8277 const RawAddress test_address1 = GetTestAddress(1);
8278 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8279 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8280 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8281 true /*connect_through_csis*/);
8282
8283 // Start streaming
8284 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8285 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8286 LeAudioClient::Get()->GroupSetActive(group_id);
8287 SyncOnMainLoop();
8288 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8289
8290 // Start streaming with new metadata, there was no previous stream so start
8291 // with this new configuration
8292 auto initial_context = types::LeAudioContextType::NOTIFICATIONS;
8293 types::BidirectionalPair<types::AudioContexts> contexts = {
8294 .sink = types::AudioContexts(initial_context), .source = types::AudioContexts()};
8295 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8296
8297 StartStreaming(AUDIO_USAGE_NOTIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8298
8299 SyncOnMainLoop();
8300 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8301 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8302 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8303
8304 // Do a metadata content switch to ALERTS but stay on previous configuration
8305 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
8306 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
8307 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
8308 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::ALERTS),
8309 .source = types::AudioContexts()};
8310 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8311 UpdateLocalSourceMetadata(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN);
8312
8313 SyncOnMainLoop();
8314 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8315 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8316 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8317
8318 // Do a metadata content switch to EMERGENCY but stay on previous
8319 // configuration
8320 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
8321 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
8322 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
8323
8324 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::EMERGENCYALARM),
8325 .source = types::AudioContexts()};
8326 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8327 UpdateLocalSourceMetadata(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN);
8328
8329 SyncOnMainLoop();
8330 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8331 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8332
8333 // Do a metadata content switch to INSTRUCTIONAL but stay on previous
8334 // configuration
8335 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
8336 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
8337 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
8338 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::INSTRUCTIONAL),
8339 .source = types::AudioContexts()};
8340 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8341 UpdateLocalSourceMetadata(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, AUDIO_CONTENT_TYPE_UNKNOWN);
8342
8343 SyncOnMainLoop();
8344 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8345 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8346 }
8347
TEST_F(UnicastTest,TwoEarbudsStopConversational_StartStreamSonification)8348 TEST_F(UnicastTest, TwoEarbudsStopConversational_StartStreamSonification) {
8349 uint8_t group_size = 2;
8350 int group_id = 2;
8351
8352 // Report working CSIS
8353 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8354
8355 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8356 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8357
8358 // First earbud
8359 const RawAddress test_address0 = GetTestAddress(0);
8360 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8361 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8362 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8363
8364 // Second earbud
8365 const RawAddress test_address1 = GetTestAddress(1);
8366 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8367 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8368 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8369 true /*connect_through_csis*/);
8370
8371 // Start streaming
8372 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8373 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8374 LeAudioClient::Get()->GroupSetActive(group_id);
8375 SyncOnMainLoop();
8376 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8377
8378 // Start streaming with CONVERSATIONAL, there was no previous stream so start
8379 // with this new configuration
8380 auto initial_context = types::LeAudioContextType::CONVERSATIONAL;
8381 types::BidirectionalPair<types::AudioContexts> contexts = {
8382 .sink = types::AudioContexts(initial_context),
8383 .source = types::AudioContexts(initial_context)};
8384 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _)).Times(1);
8385
8386 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8387
8388 SyncOnMainLoop();
8389 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8390 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8391 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8392
8393 // Stop the stream but KEEP cis UP
8394 StopStreaming(group_id, true);
8395 SyncOnMainLoop();
8396 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8397
8398 types::BidirectionalPair<types::AudioContexts> reconfigure_contexts = {
8399 .sink = types::AudioContexts(types::LeAudioContextType::ALERTS),
8400 .source = types::AudioContexts()};
8401
8402 EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, reconfigure_contexts, _))
8403 .Times(1);
8404
8405 // Change context type but expect configuration to by as previous
8406 StartStreaming(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8407
8408 SyncOnMainLoop();
8409 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8410
8411 // Stop the stream and drop CISes
8412 StopStreaming(group_id, true);
8413 SyncOnMainLoop();
8414 // simulate suspend timeout passed, alarm executing
8415 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8416 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8417
8418 auto reconfigure_context = types::LeAudioContextType::ALERTS;
8419
8420 EXPECT_CALL(mock_state_machine_, StartStream(_, reconfigure_context, reconfigure_contexts, _))
8421 .Times(1);
8422
8423 // Update metadata
8424 StartStreaming(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
8425 SyncOnMainLoop();
8426 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8427 }
8428
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchReconfigure)8429 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) {
8430 // TODO(b/352686917). Remove the test when flag will be removing
8431 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(false);
8432
8433 uint8_t group_size = 2;
8434 int group_id = 2;
8435
8436 // Report working CSIS
8437 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8438
8439 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8440 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8441
8442 // First earbud
8443 const RawAddress test_address0 = GetTestAddress(0);
8444 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8445 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8446 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8447
8448 // Second earbud
8449 const RawAddress test_address1 = GetTestAddress(1);
8450 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8451 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8452 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8453 true /*connect_through_csis*/);
8454
8455 constexpr int gmcs_ccid = 1;
8456 constexpr int gtbs_ccid = 2;
8457
8458 // Start streaming MEDIA
8459 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8460 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8461 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
8462 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
8463 LeAudioClient::Get()->GroupSetActive(group_id);
8464 SyncOnMainLoop();
8465
8466 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
8467 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
8468 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8469
8470 SyncOnMainLoop();
8471 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8472 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8473 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8474
8475 // Verify Data transfer on two peer sinks
8476 uint8_t cis_count_out = 2;
8477 uint8_t cis_count_in = 0;
8478 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8479
8480 // Stop
8481 StopStreaming(group_id);
8482 // simulate suspend timeout passed, alarm executing
8483 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8484 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8485
8486 log::info("SetInCall is used by GTBS - and only then we can expect CCID to be set.");
8487 LeAudioClient::Get()->SetInCall(true);
8488
8489 // Conversational is a bidirectional scenario so expect GTBS CCID
8490 // in the metadata for both directions. Can be called twice when one
8491 // direction resume after the other and metadata is updated.
8492 ccids = {.sink = {gtbs_ccid}, .source = {gtbs_ccid}};
8493 EXPECT_CALL(mock_state_machine_,
8494 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
8495 .Times(AtLeast(1));
8496 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8497
8498 SyncOnMainLoop();
8499 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8500 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8501
8502 // Verify Data transfer on two peer sinks and one source
8503 cis_count_out = 2;
8504 cis_count_in = 2;
8505 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8506
8507 log::info("End call");
8508 LeAudioClient::Get()->SetInCall(false);
8509 // Stop
8510 StopStreaming(group_id, true);
8511
8512 log::info("Switch back to MEDIA");
8513 ccids = {.sink = {gmcs_ccid}, .source = {}};
8514 types::BidirectionalPair<types::AudioContexts> contexts = {
8515 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
8516 .source = types::AudioContexts()};
8517 EXPECT_CALL(mock_state_machine_,
8518 ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts,
8519 ccids, _))
8520 .Times(1);
8521 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID, true);
8522
8523 SyncOnMainLoop();
8524 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8525 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8526 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8527 }
8528
TEST_F(UnicastTest,TwoEarbudsStreamingContextSwitchReconfigure_SpeedUpReconfigFlagEnabled)8529 TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure_SpeedUpReconfigFlagEnabled) {
8530 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(true);
8531
8532 uint8_t group_size = 2;
8533 int group_id = 2;
8534
8535 // Report working CSIS
8536 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8537
8538 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8539 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8540
8541 // First earbud
8542 const RawAddress test_address0 = GetTestAddress(0);
8543 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8544 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8545 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8546
8547 // Second earbud
8548 const RawAddress test_address1 = GetTestAddress(1);
8549 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8550 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8551 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8552 true /*connect_through_csis*/);
8553
8554 constexpr int gmcs_ccid = 1;
8555 constexpr int gtbs_ccid = 2;
8556
8557 log::info("Start streaming MEDIA");
8558 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8559 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8560 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
8561 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
8562 LeAudioClient::Get()->GroupSetActive(group_id);
8563 SyncOnMainLoop();
8564
8565 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
8566 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
8567 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8568
8569 SyncOnMainLoop();
8570 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8571 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8572 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8573
8574 // Verify Data transfer on two peer sinks
8575 uint8_t cis_count_out = 2;
8576 uint8_t cis_count_in = 0;
8577 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8578
8579 log::info("Simulate incoming call");
8580
8581 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
8582 Expectation reconfigure =
8583 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(1);
8584 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
8585 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
8586 .Times(1)
8587 .After(reconfigure);
8588 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1);
8589 // SetInCall is used by GTBS - and only then we can expect CCID to be set.
8590 LeAudioClient::Get()->SetInCall(true);
8591 SyncOnMainLoop();
8592 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8593 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8594
8595 // Conversational is a bidirectional scenario so expect GTBS CCID
8596 // in the metadata for both directions. Can be called twice when one
8597 // direction resume after the other and metadata is updated.
8598 ccids = {.sink = {gtbs_ccid}, .source = {gtbs_ccid}};
8599 EXPECT_CALL(mock_state_machine_,
8600 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
8601 .Times(AtLeast(1));
8602 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
8603
8604 SyncOnMainLoop();
8605 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8606 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8607
8608 // Verify Data transfer on two peer sinks and one source
8609 cis_count_out = 2;
8610 cis_count_in = 2;
8611 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
8612
8613 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8614
8615 // Stop stream will be called by SetInCall
8616 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
8617 reconfigure =
8618 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(1);
8619 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(1);
8620 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
8621 .Times(1)
8622 .After(reconfigure);
8623 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1);
8624
8625 LeAudioClient::Get()->SetInCall(false);
8626 SyncOnMainLoop();
8627
8628 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8629 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8630
8631 log::info("Switch back to media");
8632
8633 ccids = {.sink = {gmcs_ccid}, .source = {}};
8634 types::BidirectionalPair<types::AudioContexts> contexts = {
8635 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
8636 .source = types::AudioContexts()};
8637 EXPECT_CALL(mock_state_machine_,
8638 ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts,
8639 ccids, _))
8640 .Times(0);
8641 EXPECT_CALL(
8642 mock_state_machine_,
8643 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, ccids))
8644 .Times(1);
8645 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID,
8646 false);
8647
8648 SyncOnMainLoop();
8649 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8650 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8651 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8652 }
8653
TEST_F(UnicastTest,TwoEarbudsVoipStreamingVerifyMetadataUpdate)8654 TEST_F(UnicastTest, TwoEarbudsVoipStreamingVerifyMetadataUpdate) {
8655 uint8_t group_size = 2;
8656 int group_id = 2;
8657
8658 /*
8659 * Scenario
8660 * 1. Configure stream for the VOIP
8661 * 2. Verify CONVERSATIONAL metadata and context is used.
8662 * 3. Resume LocalSink
8663 * 4. Make sure there is no change of the metadata and context
8664 */
8665
8666 // Report working CSIS
8667 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8668
8669 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8670 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8671
8672 // First earbud
8673 const RawAddress test_address0 = GetTestAddress(0);
8674 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8675 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8676 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8677
8678 // Second earbud
8679 const RawAddress test_address1 = GetTestAddress(1);
8680 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8681 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8682 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8683 true /*connect_through_csis*/);
8684
8685 constexpr int gtbs_ccid = 2;
8686
8687 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
8688 LeAudioClient::Get()->GroupSetActive(group_id);
8689 SyncOnMainLoop();
8690
8691 // VOIP not using Telecom API has no ccids.
8692 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {}, .source = {}};
8693 EXPECT_CALL(mock_state_machine_,
8694 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
8695 .Times(AtLeast(1));
8696
8697 UpdateLocalSourceMetadata(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH);
8698 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
8699
8700 LocalAudioSourceResume();
8701 SyncOnMainLoop();
8702 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8703
8704 SyncOnMainLoop();
8705 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8706 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8707
8708 // Verify Data transfer are sending. The LocalSink is not yet resumed.
8709 uint8_t cis_count_out = 2;
8710 uint8_t cis_count_in = 0;
8711 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 0);
8712
8713 types::BidirectionalPair<types::AudioContexts> contexts = {
8714 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
8715 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
8716 EXPECT_CALL(mock_state_machine_,
8717 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, contexts, ccids))
8718 .Times(AtLeast(1));
8719
8720 LocalAudioSinkResume();
8721 SyncOnMainLoop();
8722 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8723 }
8724
TEST_F(UnicastTest,TwoReconfigureAndVerifyEnableContextType)8725 TEST_F(UnicastTest, TwoReconfigureAndVerifyEnableContextType) {
8726 uint8_t group_size = 2;
8727 int group_id = 2;
8728
8729 /* Scenario
8730 * 1. Earbuds streaming MEDIA
8731 * 2. Reconfigure to VOIP
8732 * 3. Check if Metadata in Enable command are set to CONVERSATIONAL
8733 */
8734
8735 // Report working CSIS
8736 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8737
8738 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8739 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8740
8741 // First earbud
8742 const RawAddress test_address0 = GetTestAddress(0);
8743 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
8744 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8745 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8746
8747 // Second earbud
8748 const RawAddress test_address1 = GetTestAddress(1);
8749 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
8750 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8751 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8752 true /*connect_through_csis*/);
8753
8754 constexpr int gmcs_ccid = 1;
8755 constexpr int gtbs_ccid = 2;
8756
8757 // Start streaming MEDIA
8758 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8759 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8760 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
8761 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
8762 LeAudioClient::Get()->GroupSetActive(group_id);
8763 SyncOnMainLoop();
8764
8765 // Update metadata on local audio sink
8766 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
8767
8768 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
8769 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
8770 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8771
8772 SyncOnMainLoop();
8773 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8774 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8775 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8776
8777 // Verify Data transfer on two peer sinks
8778 uint8_t cis_count_out = 2;
8779 uint8_t cis_count_in = 0;
8780 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8781
8782 // Conversational is a bidirectional scenario so expect GTBS CCID
8783 // in the metadata for both directions. Can be called twice when one
8784 // direction resume after the other and metadata is updated.
8785 ccids = {.sink = {gtbs_ccid}, .source = {gtbs_ccid}};
8786 types::BidirectionalPair<types::AudioContexts> conversiational_contexts = {
8787 .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
8788 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
8789
8790 EXPECT_CALL(mock_state_machine_,
8791 ConfigureStream(_, types::LeAudioContextType::CONVERSATIONAL, _, _, _))
8792 .Times(AtLeast(1));
8793
8794 // Update metadata and resume
8795 UpdateLocalSourceMetadata(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, true);
8796 SyncOnMainLoop();
8797
8798 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8799 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8800 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8801
8802 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::CONVERSATIONAL,
8803 conversiational_contexts, ccids))
8804 .Times(AtLeast(1));
8805
8806 LeAudioClient::Get()->SetInCall(true);
8807
8808 LocalAudioSourceResume(true);
8809 SyncOnMainLoop();
8810
8811 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8812 }
8813
TEST_F(UnicastTest,TwoEarbuds2ndLateConnect)8814 TEST_F(UnicastTest, TwoEarbuds2ndLateConnect) {
8815 uint8_t group_size = 2;
8816 int group_id = 2;
8817
8818 // Report working CSIS
8819 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8820
8821 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8822 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8823
8824 const RawAddress test_address0 = GetTestAddress(0);
8825 const RawAddress test_address1 = GetTestAddress(1);
8826
8827 // First earbud
8828 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8829 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8830
8831 // Start streaming
8832 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8833 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8834 LeAudioClient::Get()->GroupSetActive(group_id);
8835 SyncOnMainLoop();
8836
8837 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8838
8839 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
8840 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8841 SyncOnMainLoop();
8842
8843 // Expect one iso channel to be fed with data
8844 uint8_t cis_count_out = 1;
8845 uint8_t cis_count_in = 0;
8846 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8847
8848 // Second earbud connects during stream
8849 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8850 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8851 true /*connect_through_csis*/);
8852
8853 cis_count_out = 2;
8854 cis_count_in = 0;
8855
8856 /* The above will trigger reconfiguration. After that Audio Hal action
8857 * is needed to restart the stream */
8858 LocalAudioSourceResume();
8859
8860 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8861 }
8862
TEST_F(UnicastTest,LateStreamConnectBasedOnContextType)8863 TEST_F(UnicastTest, LateStreamConnectBasedOnContextType) {
8864 uint8_t group_size = 2;
8865 int group_id = 2;
8866
8867 /* Scenario
8868 * 1. Two devices A and B are connect. Device A has all available context
8869 * types, Device B has no available context types.
8870 * 2. Stream creation to Device A has been started
8871 * 3. Device B notified us with new available Context Types - while A is not
8872 * yet streaming
8873 * 4. Make sure AttachToStream was called for Device B
8874 */
8875
8876 // Report working CSIS
8877 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8878
8879 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8880 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8881
8882 const RawAddress test_address0 = GetTestAddress(0);
8883 const RawAddress test_address1 = GetTestAddress(1);
8884
8885 // First earbud connects
8886 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8887 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8888
8889 // Second earbud connects
8890 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8891 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8892 true /*connect_through_csis*/);
8893
8894 // Start streaming
8895 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8896 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8897 LeAudioClient::Get()->GroupSetActive(group_id);
8898 SyncOnMainLoop();
8899
8900 /* Simulate available context type being cleared */
8901 InjectAvailableContextTypes(test_address1, 2, types::AudioContexts(0), types::AudioContexts(0));
8902
8903 // Block streaming state
8904 stay_at_qos_config_in_start_stream = true;
8905
8906 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
8907 LocalAudioSourceResume(false);
8908
8909 SyncOnMainLoop();
8910 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
8911
8912 InjectAvailableContextTypes(test_address1, 2, types::kLeAudioContextAllRemoteSinkOnly,
8913 types::AudioContexts(0), false);
8914
8915 // Now simulate group is finally streaming
8916 auto group = streaming_groups.at(group_id);
8917 do_in_main_thread(base::BindOnce(
8918 [](int group_id,
8919 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
8920 LeAudioDeviceGroup* group) {
8921 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8922
8923 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
8924 },
8925 group_id, base::Unretained(this->state_machine_callbacks_), std::move(group)));
8926
8927 SyncOnMainLoop();
8928
8929 /* verify AttachToStream was called while stream was not yet created. */
8930 ASSERT_TRUE(attach_to_stream_scheduled);
8931
8932 // Expect two iso channel to be fed with data
8933 uint8_t cis_count_out = 2;
8934 uint8_t cis_count_in = 0;
8935 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
8936 SyncOnMainLoop();
8937 }
8938
TEST_F(UnicastTest,LateStreamConnectBasedOnContextTypeNotFullyConnected)8939 TEST_F(UnicastTest, LateStreamConnectBasedOnContextTypeNotFullyConnected) {
8940 uint8_t group_size = 2;
8941 int group_id = 2;
8942
8943 /* Scenario
8944 * 1. Device A is connected
8945 * 2. Stream creation to Device A has been started
8946 * 3. Stream is stopped
8947 * 4. Device B is connected but has ongoing operations of available context types read.
8948 * 5. Device B sends available context type read response
8949 * 6. Make sure AttachToStream was NOT called for Device B since it is not in a CONNECTED state
8950 * yet
8951 */
8952
8953 // Report working CSIS
8954 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
8955
8956 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
8957 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
8958
8959 const RawAddress test_address0 = GetTestAddress(0);
8960 const RawAddress test_address1 = GetTestAddress(1);
8961
8962 // First earbud connects
8963 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
8964 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
8965 // Start streaming
8966 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
8967 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
8968 LeAudioClient::Get()->GroupSetActive(group_id);
8969 SyncOnMainLoop();
8970
8971 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
8972 auto group = streaming_groups.at(group_id);
8973
8974 // Stop streaming - simulate suspend timeout passed, alarm executing
8975 StopStreaming(group_id);
8976 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
8977 SyncOnMainLoop();
8978
8979 // Second earbud connects and is set to Getting Ready state
8980 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
8981 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
8982 true /*connect_through_csis*/);
8983 auto device1 = group->GetNextDevice(group->GetFirstDevice());
8984 device1->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
8985
8986 // Resume but block the final streaming state - keep the group in transition
8987 stay_at_qos_config_in_start_stream = true;
8988 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
8989 LocalAudioSourceResume(false);
8990
8991 // Do not expect to attach the device on context update as it is not fully connected
8992 EXPECT_CALL(mock_state_machine_, AttachToStream(_, _, _)).Times(0);
8993 InjectAvailableContextTypes(test_address1, 2, types::kLeAudioContextAllRemoteSinkOnly,
8994 types::AudioContexts(0), false);
8995
8996 Mock::VerifyAndClearExpectations(&mock_state_machine_);
8997 SyncOnMainLoop();
8998 }
8999
TEST_F(UnicastTest,CheckDeviceIsNotAttachedToStreamWhenNotNeeded)9000 TEST_F(UnicastTest, CheckDeviceIsNotAttachedToStreamWhenNotNeeded) {
9001 uint8_t group_size = 2;
9002 int group_id = 2;
9003
9004 /* Scenario
9005 * 1. Two devices A and B are connect. Both Devices have all available
9006 * contexts types
9007 * 2. Stream creation to Device A and B has been started
9008 * 3. Device B notified us with new available Context Types - while Group is
9009 * not yet streaming
9010 * 4. Make sure AttachToStream was not called for Device B since it is taking
9011 * part in Stream creation already
9012 */
9013
9014 // Report working CSIS
9015 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9016
9017 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9018 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9019
9020 const RawAddress test_address0 = GetTestAddress(0);
9021 const RawAddress test_address1 = GetTestAddress(1);
9022
9023 // First earbud connects
9024 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9025 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9026
9027 // Second earbud connects
9028 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9029 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9030 true /*connect_through_csis*/);
9031
9032 // Start streaming
9033 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9034 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9035 LeAudioClient::Get()->GroupSetActive(group_id);
9036 SyncOnMainLoop();
9037
9038 // Block streaming state
9039 stay_at_qos_config_in_start_stream = true;
9040
9041 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
9042 LocalAudioSourceResume(false);
9043
9044 SyncOnMainLoop();
9045 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9046
9047 InjectAvailableContextTypes(test_address1, 2, types::kLeAudioContextAllRemoteSinkOnly,
9048 types::AudioContexts(0), false);
9049
9050 // Now simulate group is finally streaming
9051 auto group = streaming_groups.at(group_id);
9052 do_in_main_thread(base::BindOnce(
9053 [](int group_id,
9054 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
9055 LeAudioDeviceGroup* group) {
9056 group->SetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9057
9058 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
9059 },
9060 group_id, base::Unretained(this->state_machine_callbacks_), std::move(group)));
9061
9062 SyncOnMainLoop();
9063
9064 /* verify AttachToStream was NOT called while stream was not yet created. */
9065 ASSERT_FALSE(attach_to_stream_scheduled);
9066
9067 // Expect two iso channel to be fed with data
9068 uint8_t cis_count_out = 2;
9069 uint8_t cis_count_in = 0;
9070 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9071 SyncOnMainLoop();
9072 }
9073
TEST_F(UnicastTest,ReconnectedDeviceAndAttachedToStreamBecauseOfAvailableContextTypeChange)9074 TEST_F(UnicastTest, ReconnectedDeviceAndAttachedToStreamBecauseOfAvailableContextTypeChange) {
9075 com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true);
9076
9077 uint8_t group_size = 2;
9078 int group_id = 2;
9079
9080 /* Scenario
9081 * 1. Two devices A and B are streaming
9082 * 2. Device A Release ASE and removes all available context types
9083 * 3. Device B keeps streaming
9084 * 4. Device A disconnectes
9085 * 5. Device A reconnect
9086 * 6. Device A has context available for streaming and should be attached to the stream
9087 */
9088
9089 // Report working CSIS
9090 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9091
9092 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9093 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9094
9095 const RawAddress test_address0 = GetTestAddress(0);
9096 const RawAddress test_address1 = GetTestAddress(1);
9097
9098 // First earbud connects
9099 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9100 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9101
9102 // Second earbud connects
9103 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9104 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9105 true /*connect_through_csis*/);
9106
9107 // Start streaming
9108 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9109 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9110 LeAudioClient::Get()->GroupSetActive(group_id);
9111 SyncOnMainLoop();
9112
9113 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9114
9115 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9116 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9117 SyncOnMainLoop();
9118
9119 // Expect two iso channel to be fed with data
9120 uint8_t cis_count_out = 2;
9121 uint8_t cis_count_in = 0;
9122 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9123
9124 /* Get group and Device A */
9125 ASSERT_NE(0lu, streaming_groups.count(group_id));
9126 auto group = streaming_groups.at(group_id);
9127 ASSERT_NE(group, nullptr);
9128 auto device = group->GetFirstDevice();
9129
9130 /* Simulate available context type being cleared */
9131 InjectAvailableContextTypes(device->address_, device->conn_id_, types::AudioContexts(0),
9132 types::AudioContexts(0));
9133
9134 /* Simulate ASE releasing and CIS Disconnection */
9135 for (auto& ase : device->ases_) {
9136 /* Releasing state */
9137 if (!ase.active) {
9138 continue;
9139 }
9140
9141 std::vector<uint8_t> releasing_state = {
9142 ase.id, static_cast<uint8_t>(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
9143 InjectNotificationEvent(device->address_, device->conn_id_, ase.hdls.val_hdl, releasing_state);
9144 SyncOnMainLoop();
9145 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
9146 SyncOnMainLoop();
9147 }
9148
9149 cis_count_out = 1;
9150 cis_count_in = 0;
9151 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9152
9153 /* Device A will disconnect, and do not reconnect automatically */
9154 ON_CALL(mock_gatt_interface_, Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, _))
9155 .WillByDefault(Return());
9156
9157 /* Disconnect first device */
9158 auto conn_id = device->conn_id_;
9159 InjectDisconnectedEvent(conn_id, GATT_CONN_TERMINATE_PEER_USER);
9160 SyncOnMainLoop();
9161
9162 /* For background connect, test needs to Inject Connected Event.
9163 * Note that initial available_snk_context_types_ available_src_context_types_ will
9164 * be read after reconnection, which should bring device to the stream again. */
9165
9166 InjectConnectedEvent(device->address_, conn_id);
9167 SyncOnMainLoop();
9168
9169 /* Check single device is streaming */
9170 cis_count_out = 2;
9171 cis_count_in = 0;
9172 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9173 }
9174
TEST_F(UnicastTest,ReconnectedDeviceNotAttachedToStreamBecauseOfNotAvailableContext)9175 TEST_F(UnicastTest, ReconnectedDeviceNotAttachedToStreamBecauseOfNotAvailableContext) {
9176 uint8_t group_size = 2;
9177 int group_id = 2;
9178
9179 /* Scenario
9180 * 1. Two devices A and B are streaming
9181 * 2. Device A Release ASE and removes all available context types
9182 * 3. Device B keeps streaming
9183 * 4. Device A disconnectes
9184 * 5. Device A reconnect and should not be attached to the stream
9185 */
9186
9187 // Report working CSIS
9188 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9189
9190 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9191 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9192
9193 const RawAddress test_address0 = GetTestAddress(0);
9194 const RawAddress test_address1 = GetTestAddress(1);
9195
9196 // First earbud connects
9197 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9198 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9199
9200 // Second earbud connects
9201 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9202 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9203 true /*connect_through_csis*/);
9204
9205 // Start streaming
9206 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9207 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9208 LeAudioClient::Get()->GroupSetActive(group_id);
9209 SyncOnMainLoop();
9210
9211 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9212
9213 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9214 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9215 SyncOnMainLoop();
9216
9217 // Expect two iso channel to be fed with data
9218 uint8_t cis_count_out = 2;
9219 uint8_t cis_count_in = 0;
9220 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9221
9222 /* Get group and Device A */
9223 ASSERT_NE(0lu, streaming_groups.count(group_id));
9224 auto group = streaming_groups.at(group_id);
9225 ASSERT_NE(group, nullptr);
9226 auto device = group->GetFirstDevice();
9227
9228 /* Simulate available context type being cleared */
9229 InjectAvailableContextTypes(device->address_, device->conn_id_, types::AudioContexts(0),
9230 types::AudioContexts(0));
9231
9232 /* Simulate ASE releasing and CIS Disconnection */
9233 for (auto& ase : device->ases_) {
9234 /* Releasing state */
9235 if (!ase.active) {
9236 continue;
9237 }
9238
9239 std::vector<uint8_t> releasing_state = {
9240 ase.id, static_cast<uint8_t>(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
9241 InjectNotificationEvent(device->address_, device->conn_id_, ase.hdls.val_hdl, releasing_state);
9242 SyncOnMainLoop();
9243 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
9244 SyncOnMainLoop();
9245 }
9246
9247 cis_count_out = 1;
9248 cis_count_in = 0;
9249 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9250
9251 /* Device A will disconnect, and do not reconnect automatically */
9252 ON_CALL(mock_gatt_interface_, Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, _))
9253 .WillByDefault(Return());
9254
9255 /* Disconnect first device */
9256 auto conn_id = device->conn_id_;
9257 InjectDisconnectedEvent(conn_id, GATT_CONN_TERMINATE_PEER_USER);
9258 SyncOnMainLoop();
9259
9260 /* For background connect, test needs to Inject Connected Event.
9261 * Since after reconnect Android reads available context types, make sure
9262 * 0 is read */
9263 available_snk_context_types_ = 0;
9264 available_src_context_types_ = 0;
9265
9266 InjectConnectedEvent(device->address_, conn_id);
9267 SyncOnMainLoop();
9268
9269 /* Check single device is streaming */
9270 cis_count_out = 1;
9271 cis_count_in = 0;
9272 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9273 }
9274
TEST_F(UnicastTest,TwoEarbuds2ndReleaseAseRemoveAvailableContextAndBack)9275 TEST_F(UnicastTest, TwoEarbuds2ndReleaseAseRemoveAvailableContextAndBack) {
9276 uint8_t group_size = 2;
9277 int group_id = 2;
9278
9279 /* Scenario
9280 * 1. Two devices A and B are streaming
9281 * 2. Device A Release ASE and removes all available context types
9282 * 3. Device B keeps streaming
9283 * 4. Device A sets available context types
9284 * 5. Device A should be attached to the stream
9285 */
9286
9287 // Report working CSIS
9288 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9289
9290 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9291 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9292
9293 const RawAddress test_address0 = GetTestAddress(0);
9294 const RawAddress test_address1 = GetTestAddress(1);
9295
9296 // First earbud connects
9297 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9298 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9299
9300 // Second earbud connects
9301 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9302 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9303 true /*connect_through_csis*/);
9304
9305 // Start streaming
9306 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9307 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9308 LeAudioClient::Get()->GroupSetActive(group_id);
9309 SyncOnMainLoop();
9310
9311 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9312
9313 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9314 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9315 SyncOnMainLoop();
9316
9317 // Expect two iso channel to be fed with data
9318 uint8_t cis_count_out = 2;
9319 uint8_t cis_count_in = 0;
9320 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9321
9322 /* Get group and Device A */
9323 ASSERT_NE(0lu, streaming_groups.count(group_id));
9324 auto group = streaming_groups.at(group_id);
9325 ASSERT_NE(group, nullptr);
9326 auto device = group->GetFirstDevice();
9327
9328 /* Simulate available context type being cleared */
9329 InjectAvailableContextTypes(device->address_, device->conn_id_, types::AudioContexts(0),
9330 types::AudioContexts(0));
9331
9332 /* Simulate ASE releasing and CIS Disconnection */
9333 for (auto& ase : device->ases_) {
9334 /* Releasing state */
9335 if (!ase.active) {
9336 continue;
9337 }
9338
9339 std::vector<uint8_t> releasing_state = {
9340 ase.id, static_cast<uint8_t>(types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING)};
9341 InjectNotificationEvent(device->address_, device->conn_id_, ase.hdls.val_hdl, releasing_state);
9342 SyncOnMainLoop();
9343 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
9344 SyncOnMainLoop();
9345 }
9346
9347 cis_count_out = 1;
9348 cis_count_in = 0;
9349 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9350
9351 /* Bring back available context types */
9352 InjectAvailableContextTypes(device->address_, device->conn_id_, types::kLeAudioContextAllTypes,
9353 types::kLeAudioContextAllTypes);
9354
9355 /* Check both devices are streaming */
9356 cis_count_out = 2;
9357 cis_count_in = 0;
9358 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9359 }
9360
TEST_F(UnicastTest,StartStream_AvailableContextTypeNotifiedLater)9361 TEST_F(UnicastTest, StartStream_AvailableContextTypeNotifiedLater) {
9362 uint8_t group_size = 2;
9363 int group_id = 2;
9364
9365 available_snk_context_types_ = 0;
9366
9367 /* Scenario (Devices A and B called "Remote")
9368 * 1. Remote does supports all the context types, but has NO available
9369 * contexts at the beginning
9370 * 2. After connection Remote add Available context types
9371 * 3. Android start stream with MEDIA
9372 * 4. Make sure stream will be started
9373 */
9374
9375 // Report working CSIS
9376 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9377
9378 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9379 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9380
9381 const RawAddress test_address0 = GetTestAddress(0);
9382 const RawAddress test_address1 = GetTestAddress(1);
9383
9384 // First earbud connects
9385 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9386 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9387
9388 // Second earbud connects
9389 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9390 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9391 true /*connect_through_csis*/);
9392
9393 // Inject Supported and available context types
9394 auto sink_available_contexts = types::kLeAudioContextAllRemoteSinkOnly;
9395 auto source_available_contexts = types::kLeAudioContextAllRemoteSource;
9396
9397 InjectAvailableContextTypes(test_address0, 1, sink_available_contexts, source_available_contexts);
9398 InjectAvailableContextTypes(test_address1, 2, sink_available_contexts, source_available_contexts);
9399 // Start streaming
9400 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9401 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9402 LeAudioClient::Get()->GroupSetActive(group_id);
9403 SyncOnMainLoop();
9404
9405 BidirectionalPair<AudioContexts> contexts = {
9406 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
9407 .source = types::AudioContexts()};
9408
9409 EXPECT_CALL(mock_state_machine_,
9410 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
9411 .Times(1);
9412
9413 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9414 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9415 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9416
9417 // Expect two iso channel to be fed with data
9418 uint8_t cis_count_out = 2;
9419 uint8_t cis_count_in = 0;
9420 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9421 }
9422
TEST_F(UnicastTest,ModifyContextTypeOnDeviceA_WhileDeviceB_IsDisconnected)9423 TEST_F(UnicastTest, ModifyContextTypeOnDeviceA_WhileDeviceB_IsDisconnected) {
9424 uint8_t group_size = 2;
9425 int group_id = 2;
9426
9427 /* Scenario (Device A and B called Remote)
9428 * 1. Remote set does supports all the context types and make them available
9429 * 2. Android start stream with MEDIA, verify it works.
9430 * 3. Android stops the stream
9431 * 4. Device B disconnects
9432 * 5. Device A removes Media from Available Contexts
9433 * 6. Android start stream with MEDIA, verify it will not be started
9434 */
9435
9436 // Report working CSIS
9437 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9438
9439 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9440 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9441
9442 const RawAddress test_address0 = GetTestAddress(0);
9443 const RawAddress test_address1 = GetTestAddress(1);
9444
9445 // First earbud connects
9446 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9447 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9448
9449 // Second earbud connects
9450 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9451 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9452 true /*connect_through_csis*/);
9453
9454 // Start streaming
9455 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9456 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9457 LeAudioClient::Get()->GroupSetActive(group_id);
9458 SyncOnMainLoop();
9459
9460 BidirectionalPair<AudioContexts> contexts = {
9461 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
9462 .source = types::AudioContexts()};
9463
9464 EXPECT_CALL(mock_state_machine_,
9465 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
9466 .Times(1);
9467
9468 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9469
9470 SyncOnMainLoop();
9471 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9472 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9473 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9474
9475 // Expect two iso channel to be fed with data
9476 uint8_t cis_count_out = 2;
9477 uint8_t cis_count_in = 0;
9478 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9479
9480 // Stop
9481 StopStreaming(group_id);
9482 // simulate suspend timeout passed, alarm executing
9483 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
9484 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9485
9486 // Device B got disconnected and will not reconnect.
9487 ON_CALL(mock_gatt_interface_, Open(_, test_address1, BTM_BLE_DIRECT_CONNECTION, _))
9488 .WillByDefault(Return());
9489 InjectDisconnectedEvent(2, GATT_CONN_TERMINATE_PEER_USER);
9490 SyncOnMainLoop();
9491
9492 // Device A changes available context type
9493 // Inject Supported and available context types
9494 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
9495 sink_supported_context.unset(LeAudioContextType::MEDIA);
9496 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
9497
9498 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
9499 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
9500
9501 InjectSupportedContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9502 InjectAvailableContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9503
9504 /* Android starts stream. */
9505 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, _)).Times(0);
9506
9507 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID, false,
9508 false);
9509 SyncOnMainLoop();
9510
9511 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9512 }
9513
TEST_F(UnicastTest,StartStreamToUnsupportedContextTypeUsingUnspecified)9514 TEST_F(UnicastTest, StartStreamToUnsupportedContextTypeUsingUnspecified) {
9515 uint8_t group_size = 2;
9516 int group_id = 2;
9517
9518 /* Scenario (Devices A and B called "Remote")
9519 * 1. Remote does supports all the context types and make them available
9520 * 2. Remote removes SoundEffect from the supported and available context
9521 * types
9522 * 3. Android start stream with SoundEffects
9523 * 4. Make sure stream will be started with Unspecified context type
9524 */
9525
9526 // Report working CSIS
9527 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9528
9529 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9530 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9531
9532 const RawAddress test_address0 = GetTestAddress(0);
9533 const RawAddress test_address1 = GetTestAddress(1);
9534
9535 // First earbud connects
9536 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9537 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9538
9539 // Second earbud connects
9540 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9541 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9542 true /*connect_through_csis*/);
9543
9544 // Inject Supported and available context types
9545 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
9546 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
9547 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
9548
9549 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
9550 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
9551
9552 InjectSupportedContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9553 InjectAvailableContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9554 InjectSupportedContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
9555 InjectAvailableContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
9556 // Start streaming
9557 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9558 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9559 LeAudioClient::Get()->GroupSetActive(group_id);
9560 SyncOnMainLoop();
9561
9562 BidirectionalPair<AudioContexts> contexts = {
9563 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
9564 .source = types::AudioContexts(0)};
9565
9566 EXPECT_CALL(
9567 mock_state_machine_,
9568 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::SOUNDEFFECTS, contexts, _))
9569 .Times(1);
9570
9571 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION, group_id);
9572
9573 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9574 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9575 SyncOnMainLoop();
9576
9577 // Expect two iso channel to be fed with data
9578 uint8_t cis_count_out = 2;
9579 uint8_t cis_count_in = 0;
9580 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9581 }
9582
TEST_F(UnicastTest,StartStreamToUnsupportedContextTypeUnspecifiedNotAvailable)9583 TEST_F(UnicastTest, StartStreamToUnsupportedContextTypeUnspecifiedNotAvailable) {
9584 uint8_t group_size = 2;
9585 int group_id = 2;
9586
9587 /* Scenario (Device A and B called Remote)
9588 * 1. Remote does supports all the context types and make them available
9589 * 2. Remote removes SoundEffect from the Available Context Types
9590 * 3. Remote also removes UNSPECIFIED from the Available Context Types.
9591 * 4. Android start stream with SoundEffects
9592 * 5. Make sure stream will be NOT be started
9593 */
9594
9595 // Report working CSIS
9596 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9597
9598 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9599 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9600
9601 const RawAddress test_address0 = GetTestAddress(0);
9602 const RawAddress test_address1 = GetTestAddress(1);
9603
9604 // First earbud connects
9605 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9606 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9607
9608 // Second earbud connects
9609 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9610 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9611 true /*connect_through_csis*/);
9612
9613 // Inject Supported and available context types
9614 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
9615 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
9616 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
9617
9618 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
9619 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
9620
9621 InjectSupportedContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9622 InjectSupportedContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
9623
9624 auto sink_available_context = sink_supported_context;
9625 sink_available_context.unset(LeAudioContextType::UNSPECIFIED);
9626
9627 auto source_available_context = source_supported_context;
9628 source_available_context.unset(LeAudioContextType::UNSPECIFIED);
9629
9630 InjectAvailableContextTypes(test_address0, 1, sink_available_context, source_available_context);
9631 InjectAvailableContextTypes(test_address1, 2, sink_available_context, source_available_context);
9632 // Start streaming
9633 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9634 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9635 LeAudioClient::Get()->GroupSetActive(group_id);
9636 SyncOnMainLoop();
9637
9638 BidirectionalPair<AudioContexts> contexts = {
9639 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
9640 .source = types::AudioContexts()};
9641
9642 EXPECT_CALL(
9643 mock_state_machine_,
9644 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::SOUNDEFFECTS, contexts, _))
9645 .Times(0);
9646
9647 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION, group_id,
9648 AUDIO_SOURCE_INVALID, false, false);
9649
9650 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9651 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9652 SyncOnMainLoop();
9653 }
9654
TEST_F(UnicastTest,StartStreamToSupportedContextTypeThenMixUnavailable)9655 TEST_F(UnicastTest, StartStreamToSupportedContextTypeThenMixUnavailable) {
9656 uint8_t group_size = 2;
9657 int group_id = 2;
9658
9659 /* Scenario (Device A and B called Remote)
9660 * 1. Remote set does supports all the context types and make them available
9661 * 2. Abdriud start stream with MEDIA, verify it works.
9662 * 3. Stream becomes to be mixed with Soundeffect and Media - verify metadata
9663 * update
9664 * 4. Android Stop stream.
9665 * 5. Remote removes SoundEffect from the supported and available context
9666 * types
9667 * 6. Android start stream with MEDIA, verify it works.
9668 * 7. Stream becomes to be mixed with Soundeffect and Media
9669 * 8. Make sure metadata updated does not contain unavailable context
9670 * note: eventually, Audio framework should not give us unwanted context
9671 * types
9672 */
9673
9674 // Report working CSIS
9675 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9676
9677 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9678 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9679
9680 const RawAddress test_address0 = GetTestAddress(0);
9681 const RawAddress test_address1 = GetTestAddress(1);
9682
9683 // First earbud connects
9684 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9685 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9686
9687 // Second earbud connects
9688 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9689 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9690 true /*connect_through_csis*/);
9691
9692 // Start streaming
9693 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9694 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9695 LeAudioClient::Get()->GroupSetActive(group_id);
9696 SyncOnMainLoop();
9697
9698 BidirectionalPair<AudioContexts> contexts = {
9699 .sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
9700 .source = types::AudioContexts()};
9701
9702 EXPECT_CALL(mock_state_machine_,
9703 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
9704 .Times(1);
9705
9706 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9707
9708 SyncOnMainLoop();
9709 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9710 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9711 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9712
9713 ASSERT_NE(0lu, streaming_groups.count(group_id));
9714 auto group = streaming_groups.at(group_id);
9715
9716 // Expect two iso channel to be fed with data
9717 uint8_t cis_count_out = 2;
9718 uint8_t cis_count_in = 0;
9719 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9720
9721 contexts.sink = types::AudioContexts(types::LeAudioContextType::MEDIA |
9722 types::LeAudioContextType::SOUNDEFFECTS);
9723 EXPECT_CALL(mock_state_machine_,
9724 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
9725 .Times(1);
9726
9727 /* Simulate metadata update, expect upadate , metadata */
9728 std::vector<struct playback_track_metadata> tracks = {
9729 {{AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, 0},
9730 {AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION, 0}}};
9731 UpdateLocalSourceMetadata(tracks);
9732 SyncOnMainLoop();
9733
9734 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9735
9736 /* Stop stream */
9737 StopStreaming(group_id);
9738 // simulate suspend timeout passed, alarm executing
9739 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
9740 SyncOnMainLoop();
9741
9742 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9743
9744 // Inject Supported and available context types
9745 auto sink_supported_context = types::kLeAudioContextAllRemoteSinkOnly;
9746 sink_supported_context.unset(LeAudioContextType::SOUNDEFFECTS);
9747 sink_supported_context.set(LeAudioContextType::UNSPECIFIED);
9748
9749 auto source_supported_context = types::kLeAudioContextAllRemoteSource;
9750 source_supported_context.set(LeAudioContextType::UNSPECIFIED);
9751
9752 InjectSupportedContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9753 InjectAvailableContextTypes(test_address0, 1, sink_supported_context, source_supported_context);
9754 InjectSupportedContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
9755 InjectAvailableContextTypes(test_address1, 2, sink_supported_context, source_supported_context);
9756
9757 // Verify cache has been removed due to available context change
9758 ASSERT_EQ(nullptr, group->GetCachedConfiguration(types::LeAudioContextType::MEDIA));
9759 /* Start Media again */
9760 contexts.sink = types::AudioContexts(types::LeAudioContextType::MEDIA);
9761 EXPECT_CALL(mock_state_machine_,
9762 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
9763 .Times(1);
9764
9765 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9766
9767 SyncOnMainLoop();
9768
9769 // Verify cache has been rebuilt
9770 ASSERT_NE(nullptr, group->GetCachedConfiguration(types::LeAudioContextType::MEDIA));
9771 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::MEDIA)
9772 ->confs.get(le_audio::types::kLeAudioDirectionSink)
9773 .size());
9774
9775 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9776 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9777 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9778
9779 // Expect two iso channel to be fed with data
9780 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9781
9782 /* Update metadata, and do not expect new context type*/
9783 EXPECT_CALL(mock_state_machine_,
9784 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, contexts, _))
9785 .Times(1);
9786
9787 /* Simulate metadata update */
9788 UpdateLocalSourceMetadata(tracks);
9789 SyncOnMainLoop();
9790 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9791 }
9792
TEST_F(UnicastTest,TwoEarbuds2ndDisconnected)9793 TEST_F(UnicastTest, TwoEarbuds2ndDisconnected) {
9794 uint8_t group_size = 2;
9795 int group_id = 2;
9796
9797 // Report working CSIS
9798 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9799
9800 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9801 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9802
9803 // First earbud
9804 const RawAddress test_address0 = GetTestAddress(0);
9805 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9806 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9807
9808 // Second earbud
9809 const RawAddress test_address1 = GetTestAddress(1);
9810 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9811 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9812 true /*connect_through_csis*/);
9813
9814 // Audio sessions are started only when device gets active
9815 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9816 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9817 LeAudioClient::Get()->GroupSetActive(group_id);
9818 SyncOnMainLoop();
9819
9820 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9821 ASSERT_NE(0lu, streaming_groups.count(group_id));
9822 auto group = streaming_groups.at(group_id);
9823
9824 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9825 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9826 SyncOnMainLoop();
9827 ASSERT_EQ(2, group->NumOfConnected());
9828
9829 // Expect two iso channels to be fed with data
9830 uint8_t cis_count_out = 2;
9831 uint8_t cis_count_in = 0;
9832 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9833
9834 // Disconnect one device and expect the group to keep on streaming
9835 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
9836 auto device = group->GetFirstDevice();
9837 for (auto& ase : device->ases_) {
9838 InjectCisDisconnected(group_id, ase.cis_conn_hdl);
9839 }
9840
9841 /* Disconnect ACL and do not reconnect. */
9842 ON_CALL(mock_gatt_interface_, Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, _))
9843 .WillByDefault(Return());
9844 EXPECT_CALL(mock_gatt_interface_, Open(_, device->address_, BTM_BLE_DIRECT_CONNECTION, false))
9845 .Times(1);
9846
9847 // Record NumOfConnected when groupStateMachine_ gets notified about the
9848 // disconnection
9849 int num_of_connected = 0;
9850 ON_CALL(mock_state_machine_, ProcessHciNotifAclDisconnected(_, _))
9851 .WillByDefault(
9852 [&num_of_connected](LeAudioDeviceGroup* group, LeAudioDevice* /*leAudioDevice*/) {
9853 num_of_connected = group->NumOfConnected();
9854 });
9855
9856 auto conn_id = device->conn_id_;
9857 InjectDisconnectedEvent(device->conn_id_, GATT_CONN_TERMINATE_PEER_USER);
9858 SyncOnMainLoop();
9859
9860 // Make sure the state machine knows about the disconnected device
9861 ASSERT_EQ(1, num_of_connected);
9862
9863 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9864 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9865
9866 // Expect one channel ISO Data to be sent
9867 cis_count_out = 1;
9868 cis_count_in = 0;
9869 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9870
9871 InjectConnectedEvent(device->address_, conn_id);
9872 SyncOnMainLoop();
9873
9874 // Expect two iso channels to be fed with data
9875 cis_count_out = 2;
9876 cis_count_in = 0;
9877 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9878 }
9879
TEST_F(UnicastTest,TwoEarbudsStreamingProfileDisconnect)9880 TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnect) {
9881 uint8_t group_size = 2;
9882 int group_id = 2;
9883
9884 // Report working CSIS
9885 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9886
9887 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9888 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9889
9890 // First earbud
9891 const RawAddress test_address0 = GetTestAddress(0);
9892 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9893 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9894
9895 // Second earbud
9896 const RawAddress test_address1 = GetTestAddress(1);
9897 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9898 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9899 true /*connect_through_csis*/);
9900
9901 // Audio sessions are started only when device gets active
9902 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9903 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9904 LeAudioClient::Get()->GroupSetActive(group_id);
9905 SyncOnMainLoop();
9906
9907 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9908
9909 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9910 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9911 SyncOnMainLoop();
9912
9913 // Expect two iso channels to be fed with data
9914 uint8_t cis_count_out = 2;
9915 uint8_t cis_count_in = 0;
9916 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9917
9918 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
9919
9920 /* Do not inject OPEN_EVENT by default */
9921 ON_CALL(mock_gatt_interface_, Open(_, _, _, _)).WillByDefault(DoAll(Return()));
9922 ON_CALL(mock_gatt_interface_, Close(_)).WillByDefault(DoAll(Return()));
9923 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).WillByDefault(DoAll(Return()));
9924
9925 DisconnectLeAudioNoDisconnectedEvtExpected(test_address0, 1);
9926 DisconnectLeAudioNoDisconnectedEvtExpected(test_address1, 2);
9927
9928 EXPECT_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
9929 .Times(2);
9930
9931 InjectDisconnectedEvent(1);
9932 InjectDisconnectedEvent(2);
9933
9934 SyncOnMainLoop();
9935 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9936 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9937 }
9938
TEST_F(UnicastTest,TwoEarbudsStreamingProfileDisconnectStreamStopTimeout)9939 TEST_F(UnicastTest, TwoEarbudsStreamingProfileDisconnectStreamStopTimeout) {
9940 uint8_t group_size = 2;
9941 int group_id = 2;
9942
9943 // Report working CSIS
9944 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
9945
9946 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
9947 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
9948
9949 // First earbud
9950 const RawAddress test_address0 = GetTestAddress(0);
9951 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
9952 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
9953
9954 // Second earbud
9955 const RawAddress test_address1 = GetTestAddress(1);
9956 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
9957 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
9958 true /*connect_through_csis*/);
9959
9960 // Audio sessions are started only when device gets active
9961 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
9962 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
9963 LeAudioClient::Get()->GroupSetActive(group_id);
9964 SyncOnMainLoop();
9965
9966 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
9967
9968 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
9969 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
9970 SyncOnMainLoop();
9971
9972 // Expect two iso channels to be fed with data
9973 uint8_t cis_count_out = 2;
9974 uint8_t cis_count_in = 0;
9975 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
9976
9977 // Expect StopStream to be called before Close or ACL Disconnect is called.
9978 ON_CALL(mock_state_machine_, StopStream(_)).WillByDefault([](LeAudioDeviceGroup* group) {
9979 /* Stub the process of stopping stream, just set the target state.
9980 * this simulates issue with stopping the stream
9981 */
9982 group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
9983 });
9984
9985 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(2);
9986 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
9987 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).Times(0);
9988
9989 do_in_main_thread(base::Bind(&LeAudioClient::Disconnect, base::Unretained(LeAudioClient::Get()),
9990 test_address0));
9991 do_in_main_thread(base::Bind(&LeAudioClient::Disconnect, base::Unretained(LeAudioClient::Get()),
9992 test_address1));
9993
9994 SyncOnMainLoop();
9995 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
9996 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
9997 Mock::VerifyAndClearExpectations(&mock_state_machine_);
9998
9999 /* Now stream is trying to be stopped and devices are about to be
10000 * disconnected. Simulate stop stream failure and timeout fired. Make sure
10001 * code will not try to do recovery connect
10002 */
10003 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).WillByDefault(DoAll(Return()));
10004 EXPECT_CALL(mock_gatt_interface_, Close(_)).Times(0);
10005 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _)).Times(2);
10006
10007 ASSERT_NE(0lu, streaming_groups.count(group_id));
10008 auto group = streaming_groups.at(group_id);
10009 ASSERT_TRUE(group != nullptr);
10010 ASSERT_GT(group->NumOfConnected(), 0);
10011
10012 state_machine_callbacks_->OnStateTransitionTimeout(group_id);
10013 SyncOnMainLoop();
10014
10015 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
10016 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
10017
10018 auto device = group->GetFirstDevice();
10019 ASSERT_TRUE(device != nullptr);
10020 ASSERT_NE(device->GetConnectionState(), DeviceConnectState::DISCONNECTING_AND_RECOVER);
10021 device = group->GetNextDevice(device);
10022 ASSERT_TRUE(device != nullptr);
10023 ASSERT_NE(device->GetConnectionState(), DeviceConnectState::DISCONNECTING_AND_RECOVER);
10024 }
10025
TEST_F(UnicastTest,EarbudsWithStereoSinkMonoSourceSupporting32kHz)10026 TEST_F(UnicastTest, EarbudsWithStereoSinkMonoSourceSupporting32kHz) {
10027 const RawAddress test_address0 = GetTestAddress(0);
10028 int group_id = 0;
10029 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10030 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
10031 default_channel_cnt, 0x0024,
10032 /* source sample freq 32/16khz */ true, /*add_csis*/
10033 true, /*add_cas*/
10034 true, /*add_pacs*/
10035 default_ase_cnt /*add_ascs_cnt*/);
10036 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10037 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10038 .Times(1);
10039 ConnectLeAudio(test_address0);
10040
10041 // LeAudioCodecConfiguration received_af_sink_config;
10042 const LeAudioCodecConfiguration expected_af_sink_config = {
10043 .num_channels = 2,
10044 .sample_rate = bluetooth::audio::le_audio::kSampleRate32000,
10045 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
10046 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
10047 };
10048
10049 // Audio sessions are started only when device gets active
10050 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10051 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(expected_af_sink_config, _, _)).Times(1);
10052 LeAudioClient::Get()->GroupSetActive(group_id);
10053 SyncOnMainLoop();
10054 }
10055
TEST_F(UnicastTest,TwoEarbudsWithSourceSupporting32kHz)10056 TEST_F(UnicastTest, TwoEarbudsWithSourceSupporting32kHz) {
10057 const RawAddress test_address0 = GetTestAddress(0);
10058 int group_id = 0;
10059 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10060 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10061 default_channel_cnt, 0x0024,
10062 /* source sample freq 32/16khz */ true, /*add_csis*/
10063 true, /*add_cas*/
10064 true, /*add_pacs*/
10065 default_ase_cnt /*add_ascs_cnt*/);
10066 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10067 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10068 .Times(1);
10069 ConnectLeAudio(test_address0);
10070
10071 // LeAudioCodecConfiguration received_af_sink_config;
10072 const LeAudioCodecConfiguration expected_af_sink_config = {
10073 .num_channels = 2,
10074 .sample_rate = bluetooth::audio::le_audio::kSampleRate32000,
10075 .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
10076 .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
10077 };
10078
10079 // Audio sessions are started only when device gets active
10080 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10081 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(expected_af_sink_config, _, _)).Times(1);
10082 LeAudioClient::Get()->GroupSetActive(group_id);
10083 SyncOnMainLoop();
10084 }
10085
TEST_F(UnicastTest,MicrophoneAttachToCurrentMediaScenario)10086 TEST_F(UnicastTest, MicrophoneAttachToCurrentMediaScenario) {
10087 const RawAddress test_address0 = GetTestAddress(0);
10088 int group_id = bluetooth::groups::kGroupUnknown;
10089
10090 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10091 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
10092 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10093 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10094 0 /*rank*/);
10095 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10096 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10097 .Times(1);
10098 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10099 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10100 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10101
10102 ConnectLeAudio(test_address0);
10103 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10104
10105 // Audio sessions are started only when device gets active
10106 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10107 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10108 LeAudioClient::Get()->GroupSetActive(group_id);
10109 SyncOnMainLoop();
10110
10111 // When the local audio source resumes we have no knowledge of recording
10112 EXPECT_CALL(mock_state_machine_,
10113 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, _, _))
10114 .Times(1);
10115
10116 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_INVALID);
10117 SyncOnMainLoop();
10118
10119 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10120 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10121
10122 // Verify Data transfer on one audio source cis
10123 uint8_t cis_count_out = 1;
10124 uint8_t cis_count_in = 0;
10125 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10126
10127 // When the local audio sink resumes we should reconfigure
10128 EXPECT_CALL(mock_state_machine_,
10129 ConfigureStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, _, _, _))
10130 .Times(1);
10131 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(1);
10132
10133 // Update metadata on local audio sink
10134 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
10135
10136 // Resume on local audio sink
10137 ASSERT_NE(unicast_sink_hal_cb_, nullptr);
10138 do_in_main_thread(
10139 base::BindOnce([](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
10140 unicast_sink_hal_cb_));
10141
10142 /* The above will trigger reconfiguration. After that Audio Hal action
10143 * is needed to restart the stream */
10144 SyncOnMainLoop();
10145
10146 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10147 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10148
10149 LocalAudioSourceResume();
10150 do_in_main_thread(
10151 base::BindOnce([](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
10152 unicast_sink_hal_cb_));
10153 SyncOnMainLoop();
10154
10155 auto group = streaming_groups.at(group_id);
10156 group->PrintDebugState();
10157
10158 // Verify Data transfer on one audio source and sink cis
10159 cis_count_out = 1;
10160 cis_count_in = 1;
10161 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
10162
10163 // Stop
10164 StopStreaming(group_id);
10165 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10166
10167 // Release
10168 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10169 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10170 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10171 do_in_main_thread(base::BindOnce(
10172 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
10173 LeAudioClient::Get()));
10174 SyncOnMainLoop();
10175
10176 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10177 }
10178
TEST_F(UnicastTest,SwitchBetweenMicrophoneAndSoundEffectScenario)10179 TEST_F(UnicastTest, SwitchBetweenMicrophoneAndSoundEffectScenario) {
10180 const RawAddress test_address0 = GetTestAddress(0);
10181 int group_id = bluetooth::groups::kGroupUnknown;
10182
10183 /* Scenario:
10184 * 1. User starts Recording - this creates bidiretional CISes
10185 * 2. User stops recording - this starts suspend timeout (500ms)
10186 * 3. Since user touch the screen it generates touch tone - this shall reuse existing CISes when
10187 * it happens 500ms before stop
10188 */
10189 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10190 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
10191 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10192 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10193 0 /*rank*/);
10194 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10195 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10196 .Times(1);
10197 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10198 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10199 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10200
10201 ConnectLeAudio(test_address0);
10202 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10203
10204 // Audio sessions are started only when device gets active
10205 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10206 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10207 LeAudioClient::Get()->GroupSetActive(group_id);
10208 SyncOnMainLoop();
10209
10210 // When the local audio source resumes we have no knowledge of recording
10211 EXPECT_CALL(mock_state_machine_,
10212 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, _, _))
10213 .Times(1);
10214
10215 log::info("Start Microphone recording - bidirectional CISes are expected");
10216 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
10217 LocalAudioSinkResume();
10218
10219 ASSERT_EQ(0, get_func_call_count("alarm_set_on_mloop"));
10220 SyncOnMainLoop();
10221
10222 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10223 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10224 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10225
10226 // Verify Data transfer on one audio source cis
10227 uint8_t cis_count_out = 0;
10228 uint8_t cis_count_in = 1;
10229 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
10230
10231 log::info("Suspend microphone recording - suspend timeout is not fired");
10232 LocalAudioSinkSuspend();
10233 SyncOnMainLoop();
10234
10235 log::info("Expect VBC and Suspend timeouts to be started");
10236 ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
10237 ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
10238
10239 log::info("Resume local source with touch tone - expect suspend timeout to be canceled");
10240
10241 UpdateLocalSourceMetadata(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_SONIFICATION);
10242 LocalAudioSourceResume();
10243 SyncOnMainLoop();
10244
10245 log::info("Expect VBC and Suspend timeouts to be started");
10246 ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
10247
10248 auto group = streaming_groups.at(group_id);
10249 group->PrintDebugState();
10250
10251 // Verify Data transfer on one audio source and sink cis
10252 cis_count_out = 1;
10253 cis_count_in = 0;
10254 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);
10255 }
10256
10257 /* When a certain context is unavailable and not supported we should stream
10258 * as UNSPECIFIED for the backwards compatibility.
10259 * Since UNSPECIFIED is available, put the UNSPECIFIED into the metadata instead
10260 * What we can do now is to keep streaming (and reconfigure if needed for the
10261 * use case).
10262 */
TEST_F(UnicastTest,UpdateNotSupportedContextTypeUnspecifiedAvailable)10263 TEST_F(UnicastTest, UpdateNotSupportedContextTypeUnspecifiedAvailable) {
10264 // TODO(b/352686917). Remove the test when flag will be removing
10265 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(false);
10266
10267 const RawAddress test_address0 = GetTestAddress(0);
10268 int group_id = bluetooth::groups::kGroupUnknown;
10269
10270 available_snk_context_types_ =
10271 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
10272 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
10273 .value();
10274 supported_snk_context_types_ = available_snk_context_types_;
10275 available_src_context_types_ = available_snk_context_types_;
10276 supported_src_context_types_ = available_src_context_types_;
10277
10278 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10279 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10280 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
10281 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10282 0 /*rank*/);
10283 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10284 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10285 .Times(1);
10286 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10287 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10288 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10289
10290 ConnectLeAudio(test_address0);
10291 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10292
10293 // Start streaming
10294 uint8_t cis_count_out = 1;
10295 uint8_t cis_count_in = 0;
10296
10297 LeAudioClient::Get()->SetInCall(true);
10298
10299 // Audio sessions are started only when device gets active
10300 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10301 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10302 LeAudioClient::Get()->GroupSetActive(group_id);
10303 SyncOnMainLoop();
10304
10305 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
10306 LocalAudioSourceResume();
10307 LocalAudioSinkResume();
10308
10309 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10310 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10311 SyncOnMainLoop();
10312
10313 // Verify Data transfer on one audio source cis
10314 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10315
10316 LeAudioClient::Get()->SetInCall(false);
10317 LocalAudioSinkSuspend();
10318
10319 /* We should use GAME configuration, but do not send the GAME context type, as
10320 * it is not available on the remote device.
10321 */
10322 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10323 types::BidirectionalPair<types::AudioContexts> contexts = {
10324 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
10325 .source = types::AudioContexts()};
10326 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::GAME, contexts, _))
10327 .Times(1);
10328 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false);
10329 SyncOnMainLoop();
10330 }
10331
TEST_F(UnicastTest,UpdateNotSupportedContextTypeUnspecifiedAvailable_SpeedUpReconfigFlagEnabled)10332 TEST_F(UnicastTest, UpdateNotSupportedContextTypeUnspecifiedAvailable_SpeedUpReconfigFlagEnabled) {
10333 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(true);
10334
10335 const RawAddress test_address0 = GetTestAddress(0);
10336 int group_id = bluetooth::groups::kGroupUnknown;
10337
10338 available_snk_context_types_ =
10339 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
10340 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
10341 .value();
10342 supported_snk_context_types_ = available_snk_context_types_;
10343 available_src_context_types_ = available_snk_context_types_;
10344 supported_src_context_types_ = available_src_context_types_;
10345
10346 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
10347 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10348 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
10349 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10350 0 /*rank*/);
10351 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10352 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10353 .Times(1);
10354 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10355 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10356 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10357
10358 ConnectLeAudio(test_address0);
10359 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10360
10361 // Start streaming
10362 uint8_t cis_count_out = 1;
10363 uint8_t cis_count_in = 0;
10364
10365 LeAudioClient::Get()->SetInCall(true);
10366
10367 // Audio sessions are started only when device gets active
10368 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10369 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10370 LeAudioClient::Get()->GroupSetActive(group_id);
10371 SyncOnMainLoop();
10372
10373 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
10374 LocalAudioSourceResume();
10375 LocalAudioSinkResume();
10376
10377 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10378 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10379 SyncOnMainLoop();
10380
10381 // Verify Data transfer on one audio source cis
10382 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
10383
10384 LeAudioClient::Get()->SetInCall(false);
10385 LocalAudioSinkSuspend();
10386
10387 /* We should use GAME configuration, but do not send the GAME context type, as
10388 * it is not available on the remote device.
10389 */
10390 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10391 types::BidirectionalPair<types::AudioContexts> contexts = {
10392 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
10393 .source = types::AudioContexts()};
10394 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::GAME, contexts, _))
10395 .Times(1);
10396 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false);
10397 SyncOnMainLoop();
10398 }
10399
10400 /* Some bidirectional scenarios are triggered by the local sink, local source
10401 * metadata or the In Call preference callback call. Since each call invalidates
10402 * previous context source, make sure that getting all of these in a sequence,
10403 * always results with one bidirectional context, so that the remote device
10404 * is not confused about our intentions.
10405 */
TEST_F(UnicastTest,UpdateMultipleBidirContextTypes)10406 TEST_F(UnicastTest, UpdateMultipleBidirContextTypes) {
10407 // TODO(b/352686917). Remove the test when flag will be removing
10408 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(false);
10409
10410 const RawAddress test_address0 = GetTestAddress(0);
10411 int group_id = bluetooth::groups::kGroupUnknown;
10412
10413 available_snk_context_types_ = (types::LeAudioContextType::CONVERSATIONAL |
10414 types::LeAudioContextType::GAME | types::LeAudioContextType::LIVE)
10415 .value();
10416 supported_snk_context_types_ =
10417 available_snk_context_types_ |
10418 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10419 available_src_context_types_ = available_snk_context_types_;
10420 supported_src_context_types_ =
10421 available_src_context_types_ |
10422 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10423
10424 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
10425 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10426 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10427 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10428 0 /*rank*/);
10429 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10430 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10431 .Times(1);
10432 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10433 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10434 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10435
10436 ConnectLeAudio(test_address0);
10437 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10438
10439 // Audio sessions are started only when device gets active
10440 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10441 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10442 LeAudioClient::Get()->GroupSetActive(group_id);
10443 SyncOnMainLoop();
10444
10445 // When the local audio sink resumes expect only LIVE context
10446 types::BidirectionalPair<types::AudioContexts> contexts = {
10447 .sink = types::AudioContexts(types::LeAudioContextType::LIVE),
10448 .source = types::AudioContexts(types::LeAudioContextType::LIVE)};
10449 EXPECT_CALL(mock_state_machine_,
10450 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, contexts, _))
10451 .Times(1);
10452
10453 // 1) Start the recording. Sink resume will trigger the reconfiguration
10454 // ---------------------------------------------------------------------
10455 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
10456 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
10457 LocalAudioSinkResume();
10458
10459 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10460 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10461 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10462
10463 /* After the reconfiguration the local Audio Sink HAL has to resume again */
10464 LocalAudioSourceResume();
10465 LocalAudioSinkResume();
10466
10467 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10468 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10469 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10470
10471 // Verify Data transfer on one audio source and sink cis
10472 uint8_t cis_count_out = 1;
10473 uint8_t cis_count_in = 1;
10474 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10475
10476 // Stop
10477 StopStreaming(group_id);
10478 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10479
10480 // 2) Now set in call preference to get CONVERSATIONAL into the mix
10481 // -----------------------------------------------------------------
10482 LeAudioClient::Get()->SetInCall(true);
10483
10484 // Verify that we only got CONVERSATIONAL context and no LIVE
10485 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
10486 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
10487 EXPECT_CALL(mock_state_machine_,
10488 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
10489 contexts, _))
10490 .Times(1);
10491
10492 // Start with ringtone on local source
10493 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
10494 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
10495
10496 // Resume both directions
10497 LocalAudioSourceResume();
10498 LocalAudioSinkResume();
10499
10500 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10501 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10502 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10503
10504 // Verify Data transfer on one audio source cis
10505 cis_count_out = 1;
10506 cis_count_in = 1;
10507 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10508
10509 // 3) Disable call so we could go to GAME
10510 // ---------------------------------------
10511 LeAudioClient::Get()->SetInCall(false);
10512
10513 /* Start the game on local source - expect no previous sink (LIVE) metadata */
10514 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10515 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::GAME),
10516 .source = types::AudioContexts(types::LeAudioContextType::GAME)};
10517 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::GAME, contexts, _))
10518 .Times(1);
10519 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false);
10520
10521 /* If the above triggers reconfiguration, Audio Hal action is needed to
10522 * restart the stream.
10523 */
10524 LocalAudioSourceResume();
10525 LocalAudioSinkResume();
10526 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10527
10528 // 4) Stop streaming
10529 // ------------------
10530 StopStreaming(group_id);
10531 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10532
10533 // Release
10534 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10535 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10536 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10537 do_in_main_thread(base::BindOnce(
10538 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
10539 LeAudioClient::Get()));
10540 SyncOnMainLoop();
10541 }
10542
TEST_F(UnicastTest,UpdateMultipleBidirContextTypes_SpeedUpReconfigFlagEnabled)10543 TEST_F(UnicastTest, UpdateMultipleBidirContextTypes_SpeedUpReconfigFlagEnabled) {
10544 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(true);
10545
10546 const RawAddress test_address0 = GetTestAddress(0);
10547 int group_id = bluetooth::groups::kGroupUnknown;
10548
10549 available_snk_context_types_ = (types::LeAudioContextType::CONVERSATIONAL |
10550 types::LeAudioContextType::GAME | types::LeAudioContextType::LIVE)
10551 .value();
10552 supported_snk_context_types_ =
10553 available_snk_context_types_ |
10554 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10555 available_src_context_types_ = available_snk_context_types_;
10556 supported_src_context_types_ =
10557 available_src_context_types_ |
10558 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10559
10560 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
10561 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10562 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10563 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10564 0 /*rank*/);
10565 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10566 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10567 .Times(1);
10568 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10569 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10570 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10571
10572 ConnectLeAudio(test_address0);
10573 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10574
10575 // Audio sessions are started only when device gets active
10576 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10577 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10578 LeAudioClient::Get()->GroupSetActive(group_id);
10579 SyncOnMainLoop();
10580
10581 // When the local audio sink resumes expect only LIVE context
10582 types::BidirectionalPair<types::AudioContexts> contexts = {
10583 .sink = types::AudioContexts(types::LeAudioContextType::LIVE),
10584 .source = types::AudioContexts(types::LeAudioContextType::LIVE)};
10585 EXPECT_CALL(mock_state_machine_,
10586 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::LIVE, contexts, _))
10587 .Times(1);
10588
10589 log::info("Step 1 Start the recording. Sink resume will trigger the reconfiguration");
10590 // ---------------------------------------------------------------------
10591 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
10592 UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);
10593 LocalAudioSinkResume();
10594
10595 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10596 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10597 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10598
10599 log::info("After the reconfiguration the local Audio Sink HAL has to resume again");
10600
10601 LocalAudioSourceResume();
10602 LocalAudioSinkResume();
10603
10604 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10605 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10606 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10607
10608 log::info("Verify Data transfer on one audio source and sink cis");
10609
10610 uint8_t cis_count_out = 1;
10611 uint8_t cis_count_in = 1;
10612 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10613
10614 log::info("Step 2 Now set in call preference to get CONVERSATIONAL into the mix");
10615 // -----------------------------------------------------------------
10616
10617 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(0);
10618 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(0);
10619 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0);
10620 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0);
10621 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10622 LeAudioClient::Get()->SetInCall(true);
10623 SyncOnMainLoop();
10624
10625 // Verify that we only got CONVERSATIONAL context and no LIVE
10626 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
10627 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
10628 EXPECT_CALL(mock_state_machine_,
10629 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
10630 contexts, _))
10631 .Times(1);
10632
10633 log::info("Start with ringtone on local source");
10634 ASSERT_NE(nullptr, unicast_sink_hal_cb_);
10635 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
10636
10637 // Resume both directions
10638 LocalAudioSourceResume();
10639 LocalAudioSinkResume();
10640
10641 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10642 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10643 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10644
10645 // Verify Data transfer on one audio source cis
10646 cis_count_out = 1;
10647 cis_count_in = 1;
10648 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10649
10650 log::info("Step 3 Disable call so we could go to GAME");
10651 // ---------------------------------------
10652 EXPECT_CALL(*mock_le_audio_source_hal_client_, SuspendedForReconfiguration()).Times(0);
10653 EXPECT_CALL(*mock_le_audio_source_hal_client_, CancelStreamingRequest()).Times(0);
10654 EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete()).Times(0);
10655 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0);
10656 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10657
10658 LeAudioClient::Get()->SetInCall(false);
10659 SyncOnMainLoop();
10660 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10661 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10662
10663 log::info("Start the game on local source - expect no previous sink (LIVE) metadata");
10664
10665 /* Stream shall keep streaming */
10666 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::GAME),
10667 .source = types::AudioContexts(types::LeAudioContextType::GAME)};
10668 EXPECT_CALL(mock_state_machine_, StartStream(_, _, contexts, _)).Times(1);
10669
10670 UpdateLocalSourceMetadata(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_UNKNOWN, false);
10671 LocalAudioSourceResume();
10672 SyncOnMainLoop();
10673
10674 // Verify Data transfer on one audio source cis
10675 cis_count_out = 1;
10676 cis_count_in = 1;
10677 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10678 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10679
10680 log::info(" Step 4 Stop streaming");
10681 // ------------------
10682 StopStreaming(group_id);
10683 SyncOnMainLoop();
10684 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10685
10686 // Release
10687 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10688 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10689 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10690 do_in_main_thread(base::BindOnce(
10691 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
10692 LeAudioClient::Get()));
10693 SyncOnMainLoop();
10694 }
10695
TEST_F(UnicastTest,UpdateDisableLocalAudioSinkOnGame)10696 TEST_F(UnicastTest, UpdateDisableLocalAudioSinkOnGame) {
10697 const RawAddress test_address0 = GetTestAddress(0);
10698 int group_id = bluetooth::groups::kGroupUnknown;
10699
10700 available_snk_context_types_ = (types::LeAudioContextType::CONVERSATIONAL |
10701 types::LeAudioContextType::GAME | types::LeAudioContextType::LIVE)
10702 .value();
10703 supported_snk_context_types_ =
10704 available_snk_context_types_ |
10705 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10706 available_src_context_types_ = available_snk_context_types_;
10707 supported_src_context_types_ =
10708 available_src_context_types_ |
10709 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10710
10711 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
10712 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10713 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10714 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10715 0 /*rank*/);
10716 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10717 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10718 .Times(1);
10719 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10720 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10721 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10722
10723 ConnectLeAudio(test_address0);
10724 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10725
10726 // Audio sessions are started only when device gets active
10727 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10728 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10729 LeAudioClient::Get()->GroupSetActive(group_id);
10730 SyncOnMainLoop();
10731
10732 // Start GAME stream
10733 types::BidirectionalPair<types::AudioContexts> contexts = {
10734 .sink = types::AudioContexts(types::LeAudioContextType::GAME),
10735 .source = types::AudioContexts(types::LeAudioContextType::GAME)};
10736 EXPECT_CALL(mock_state_machine_,
10737 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::GAME, contexts, _))
10738 .Times(1);
10739
10740 // 1) Start the recording. Sink resume will trigger the reconfiguration
10741 // ---------------------------------------------------------------------
10742 StartStreaming(AUDIO_USAGE_GAME, AUDIO_CONTENT_TYPE_MUSIC, group_id, AUDIO_SOURCE_MIC);
10743
10744 SyncOnMainLoop();
10745
10746 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10747 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10748 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10749
10750 // Verify Data transfer on one audio source and sink cis
10751 uint8_t cis_count_out = 1;
10752 uint8_t cis_count_in = 1;
10753 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10754
10755 SyncOnMainLoop();
10756
10757 // 2) Now Lets suspend MIC and do not expect reconfiguration
10758 // -----------------------------------------------------------------
10759
10760 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10761 LocalAudioSinkSuspend();
10762 // simulate suspend timeout passed, alarm executing
10763 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
10764 SyncOnMainLoop();
10765 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10766 }
10767
10768 /* Start music when in a call, end the call, continue with music only */
TEST_F(UnicastTest,MusicDuringCallContextTypes)10769 TEST_F(UnicastTest, MusicDuringCallContextTypes) {
10770 // TODO(b/352686917). Remove the test when flag will be removing
10771 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(false);
10772
10773 const RawAddress test_address0 = GetTestAddress(0);
10774 int group_id = bluetooth::groups::kGroupUnknown;
10775
10776 available_snk_context_types_ =
10777 (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::RINGTONE |
10778 types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA |
10779 types::LeAudioContextType::LIVE | types::LeAudioContextType::NOTIFICATIONS)
10780 .value();
10781 supported_snk_context_types_ =
10782 available_snk_context_types_ |
10783 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10784 available_src_context_types_ = available_snk_context_types_;
10785 available_src_context_types_ &=
10786 ~((types::LeAudioContextType::NOTIFICATIONS | types::LeAudioContextType::MEDIA).value());
10787 supported_src_context_types_ =
10788 available_src_context_types_ |
10789 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10790
10791 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
10792 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10793 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10794 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10795 0 /*rank*/);
10796 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10797 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10798 .Times(1);
10799 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10800 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10801 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10802
10803 ConnectLeAudio(test_address0);
10804 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10805
10806 // Audio sessions are started only when device gets active
10807 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10808 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10809 LeAudioClient::Get()->GroupSetActive(group_id);
10810 SyncOnMainLoop();
10811
10812 log::info("TESTPOINT 1: Start with the call first");
10813 // -----------------------------
10814 // CONVERSATIONAL is from In Call preference, and RINGTONE is from metadata
10815 LeAudioClient::Get()->SetInCall(true);
10816 types::BidirectionalPair<types::AudioContexts> contexts = {
10817 .sink = types::AudioContexts(types::LeAudioContextType::RINGTONE |
10818 types::LeAudioContextType::CONVERSATIONAL),
10819 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
10820 EXPECT_CALL(mock_state_machine_,
10821 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
10822 contexts, _))
10823 .Times(1);
10824 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
10825 LocalAudioSinkResume();
10826
10827 // Verify
10828 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10829 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10830 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10831
10832 // Verify Data transfer
10833 uint8_t cis_count_out = 1;
10834 uint8_t cis_count_in = 1;
10835 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
10836
10837 log::info("TESTPOINT 2: Start MEDIA during the call, expect MEDIA only on the remote sink");
10838 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL |
10839 types::LeAudioContextType::MEDIA),
10840 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
10841 EXPECT_CALL(mock_state_machine_,
10842 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
10843 contexts, _))
10844 .Times(1);
10845 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, false);
10846 SyncOnMainLoop();
10847
10848 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10849 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10850 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10851
10852 log::info(
10853 "TESTPOINT 3: Disable In Call preference but do not suspend the local sink. Play "
10854 "notification on the same stream.");
10855 // Verify both context are sent as the metadata.
10856 // ---------------------------------------
10857 LeAudioClient::Get()->SetInCall(false);
10858
10859 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10860 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::NOTIFICATIONS |
10861 types::LeAudioContextType::CONVERSATIONAL),
10862 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
10863 EXPECT_CALL(mock_state_machine_,
10864 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, contexts, _))
10865 .Times(1);
10866 UpdateLocalSourceMetadata(AUDIO_USAGE_NOTIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN,
10867 /*reconfigure=*/false);
10868 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10869 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10870 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10871
10872 log::info("TESTPOINT 4: Disable call so we could go back to MEDIA");
10873 // ---------------------------------------
10874 // Suspend should stop the stream
10875 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
10876 LocalAudioSourceSuspend();
10877 LocalAudioSinkSuspend();
10878 // simulate suspend timeout passed, alarm executing
10879 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
10880 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10881
10882 // Restart the stream with MEDIA
10883 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
10884 .source = types::AudioContexts()};
10885 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::MEDIA, contexts, _))
10886 .Times(1);
10887 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC,
10888 /*reconfigure=*/false);
10889 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10890 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10891
10892 /* The source needs to resume to reconfigure to MEDIA */
10893 LocalAudioSourceResume(/*expect_confirm=*/false);
10894 LocalAudioSourceResume(/*expect_confirm=*/true);
10895 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10896 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
10897 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
10898
10899 log::info("TESTPOINT 5: Stop streaming");
10900 // ------------------
10901 StopStreaming(group_id);
10902 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
10903
10904 // Release
10905 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
10906 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
10907 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
10908 do_in_main_thread(base::BindOnce(
10909 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
10910 LeAudioClient::Get()));
10911 SyncOnMainLoop();
10912 }
10913
TEST_F(UnicastTest,MetadataUpdateDuringReconfiguration)10914 TEST_F(UnicastTest, MetadataUpdateDuringReconfiguration) {
10915 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(true);
10916 const RawAddress test_address0 = GetTestAddress(0);
10917 int group_id = bluetooth::groups::kGroupUnknown;
10918
10919 /* Scenario
10920 * 1. Start reconfiguration
10921 * 2. Send metadata update
10922 * 3. Make sure metadata updates are ignored
10923 */
10924 available_snk_context_types_ =
10925 (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::RINGTONE |
10926 types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA |
10927 types::LeAudioContextType::LIVE | types::LeAudioContextType::NOTIFICATIONS)
10928 .value();
10929 supported_snk_context_types_ =
10930 available_snk_context_types_ |
10931 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10932 available_src_context_types_ = available_snk_context_types_;
10933 supported_src_context_types_ =
10934 available_src_context_types_ |
10935 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
10936
10937 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
10938 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
10939 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
10940 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
10941 0 /*rank*/);
10942 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10943 OnConnectionState(ConnectionState::CONNECTED, test_address0))
10944 .Times(1);
10945 EXPECT_CALL(mock_audio_hal_client_callbacks_,
10946 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
10947 .WillOnce(DoAll(SaveArg<1>(&group_id)));
10948
10949 ConnectLeAudio(test_address0);
10950 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
10951
10952 // Audio sessions are started only when device gets active
10953 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
10954 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
10955 LeAudioClient::Get()->GroupSetActive(group_id);
10956 SyncOnMainLoop();
10957 EXPECT_CALL(mock_state_machine_,
10958 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::MEDIA, _, _))
10959 .Times(1);
10960 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
10961 SyncOnMainLoop();
10962 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10963
10964 auto group = streaming_groups.at(group_id);
10965
10966 stay_at_qos_config_in_start_stream = true;
10967 log::info("Reconfigure to conversational and stay in Codec Config");
10968
10969 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
10970 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(1);
10971
10972 LeAudioClient::Get()->SetInCall(true);
10973 SyncOnMainLoop();
10974
10975 ASSERT_TRUE(group->GetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
10976
10977 log::info("Expect not action on metadata change");
10978
10979 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
10980 EXPECT_CALL(mock_state_machine_, ConfigureStream(_, _, _, _, _)).Times(0);
10981
10982 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
10983 SyncOnMainLoop();
10984 Mock::VerifyAndClearExpectations(&mock_state_machine_);
10985 }
10986
TEST_F(UnicastTest,MusicDuringCallContextTypes_SpeedUpReconfigFlagEnabled)10987 TEST_F(UnicastTest, MusicDuringCallContextTypes_SpeedUpReconfigFlagEnabled) {
10988 com::android::bluetooth::flags::provider_->leaudio_speed_up_reconfiguration_between_call(true);
10989
10990 const RawAddress test_address0 = GetTestAddress(0);
10991 int group_id = bluetooth::groups::kGroupUnknown;
10992
10993 available_snk_context_types_ =
10994 (types::LeAudioContextType::CONVERSATIONAL | types::LeAudioContextType::RINGTONE |
10995 types::LeAudioContextType::GAME | types::LeAudioContextType::MEDIA |
10996 types::LeAudioContextType::LIVE | types::LeAudioContextType::NOTIFICATIONS)
10997 .value();
10998 supported_snk_context_types_ =
10999 available_snk_context_types_ |
11000 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
11001 available_src_context_types_ = available_snk_context_types_;
11002 supported_src_context_types_ =
11003 available_src_context_types_ |
11004 types::AudioContexts(types::LeAudioContextType::UNSPECIFIED).value();
11005
11006 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationAnyLeft,
11007 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11008 default_channel_cnt, 0x0024, false /*add_csis*/, true /*add_cas*/,
11009 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11010 0 /*rank*/);
11011 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11012 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11013 .Times(1);
11014 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11015 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11016 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11017
11018 ConnectLeAudio(test_address0);
11019 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11020
11021 // Audio sessions are started only when device gets active
11022 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11023 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11024 LeAudioClient::Get()->GroupSetActive(group_id);
11025 SyncOnMainLoop();
11026
11027 log::info("Step 1 Start with the call first");
11028 // -----------------------------
11029 // CONVERSATIONAL is from In Call preference, and RINGTONE is from metadata
11030 LeAudioClient::Get()->SetInCall(true);
11031 types::BidirectionalPair<types::AudioContexts> contexts = {
11032 .sink = types::AudioContexts(types::LeAudioContextType::RINGTONE |
11033 types::LeAudioContextType::CONVERSATIONAL),
11034 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
11035 EXPECT_CALL(mock_state_machine_,
11036 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
11037 contexts, _))
11038 .Times(1);
11039 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
11040 LocalAudioSourceResume();
11041 LocalAudioSinkResume();
11042
11043 // Verify
11044 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11045 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11046 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11047
11048 // Verify Data transfer
11049 uint8_t cis_count_out = 1;
11050 uint8_t cis_count_in = 1;
11051 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
11052
11053 log::info("Step 2) Start MEDIA during the call, expect MEDIA only on the remote sink");
11054
11055 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL |
11056 types::LeAudioContextType::MEDIA),
11057 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
11058 EXPECT_CALL(mock_state_machine_,
11059 StartStream(_, bluetooth::le_audio::types::LeAudioContextType::CONVERSATIONAL,
11060 contexts, _))
11061 .Times(1);
11062 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, false);
11063 SyncOnMainLoop();
11064
11065 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11066 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11067 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11068
11069 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
11070 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::MEDIA |
11071 types::LeAudioContextType::CONVERSATIONAL),
11072 .source = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
11073 EXPECT_CALL(mock_state_machine_,
11074 StartStream(_, types::LeAudioContextType::CONVERSATIONAL, contexts, _))
11075 .Times(1);
11076 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC,
11077 /*reconfigure=*/false);
11078 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11079 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11080 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11081
11082 log::info("Step 3) Disable call so we could go back to MEDIA");
11083 // ---------------------------------------
11084 // Suspend should stop the stream
11085 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
11086 LocalAudioSourceSuspend();
11087 LocalAudioSinkSuspend();
11088 // simulate suspend timeout passed, alarm executing
11089 fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
11090
11091 LeAudioClient::Get()->SetInCall(false);
11092 SyncOnMainLoop();
11093 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11094
11095 // Restart the stream with MEDIA
11096 contexts = {.sink = types::AudioContexts(types::LeAudioContextType::MEDIA),
11097 .source = types::AudioContexts()};
11098 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::MEDIA, contexts, _))
11099 .Times(1);
11100 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC,
11101 /*reconfigure=*/false);
11102 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11103 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11104
11105 /* The source needs to resume to reconfigure to MEDIA */
11106 LocalAudioSourceResume(/*expect_confirm=*/false);
11107 LocalAudioSourceResume(/*expect_confirm=*/true);
11108 Mock::VerifyAndClearExpectations(&mock_state_machine_);
11109 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11110 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
11111
11112 log::info("Step 3) Stop streaming");
11113
11114 // ------------------
11115 StopStreaming(group_id);
11116 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11117
11118 // Release
11119 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
11120 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
11121 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
11122 do_in_main_thread(base::BindOnce(
11123 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
11124 LeAudioClient::Get()));
11125 SyncOnMainLoop();
11126 }
11127
11128 /* When a certain context is unavailable but supported we should not stream that
11129 * context - either stop the stream or eliminate this strim from the mix
11130 * This could be na IOP issue so continue streaming (and reconfigure if needed
11131 * for that use case).
11132 * Since the unavailable context is supported, do not put this context into
11133 * the metadata, and do not replace it with UNSPECIFIED.
11134 */
TEST_F(UnicastTest,StartNotAvailableSupportedContextType)11135 TEST_F(UnicastTest, StartNotAvailableSupportedContextType) {
11136 const RawAddress test_address0 = GetTestAddress(0);
11137 int group_id = bluetooth::groups::kGroupUnknown;
11138
11139 // EMERGENCYALARM is not available, but supported
11140 available_snk_context_types_ =
11141 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
11142 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
11143 .value();
11144 available_src_context_types_ = available_snk_context_types_;
11145 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
11146 supported_src_context_types_ =
11147 (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED).value();
11148
11149 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11150 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11151 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11152 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11153 0 /*rank*/);
11154 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11155 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11156 .Times(1);
11157 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11158 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11159 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11160
11161 ConnectLeAudio(test_address0);
11162 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11163
11164 // Expect configuring to (or staying with) the right configuration but the
11165 // metadata should not get the EMERGENCYALARM context, nor the UNSPECIFIED
11166 // Since the initial config is UNSPECIFIED, then even for sonification events
11167 // we should reconfigure to less generic EMERGENCYALARM scenario
11168 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11169 types::BidirectionalPair<types::AudioContexts> metadata = {.sink = types::AudioContexts(),
11170 .source = types::AudioContexts()};
11171 EXPECT_CALL(mock_state_machine_,
11172 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
11173 .Times(0);
11174
11175 LeAudioClient::Get()->GroupSetActive(group_id);
11176 SyncOnMainLoop();
11177
11178 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID,
11179 false, false);
11180
11181 SyncOnMainLoop();
11182 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11183 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11184 }
11185
11186 /* When a certain context is unavailable and not supported and the UNSPECIFIED
11187 * is not available we should stop the stream.
11188 * For now, stream will not be started in such a case.
11189 * In future we should be able to eliminate this context from the track mix.
11190 */
TEST_F(UnicastTest,StartNotAvailableUnsupportedContextTypeUnspecifiedUnavail)11191 TEST_F(UnicastTest, StartNotAvailableUnsupportedContextTypeUnspecifiedUnavail) {
11192 const RawAddress test_address0 = GetTestAddress(0);
11193 int group_id = bluetooth::groups::kGroupUnknown;
11194
11195 // EMERGENCYALARM is not available, nor supported
11196 available_snk_context_types_ =
11197 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
11198 types::LeAudioContextType::MEDIA)
11199 .value();
11200 available_src_context_types_ = available_snk_context_types_;
11201 supported_snk_context_types_ =
11202 (available_snk_context_types_ | types::LeAudioContextType::UNSPECIFIED).value();
11203 supported_src_context_types_ =
11204 (available_src_context_types_ | types::LeAudioContextType::UNSPECIFIED).value();
11205
11206 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11207 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11208 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11209 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11210 0 /*rank*/);
11211 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11212 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11213 .Times(1);
11214 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11215 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11216 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11217
11218 ConnectLeAudio(test_address0);
11219 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11220
11221 // Expect configuring to the default config since the EMERGENCYALARM is
11222 // not on the list of supported contexts and UNSPECIFIED should not be
11223 // in the metadata as it is unavailable.
11224 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11225 types::BidirectionalPair<types::AudioContexts> metadata = {.sink = types::AudioContexts(),
11226 .source = types::AudioContexts()};
11227 EXPECT_CALL(mock_state_machine_,
11228 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
11229 .Times(0);
11230
11231 LeAudioClient::Get()->GroupSetActive(group_id);
11232 SyncOnMainLoop();
11233
11234 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id, AUDIO_SOURCE_INVALID,
11235 false, false);
11236
11237 SyncOnMainLoop();
11238 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11239 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11240 }
11241
11242 /* This test verifies if we use UNSPCIFIED context when another context is
11243 * unavailable and not supported but UNSPCIFIED is in available audio contexts.
11244 */
TEST_F(UnicastTest,StartNotAvailableUnsupportedContextTypeUnspecifiedAvail)11245 TEST_F(UnicastTest, StartNotAvailableUnsupportedContextTypeUnspecifiedAvail) {
11246 const RawAddress test_address0 = GetTestAddress(0);
11247 int group_id = bluetooth::groups::kGroupUnknown;
11248
11249 // EMERGENCYALARM is not available, nor supported
11250 available_snk_context_types_ =
11251 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
11252 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
11253 .value();
11254 available_src_context_types_ = available_snk_context_types_;
11255 supported_snk_context_types_ = available_snk_context_types_;
11256 supported_src_context_types_ = available_src_context_types_;
11257
11258 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11259 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11260 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11261 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11262 0 /*rank*/);
11263 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11264 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11265 .Times(1);
11266 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11267 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11268 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11269
11270 ConnectLeAudio(test_address0);
11271 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11272
11273 // Expect configuring to the default config since the EMERGENCYALARM is
11274 // not on the list of supported contexts and UNSPECIFIED will be used in
11275 // the metadata.
11276 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11277 types::BidirectionalPair<types::AudioContexts> metadata = {
11278 .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
11279 .source = types::AudioContexts()};
11280 EXPECT_CALL(mock_state_machine_,
11281 StartStream(_, types::LeAudioContextType::EMERGENCYALARM, metadata, _))
11282 .Times(1);
11283
11284 LeAudioClient::Get()->GroupSetActive(group_id);
11285 SyncOnMainLoop();
11286
11287 StartStreaming(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
11288
11289 SyncOnMainLoop();
11290 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11291 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11292
11293 // Verify Data transfer on one audio source cis
11294 uint8_t cis_count_out = 1;
11295 uint8_t cis_count_in = 0;
11296 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
11297 }
11298
TEST_F(UnicastTest,NotifyAboutGroupTunrnedIdleEnabled)11299 TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleEnabled) {
11300 const RawAddress test_address0 = GetTestAddress(0);
11301 int group_id = bluetooth::groups::kGroupUnknown;
11302
11303 osi_property_set_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall, true);
11304
11305 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11306 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11307 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11308 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11309 0 /*rank*/);
11310 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11311 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11312 .Times(1);
11313 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11314 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11315 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11316
11317 ConnectLeAudio(test_address0);
11318 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11319
11320 // Start streaming
11321 uint8_t cis_count_out = 1;
11322 uint8_t cis_count_in = 0;
11323
11324 LeAudioClient::Get()->SetInCall(true);
11325
11326 // Audio sessions are started only when device gets active
11327 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11328 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11329 LeAudioClient::Get()->GroupSetActive(group_id);
11330 SyncOnMainLoop();
11331
11332 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
11333
11334 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11335 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11336 SyncOnMainLoop();
11337
11338 // Verify Data transfer on one audio source cis
11339 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
11340
11341 // Release
11342
11343 /* To be called twice
11344 * 1. GroupStatus::INACTIVE
11345 * 2. GroupStatus::TURNED_IDLE_DURING_CALL
11346 */
11347 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, _)).Times(2);
11348
11349 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
11350 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
11351 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
11352
11353 do_in_main_thread(base::BindOnce(
11354 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
11355 LeAudioClient::Get()));
11356
11357 SyncOnMainLoop();
11358 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11359
11360 LeAudioClient::Get()->SetInCall(false);
11361 osi_property_set_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall, false);
11362 }
11363
TEST_F(UnicastTest,NotifyAboutGroupTunrnedIdleDisabled)11364 TEST_F(UnicastTest, NotifyAboutGroupTunrnedIdleDisabled) {
11365 const RawAddress test_address0 = GetTestAddress(0);
11366 int group_id = bluetooth::groups::kGroupUnknown;
11367
11368 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11369 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11370 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11371 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11372 0 /*rank*/);
11373 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11374 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11375 .Times(1);
11376 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11377 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11378 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11379
11380 ConnectLeAudio(test_address0);
11381 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11382
11383 // Start streaming
11384 uint8_t cis_count_out = 1;
11385 uint8_t cis_count_in = 0;
11386
11387 LeAudioClient::Get()->SetInCall(true);
11388
11389 // Audio sessions are started only when device gets active
11390 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11391 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11392 LeAudioClient::Get()->GroupSetActive(group_id);
11393 SyncOnMainLoop();
11394
11395 StartStreaming(AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
11396
11397 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11398 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11399 SyncOnMainLoop();
11400
11401 // Verify Data transfer on one audio source cis
11402 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
11403
11404 // Release
11405
11406 /* To be called once only
11407 * 1. GroupStatus::INACTIVE
11408 */
11409 EXPECT_CALL(mock_audio_hal_client_callbacks_, OnGroupStatus(group_id, _)).Times(1);
11410
11411 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
11412 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
11413 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
11414
11415 do_in_main_thread(base::BindOnce(
11416 [](LeAudioClient* client) { client->GroupSetActive(bluetooth::groups::kGroupUnknown); },
11417 LeAudioClient::Get()));
11418
11419 SyncOnMainLoop();
11420 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11421
11422 LeAudioClient::Get()->SetInCall(false);
11423 }
11424
TEST_F(UnicastTest,HandleDatabaseOutOfSync)11425 TEST_F(UnicastTest, HandleDatabaseOutOfSync) {
11426 const RawAddress test_address0 = GetTestAddress(0);
11427 int group_id = bluetooth::groups::kGroupUnknown;
11428
11429 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11430 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11431 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11432 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11433 0 /*rank*/);
11434 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11435 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11436 .Times(1);
11437 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11438 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11439 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11440
11441 ConnectLeAudio(test_address0);
11442 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11443
11444 SyncOnMainLoop();
11445 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11446
11447 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11448 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
11449 .Times(1);
11450 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
11451 SyncOnMainLoop();
11452 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11453 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11454
11455 /* Simulate DATABASE OUT OF SYNC */
11456 ccc_stored_byte_val_ = 0x01;
11457 gatt_read_ctp_ccc_status_ = GATT_DATABASE_OUT_OF_SYNC;
11458
11459 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)).Times(0);
11460 ON_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _)).WillByDefault(Return());
11461 EXPECT_CALL(mock_gatt_interface_, ServiceSearchRequest(_, _));
11462
11463 InjectConnectedEvent(test_address0, 1);
11464 SyncOnMainLoop();
11465 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11466 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11467 }
11468
TEST_F(UnicastTest,TestRemoteDeviceKeepCccValues)11469 TEST_F(UnicastTest, TestRemoteDeviceKeepCccValues) {
11470 const RawAddress test_address0 = GetTestAddress(0);
11471 int group_id = bluetooth::groups::kGroupUnknown;
11472
11473 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11474 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11475 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11476 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11477 0 /*rank*/);
11478 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11479 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11480 .Times(1);
11481 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11482 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11483 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11484
11485 ConnectLeAudio(test_address0);
11486 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11487
11488 SyncOnMainLoop();
11489 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11490
11491 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11492 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
11493 .Times(1);
11494 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
11495 SyncOnMainLoop();
11496 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11497 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11498
11499 /* Simulate remote cache is good */
11500 ccc_stored_byte_val_ = 0x01;
11501
11502 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)).Times(0);
11503 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11504 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11505 .Times(1);
11506
11507 InjectConnectedEvent(test_address0, 1);
11508 SyncOnMainLoop();
11509 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11510 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11511 }
11512
TEST_F(UnicastTest,TestRemoteDeviceForgetsCccValues)11513 TEST_F(UnicastTest, TestRemoteDeviceForgetsCccValues) {
11514 const RawAddress test_address0 = GetTestAddress(0);
11515 int group_id = bluetooth::groups::kGroupUnknown;
11516
11517 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11518 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
11519 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
11520 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
11521 0 /*rank*/);
11522 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11523 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11524 .Times(1);
11525 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11526 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11527 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11528
11529 ConnectLeAudio(test_address0);
11530 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11531
11532 SyncOnMainLoop();
11533 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11534
11535 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11536 OnConnectionState(ConnectionState::DISCONNECTED, test_address0))
11537 .Times(1);
11538 InjectDisconnectedEvent(1, GATT_CONN_TERMINATE_PEER_USER);
11539 SyncOnMainLoop();
11540 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11541 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11542
11543 /* Simulate remote cache is broken */
11544 ccc_stored_byte_val_ = 0;
11545 EXPECT_CALL(mock_gatt_queue_, WriteDescriptor(_, _, _, _, _, _)).Times(AtLeast(1));
11546 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11547 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11548 .Times(1);
11549
11550 InjectConnectedEvent(test_address0, 1);
11551 SyncOnMainLoop();
11552 Mock::VerifyAndClearExpectations(&mock_gatt_queue_);
11553 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11554 }
11555
TEST_F(UnicastTest,SpeakerStreamingTimeout)11556 TEST_F(UnicastTest, SpeakerStreamingTimeout) {
11557 const RawAddress test_address0 = GetTestAddress(0);
11558 int group_id = bluetooth::groups::kGroupUnknown;
11559
11560 SetSampleDatabaseEarbudsValid(
11561 1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
11562 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt, default_channel_cnt, 0x0004,
11563 /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/, true /*add_pacs*/,
11564 default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/, 0 /*rank*/);
11565 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11566 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11567 .Times(1);
11568 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11569 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
11570 .WillOnce(DoAll(SaveArg<1>(&group_id)));
11571
11572 ConnectLeAudio(test_address0);
11573 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
11574
11575 // Start streaming
11576 uint8_t cis_count_out = 1;
11577 uint8_t cis_count_in = 0;
11578
11579 // Audio sessions are started only when device gets active
11580 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
11581 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
11582 LeAudioClient::Get()->GroupSetActive(group_id);
11583 SyncOnMainLoop();
11584
11585 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);
11586
11587 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11588 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
11589 SyncOnMainLoop();
11590
11591 // Verify Data transfer on one audio source cis
11592 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
11593
11594 auto group = streaming_groups.at(group_id);
11595 auto device = group->GetFirstActiveDevice();
11596
11597 // Do not accept direct connect, but expect it to arrive.
11598 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
11599
11600 EXPECT_CALL(mock_btm_interface_, AclDisconnectFromHandle(device->conn_id_, _)).Times(1);
11601 ON_CALL(mock_btm_interface_, AclDisconnectFromHandle(_, _))
11602 .WillByDefault([](uint16_t handle, tHCI_STATUS /*rs*/) {
11603 ASSERT_NE(handle, GATT_INVALID_CONN_ID);
11604 // Do nothing here now.
11605 });
11606
11607 state_machine_callbacks_->OnStateTransitionTimeout(group_id);
11608 SyncOnMainLoop();
11609 ASSERT_EQ(device->GetConnectionState(), DeviceConnectState::DISCONNECTING_AND_RECOVER);
11610
11611 InjectDisconnectedEvent(device->conn_id_, GATT_CONN_TERMINATE_LOCAL_HOST);
11612 SyncOnMainLoop();
11613
11614 /* No assigned cises should remain when transition remains in IDLE state */
11615 ASSERT_NE(0lu, streaming_groups.count(group_id));
11616 ASSERT_EQ(0, static_cast<int>(group->cig.cises.size()));
11617 ASSERT_TRUE(device != nullptr);
11618 ASSERT_EQ(device->GetConnectionState(), DeviceConnectState::CONNECTING_AUTOCONNECT);
11619 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
11620 }
11621
TEST_F(UnicastTest,AddMemberToAllowListWhenOneDeviceConnected)11622 TEST_F(UnicastTest, AddMemberToAllowListWhenOneDeviceConnected) {
11623 uint8_t group_size = 2;
11624 int group_id = 2;
11625 int conn_id_dev_0 = 1;
11626 int conn_id_dev_1 = 2;
11627
11628 /*Scenario to test
11629 * 1. Connect Device A and disconnect
11630 * 2. Connect Device B
11631 * 3. verify Device B is in the allow list with direct connect.
11632 */
11633 // Report working CSIS
11634 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
11635
11636 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
11637 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
11638
11639 // First earbud
11640 const RawAddress test_address0 = GetTestAddress(0);
11641 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
11642
11643 ConnectCsisDevice(test_address0, conn_id_dev_0, codec_spec_conf::kLeAudioLocationFrontLeft,
11644 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
11645
11646 SyncOnMainLoop();
11647
11648 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
11649 EXPECT_CALL(mock_gatt_interface_,
11650 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11651 .Times(1);
11652
11653 InjectDisconnectedEvent(conn_id_dev_0);
11654
11655 SyncOnMainLoop();
11656 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11657
11658 // Second earbud
11659 const RawAddress test_address1 = GetTestAddress(1);
11660 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
11661
11662 /* Do not connect first device but expect Open will arrive.*/
11663 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
11664 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11665 .Times(1);
11666 ON_CALL(mock_gatt_interface_, Open(_, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11667 .WillByDefault(Return());
11668
11669 ConnectCsisDevice(test_address1, conn_id_dev_1, codec_spec_conf::kLeAudioLocationFrontRight,
11670 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
11671 true /*connect_through_csis*/);
11672
11673 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11674 }
11675
TEST_F(UnicastTest,ResetToDefaultReconnectionMode)11676 TEST_F(UnicastTest, ResetToDefaultReconnectionMode) {
11677 uint8_t group_size = 2;
11678 int group_id = 2;
11679 int conn_id_dev_0 = 1;
11680 int conn_id_dev_1 = 2;
11681
11682 /*Scenario to test
11683 * 1. Connect Device A and disconnect
11684 * 2. Connect Device B
11685 * 3. verify Device B is in the allow list.
11686 * 4. Disconnect B device
11687 * 5, Verify A and B device are back in targeted announcement reconnection
11688 * mode
11689 */
11690 // Report working CSIS
11691 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
11692
11693 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
11694 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
11695
11696 // First earbud
11697 const RawAddress test_address0 = GetTestAddress(0);
11698 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
11699
11700 ConnectCsisDevice(test_address0, conn_id_dev_0, codec_spec_conf::kLeAudioLocationFrontLeft,
11701 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
11702
11703 SyncOnMainLoop();
11704
11705 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
11706 EXPECT_CALL(mock_gatt_interface_,
11707 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11708 .Times(1);
11709
11710 InjectDisconnectedEvent(conn_id_dev_0);
11711
11712 SyncOnMainLoop();
11713 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11714
11715 // Second earbud
11716 const RawAddress test_address1 = GetTestAddress(1);
11717 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
11718
11719 /* Verify first earbud will start doing direct connect first */
11720 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
11721 ON_CALL(mock_gatt_interface_, Open(_, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11722 .WillByDefault(Return());
11723 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11724 .Times(1);
11725
11726 ConnectCsisDevice(test_address1, conn_id_dev_1, codec_spec_conf::kLeAudioLocationFrontRight,
11727 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
11728 true /*connect_through_csis*/);
11729
11730 SyncOnMainLoop();
11731 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11732
11733 // Disconnect Device B, expect default reconnection mode for Device A.
11734 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, false)).Times(1);
11735 EXPECT_CALL(mock_gatt_interface_,
11736 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11737 .Times(1);
11738 EXPECT_CALL(mock_gatt_interface_,
11739 Open(gatt_if, test_address1, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11740 .Times(1);
11741 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address1, false)).Times(1);
11742
11743 InjectDisconnectedEvent(conn_id_dev_1, GATT_CONN_TERMINATE_PEER_USER);
11744 SyncOnMainLoop();
11745
11746 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11747 }
11748
TEST_F(UnicastTest,DisconnectAclBeforeGettingReadResponses)11749 TEST_F(UnicastTest, DisconnectAclBeforeGettingReadResponses) {
11750 uint8_t group_size = 2;
11751 int group_id = 2;
11752
11753 // Report working CSIS
11754 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
11755
11756 const RawAddress test_address0 = GetTestAddress(0);
11757 const RawAddress test_address1 = GetTestAddress(1);
11758
11759 /* Due to imitated problems with GATT read operations (status != GATT_SUCCESS)
11760 * a CONNECTED state should not be propagated together with audio location
11761 */
11762 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11763 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11764 .Times(0);
11765 EXPECT_CALL(
11766 mock_audio_hal_client_callbacks_,
11767 OnSinkAudioLocationAvailable(test_address0, codec_spec_conf::kLeAudioLocationFrontLeft))
11768 .Times(0);
11769
11770 // First earbud initial connection
11771 SetSampleDatabaseEarbudsValid(1 /* conn_id */, test_address0,
11772 codec_spec_conf::kLeAudioLocationFrontLeft,
11773 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
11774 default_channel_cnt, 0x0004, /* source sample freq 16khz */
11775 true, /*add_csis*/
11776 true, /*add_cas*/
11777 true, /*add_pacs*/
11778 true, /*add_ascs*/
11779 group_size, 1 /* rank */, GATT_INTERNAL_ERROR);
11780 groups[test_address0] = group_id;
11781 // by default indicate link as encrypted
11782 ON_CALL(mock_btm_interface_, BTM_IsEncrypted(test_address0, _))
11783 .WillByDefault(DoAll(Return(true)));
11784
11785 EXPECT_CALL(mock_gatt_interface_, Open(gatt_if, test_address0, BTM_BLE_DIRECT_CONNECTION, _))
11786 .Times(1);
11787 /* When connected it will got to TA */
11788 EXPECT_CALL(mock_gatt_interface_, CancelOpen(gatt_if, test_address0, _)).Times(1);
11789 EXPECT_CALL(mock_gatt_interface_,
11790 Open(gatt_if, test_address0, BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS, _))
11791 .Times(1);
11792
11793 do_in_main_thread(base::BindOnce(&LeAudioClient::Connect, base::Unretained(LeAudioClient::Get()),
11794 test_address0));
11795
11796 SyncOnMainLoop();
11797 Mock::VerifyAndClearExpectations(&mock_btm_interface_);
11798 Mock::VerifyAndClearExpectations(&mock_gatt_interface_);
11799 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
11800 InjectGroupDeviceAdded(test_address0, group_id);
11801
11802 // Second earbud initial connection
11803 EXPECT_CALL(
11804 mock_audio_hal_client_callbacks_,
11805 OnSinkAudioLocationAvailable(test_address1, codec_spec_conf::kLeAudioLocationFrontRight))
11806 .Times(1);
11807
11808 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
11809 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
11810 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
11811 true /*connect_through_csis*/);
11812
11813 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
11814
11815 /* for Target announcements AutoConnect is always there, until
11816 * device is removed
11817 */
11818 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, false)).Times(0);
11819 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, false)).Times(0);
11820
11821 // Verify grouping information
11822 std::vector<RawAddress> devs = LeAudioClient::Get()->GetGroupDevices(group_id);
11823 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address0), devs.end());
11824 ASSERT_NE(std::find(devs.begin(), devs.end(), test_address1), devs.end());
11825
11826 /* Remove default action on the direct connect */
11827 ON_CALL(mock_gatt_interface_, Open(_, _, BTM_BLE_DIRECT_CONNECTION, _)).WillByDefault(Return());
11828
11829 /* Initiate disconnection with timeout reason, the possible reason why GATT
11830 * read attribute operation may be not handled
11831 */
11832 InjectDisconnectedEvent(1, GATT_CONN_TIMEOUT);
11833 SyncOnMainLoop();
11834
11835 /* After reconnection a sink audio location callback with connection state
11836 * should be propagated.
11837 */
11838 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11839 OnConnectionState(ConnectionState::CONNECTED, test_address0))
11840 .Times(1);
11841 EXPECT_CALL(
11842 mock_audio_hal_client_callbacks_,
11843 OnSinkAudioLocationAvailable(test_address0, codec_spec_conf::kLeAudioLocationFrontLeft))
11844 .Times(1);
11845
11846 /* Prepare valid GATT status responsing attributes */
11847 SetSampleDatabaseEarbudsValid(1 /* conn_id */, test_address0,
11848 codec_spec_conf::kLeAudioLocationFrontLeft,
11849 codec_spec_conf::kLeAudioLocationFrontLeft, default_channel_cnt,
11850 default_channel_cnt, 0x0004, /* source sample freq 16khz */
11851 true, /*add_csis*/
11852 true, /*add_cas*/
11853 true, /*add_pacs*/
11854 true, /*add_ascs*/
11855 group_size, 1 /* rank */);
11856
11857 /* For background connect, test needs to Inject Connected Event */
11858 InjectConnectedEvent(test_address0, 1);
11859 SyncOnMainLoop();
11860 }
11861
TEST_F(UnicastTest,GroupStreamStatus)11862 TEST_F(UnicastTest, GroupStreamStatus) {
11863 int group_id = bluetooth::groups::kGroupUnknown;
11864
11865 InSequence s;
11866
11867 /* Check if all states are properly notified */
11868 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11869 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
11870 .Times(1);
11871 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
11872
11873 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11874 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
11875 .Times(1);
11876 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
11877
11878 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11879 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
11880 .Times(1);
11881 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::RELEASING);
11882
11883 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11884 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
11885 .Times(1);
11886 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
11887
11888 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11889 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
11890 .Times(1);
11891 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::SUSPENDING);
11892
11893 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11894 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
11895 .Times(1);
11896 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
11897
11898 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11899 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
11900 .Times(1);
11901 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::SUSPENDED);
11902
11903 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11904 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
11905 .Times(1);
11906 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
11907
11908 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11909 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
11910 .Times(1);
11911 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::CONFIGURED_AUTONOMOUS);
11912
11913 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11914 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
11915 .Times(1);
11916 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
11917
11918 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11919 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
11920 .Times(1);
11921 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::CONFIGURED_BY_USER);
11922
11923 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11924 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
11925 .Times(1);
11926 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
11927
11928 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11929 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
11930 .Times(1);
11931 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::DESTROYED);
11932
11933 /* Check if there are no resending of the same state */
11934 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::RELEASING);
11935 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::SUSPENDING);
11936 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::SUSPENDED);
11937 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::CONFIGURED_AUTONOMOUS);
11938 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::CONFIGURED_BY_USER);
11939 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
11940
11941 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11942 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
11943 .Times(1);
11944 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
11945 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
11946 }
11947
TEST_F(UnicastTest,GroupStreamStatusManyGroups)11948 TEST_F(UnicastTest, GroupStreamStatusManyGroups) {
11949 uint8_t group_size = 2;
11950 int group_id_1 = 1;
11951 int group_id_2 = 2;
11952
11953 // Report working CSIS
11954 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
11955
11956 ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Return(group_size));
11957
11958 // First group - First earbud
11959 const RawAddress test_address0 = GetTestAddress(0);
11960 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
11961 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
11962 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_1,
11963 1 /* rank*/);
11964
11965 // First group - Second earbud
11966 const RawAddress test_address1 = GetTestAddress(1);
11967 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
11968 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
11969 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id_1,
11970 2 /* rank*/, true /*connect_through_csis*/);
11971
11972 // Second group - First earbud
11973 const RawAddress test_address2 = GetTestAddress(2);
11974 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address2, true)).Times(1);
11975 ConnectCsisDevice(test_address2, 3 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
11976 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id_2,
11977 1 /* rank*/);
11978
11979 // Second group - Second earbud
11980 const RawAddress test_address3 = GetTestAddress(3);
11981 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address3, true)).Times(1);
11982 ConnectCsisDevice(test_address3, 4 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
11983 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id_2,
11984 2 /* rank*/, true /*connect_through_csis*/);
11985
11986 InSequence s;
11987
11988 // Group 1 IDLE
11989 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11990 OnGroupStreamStatus(group_id_1, GroupStreamStatus::IDLE))
11991 .Times(1);
11992 state_machine_callbacks_->StatusReportCb(group_id_1, GroupStreamStatus::IDLE);
11993
11994 // Group 2 IDLE
11995 EXPECT_CALL(mock_audio_hal_client_callbacks_,
11996 OnGroupStreamStatus(group_id_2, GroupStreamStatus::IDLE))
11997 .Times(1);
11998 state_machine_callbacks_->StatusReportCb(group_id_2, GroupStreamStatus::IDLE);
11999
12000 // Group 1 active and start streaming
12001 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12002 OnGroupStreamStatus(group_id_1, GroupStreamStatus::STREAMING))
12003 .Times(1);
12004 LeAudioClient::Get()->GroupSetActive(group_id_1);
12005 SyncOnMainLoop();
12006 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_1);
12007 SyncOnMainLoop();
12008 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12009
12010 // Group 2 active
12011 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12012 OnGroupStreamStatus(group_id_1, GroupStreamStatus::IDLE))
12013 .Times(1);
12014 LeAudioClient::Get()->GroupSetActive(group_id_2);
12015 SyncOnMainLoop();
12016 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12017
12018 // Group 2 start streaming
12019 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12020 OnGroupStreamStatus(group_id_2, GroupStreamStatus::STREAMING))
12021 .Times(1);
12022 StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id_2);
12023 SyncOnMainLoop();
12024 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12025 }
12026
TEST_F(UnicastTest,GroupStreamStatusResendAfterRemove)12027 TEST_F(UnicastTest, GroupStreamStatusResendAfterRemove) {
12028 uint8_t group_size = 2;
12029 int group_id = 1;
12030
12031 // Report working CSIS
12032 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12033
12034 ON_CALL(mock_csis_client_module_, GetDesiredSize(_)).WillByDefault(Return(group_size));
12035
12036 // First earbud
12037 const RawAddress test_address0 = GetTestAddress(0);
12038 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12039 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12040 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12041
12042 // Second earbud
12043 const RawAddress test_address1 = GetTestAddress(1);
12044 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12045 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12046 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12047 true /*connect_through_csis*/);
12048
12049 Mock::VerifyAndClearExpectations(&mock_btif_storage_);
12050
12051 InSequence s;
12052
12053 // Activate group, start streaming and immediately stop
12054 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12055 OnGroupStreamStatus(group_id, GroupStreamStatus::STREAMING))
12056 .Times(1);
12057 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12058 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12059 .Times(1);
12060 LeAudioClient::Get()->GroupSetActive(group_id);
12061 SyncOnMainLoop();
12062 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12063 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12064
12065 // No resend
12066 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12067 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12068 .Times(0);
12069 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12070
12071 // No resend after removing only one device
12072 /*
12073 * StopStream will put calls on main_loop so to keep the correct order
12074 * of operations and to avoid races we put the test command on main_loop as
12075 * well.
12076 */
12077 do_in_main_thread(base::BindOnce(
12078 [](LeAudioClient* client, const RawAddress& test_address0) {
12079 client->RemoveDevice(test_address0);
12080 },
12081 LeAudioClient::Get(), test_address0));
12082 SyncOnMainLoop();
12083 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12084 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12085 .Times(0);
12086 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12087 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12088
12089 // Resend after removing last device
12090 /*
12091 * StopStream will put calls on main_loop so to keep the correct order
12092 * of operations and to avoid races we put the test command on main_loop as
12093 * well.
12094 */
12095 do_in_main_thread(base::BindOnce(
12096 [](LeAudioClient* client, const RawAddress& test_address1) {
12097 client->RemoveDevice(test_address1);
12098 },
12099 LeAudioClient::Get(), test_address1));
12100 SyncOnMainLoop();
12101 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12102 OnGroupStreamStatus(group_id, GroupStreamStatus::IDLE))
12103 .Times(1);
12104 state_machine_callbacks_->StatusReportCb(group_id, GroupStreamStatus::IDLE);
12105 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12106 }
12107
TEST_F(UnicastTestHandoverMode,SetSinkMonitorModeWhileUnicastIsActive)12108 TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsActive) {
12109 uint8_t group_size = 2;
12110 int group_id = 2;
12111
12112 // Report working CSIS
12113 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12114
12115 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
12116 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
12117
12118 // First earbud
12119 const RawAddress test_address0 = GetTestAddress(0);
12120 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12121 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12122 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12123
12124 // Second earbud
12125 const RawAddress test_address1 = GetTestAddress(1);
12126 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12127 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12128 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12129 true /*connect_through_csis*/);
12130
12131 // Start streaming
12132 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12133 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12134 LeAudioClient::Get()->GroupSetActive(group_id);
12135 SyncOnMainLoop();
12136
12137 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12138
12139 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12140
12141 SyncOnMainLoop();
12142 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12143 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12144
12145 // Verify Data transfer on two peer sinks and one source
12146 uint8_t cis_count_out = 2;
12147 uint8_t cis_count_in = 2;
12148 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
12149
12150 // Imitate activation of monitor mode
12151 do_in_main_thread(base::BindOnce(
12152 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12153 bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */));
12154
12155 ASSERT_NE(0lu, streaming_groups.count(group_id));
12156 auto group = streaming_groups.at(group_id);
12157
12158 // Stop streaming and expect Service to be informed about straming suspension
12159 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12160 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12161 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12162 .Times(1);
12163
12164 // Stop
12165 StopStreaming(group_id, true);
12166
12167 // Check if cache configuration is still present
12168 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12169 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12170 .size());
12171 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12172 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12173 .size());
12174
12175 // Release, Sink HAL client should remain in monitor mode
12176 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12177 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12178 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
12179 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
12180 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12181 SyncOnMainLoop();
12182
12183 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12184 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12185 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12186
12187 // Re-initialize mock for destroyed hal client
12188 RegisterSourceHalClientMock();
12189
12190 // Setting group inactive, shall not change cached configuration
12191 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12192 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12193 .size());
12194 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12195 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12196 .size());
12197
12198 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12199 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12200 UnicastMonitorModeStatus::STREAMING_REQUESTED))
12201 .Times(1);
12202
12203 // Start streaming to trigger next group going to IDLE state
12204 LocalAudioSinkResume();
12205
12206 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12207 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12208 LeAudioClient::Get()->GroupSetActive(group_id);
12209 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12210 SyncOnMainLoop();
12211
12212 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12213
12214 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12215 SyncOnMainLoop();
12216 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12217
12218 // Stop streaming and expect Service to be informed about straming suspension
12219 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12220 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12221 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12222 .Times(1);
12223
12224 // Stop
12225 StopStreaming(group_id, true);
12226
12227 // Release, Sink HAL client should remain in monitor mode
12228 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12229 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12230 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
12231 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
12232 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12233 SyncOnMainLoop();
12234
12235 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12236 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12237 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12238
12239 // De-activate monitoring mode
12240 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
12241 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
12242 do_in_main_thread(base::BindOnce(
12243 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12244 bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */));
12245 SyncOnMainLoop();
12246 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12247 }
12248
TEST_F(UnicastTestHandoverMode,SetSinkMonitorModeWhileUnicastIsInactive)12249 TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsInactive) {
12250 uint8_t group_size = 2;
12251 int group_id = 2;
12252
12253 // Imitate activation of monitor mode
12254 do_in_main_thread(base::BindOnce(
12255 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12256 bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */));
12257
12258 // Report working CSIS
12259 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12260
12261 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
12262 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
12263
12264 // First earbud
12265 const RawAddress test_address0 = GetTestAddress(0);
12266 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12267 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12268 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12269
12270 // Second earbud
12271 const RawAddress test_address1 = GetTestAddress(1);
12272 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12273 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12274 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12275 true /*connect_through_csis*/);
12276
12277 // Start streaming
12278 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12279 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12280 LeAudioClient::Get()->GroupSetActive(group_id);
12281 SyncOnMainLoop();
12282
12283 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12284
12285 // Expect no streaming request on stream resume when group is already active
12286 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12287 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12288 UnicastMonitorModeStatus::STREAMING_REQUESTED))
12289 .Times(0);
12290
12291 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12292
12293 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12294 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12295 SyncOnMainLoop();
12296
12297 // Verify Data transfer on two peer sinks and one source
12298 uint8_t cis_count_out = 2;
12299 uint8_t cis_count_in = 2;
12300 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
12301
12302 ASSERT_NE(0lu, streaming_groups.count(group_id));
12303 auto group = streaming_groups.at(group_id);
12304
12305 // Stop streaming and expect Service to be informed about straming suspension
12306 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12307 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12308 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12309 .Times(1);
12310
12311 // Stop
12312 StopStreaming(group_id, true);
12313
12314 // Check if cache configuration is still present
12315 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12316 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12317 .size());
12318 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12319 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12320 .size());
12321
12322 // Release, Sink HAL client should remain in monitor mode
12323 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12324 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12325 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
12326 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
12327 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12328 SyncOnMainLoop();
12329
12330 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12331 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12332 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12333
12334 // Setting group inactive, shall not change cached configuration
12335 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12336 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12337 .size());
12338 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12339 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12340 .size());
12341 }
12342
TEST_F(UnicastTestHandoverMode,ClearSinkMonitorModeWhileUnicastIsActive)12343 TEST_F(UnicastTestHandoverMode, ClearSinkMonitorModeWhileUnicastIsActive) {
12344 uint8_t group_size = 2;
12345 int group_id = 2;
12346
12347 // Imitate activation of monitor mode
12348 do_in_main_thread(base::BindOnce(
12349 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12350 bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */));
12351
12352 // Report working CSIS
12353 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12354
12355 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
12356 .WillByDefault(Invoke([&](int /*group_id*/) { return group_size; }));
12357
12358 // First earbud
12359 const RawAddress test_address0 = GetTestAddress(0);
12360 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12361 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12362 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12363
12364 // Second earbud
12365 const RawAddress test_address1 = GetTestAddress(1);
12366 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12367 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12368 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12369 true /*connect_through_csis*/);
12370
12371 // Start streaming
12372 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12373 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12374 LeAudioClient::Get()->GroupSetActive(group_id);
12375 SyncOnMainLoop();
12376
12377 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12378
12379 // Expect no streaming request on stream resume when group is already active
12380 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12381 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
12382 UnicastMonitorModeStatus::STREAMING_REQUESTED))
12383 .Times(0);
12384
12385 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12386
12387 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12388 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12389 SyncOnMainLoop();
12390
12391 // Verify Data transfer on two peer sinks and one source
12392 uint8_t cis_count_out = 2;
12393 uint8_t cis_count_in = 2;
12394 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
12395
12396 ASSERT_NE(0lu, streaming_groups.count(group_id));
12397 auto group = streaming_groups.at(group_id);
12398
12399 // De-activate monitoring mode
12400 do_in_main_thread(base::BindOnce(
12401 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12402 bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */));
12403
12404 // Stop
12405 StopStreaming(group_id, true);
12406 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12407
12408 // Check if cache configuration is still present
12409 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12410 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12411 .size());
12412 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12413 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12414 .size());
12415
12416 // Release of sink and source hals due to de-activating monitor mode
12417 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12418 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12419 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
12420 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
12421 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12422 SyncOnMainLoop();
12423
12424 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12425 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12426
12427 // Setting group inactive, shall not change cached configuration
12428 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12429 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12430 .size());
12431 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12432 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12433 .size());
12434 }
12435
TEST_F(UnicastTestHandoverMode,SetAndClearSinkMonitorModeWhileUnicastIsInactive)12436 TEST_F(UnicastTestHandoverMode, SetAndClearSinkMonitorModeWhileUnicastIsInactive) {
12437 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(0);
12438 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(0);
12439 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
12440 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(0);
12441 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0);
12442 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0);
12443
12444 // Imitate activation of monitor mode
12445 do_in_main_thread(base::BindOnce(
12446 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12447 bluetooth::le_audio::types::kLeAudioDirectionSink, true /* enable */));
12448 do_in_main_thread(base::BindOnce(
12449 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12450 bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */));
12451
12452 SyncOnMainLoop();
12453
12454 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12455 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12456 }
12457
TEST_F(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsInactive)12458 TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsInactive) {
12459 /* Enabling monitor mode for source while group is not active should result in
12460 * sending STREAMING_SUSPENDED notification.
12461 */
12462 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12463 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12464 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12465 .Times(1);
12466
12467 // Imitate activation of monitor mode
12468 do_in_main_thread(base::BindOnce(
12469 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12470 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12471 SyncOnMainLoop();
12472 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12473 }
12474
TEST_F(UnicastTestHandoverMode,SetTwiceSourceMonitorModeWhileUnicastIsInactive)12475 TEST_F(UnicastTestHandoverMode, SetTwiceSourceMonitorModeWhileUnicastIsInactive) {
12476 /* Enabling monitor mode for source while group is not active should result in
12477 * sending STREAMING_SUSPENDED notification.
12478 */
12479 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12480 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12481 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12482 .Times(1);
12483
12484 // Imitate activation of monitor mode
12485 do_in_main_thread(base::BindOnce(
12486 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12487 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12488 // Imitate second activation of monitor mode - should not be notified
12489 do_in_main_thread(base::BindOnce(
12490 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12491 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12492 SyncOnMainLoop();
12493 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12494 }
12495
TEST_F(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsNotStreaming)12496 TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsNotStreaming) {
12497 int group_id = 2;
12498
12499 LeAudioClient::Get()->GroupSetActive(group_id);
12500
12501 /* Enabling monitor mode for source while group is not active should result in
12502 * sending STREAMING_SUSPENDED notification.
12503 */
12504 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12505 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12506 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12507 .Times(1);
12508
12509 // Imitate activation of monitor mode
12510 do_in_main_thread(base::BindOnce(
12511 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12512 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12513 SyncOnMainLoop();
12514 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12515 }
12516
TEST_F(UnicastTestHandoverMode,SetSourceMonitorModeWhileUnicastIsActive)12517 TEST_F(UnicastTestHandoverMode, SetSourceMonitorModeWhileUnicastIsActive) {
12518 uint8_t group_size = 2;
12519 int group_id = 2;
12520
12521 // Report working CSIS
12522 ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
12523
12524 // First earbud
12525 const RawAddress test_address0 = GetTestAddress(0);
12526 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true)).Times(1);
12527 ConnectCsisDevice(test_address0, 1 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontLeft,
12528 codec_spec_conf::kLeAudioLocationFrontLeft, group_size, group_id, 1 /* rank*/);
12529
12530 // Second earbud
12531 const RawAddress test_address1 = GetTestAddress(1);
12532 EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true)).Times(1);
12533 ConnectCsisDevice(test_address1, 2 /*conn_id*/, codec_spec_conf::kLeAudioLocationFrontRight,
12534 codec_spec_conf::kLeAudioLocationFrontRight, group_size, group_id, 2 /* rank*/,
12535 true /*connect_through_csis*/);
12536
12537 ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
12538 .WillByDefault(Invoke([&](int /*group_id*/) { return 2; }));
12539
12540 // Start streaming
12541 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12542 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12543 LeAudioClient::Get()->GroupSetActive(group_id);
12544 SyncOnMainLoop();
12545
12546 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12547
12548 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12549 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12550 SyncOnMainLoop();
12551
12552 // Verify Data transfer on two peer sinks and one source
12553 uint8_t cis_count_out = 2;
12554 uint8_t cis_count_in = 2;
12555 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
12556
12557 /* Enabling monitor mode for source while stream is active should result in
12558 * sending STREAMING notification.
12559 */
12560 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12561 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12562 UnicastMonitorModeStatus::STREAMING))
12563 .Times(1);
12564
12565 // Imitate activation of monitor mode
12566 do_in_main_thread(base::BindOnce(
12567 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12568 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12569 SyncOnMainLoop();
12570 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12571
12572 ASSERT_NE(0lu, streaming_groups.count(group_id));
12573 auto group = streaming_groups.at(group_id);
12574
12575 // Stop streaming and expect Service to be informed about straming suspension
12576 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12577 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12578 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12579 .Times(1);
12580
12581 // Stop
12582 StopStreaming(group_id, true);
12583
12584 // Check if cache configuration is still present
12585 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12586 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12587 .size());
12588 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12589 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12590 .size());
12591
12592 // Both Sink and Source HAL clients should be stopped
12593 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12594 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12595 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
12596 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
12597 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12598 SyncOnMainLoop();
12599
12600 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12601 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12602 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12603
12604 // Re-initialize mock for destroyed hal client
12605 RegisterSourceHalClientMock();
12606 RegisterSinkHalClientMock();
12607
12608 // Setting group inactive, shall not change cached configuration
12609 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12610 ->confs.get(le_audio::types::kLeAudioDirectionSink)
12611 .size());
12612 ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL)
12613 ->confs.get(le_audio::types::kLeAudioDirectionSource)
12614 .size());
12615
12616 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12617 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12618 UnicastMonitorModeStatus::STREAMING_REQUESTED))
12619 .Times(1);
12620
12621 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12622 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12623 LeAudioClient::Get()->GroupSetActive(group_id);
12624
12625 // Start streaming to trigger next group going to IDLE state
12626 StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id);
12627 SyncOnMainLoop();
12628
12629 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12630 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12631 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12632
12633 // Stop streaming and expect Service to be informed about straming suspension
12634 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12635 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12636 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12637 .Times(1);
12638
12639 // Stop
12640 StopStreaming(group_id, true);
12641
12642 // Both Sink and Source HAL clients should be stopped
12643 EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1);
12644 EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1);
12645 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1);
12646 EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1);
12647 LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);
12648 SyncOnMainLoop();
12649
12650 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12651 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12652 Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
12653
12654 // De-activate monitoring mode
12655 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12656 OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
12657 UnicastMonitorModeStatus::STREAMING_SUSPENDED))
12658 .Times(0);
12659
12660 do_in_main_thread(base::BindOnce(
12661 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12662 bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */));
12663 }
12664
TEST_F(UnicastTestHandoverMode,SetAllowedContextMask)12665 TEST_F(UnicastTestHandoverMode, SetAllowedContextMask) {
12666 const RawAddress test_address0 = GetTestAddress(0);
12667 int group_id = bluetooth::groups::kGroupUnknown;
12668
12669 available_snk_context_types_ =
12670 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
12671 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA |
12672 types::LeAudioContextType::SOUNDEFFECTS)
12673 .value();
12674 available_src_context_types_ = available_snk_context_types_;
12675 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
12676 supported_src_context_types_ =
12677 (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED).value();
12678 /* Don't allow SOUNDEFFECTS context type to be streamed */
12679 int allowed_context_types =
12680 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
12681 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
12682 .value();
12683
12684 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
12685 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
12686 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
12687 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
12688 0 /*rank*/);
12689 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12690 OnConnectionState(ConnectionState::CONNECTED, test_address0))
12691 .Times(1);
12692 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12693 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
12694 .WillOnce(DoAll(SaveArg<1>(&group_id)));
12695
12696 ConnectLeAudio(test_address0);
12697 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
12698
12699 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12700 EXPECT_CALL(mock_state_machine_, StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, _, _))
12701 .Times(0);
12702
12703 LeAudioClient::Get()->GroupSetActive(group_id);
12704 SyncOnMainLoop();
12705
12706 /* Set the same allowed context mask for sink and source */
12707 LeAudioClient::Get()->SetGroupAllowedContextMask(group_id, allowed_context_types,
12708 allowed_context_types);
12709
12710 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, group_id,
12711 AUDIO_SOURCE_INVALID, false, false);
12712
12713 SyncOnMainLoop();
12714 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12715 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12716 }
12717
TEST_F(UnicastTest,NoContextvalidateStreamingRequest)12718 TEST_F(UnicastTest, NoContextvalidateStreamingRequest) {
12719 com::android::bluetooth::flags::provider_->leaudio_no_context_validate_streaming_request(true);
12720
12721 const RawAddress test_address0 = GetTestAddress(0);
12722 int group_id = bluetooth::groups::kGroupUnknown;
12723
12724 available_snk_context_types_ =
12725 (types::LeAudioContextType::RINGTONE | types::LeAudioContextType::CONVERSATIONAL |
12726 types::LeAudioContextType::UNSPECIFIED | types::LeAudioContextType::MEDIA)
12727 .value();
12728 available_src_context_types_ = available_snk_context_types_;
12729 supported_snk_context_types_ = types::kLeAudioContextAllTypes.value();
12730 supported_src_context_types_ =
12731 (types::kLeAudioContextAllRemoteSource | types::LeAudioContextType::UNSPECIFIED).value();
12732
12733 SetSampleDatabaseEarbudsValid(1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
12734 codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
12735 default_channel_cnt, 0x0004, false /*add_csis*/, true /*add_cas*/,
12736 true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
12737 0 /*rank*/);
12738 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12739 OnConnectionState(ConnectionState::CONNECTED, test_address0))
12740 .Times(1);
12741 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12742 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
12743 .WillOnce(DoAll(SaveArg<1>(&group_id)));
12744
12745 ConnectLeAudio(test_address0);
12746 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
12747
12748 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12749 types::BidirectionalPair<types::AudioContexts> metadata = {.sink = types::AudioContexts(),
12750 .source = types::AudioContexts()};
12751 EXPECT_CALL(mock_state_machine_,
12752 StartStream(_, types::LeAudioContextType::SOUNDEFFECTS, metadata, _))
12753 .Times(0);
12754
12755 LeAudioClient::Get()->GroupSetActive(group_id);
12756
12757 // Imitate activation of monitor mode
12758 do_in_main_thread(base::BindOnce(
12759 &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()),
12760 bluetooth::le_audio::types::kLeAudioDirectionSource, true /* enable */));
12761 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12762 SyncOnMainLoop();
12763
12764 // Stop streaming and expect Service to be informed about streaming suspension
12765 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12766 OnUnicastMonitorModeStatus(
12767 bluetooth::le_audio::types::kLeAudioDirectionSource,
12768 UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE))
12769 .Times(1);
12770
12771 StartStreaming(AUDIO_USAGE_ASSISTANCE_SONIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN, group_id,
12772 AUDIO_SOURCE_INVALID, false, false);
12773
12774 SyncOnMainLoop();
12775 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12776 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12777 }
12778
TEST_F(UnicastTest,CodecFrameBlocks2)12779 TEST_F(UnicastTest, CodecFrameBlocks2) {
12780 auto const max_codec_frames_per_sdu = 2;
12781 uint32_t data_len = 1920;
12782
12783 // Register a on-the-fly hook for codec interface mock mutation to prepare the
12784 // codec mock for encoding
12785 std::list<MockCodecInterface*> codec_mocks;
12786 MockCodecInterface::RegisterMockInstanceHook([&](MockCodecInterface* mock, bool is_destroyed) {
12787 if (is_destroyed) {
12788 log::debug("Codec Interface Destroyed: {}", std::format_ptr(mock));
12789 codec_mocks.remove(mock);
12790 } else {
12791 log::debug("Codec Interface Created: {}", std::format_ptr(mock));
12792 ON_CALL(*mock, GetNumOfSamplesPerChannel()).WillByDefault(Return(960));
12793 ON_CALL(*mock, GetNumOfBytesPerSample()).WillByDefault(Return(2)); // 16bits samples
12794 ON_CALL(*mock, Encode(_, _, _, _, _))
12795 .WillByDefault(Return(CodecInterface::Status::STATUS_OK));
12796 codec_mocks.push_back(mock);
12797 }
12798 });
12799
12800 // Add a frame block PAC passing provider
12801 bool is_fb2_passed_as_requirement = false;
12802 ON_CALL(*mock_codec_manager_, GetCodecConfig)
12803 .WillByDefault(Invoke(
12804 [&](const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements&
12805 requirements,
12806 bluetooth::le_audio::CodecManager::UnicastConfigurationProvider provider) {
12807 auto filtered = *bluetooth::le_audio::AudioSetConfigurationProvider::Get()
12808 ->GetConfigurations(requirements.audio_context_type);
12809 // Filter out the dual bidir SWB configurations
12810 if (!bluetooth::le_audio::CodecManager::GetInstance()
12811 ->IsDualBiDirSwbSupported()) {
12812 filtered.erase(
12813 std::remove_if(filtered.begin(), filtered.end(),
12814 [](auto const& el) {
12815 if (el->confs.source.empty()) {
12816 return false;
12817 }
12818 return AudioSetConfigurationProvider::Get()
12819 ->CheckConfigurationIsDualBiDirSwb(*el);
12820 }),
12821 filtered.end());
12822 }
12823 auto cfg = provider(requirements, &filtered);
12824 if (cfg == nullptr) {
12825 return std::unique_ptr<
12826 bluetooth::le_audio::set_configurations::AudioSetConfiguration>(
12827 nullptr);
12828 }
12829
12830 if (requirements.sink_pacs.has_value()) {
12831 for (auto const& rec : requirements.sink_pacs.value()) {
12832 auto caps = rec.codec_spec_caps.GetAsCoreCodecCapabilities();
12833 if (caps.HasSupportedMaxCodecFramesPerSdu()) {
12834 if (caps.supported_max_codec_frames_per_sdu.value() ==
12835 max_codec_frames_per_sdu) {
12836 // Inject the proper Codec Frames Per SDU as the json
12837 // configs are conservative and will always give us 1
12838 for (auto& entry : cfg->confs.sink) {
12839 entry.codec.params.Add(
12840 codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
12841 (uint8_t)max_codec_frames_per_sdu);
12842 }
12843 is_fb2_passed_as_requirement = true;
12844 }
12845 }
12846 }
12847 }
12848 return cfg;
12849 }));
12850
12851 types::BidirectionalPair<stream_parameters> codec_manager_stream_params;
12852 ON_CALL(*mock_codec_manager_, UpdateActiveAudioConfig)
12853 .WillByDefault(
12854 Invoke([&](const types::BidirectionalPair<stream_parameters>& stream_params,
12855 types::BidirectionalPair<uint16_t> /*delays_ms*/,
12856 std::function<void(const offload_config& config, uint8_t direction)>
12857 /*updater*/) { codec_manager_stream_params = stream_params; }));
12858
12859 const RawAddress test_address0 = GetTestAddress(0);
12860 int group_id = bluetooth::groups::kGroupUnknown;
12861
12862 SampleDatabaseParameters remote_params{
12863 .conn_id = 1,
12864 .addr = test_address0,
12865 .add_csis = false,
12866 .set_size = 0,
12867 .rank = 0,
12868 .max_supported_codec_frames_per_sdu = 2,
12869 };
12870 SetSampleDatabaseEarbudsValid(remote_params);
12871
12872 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12873 OnConnectionState(ConnectionState::CONNECTED, test_address0))
12874 .Times(1);
12875 EXPECT_CALL(mock_audio_hal_client_callbacks_,
12876 OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
12877 .WillOnce(DoAll(SaveArg<1>(&group_id)));
12878
12879 ConnectLeAudio(test_address0);
12880 ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);
12881
12882 constexpr int gmcs_ccid = 1;
12883 constexpr int gtbs_ccid = 2;
12884
12885 // Audio sessions are started only when device gets active
12886 EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
12887 EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
12888 LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
12889 LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
12890 LeAudioClient::Get()->GroupSetActive(group_id);
12891 SyncOnMainLoop();
12892
12893 types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid}, .source = {}};
12894 EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);
12895
12896 stay_at_qos_config_in_start_stream = true;
12897
12898 UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
12899 LocalAudioSourceResume(false);
12900
12901 SyncOnMainLoop();
12902 Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
12903 Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
12904 ASSERT_TRUE(is_fb2_passed_as_requirement);
12905
12906 // Verify codec fram blocks per SDU has been applied to the device
12907 ASSERT_NE(0lu, streaming_groups.count(group_id));
12908 uint8_t device_configured_codec_frame_blocks_per_sdu = 0;
12909 auto group = streaming_groups.at(group_id);
12910 for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
12911 device = group->GetNextDevice(device)) {
12912 for (auto& ase : device->ases_) {
12913 if (ase.active) {
12914 auto cfg = ase.codec_config.GetAsCoreCodecConfig();
12915 ASSERT_TRUE(cfg.codec_frames_blocks_per_sdu.has_value());
12916 device_configured_codec_frame_blocks_per_sdu = cfg.codec_frames_blocks_per_sdu.value();
12917 }
12918 }
12919 }
12920
12921 // Verify the configured codec frame blocks per SDU
12922 ASSERT_EQ(device_configured_codec_frame_blocks_per_sdu,
12923 remote_params.max_supported_codec_frames_per_sdu);
12924
12925 EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
12926 do_in_main_thread(base::BindOnce(
12927 [](int group_id,
12928 bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks* state_machine_callbacks) {
12929 state_machine_callbacks->StatusReportCb(group_id, GroupStreamStatus::STREAMING);
12930 },
12931 group_id, base::Unretained(state_machine_callbacks_)));
12932 SyncOnMainLoop();
12933 Mock::VerifyAndClearExpectations(&mock_state_machine_);
12934
12935 // Verify Data transfer on one audio source cis
12936 constexpr uint8_t cis_count_out = 1;
12937 constexpr uint8_t cis_count_in = 0;
12938 TestAudioDataTransfer(group_id, cis_count_out, cis_count_in,
12939 data_len * device_configured_codec_frame_blocks_per_sdu);
12940
12941 ASSERT_NE(codec_mocks.size(), 0ul);
12942
12943 // Verify that the initially started session was updated with the new params
12944 ASSERT_EQ(codec_manager_stream_params.sink.codec_frames_blocks_per_sdu, max_codec_frames_per_sdu);
12945 }
12946
12947 } // namespace bluetooth::le_audio
12948