1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "chre/pal/util/wifi_scan_cache.h"
18
19 #include <algorithm>
20 #include <cinttypes>
21 #include <cstring>
22
23 #include "chre/platform/log.h"
24 #include "chre/platform/shared/pal_system_api.h"
25 #include "chre/util/fixed_size_vector.h"
26 #include "chre/util/macros.h"
27 #include "chre/util/nanoapp/wifi.h"
28 #include "chre/util/optional.h"
29 #include "chre_api/chre/common.h"
30 #include "gtest/gtest.h"
31
32 namespace {
33
34 /************************************************
35 * Prototypes
36 ***********************************************/
37 void chreWifiScanResponseCallback(bool pending, uint8_t errorCode);
38 void chreWifiScanEventCallback(struct chreWifiScanEvent *event);
39
40 struct WifiScanResponse {
41 bool pending;
42 uint8_t errorCode;
43 };
44
45 /************************************************
46 * Global variables
47 ***********************************************/
48 const chrePalWifiCallbacks gChreWifiPalCallbacks = {
49 .scanResponseCallback = chreWifiScanResponseCallback,
50 .scanEventCallback = chreWifiScanEventCallback,
51 };
52
53 chre::Optional<WifiScanResponse> gWifiScanResponse;
54 chre::FixedSizeVector<chreWifiScanResult, CHRE_PAL_WIFI_SCAN_CACHE_CAPACITY>
55 gWifiScanResultList;
56 chre::Optional<chreWifiScanEvent> gExpectedWifiScanEvent;
57 bool gWifiScanEventCompleted;
58
59 /************************************************
60 * Test class
61 ***********************************************/
62 class WifiScanCacheTests : public ::testing::Test {
63 protected:
SetUp()64 void SetUp() override {
65 clearTestState();
66 EXPECT_TRUE(chreWifiScanCacheInit(&chre::gChrePalSystemApi,
67 &gChreWifiPalCallbacks));
68 }
69
TearDown()70 void TearDown() override {
71 chreWifiScanCacheDeinit();
72 }
73
clearTestState()74 void clearTestState() {
75 gExpectedWifiScanEvent.reset();
76 gWifiScanResponse.reset();
77 while (!gWifiScanResultList.empty()) {
78 gWifiScanResultList.pop_back();
79 }
80 }
81 };
82
83 /************************************************
84 * Private functions
85 ***********************************************/
chreWifiScanResponseCallback(bool pending,uint8_t errorCode)86 void chreWifiScanResponseCallback(bool pending, uint8_t errorCode) {
87 WifiScanResponse response = {
88 .pending = pending,
89 .errorCode = errorCode,
90 };
91 gWifiScanResponse = response;
92 }
93
chreWifiScanEventCallback(struct chreWifiScanEvent * event)94 void chreWifiScanEventCallback(struct chreWifiScanEvent *event) {
95 ASSERT_TRUE(gExpectedWifiScanEvent.has_value());
96 EXPECT_EQ(event->version, gExpectedWifiScanEvent->version);
97 EXPECT_EQ(event->scanType, gExpectedWifiScanEvent->scanType);
98 EXPECT_EQ(event->ssidSetSize, gExpectedWifiScanEvent->ssidSetSize);
99 ASSERT_EQ(event->scannedFreqListLen,
100 gExpectedWifiScanEvent->scannedFreqListLen);
101 if (event->scannedFreqListLen > 0) {
102 ASSERT_NE(event->scannedFreqList, nullptr);
103 EXPECT_EQ(
104 memcmp(gExpectedWifiScanEvent->scannedFreqList, event->scannedFreqList,
105 event->scannedFreqListLen * sizeof(uint32_t)),
106 0);
107 }
108
109 EXPECT_EQ(event->radioChainPref, gExpectedWifiScanEvent->radioChainPref);
110 EXPECT_EQ(event->eventIndex, gExpectedWifiScanEvent->eventIndex);
111 gExpectedWifiScanEvent->eventIndex++;
112
113 for (uint8_t i = 0; i < event->resultCount; i++) {
114 const chreWifiScanResult &result = event->results[i];
115 gWifiScanResultList.push_back(result);
116 }
117
118 if (gWifiScanResultList.size() == event->resultTotal) {
119 gWifiScanEventCompleted = true;
120 }
121
122 chreWifiScanCacheReleaseScanEvent(event);
123 }
124
beginDefaultWifiCache(const uint32_t * scannedFreqList,uint16_t scannedFreqListLen,bool activeScanResult=true)125 void beginDefaultWifiCache(const uint32_t *scannedFreqList,
126 uint16_t scannedFreqListLen,
127 bool activeScanResult = true) {
128 chreWifiScanEvent event;
129 memset(&event, 0, sizeof(chreWifiScanEvent));
130 event.version = CHRE_WIFI_SCAN_EVENT_VERSION;
131 event.scanType = CHRE_WIFI_SCAN_TYPE_ACTIVE;
132 event.scannedFreqList = scannedFreqList;
133 event.scannedFreqListLen = scannedFreqListLen;
134 event.radioChainPref = CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT;
135 gExpectedWifiScanEvent = event;
136
137 chreWifiScanCacheScanEventBegin(
138 static_cast<enum chreWifiScanType>(gExpectedWifiScanEvent->scanType),
139 gExpectedWifiScanEvent->ssidSetSize,
140 gExpectedWifiScanEvent->scannedFreqList,
141 gExpectedWifiScanEvent->scannedFreqListLen,
142 gExpectedWifiScanEvent->radioChainPref, activeScanResult);
143 }
144
cacheDefaultWifiCacheTest(size_t numEvents,const uint32_t * scannedFreqList,uint16_t scannedFreqListLen,bool activeScanResult=true,bool scanMonitoringEnabled=false)145 void cacheDefaultWifiCacheTest(size_t numEvents,
146 const uint32_t *scannedFreqList,
147 uint16_t scannedFreqListLen,
148 bool activeScanResult = true,
149 bool scanMonitoringEnabled = false) {
150 gWifiScanEventCompleted = false;
151 beginDefaultWifiCache(scannedFreqList, scannedFreqListLen, activeScanResult);
152
153 chreWifiScanResult result = {};
154 for (size_t i = 0; i < numEvents; i++) {
155 result.rssi = static_cast<int8_t>(i);
156 memcpy(result.bssid, &i, sizeof(i));
157 chreWifiScanCacheScanEventAdd(&result);
158 }
159
160 chreWifiScanCacheScanEventEnd(CHRE_ERROR_NONE);
161
162 if (activeScanResult) {
163 EXPECT_TRUE(gWifiScanResponse.has_value());
164 EXPECT_EQ(gWifiScanResponse->pending, true);
165 ASSERT_EQ(gWifiScanResponse->errorCode, CHRE_ERROR_NONE);
166 } else {
167 EXPECT_FALSE(gWifiScanResponse.has_value());
168 }
169
170 size_t numEventsExpected = 0;
171 if (activeScanResult || scanMonitoringEnabled) {
172 numEventsExpected = std::min(
173 numEvents, static_cast<size_t>(CHRE_PAL_WIFI_SCAN_CACHE_CAPACITY));
174 ASSERT_TRUE(gWifiScanEventCompleted);
175 }
176
177 ASSERT_EQ(gWifiScanResultList.size(), numEventsExpected);
178 for (size_t i = 0; i < gWifiScanResultList.size(); i++) {
179 // ageMs is not known apriori
180 result.ageMs = gWifiScanResultList[i].ageMs;
181 result.rssi = static_cast<int8_t>(i);
182 memcpy(result.bssid, &i, sizeof(i));
183 EXPECT_EQ(
184 memcmp(&gWifiScanResultList[i], &result, sizeof(chreWifiScanResult)),
185 0);
186 }
187 }
188
testCacheDispatch(size_t numEvents,uint32_t maxScanAgeMs,bool expectSuccess)189 void testCacheDispatch(size_t numEvents, uint32_t maxScanAgeMs,
190 bool expectSuccess) {
191 cacheDefaultWifiCacheTest(numEvents, nullptr /* scannedFreqList */,
192 0 /* scannedFreqListLen */);
193
194 gExpectedWifiScanEvent->eventIndex = 0;
195 gWifiScanResponse.reset();
196 while (!gWifiScanResultList.empty()) {
197 gWifiScanResultList.pop_back();
198 }
199
200 struct chreWifiScanParams params = {
201 .scanType = CHRE_WIFI_SCAN_TYPE_NO_PREFERENCE,
202 .maxScanAgeMs = maxScanAgeMs,
203 .frequencyListLen = 0,
204 .frequencyList = nullptr,
205 .ssidListLen = 0,
206 .ssidList = nullptr,
207 .radioChainPref = CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT,
208 .channelSet = CHRE_WIFI_CHANNEL_SET_NON_DFS,
209 };
210 EXPECT_EQ(chreWifiScanCacheDispatchFromCache(¶ms), expectSuccess);
211
212 EXPECT_EQ(gWifiScanResponse.has_value(), expectSuccess);
213 if (expectSuccess) {
214 EXPECT_TRUE(gWifiScanResponse->pending);
215 EXPECT_EQ(gWifiScanResponse->errorCode, CHRE_ERROR_NONE);
216 }
217
218 EXPECT_EQ(gWifiScanResultList.size(), expectSuccess ? numEvents : 0);
219 }
220
221 } // anonymous namespace
222
223 /************************************************
224 * Tests
225 ***********************************************/
TEST_F(WifiScanCacheTests,SingleWifiResultTest)226 TEST_F(WifiScanCacheTests, SingleWifiResultTest) {
227 cacheDefaultWifiCacheTest(1 /* numEvents */, nullptr /* scannedFreqList */,
228 0 /* scannedFreqListLen */);
229 }
230
TEST_F(WifiScanCacheTests,MultiWifiResultTest)231 TEST_F(WifiScanCacheTests, MultiWifiResultTest) {
232 cacheDefaultWifiCacheTest(
233 CHRE_PAL_WIFI_SCAN_CACHE_MAX_RESULT_COUNT + 1 /* numEvents */,
234 nullptr /* scannedFreqList */, 0 /* scannedFreqListLen */);
235 }
236
TEST_F(WifiScanCacheTests,WifiResultOverflowTest)237 TEST_F(WifiScanCacheTests, WifiResultOverflowTest) {
238 cacheDefaultWifiCacheTest(
239 CHRE_PAL_WIFI_SCAN_CACHE_CAPACITY + 1 /* numEvents */,
240 nullptr /* scannedFreqList */, 0 /* scannedFreqListLen */);
241 }
242
TEST_F(WifiScanCacheTests,EmptyWifiResultTest)243 TEST_F(WifiScanCacheTests, EmptyWifiResultTest) {
244 cacheDefaultWifiCacheTest(0 /* numEvents */, nullptr /* scannedFreqList */,
245 0 /* scannedFreqListLen */);
246 }
247
TEST_F(WifiScanCacheTests,FailedWifiCacheTest)248 TEST_F(WifiScanCacheTests, FailedWifiCacheTest) {
249 beginDefaultWifiCache(nullptr /* scannedFreqList */,
250 0 /* scannedFreqListLen */);
251
252 chreWifiScanCacheScanEventEnd(CHRE_ERROR);
253
254 EXPECT_TRUE(gWifiScanResponse.has_value());
255 EXPECT_FALSE(gWifiScanResponse->pending);
256 EXPECT_EQ(gWifiScanResponse->errorCode, CHRE_ERROR);
257
258 EXPECT_EQ(gWifiScanResultList.size(), 0);
259 }
260
TEST_F(WifiScanCacheTests,FrequencyListTest)261 TEST_F(WifiScanCacheTests, FrequencyListTest) {
262 const uint32_t freqList[2] = {5210, 5240};
263 cacheDefaultWifiCacheTest(1 /* numEvents */, freqList, ARRAY_SIZE(freqList));
264 }
265
TEST_F(WifiScanCacheTests,InvalidFrequencyListTest)266 TEST_F(WifiScanCacheTests, InvalidFrequencyListTest) {
267 beginDefaultWifiCache(nullptr /* scannedFreqList */,
268 1 /* scannedFreqListLen */);
269
270 EXPECT_TRUE(gWifiScanResponse.has_value());
271 EXPECT_FALSE(gWifiScanResponse->pending);
272 EXPECT_EQ(gWifiScanResponse->errorCode, CHRE_ERROR_INVALID_ARGUMENT);
273
274 EXPECT_EQ(gWifiScanResultList.size(), 0);
275 }
276
TEST_F(WifiScanCacheTests,SequentialWifiResultTest)277 TEST_F(WifiScanCacheTests, SequentialWifiResultTest) {
278 cacheDefaultWifiCacheTest(1 /* numEvents */, nullptr /* scannedFreqList */,
279 0 /* scannedFreqListLen */);
280
281 clearTestState();
282 cacheDefaultWifiCacheTest(1 /* numEvents */, nullptr /* scannedFreqList */,
283 0 /* scannedFreqListLen */);
284 }
285
TEST_F(WifiScanCacheTests,ScanMonitorDisabledTest)286 TEST_F(WifiScanCacheTests, ScanMonitorDisabledTest) {
287 cacheDefaultWifiCacheTest(1 /* numEvents */, nullptr /* scannedFreqList */,
288 0 /* scannedFreqListLen */,
289 false /* activeScanResult */,
290 false /* scanMonitoringEnabled */);
291 }
292
TEST_F(WifiScanCacheTests,ScanMonitorEnabledTest)293 TEST_F(WifiScanCacheTests, ScanMonitorEnabledTest) {
294 chreWifiScanCacheConfigureScanMonitor(true /* enable */);
295 cacheDefaultWifiCacheTest(1 /* numEvents */, nullptr /* scannedFreqList */,
296 0 /* scannedFreqListLen */,
297 false /* activeScanResult */,
298 true /* scanMonitoringEnabled */);
299 }
300
TEST_F(WifiScanCacheTests,ScanMonitorEnableDisableTest)301 TEST_F(WifiScanCacheTests, ScanMonitorEnableDisableTest) {
302 chreWifiScanCacheConfigureScanMonitor(true /* enable */);
303 cacheDefaultWifiCacheTest(1 /* numEvents */, nullptr /* scannedFreqList */,
304 0 /* scannedFreqListLen */,
305 false /* activeScanResult */,
306 true /* scanMonitoringEnabled */);
307
308 clearTestState();
309 chreWifiScanCacheConfigureScanMonitor(false /* enable */);
310 cacheDefaultWifiCacheTest(1 /* numEvents */, nullptr /* scannedFreqList */,
311 0 /* scannedFreqListLen */,
312 false /* activeScanResult */,
313 false /* scanMonitoringEnabled */);
314 }
315
TEST_F(WifiScanCacheTests,CacheDispatchTest)316 TEST_F(WifiScanCacheTests, CacheDispatchTest) {
317 testCacheDispatch(1 /* numEvents */, 5000 /* maxScanAgeMs */,
318 true /* expectSuccess */);
319 }
320
TEST_F(WifiScanCacheTests,ZeroMaxScanAgeCacheDispatchTest)321 TEST_F(WifiScanCacheTests, ZeroMaxScanAgeCacheDispatchTest) {
322 testCacheDispatch(1 /* numEvents */, 0 /* maxScanAgeMs */,
323 false /* expectSuccess */);
324 }
325
TEST_F(WifiScanCacheTests,DuplicateScanResultTest)326 TEST_F(WifiScanCacheTests, DuplicateScanResultTest) {
327 beginDefaultWifiCache(nullptr /* scannedFreqList */,
328 0 /* scannedFreqListLen */,
329 true /* activeScanResult */);
330
331 chreWifiScanResult result = {};
332 result.rssi = -98;
333 result.primaryChannel = 5270;
334 const char *dummySsid = "Test ssid";
335 memcpy(result.ssid, dummySsid, strlen(dummySsid));
336 result.ssidLen = strlen(dummySsid);
337 const char *dummyBssid = "12:34:56:78:9a:bc";
338 memcpy(result.bssid, dummyBssid, strlen(dummyBssid));
339 chreWifiScanResult result2 = {};
340 result2.rssi = -98;
341 result2.primaryChannel = 5270;
342 const char *dummySsid2 = "Test ssid 2";
343 memcpy(result2.ssid, dummySsid2, strlen(dummySsid2));
344 result2.ssidLen = strlen(dummySsid2);
345 const char *dummyBssid2 = "34:56:78:9a:bc:de";
346 memcpy(result2.bssid, dummyBssid2, strlen(dummyBssid2));
347
348 chreWifiScanCacheScanEventAdd(&result);
349 chreWifiScanCacheScanEventAdd(&result2);
350 chreWifiScanCacheScanEventAdd(&result);
351
352 chreWifiScanCacheScanEventEnd(CHRE_ERROR_NONE);
353
354 EXPECT_TRUE(gWifiScanResponse.has_value());
355 EXPECT_EQ(gWifiScanResponse->pending, true);
356 ASSERT_EQ(gWifiScanResponse->errorCode, CHRE_ERROR_NONE);
357
358 ASSERT_EQ(gWifiScanResultList.size(), 2);
359 result.ageMs = gWifiScanResultList[0].ageMs;
360 EXPECT_EQ(
361 memcmp(&gWifiScanResultList[0], &result, sizeof(chreWifiScanResult)), 0);
362 result2.ageMs = gWifiScanResultList[1].ageMs;
363 EXPECT_EQ(
364 memcmp(&gWifiScanResultList[1], &result2, sizeof(chreWifiScanResult)), 0);
365 }
366