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