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(&params), 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   result.rssi = -98;
341   result.primaryChannel = 5270;
342   const char *dummySsid2 = "Test ssid 2";
343   memcpy(result.ssid, dummySsid, strlen(dummySsid2));
344   result.ssidLen = strlen(dummySsid);
345   const char *dummyBssid2 = "34:56:78:9a:bc:de";
346   memcpy(result.bssid, dummyBssid, 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