• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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