xref: /aosp_15_r20/system/chre/test/simulation/wifi_scan_test.cc (revision 84e339476a462649f82315436d70fd732297a399)
1 /*
2  * Copyright (C) 2022 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 <cstdint>
18 
19 #include "chre/core/event_loop_manager.h"
20 #include "chre/core/settings.h"
21 #include "chre/platform/linux/pal_nan.h"
22 #include "chre/platform/linux/pal_wifi.h"
23 #include "chre/platform/log.h"
24 #include "chre/util/system/napp_permissions.h"
25 #include "chre_api/chre/event.h"
26 #include "chre_api/chre/wifi.h"
27 #include "gtest/gtest.h"
28 #include "test_base.h"
29 #include "test_event.h"
30 #include "test_event_queue.h"
31 #include "test_util.h"
32 
33 namespace chre {
34 namespace {
35 using namespace std::chrono_literals;
36 
37 CREATE_CHRE_TEST_EVENT(SCAN_REQUEST, 20);
38 
39 struct WifiAsyncData {
40   const uint32_t *cookie;
41   chreError errorCode;
42 };
43 
44 constexpr uint64_t kAppOneId = 0x0123456789000001;
45 constexpr uint64_t kAppTwoId = 0x0123456789000002;
46 
47 class WifiScanRequestQueueTestBase : public TestBase {
48  public:
SetUp()49   void SetUp() {
50     TestBase::SetUp();
51     // Add delay to make sure the requests are queued.
52     chrePalWifiDelayResponse(PalWifiAsyncRequestTypes::SCAN,
53                              /* milliseconds= */ 100ms);
54   }
55 
TearDown()56   void TearDown() {
57     TestBase::TearDown();
58     chrePalWifiDelayResponse(PalWifiAsyncRequestTypes::SCAN,
59                              /* milliseconds= */ 0ms);
60   }
61 };
62 
63 class WifiScanTestNanoapp : public TestNanoapp {
64  public:
WifiScanTestNanoapp()65   WifiScanTestNanoapp()
66       : TestNanoapp(
67             TestNanoappInfo{.perms = NanoappPermissions::CHRE_PERMS_WIFI}) {}
68 
WifiScanTestNanoapp(uint64_t id)69   explicit WifiScanTestNanoapp(uint64_t id)
70       : TestNanoapp(TestNanoappInfo{
71             .id = id, .perms = NanoappPermissions::CHRE_PERMS_WIFI}) {}
72 
handleEvent(uint32_t,uint16_t eventType,const void * eventData)73   void handleEvent(uint32_t, uint16_t eventType,
74                    const void *eventData) override {
75     switch (eventType) {
76       case CHRE_EVENT_WIFI_ASYNC_RESULT: {
77         auto *event = static_cast<const chreAsyncResult *>(eventData);
78         TestEventQueueSingleton::get()->pushEvent(
79             CHRE_EVENT_WIFI_ASYNC_RESULT,
80             WifiAsyncData{
81                 .cookie = static_cast<const uint32_t *>(event->cookie),
82                 .errorCode = static_cast<chreError>(event->errorCode)});
83         break;
84       }
85 
86       case CHRE_EVENT_WIFI_SCAN_RESULT: {
87         TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
88         break;
89       }
90 
91       case CHRE_EVENT_TEST_EVENT: {
92         auto event = static_cast<const TestEvent *>(eventData);
93         switch (event->type) {
94           case SCAN_REQUEST:
95             bool success = false;
96             if (mNextFreeCookieIndex < kMaxPendingCookie) {
97               mCookies[mNextFreeCookieIndex] =
98                   *static_cast<uint32_t *>(event->data);
99               success = chreWifiRequestScanAsyncDefault(
100                   &mCookies[mNextFreeCookieIndex]);
101               mNextFreeCookieIndex++;
102             } else {
103               LOGE("Too many cookies passed from test body!");
104             }
105             TestEventQueueSingleton::get()->pushEvent(SCAN_REQUEST, success);
106         }
107       }
108     }
109   }
110 
111  protected:
112   static constexpr uint8_t kMaxPendingCookie = 10;
113   uint32_t mCookies[kMaxPendingCookie];
114   uint8_t mNextFreeCookieIndex = 0;
115 };
116 
TEST_F(TestBase,WifiScanBasicSettingTest)117 TEST_F(TestBase, WifiScanBasicSettingTest) {
118   uint64_t appId = loadNanoapp(MakeUnique<WifiScanTestNanoapp>());
119 
120   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
121       Setting::WIFI_AVAILABLE, true /* enabled */);
122 
123   constexpr uint32_t firstCookie = 0x1010;
124   bool success;
125   WifiAsyncData wifiAsyncData;
126 
127   sendEventToNanoapp(appId, SCAN_REQUEST, firstCookie);
128   waitForEvent(SCAN_REQUEST, &success);
129   EXPECT_TRUE(success);
130 
131   waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
132   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
133   EXPECT_EQ(*wifiAsyncData.cookie, firstCookie);
134   waitForEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
135 
136   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
137       Setting::WIFI_AVAILABLE, false /* enabled */);
138 
139   constexpr uint32_t secondCookie = 0x2020;
140   sendEventToNanoapp(appId, SCAN_REQUEST, secondCookie);
141   waitForEvent(SCAN_REQUEST, &success);
142   EXPECT_TRUE(success);
143 
144   waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
145   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_FUNCTION_DISABLED);
146   EXPECT_EQ(*wifiAsyncData.cookie, secondCookie);
147 
148   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
149       Setting::WIFI_AVAILABLE, true /* enabled */);
150   unloadNanoapp(appId);
151 }
152 
TEST_F(WifiScanRequestQueueTestBase,WifiQueuedScanSettingChangeTest)153 TEST_F(WifiScanRequestQueueTestBase, WifiQueuedScanSettingChangeTest) {
154   CREATE_CHRE_TEST_EVENT(CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT,
155                          1);
156   CREATE_CHRE_TEST_EVENT(CONCURRENT_NANOAPP_READ_ASYNC_EVENT, 2);
157   // Expecting to receive two event, one from each nanoapp.
158   constexpr uint8_t kExpectedReceiveAsyncResultCount = 2;
159   // receivedAsyncEventCount is shared across apps and must be static.
160   // But we want it initialized each time the test is executed.
161   static uint8_t receivedAsyncEventCount;
162   receivedAsyncEventCount = 0;
163 
164   class WifiScanTestConcurrentNanoapp : public TestNanoapp {
165    public:
166     explicit WifiScanTestConcurrentNanoapp(uint64_t id)
167         : TestNanoapp(TestNanoappInfo{
168               .id = id, .perms = NanoappPermissions::CHRE_PERMS_WIFI}) {}
169 
170     void handleEvent(uint32_t, uint16_t eventType,
171                      const void *eventData) override {
172       switch (eventType) {
173         case CHRE_EVENT_WIFI_ASYNC_RESULT: {
174           auto *event = static_cast<const chreAsyncResult *>(eventData);
175           mReceivedAsyncResult = WifiAsyncData{
176               .cookie = static_cast<const uint32_t *>(event->cookie),
177               .errorCode = static_cast<chreError>(event->errorCode)};
178           ++receivedAsyncEventCount;
179           break;
180         }
181 
182         case CHRE_EVENT_TEST_EVENT: {
183           auto event = static_cast<const TestEvent *>(eventData);
184           bool success = false;
185           switch (event->type) {
186             case SCAN_REQUEST:
187               mSentCookie = *static_cast<uint32_t *>(event->data);
188               success = chreWifiRequestScanAsyncDefault(&(mSentCookie));
189               TestEventQueueSingleton::get()->pushEvent(SCAN_REQUEST, success);
190               break;
191             case CONCURRENT_NANOAPP_READ_ASYNC_EVENT:
192               TestEventQueueSingleton::get()->pushEvent(
193                   CONCURRENT_NANOAPP_READ_ASYNC_EVENT, mReceivedAsyncResult);
194               break;
195           }
196         }
197       }
198 
199       if (receivedAsyncEventCount == kExpectedReceiveAsyncResultCount) {
200         TestEventQueueSingleton::get()->pushEvent(
201             CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT);
202       }
203     }
204 
205    protected:
206     uint32_t mSentCookie;
207     WifiAsyncData mReceivedAsyncResult;
208   };
209 
210   uint64_t appOneId =
211       loadNanoapp(MakeUnique<WifiScanTestConcurrentNanoapp>(kAppOneId));
212   uint64_t appTwoId =
213       loadNanoapp(MakeUnique<WifiScanTestConcurrentNanoapp>(kAppTwoId));
214 
215   constexpr uint32_t appOneRequestCookie = 0x1010;
216   constexpr uint32_t appTwoRequestCookie = 0x2020;
217   bool success;
218   sendEventToNanoapp(appOneId, SCAN_REQUEST, appOneRequestCookie);
219   waitForEvent(SCAN_REQUEST, &success);
220   EXPECT_TRUE(success);
221   sendEventToNanoapp(appTwoId, SCAN_REQUEST, appTwoRequestCookie);
222   waitForEvent(SCAN_REQUEST, &success);
223   EXPECT_TRUE(success);
224 
225   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
226       Setting::WIFI_AVAILABLE, false /* enabled */);
227 
228   // We need to make sure that each nanoapp has received one async result before
229   // further analysis.
230   waitForEvent(CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT);
231 
232   WifiAsyncData wifiAsyncData;
233   sendEventToNanoapp(appOneId, CONCURRENT_NANOAPP_READ_ASYNC_EVENT);
234   waitForEvent(CONCURRENT_NANOAPP_READ_ASYNC_EVENT, &wifiAsyncData);
235   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
236   EXPECT_EQ(*wifiAsyncData.cookie, appOneRequestCookie);
237 
238   sendEventToNanoapp(appTwoId, CONCURRENT_NANOAPP_READ_ASYNC_EVENT);
239   waitForEvent(CONCURRENT_NANOAPP_READ_ASYNC_EVENT, &wifiAsyncData);
240   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_FUNCTION_DISABLED);
241   EXPECT_EQ(*wifiAsyncData.cookie, appTwoRequestCookie);
242 
243   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
244       Setting::WIFI_AVAILABLE, true /* enabled */);
245 
246   unloadNanoapp(appOneId);
247   unloadNanoapp(appTwoId);
248 }
249 
TEST_F(WifiScanRequestQueueTestBase,WifiScanRejectRequestFromSameNanoapp)250 TEST_F(WifiScanRequestQueueTestBase, WifiScanRejectRequestFromSameNanoapp) {
251   CREATE_CHRE_TEST_EVENT(RECEIVED_ALL_EXPECTED_EVENTS, 1);
252   CREATE_CHRE_TEST_EVENT(READ_ASYNC_EVENT, 2);
253 
254   static constexpr uint8_t kExpectedReceivedScanRequestCount = 2;
255 
256   class WifiScanTestBufferedAsyncResultNanoapp : public TestNanoapp {
257    public:
258     WifiScanTestBufferedAsyncResultNanoapp()
259         : TestNanoapp(
260               TestNanoappInfo{.perms = NanoappPermissions::CHRE_PERMS_WIFI}) {}
261 
262     void handleEvent(uint32_t, uint16_t eventType,
263                      const void *eventData) override {
264       switch (eventType) {
265         case CHRE_EVENT_WIFI_ASYNC_RESULT: {
266           auto *event = static_cast<const chreAsyncResult *>(eventData);
267           mReceivedAsyncResult = WifiAsyncData{
268               .cookie = static_cast<const uint32_t *>(event->cookie),
269               .errorCode = static_cast<chreError>(event->errorCode)};
270           ++mReceivedAsyncEventCount;
271           break;
272         }
273 
274         case CHRE_EVENT_TEST_EVENT: {
275           auto event = static_cast<const TestEvent *>(eventData);
276           bool success = false;
277           switch (event->type) {
278             case SCAN_REQUEST:
279               if (mReceivedScanRequestCount >=
280                   kExpectedReceivedScanRequestCount) {
281                 LOGE("Asking too many scan request");
282               } else {
283                 mReceivedCookies[mReceivedScanRequestCount] =
284                     *static_cast<uint32_t *>(event->data);
285                 success = chreWifiRequestScanAsyncDefault(
286                     &(mReceivedCookies[mReceivedScanRequestCount]));
287                 ++mReceivedScanRequestCount;
288                 TestEventQueueSingleton::get()->pushEvent(SCAN_REQUEST,
289                                                           success);
290               }
291               break;
292             case READ_ASYNC_EVENT:
293               TestEventQueueSingleton::get()->pushEvent(READ_ASYNC_EVENT,
294                                                         mReceivedAsyncResult);
295               break;
296           }
297         }
298       }
299       if (mReceivedAsyncEventCount == kExpectedReceivedAsyncResultCount &&
300           mReceivedScanRequestCount == kExpectedReceivedScanRequestCount) {
301         TestEventQueueSingleton::get()->pushEvent(RECEIVED_ALL_EXPECTED_EVENTS);
302       }
303     }
304 
305    protected:
306     // We are only expecting to receive one async result since the second
307     // request is expected to fail.
308     const uint8_t kExpectedReceivedAsyncResultCount = 1;
309     uint8_t mReceivedAsyncEventCount = 0;
310     uint8_t mReceivedScanRequestCount = 0;
311 
312     // We need to have two cookie storage to separate the two scan request.
313     uint32_t mReceivedCookies[kExpectedReceivedScanRequestCount];
314     WifiAsyncData mReceivedAsyncResult;
315   };
316 
317   uint64_t appId =
318       loadNanoapp(MakeUnique<WifiScanTestBufferedAsyncResultNanoapp>());
319 
320   constexpr uint32_t kFirstRequestCookie = 0x1010;
321   constexpr uint32_t kSecondRequestCookie = 0x2020;
322   bool success;
323   sendEventToNanoapp(appId, SCAN_REQUEST, kFirstRequestCookie);
324   waitForEvent(SCAN_REQUEST, &success);
325   EXPECT_TRUE(success);
326   sendEventToNanoapp(appId, SCAN_REQUEST, kSecondRequestCookie);
327   waitForEvent(SCAN_REQUEST, &success);
328   EXPECT_FALSE(success);
329 
330   // We need to make sure that the nanoapp has received one async result and did
331   // two scan requests before further analysis.
332   waitForEvent(RECEIVED_ALL_EXPECTED_EVENTS);
333 
334   WifiAsyncData wifiAsyncData;
335   sendEventToNanoapp(appId, READ_ASYNC_EVENT);
336   waitForEvent(READ_ASYNC_EVENT, &wifiAsyncData);
337   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
338   EXPECT_EQ(*wifiAsyncData.cookie, kFirstRequestCookie);
339 
340   unloadNanoapp(appId);
341 }
342 
TEST_F(WifiScanRequestQueueTestBase,WifiScanActiveScanFromDistinctNanoapps)343 TEST_F(WifiScanRequestQueueTestBase, WifiScanActiveScanFromDistinctNanoapps) {
344   CREATE_CHRE_TEST_EVENT(CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT,
345                          1);
346   CREATE_CHRE_TEST_EVENT(CONCURRENT_NANOAPP_READ_COOKIE, 2);
347 
348   constexpr uint8_t kExpectedReceiveAsyncResultCount = 2;
349   // receivedCookieCount is shared across apps and must be static.
350   // But we want it initialized each time the test is executed.
351   static uint8_t receivedCookieCount;
352   receivedCookieCount = 0;
353 
354   class WifiScanTestConcurrentNanoapp : public TestNanoapp {
355    public:
356     explicit WifiScanTestConcurrentNanoapp(uint64_t id)
357         : TestNanoapp(TestNanoappInfo{
358               .id = id, .perms = NanoappPermissions::CHRE_PERMS_WIFI}) {}
359 
360     void handleEvent(uint32_t, uint16_t eventType,
361                      const void *eventData) override {
362       switch (eventType) {
363         case CHRE_EVENT_WIFI_ASYNC_RESULT: {
364           auto *event = static_cast<const chreAsyncResult *>(eventData);
365           if (event->errorCode == CHRE_ERROR_NONE) {
366             mReceivedCookie = *static_cast<const uint32_t *>(event->cookie);
367             ++receivedCookieCount;
368           } else {
369             LOGE("Received failed async result");
370           }
371 
372           if (receivedCookieCount == kExpectedReceiveAsyncResultCount) {
373             TestEventQueueSingleton::get()->pushEvent(
374                 CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT);
375           }
376           break;
377         }
378 
379         case CHRE_EVENT_TEST_EVENT: {
380           auto event = static_cast<const TestEvent *>(eventData);
381           bool success = false;
382           switch (event->type) {
383             case SCAN_REQUEST:
384               mSentCookie = *static_cast<uint32_t *>(event->data);
385               success = chreWifiRequestScanAsyncDefault(&(mSentCookie));
386               TestEventQueueSingleton::get()->pushEvent(SCAN_REQUEST, success);
387               break;
388             case CONCURRENT_NANOAPP_READ_COOKIE:
389               TestEventQueueSingleton::get()->pushEvent(
390                   CONCURRENT_NANOAPP_READ_COOKIE, mReceivedCookie);
391               break;
392           }
393         }
394       }
395     }
396 
397    protected:
398     uint32_t mSentCookie;
399     uint32_t mReceivedCookie;
400   };
401 
402   uint64_t appOneId =
403       loadNanoapp(MakeUnique<WifiScanTestConcurrentNanoapp>(kAppOneId));
404   uint64_t appTwoId =
405       loadNanoapp(MakeUnique<WifiScanTestConcurrentNanoapp>(kAppTwoId));
406 
407   constexpr uint32_t kAppOneRequestCookie = 0x1010;
408   constexpr uint32_t kAppTwoRequestCookie = 0x2020;
409   bool success;
410   sendEventToNanoapp(appOneId, SCAN_REQUEST, kAppOneRequestCookie);
411   waitForEvent(SCAN_REQUEST, &success);
412   EXPECT_TRUE(success);
413   sendEventToNanoapp(appTwoId, SCAN_REQUEST, kAppTwoRequestCookie);
414   waitForEvent(SCAN_REQUEST, &success);
415   EXPECT_TRUE(success);
416 
417   waitForEvent(CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT);
418 
419   uint32_t receivedCookie;
420   sendEventToNanoapp(appOneId, CONCURRENT_NANOAPP_READ_COOKIE);
421   waitForEvent(CONCURRENT_NANOAPP_READ_COOKIE, &receivedCookie);
422   EXPECT_EQ(kAppOneRequestCookie, receivedCookie);
423 
424   sendEventToNanoapp(appTwoId, CONCURRENT_NANOAPP_READ_COOKIE);
425   waitForEvent(CONCURRENT_NANOAPP_READ_COOKIE, &receivedCookie);
426   EXPECT_EQ(kAppTwoRequestCookie, receivedCookie);
427 
428   unloadNanoapp(appOneId);
429   unloadNanoapp(appTwoId);
430 }
431 
432 }  // namespace
433 }  // namespace chre