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