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