1 #include "stack/gatt/connection_manager.h"
2 
3 #include <base/bind.h>
4 #include <base/callback.h>
5 #include <base/location.h>
6 #include <gmock/gmock.h>
7 #include <gtest/gtest.h>
8 #include <memory>
9 #include "osi/include/alarm.h"
10 #include "osi/test/alarm_mock.h"
11 
12 using testing::_;
13 using testing::DoAll;
14 using testing::Mock;
15 using testing::Return;
16 using testing::SaveArg;
17 
18 using connection_manager::tAPP_ID;
19 
20 namespace {
21 // convenience mock, for verifying acceptlist operations on lower layer are
22 // actually scheduled
23 class AcceptlistMock {
24  public:
25   MOCK_METHOD1(AcceptlistAdd, bool(const RawAddress&));
26   MOCK_METHOD1(AcceptlistRemove, void(const RawAddress&));
27   MOCK_METHOD0(AcceptlistClear, void());
28   MOCK_METHOD0(SetLeConnectionModeToFast, bool());
29   MOCK_METHOD0(SetLeConnectionModeToSlow, void());
30   MOCK_METHOD2(OnConnectionTimedOut, void(uint8_t, const RawAddress&));
31 };
32 
33 std::unique_ptr<AcceptlistMock> localAcceptlistMock;
34 }  // namespace
35 
36 RawAddress address1{{0x01, 0x01, 0x01, 0x01, 0x01, 0x01}};
37 RawAddress address2{{0x22, 0x22, 0x02, 0x22, 0x33, 0x22}};
38 
39 constexpr tAPP_ID CLIENT1 = 1;
40 constexpr tAPP_ID CLIENT2 = 2;
41 constexpr tAPP_ID CLIENT3 = 3;
42 constexpr tAPP_ID CLIENT10 = 10;
43 
44 // Implementation of btm_ble_bgconn.h API for test.
BTM_AcceptlistAdd(const RawAddress & address)45 bool BTM_AcceptlistAdd(const RawAddress& address) {
46   return localAcceptlistMock->AcceptlistAdd(address);
47 }
48 
BTM_AcceptlistRemove(const RawAddress & address)49 void BTM_AcceptlistRemove(const RawAddress& address) {
50   return localAcceptlistMock->AcceptlistRemove(address);
51 }
52 
BTM_AcceptlistClear()53 void BTM_AcceptlistClear() { return localAcceptlistMock->AcceptlistClear(); }
54 
BTM_SetLeConnectionModeToFast()55 bool BTM_SetLeConnectionModeToFast() {
56   return localAcceptlistMock->SetLeConnectionModeToFast();
57 }
58 
BTM_SetLeConnectionModeToSlow()59 void BTM_SetLeConnectionModeToSlow() {
60   localAcceptlistMock->SetLeConnectionModeToSlow();
61 }
62 
63 namespace bluetooth {
64 namespace shim {
is_gd_l2cap_enabled()65 bool is_gd_l2cap_enabled() { return false; }
66 }  // namespace shim
67 }  // namespace bluetooth
68 
L2CA_ConnectFixedChnl(uint16_t fixed_cid,const RawAddress & bd_addr)69 bool L2CA_ConnectFixedChnl(uint16_t fixed_cid, const RawAddress& bd_addr) {
70   return false;
71 }
72 
73 namespace connection_manager {
74 class BleConnectionManager : public testing::Test {
SetUp()75   void SetUp() override {
76     localAcceptlistMock = std::make_unique<AcceptlistMock>();
77   }
78 
TearDown()79   void TearDown() override {
80     connection_manager::reset(true);
81     AlarmMock::Reset();
82     localAcceptlistMock.reset();
83   }
84 };
85 
on_connection_timed_out(uint8_t app_id,const RawAddress & address)86 void on_connection_timed_out(uint8_t app_id, const RawAddress& address) {
87   localAcceptlistMock->OnConnectionTimedOut(app_id, address);
88 }
89 
90 /** Verify that app can add a device to acceptlist, it is returned as interested
91  * app, and then can remove the device later. */
TEST_F(BleConnectionManager,test_background_connection_add_remove)92 TEST_F(BleConnectionManager, test_background_connection_add_remove) {
93   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1))
94       .WillOnce(Return(true));
95   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
96 
97   EXPECT_TRUE(background_connect_add(CLIENT1, address1));
98 
99   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
100 
101   std::set<tAPP_ID> apps = get_apps_connecting_to(address1);
102   EXPECT_EQ(apps.size(), 1UL);
103   EXPECT_EQ(apps.count(CLIENT1), 1UL);
104 
105   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(_)).Times(0);
106   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1);
107 
108   EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
109 
110   EXPECT_EQ(get_apps_connecting_to(address1).size(), 0UL);
111 
112   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
113 }
114 
115 /** Verify that multiple clients adding same device multiple times, result in
116  * device being added to whtie list only once, also, that device is removed only
117  * after last client removes it. */
TEST_F(BleConnectionManager,test_background_connection_multiple_clients)118 TEST_F(BleConnectionManager, test_background_connection_multiple_clients) {
119   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1))
120       .WillOnce(Return(true));
121   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
122   EXPECT_TRUE(background_connect_add(CLIENT1, address1));
123   EXPECT_TRUE(background_connect_add(CLIENT1, address1));
124   EXPECT_TRUE(background_connect_add(CLIENT2, address1));
125   EXPECT_TRUE(background_connect_add(CLIENT3, address1));
126 
127   EXPECT_EQ(get_apps_connecting_to(address1).size(), 3UL);
128 
129   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
130 
131   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(_)).Times(0);
132 
133   // removing from nonexisting client, should fail
134   EXPECT_FALSE(background_connect_remove(CLIENT10, address1));
135 
136   EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
137   // already removed,  removing from same client twice should return false;
138   EXPECT_FALSE(background_connect_remove(CLIENT1, address1));
139   EXPECT_TRUE(background_connect_remove(CLIENT2, address1));
140 
141   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1);
142   EXPECT_TRUE(background_connect_remove(CLIENT3, address1));
143 
144   EXPECT_EQ(get_apps_connecting_to(address1).size(), 0UL);
145 
146   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
147 }
148 
149 /** Verify adding/removing device to direct connection. */
TEST_F(BleConnectionManager,test_direct_connection_client)150 TEST_F(BleConnectionManager, test_direct_connection_client) {
151   // Direct connect attempt: use faster scan parameters, add to acceptlist,
152   // start 30 timeout
153   EXPECT_CALL(*localAcceptlistMock, SetLeConnectionModeToFast()).Times(1);
154   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1))
155       .WillOnce(Return(true));
156   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
157   EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
158   EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
159   EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
160 
161   // App already doing a direct connection, attempt to re-add result in failure
162   EXPECT_FALSE(direct_connect_add(CLIENT1, address1));
163 
164   // Client that don't do direct connection should fail attempt to stop it
165   EXPECT_FALSE(direct_connect_remove(CLIENT2, address1));
166 
167   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
168 
169   EXPECT_CALL(*localAcceptlistMock, SetLeConnectionModeToSlow()).Times(1);
170   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1);
171   EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
172 
173   // Removal should lower the connection parameters, and free the alarm.
174   // Even though we call AcceptlistRemove, it won't be executed over HCI until
175   // acceptlist is in use, i.e. next connection attempt
176   EXPECT_TRUE(direct_connect_remove(CLIENT1, address1));
177 
178   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
179 }
180 
181 /** Verify direct connection timeout does remove device from acceptlist, and
182  * lower the connection scan parameters */
TEST_F(BleConnectionManager,test_direct_connect_timeout)183 TEST_F(BleConnectionManager, test_direct_connect_timeout) {
184   EXPECT_CALL(*localAcceptlistMock, SetLeConnectionModeToFast()).Times(1);
185   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1))
186       .WillOnce(Return(true));
187   EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
188   alarm_callback_t alarm_callback = nullptr;
189   void* alarm_data = nullptr;
190 
191   EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _))
192       .Times(1)
193       .WillOnce(DoAll(SaveArg<2>(&alarm_callback), SaveArg<3>(&alarm_data)));
194 
195   // Start direct connect attempt...
196   EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
197 
198   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
199 
200   EXPECT_CALL(*localAcceptlistMock, SetLeConnectionModeToSlow()).Times(1);
201   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1);
202   EXPECT_CALL(*localAcceptlistMock, OnConnectionTimedOut(CLIENT1, address1))
203       .Times(1);
204   EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
205 
206   // simulate timeout seconds passed, alarm executing
207   alarm_callback(alarm_data);
208 
209   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
210 }
211 
212 /** Verify that we properly handle successfull direct connection */
TEST_F(BleConnectionManager,test_direct_connection_success)213 TEST_F(BleConnectionManager, test_direct_connection_success) {
214   EXPECT_CALL(*localAcceptlistMock, SetLeConnectionModeToFast()).Times(1);
215   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1))
216       .WillOnce(Return(true));
217   EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
218   EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
219 
220   // Start direct connect attempt...
221   EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
222 
223   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
224 
225   EXPECT_CALL(*localAcceptlistMock, SetLeConnectionModeToSlow()).Times(1);
226   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1);
227   EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
228   // simulate event from lower layers - connections was established
229   // successfully.
230   on_connection_complete(address1);
231 }
232 
233 /** Verify that we properly handle application unregistration */
TEST_F(BleConnectionManager,test_app_unregister)234 TEST_F(BleConnectionManager, test_app_unregister) {
235   /* Test scenario:
236    * - Client 1 connecting to address1 and address2.
237    * - Client 2 connecting to address2
238    * - unregistration of Client1 should trigger address1 removal from acceptlist
239    * - unregistration of Client2 should trigger address2 removal
240    */
241 
242   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1))
243       .WillOnce(Return(true));
244   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address2))
245       .WillOnce(Return(true));
246   EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
247   EXPECT_TRUE(background_connect_add(CLIENT1, address2));
248   EXPECT_TRUE(direct_connect_add(CLIENT2, address2));
249   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
250 
251   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address1)).Times(1);
252   on_app_deregistered(CLIENT1);
253   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
254 
255   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(address2)).Times(1);
256   on_app_deregistered(CLIENT2);
257 }
258 
259 /** Verify adding device to both direct connection and background connection. */
TEST_F(BleConnectionManager,test_direct_and_background_connect)260 TEST_F(BleConnectionManager, test_direct_and_background_connect) {
261   EXPECT_CALL(*localAcceptlistMock, SetLeConnectionModeToFast()).Times(1);
262   EXPECT_CALL(*localAcceptlistMock, AcceptlistAdd(address1))
263       .WillOnce(Return(true));
264   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(0);
265   EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
266   EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
267   // add device as both direct and background connection
268   EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
269   EXPECT_TRUE(background_connect_add(CLIENT1, address1));
270 
271   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
272 
273   EXPECT_CALL(*localAcceptlistMock, SetLeConnectionModeToSlow()).Times(1);
274   EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
275   // not removing from acceptlist yet, as the background connection is still
276   // pending.
277   EXPECT_TRUE(direct_connect_remove(CLIENT1, address1));
278 
279   // remove from acceptlist, because no more interest in device.
280   EXPECT_CALL(*localAcceptlistMock, AcceptlistRemove(_)).Times(1);
281   EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
282 
283   Mock::VerifyAndClearExpectations(localAcceptlistMock.get());
284 }
285 
286 }  // namespace connection_manager
287