1 #include "stack/connection_manager/connection_manager.h"
2
3 #include <base/bind_helpers.h>
4 #include <base/functional/bind.h>
5 #include <base/functional/callback.h>
6 #include <base/location.h>
7 #include <gmock/gmock.h>
8 #include <gtest/gtest.h>
9
10 #include <memory>
11
12 #include "osi/include/alarm.h"
13 #include "osi/test/alarm_mock.h"
14 #include "security_device_record.h"
15 #include "stack/btm/neighbor_inquiry.h"
16
17 // TODO(b/369381361) Enfore -Wmissing-prototypes
18 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
19
20 using testing::_;
21 using testing::DoAll;
22 using testing::Mock;
23 using testing::Return;
24 using testing::SaveArg;
25
26 using connection_manager::tAPP_ID;
27
28 namespace {
29 // convenience mock, for verifying acceptlist operations on lower layer are
30 // actually scheduled
31 class AcceptlistMock {
32 public:
33 MOCK_METHOD2(AcceptlistAdd, bool(const RawAddress&, bool is_direct));
34 MOCK_METHOD1(AcceptlistRemove, void(const RawAddress&));
35 MOCK_METHOD0(AcceptlistClear, void());
36 MOCK_METHOD2(OnConnectionTimedOut, void(uint8_t, const RawAddress&));
37
38 /* Not really accept list related, btui still BTM - just for testing put it
39 * here. */
40 MOCK_METHOD2(EnableTargetedAnnouncements, void(bool, tBTM_INQ_RESULTS_CB*));
41 };
42
43 std::unique_ptr<AcceptlistMock> localAcceptlistMock;
44 } // namespace
45
46 RawAddress address1{{0x01, 0x01, 0x01, 0x01, 0x01, 0x01}};
47 RawAddress address2{{0x22, 0x22, 0x02, 0x22, 0x33, 0x22}};
48
49 constexpr tAPP_ID CLIENT1 = 1;
50 constexpr tAPP_ID CLIENT2 = 2;
51 constexpr tAPP_ID CLIENT3 = 3;
52 constexpr tAPP_ID CLIENT10 = 10;
53
BTM_Sec_GetAddressWithType(const RawAddress & bd_addr)54 const tBLE_BD_ADDR BTM_Sec_GetAddressWithType(const RawAddress& bd_addr) {
55 return tBLE_BD_ADDR{.type = BLE_ADDR_PUBLIC, .bda = bd_addr};
56 }
57
btm_find_dev(const RawAddress &)58 tBTM_SEC_DEV_REC* btm_find_dev(const RawAddress& /* bd_addr */) { return nullptr; }
59
60 namespace bluetooth {
61 namespace shim {
62
ACL_AcceptLeConnectionFrom(const tBLE_BD_ADDR & address,bool is_direct)63 bool ACL_AcceptLeConnectionFrom(const tBLE_BD_ADDR& address, bool is_direct) {
64 return localAcceptlistMock->AcceptlistAdd(address.bda, is_direct);
65 }
ACL_IgnoreLeConnectionFrom(const tBLE_BD_ADDR & address)66 void ACL_IgnoreLeConnectionFrom(const tBLE_BD_ADDR& address) {
67 return localAcceptlistMock->AcceptlistRemove(address.bda);
68 }
69
ACL_IgnoreAllLeConnections()70 void ACL_IgnoreAllLeConnections() { return localAcceptlistMock->AcceptlistClear(); }
71
72 } // namespace shim
73 } // namespace bluetooth
74
BTM_BleTargetAnnouncementObserve(bool enable,tBTM_INQ_RESULTS_CB * p_results_cb)75 void BTM_BleTargetAnnouncementObserve(bool enable, tBTM_INQ_RESULTS_CB* p_results_cb) {
76 localAcceptlistMock->EnableTargetedAnnouncements(enable, p_results_cb);
77 }
78
BTM_LogHistory(const std::string &,const RawAddress &,const std::string &)79 void BTM_LogHistory(const std::string& /*tag*/, const RawAddress& /*bd_addr*/,
80 const std::string& /*msg*/) {}
81
82 namespace bluetooth {
83 namespace shim {
set_target_announcements_filter(bool)84 void set_target_announcements_filter(bool /*enable*/) {}
85 } // namespace shim
86 } // namespace bluetooth
87
L2CA_ConnectFixedChnl(uint16_t,const RawAddress &)88 bool L2CA_ConnectFixedChnl(uint16_t /*fixed_cid*/, const RawAddress& /*bd_addr*/) { return false; }
BTM_GetHCIConnHandle(RawAddress const &,unsigned char)89 uint16_t BTM_GetHCIConnHandle(RawAddress const&, unsigned char) { return 0xFFFF; }
90
91 namespace connection_manager {
92 class BleConnectionManager : public testing::Test {
SetUp()93 void SetUp() override {
94 localAcceptlistMock = std::make_unique<AcceptlistMock>();
95 auto alarm_mock = AlarmMock::Get();
96 ON_CALL(*alarm_mock, AlarmNew(_)).WillByDefault(testing::Invoke([](const char* /*name*/) {
97 // We must return something from alarm_new in tests, if we just return
98 // null, unique_ptr will misbehave.
99 return (alarm_t*)new uint8_t[30];
100 }));
101 ON_CALL(*alarm_mock, AlarmFree(_)).WillByDefault(testing::Invoke([](alarm_t* alarm) {
102 if (alarm) {
103 uint8_t* ptr = (uint8_t*)alarm;
104 delete[] ptr;
105 }
106 }));
107 }
108
TearDown()109 void TearDown() override {
110 connection_manager::reset(true);
111 AlarmMock::Reset();
112 localAcceptlistMock.reset();
113 }
114 };
115
on_connection_timed_out(uint8_t app_id,const RawAddress & address)116 void on_connection_timed_out(uint8_t app_id, const RawAddress& address) {
117 localAcceptlistMock->OnConnectionTimedOut(app_id, address);
118 }
119
120 /** Verify that app can add a device to acceptlist, it is returned as interested
121 * app, and then can remove the device later. */
TEST_F(BleConnectionManager,test_background_connection_add_remove)122 TEST_F(BleConnectionManager, test_background_connection_add_remove) {
123 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).WillOnce(Return(true));
124 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
125
126 EXPECT_TRUE(background_connect_add(CLIENT1, address1));
127
128 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
129
130 std::set<tAPP_ID> apps = get_apps_connecting_to(address1);
131 EXPECT_EQ(apps.size(), 1UL);
132 EXPECT_EQ(apps.count(CLIENT1), 1UL);
133
134 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(_, _)).Times(0);
135 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1);
136
137 EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
138
139 EXPECT_EQ(get_apps_connecting_to(address1).size(), 0UL);
140
141 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
142 }
143
144 /** Verify that multiple clients adding same device multiple times, result in
145 * device being added to whtie list only once, also, that device is removed only
146 * after last client removes it. */
TEST_F(BleConnectionManager,test_background_connection_multiple_clients)147 TEST_F(BleConnectionManager, test_background_connection_multiple_clients) {
148 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).WillOnce(Return(true));
149 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
150 EXPECT_TRUE(background_connect_add(CLIENT1, address1));
151 EXPECT_TRUE(background_connect_add(CLIENT1, address1));
152 EXPECT_TRUE(background_connect_add(CLIENT2, address1));
153 EXPECT_TRUE(background_connect_add(CLIENT3, address1));
154
155 EXPECT_EQ(get_apps_connecting_to(address1).size(), 3UL);
156
157 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
158
159 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(_, _)).Times(0);
160
161 // removing from nonexisting client, should fail
162 EXPECT_FALSE(background_connect_remove(CLIENT10, address1));
163
164 EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
165 // already removed, removing from same client twice should return false;
166 EXPECT_FALSE(background_connect_remove(CLIENT1, address1));
167 EXPECT_TRUE(background_connect_remove(CLIENT2, address1));
168
169 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1);
170 EXPECT_TRUE(background_connect_remove(CLIENT3, address1));
171
172 EXPECT_EQ(get_apps_connecting_to(address1).size(), 0UL);
173
174 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
175 }
176
177 /** Verify adding/removing device to direct connection. */
TEST_F(BleConnectionManager,test_direct_connection_client)178 TEST_F(BleConnectionManager, test_direct_connection_client) {
179 // Direct connect attempt: use faster scan parameters, add to acceptlist,
180 // start 30 timeout
181 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, true)).WillOnce(Return(true));
182 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
183 EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
184 EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
185 EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
186
187 // App already doing a direct connection, attempt to re-add result in failure
188 EXPECT_FALSE(direct_connect_add(CLIENT1, address1));
189
190 // Client that don't do direct connection should fail attempt to stop it
191 EXPECT_FALSE(direct_connect_remove(CLIENT2, address1));
192
193 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
194
195 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1);
196 EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
197
198 // Removal should lower the connection parameters, and free the alarm.
199 // Even though we call AcceptlistRemove, it won't be executed over HCI until
200 // acceptlist is in use, i.e. next connection attempt
201 EXPECT_TRUE(direct_connect_remove(CLIENT1, address1));
202
203 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
204 }
205
206 /** Verify direct connection timeout does remove device from acceptlist, and
207 * lower the connection scan parameters */
TEST_F(BleConnectionManager,test_direct_connect_timeout)208 TEST_F(BleConnectionManager, test_direct_connect_timeout) {
209 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, true)).WillOnce(Return(true));
210 EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
211 alarm_callback_t alarm_callback = nullptr;
212 void* alarm_data = nullptr;
213
214 EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _))
215 .Times(1)
216 .WillOnce(DoAll(SaveArg<2>(&alarm_callback), SaveArg<3>(&alarm_data)));
217
218 // Start direct connect attempt...
219 EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
220
221 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
222
223 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1);
224 EXPECT_CALL(*localAcceptlistMock, OnConnectionTimedOut(CLIENT1, address1)).Times(1);
225 EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
226
227 // simulate timeout seconds passed, alarm executing
228 alarm_callback(alarm_data);
229
230 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
231 }
232
233 /** Verify that we properly handle successfull direct connection */
TEST_F(BleConnectionManager,test_direct_connection_success)234 TEST_F(BleConnectionManager, test_direct_connection_success) {
235 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, true)).WillOnce(Return(true));
236 EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
237 EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
238
239 // Start direct connect attempt...
240 EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
241
242 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
243
244 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1);
245 EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
246 // simulate event from lower layers - connections was established
247 // successfully.
248 on_connection_complete(address1);
249 }
250
251 /** Verify that we properly handle application unregistration */
TEST_F(BleConnectionManager,test_app_unregister)252 TEST_F(BleConnectionManager, test_app_unregister) {
253 /* Test scenario:
254 * - Client 1 connecting to address1 and address2.
255 * - Client 2 connecting to address2
256 * - unregistration of Client1 should trigger address1 removal from acceptlist
257 * - unregistration of Client2 should trigger address2 removal
258 */
259
260 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, true)).WillOnce(Return(true));
261 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address2, false)).WillOnce(Return(true));
262 EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
263 EXPECT_TRUE(background_connect_add(CLIENT1, address2));
264 EXPECT_TRUE(direct_connect_add(CLIENT2, address2));
265 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
266
267 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1);
268 on_app_deregistered(CLIENT1);
269 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
270
271 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address2)).Times(1);
272 on_app_deregistered(CLIENT2);
273 }
274
275 /** Verify adding device to both direct connection and background connection. */
TEST_F(BleConnectionManager,test_direct_and_background_connect)276 TEST_F(BleConnectionManager, test_direct_and_background_connect) {
277 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, true)).WillOnce(Return(true));
278 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
279 EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
280 EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
281 // add device as both direct and background connection
282 EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
283 EXPECT_TRUE(background_connect_add(CLIENT1, address1));
284
285 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
286
287 EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
288 // not removing from acceptlist yet, as the background connection is still
289 // pending.
290 EXPECT_TRUE(direct_connect_remove(CLIENT1, address1));
291
292 // remove from acceptlist, because no more interest in device.
293 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1);
294 EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
295
296 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
297 }
298
TEST_F(BleConnectionManager,test_target_announement_connect)299 TEST_F(BleConnectionManager, test_target_announement_connect) {
300 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
301 EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT1, address1));
302 EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT1, address1));
303 }
304
TEST_F(BleConnectionManager,test_add_targeted_announement_when_allow_list_used)305 TEST_F(BleConnectionManager, test_add_targeted_announement_when_allow_list_used) {
306 /* Accept adding to allow list */
307 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).WillOnce(Return(true));
308
309 /* This shall be called when registering announcements */
310 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1);
311 EXPECT_TRUE(background_connect_add(CLIENT1, address1));
312 EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT2, address1));
313
314 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
315 }
316
TEST_F(BleConnectionManager,test_add_background_connect_when_targeted_announcement_are_enabled)317 TEST_F(BleConnectionManager, test_add_background_connect_when_targeted_announcement_are_enabled) {
318 /* Accept adding to allow list */
319 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).Times(0);
320
321 /* This shall be called when registering announcements */
322 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
323
324 EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT2, address1));
325
326 EXPECT_TRUE(background_connect_add(CLIENT1, address1));
327 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
328 }
329
TEST_F(BleConnectionManager,test_re_add_background_connect_to_allow_list)330 TEST_F(BleConnectionManager, test_re_add_background_connect_to_allow_list) {
331 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).Times(0);
332 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
333
334 EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT2, address1));
335
336 EXPECT_TRUE(background_connect_add(CLIENT1, address1));
337 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
338
339 /* Now remove app using targeted announcement and expect device
340 * to be added to white list
341 */
342
343 /* Accept adding to allow list */
344 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).WillOnce(Return(true));
345
346 EXPECT_TRUE(background_connect_remove(CLIENT2, address1));
347 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
348
349 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1);
350 EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
351 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
352 }
353
TEST_F(BleConnectionManager,test_re_add_to_allow_list_after_timeout_with_multiple_clients)354 TEST_F(BleConnectionManager, test_re_add_to_allow_list_after_timeout_with_multiple_clients) {
355 EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
356 alarm_callback_t alarm_callback = nullptr;
357 void* alarm_data = nullptr;
358
359 /* Accept adding to allow list */
360 ON_CALL(*localAcceptlistMock, AcceptlistAdd(address1, _)).WillByDefault(Return(true));
361
362 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).Times(1);
363 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
364
365 EXPECT_TRUE(background_connect_add(CLIENT1, address1));
366
367 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
368
369 EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _))
370 .Times(1)
371 .WillOnce(DoAll(SaveArg<2>(&alarm_callback), SaveArg<3>(&alarm_data)));
372 // Start direct connect attempt...
373 EXPECT_TRUE(direct_connect_add(CLIENT2, address1));
374
375 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
376
377 // simulate timeout seconds passed, alarm executing
378 EXPECT_CALL(*localAcceptlistMock, OnConnectionTimedOut(CLIENT2, address1)).Times(1);
379 EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
380 EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1, false)).Times(1);
381 EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
382 alarm_callback(alarm_data);
383
384 Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
385 }
386
387 } // namespace connection_manager
388