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