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