• 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 CREATE_CHRE_TEST_EVENT(SCAN_REQUEST, 20);
37 
38 struct WifiAsyncData {
39   const uint32_t *cookie;
40   chreError errorCode;
41 };
42 
43 class WifiScanRequestQueueTestBase : public TestBase {
44  public:
SetUp()45   void SetUp() {
46     TestBase::SetUp();
47     // Add delay to make sure the requests are queued.
48     chrePalWifiDelayResponse(PalWifiAsyncRequestTypes::SCAN,
49                              std::chrono::seconds(1));
50   }
51 
TearDown()52   void TearDown() {
53     TestBase::TearDown();
54     chrePalWifiDelayResponse(PalWifiAsyncRequestTypes::SCAN,
55                              std::chrono::seconds(0));
56   }
57 };
58 
59 struct WifiScanTestNanoapp : public TestNanoapp {
60   uint32_t perms = NanoappPermissions::CHRE_PERMS_WIFI;
61 
62   decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
__anonc888a3120202chre::__anonc888a3120111::WifiScanTestNanoapp63                                                  const void *eventData) {
64     constexpr uint8_t kMaxPendingCookie = 10;
65     static uint32_t cookies[kMaxPendingCookie];
66     static uint8_t nextFreeCookieIndex = 0;
67 
68     switch (eventType) {
69       case CHRE_EVENT_WIFI_ASYNC_RESULT: {
70         auto *event = static_cast<const chreAsyncResult *>(eventData);
71         TestEventQueueSingleton::get()->pushEvent(
72             CHRE_EVENT_WIFI_ASYNC_RESULT,
73             WifiAsyncData{
74                 .cookie = static_cast<const uint32_t *>(event->cookie),
75                 .errorCode = static_cast<chreError>(event->errorCode)});
76         break;
77       }
78 
79       case CHRE_EVENT_WIFI_SCAN_RESULT: {
80         TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
81         break;
82       }
83 
84       case CHRE_EVENT_TEST_EVENT: {
85         auto event = static_cast<const TestEvent *>(eventData);
86         switch (event->type) {
87           case SCAN_REQUEST:
88             bool success = false;
89             if (nextFreeCookieIndex < kMaxPendingCookie) {
90               cookies[nextFreeCookieIndex] =
91                   *static_cast<uint32_t *>(event->data);
92               success = chreWifiRequestScanAsyncDefault(
93                   &cookies[nextFreeCookieIndex]);
94               nextFreeCookieIndex++;
95             } else {
96               LOGE("Too many cookies passed from test body!");
97             }
98             TestEventQueueSingleton::get()->pushEvent(SCAN_REQUEST, success);
99         }
100       }
101     }
102   };
103 };
104 
TEST_F(TestBase,WifiScanBasicSettingTest)105 TEST_F(TestBase, WifiScanBasicSettingTest) {
106   auto app = loadNanoapp<WifiScanTestNanoapp>();
107 
108   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
109       Setting::WIFI_AVAILABLE, true /* enabled */);
110 
111   constexpr uint32_t firstCookie = 0x1010;
112   bool success;
113   WifiAsyncData wifiAsyncData;
114 
115   sendEventToNanoapp(app, SCAN_REQUEST, firstCookie);
116   waitForEvent(SCAN_REQUEST, &success);
117   EXPECT_TRUE(success);
118 
119   waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
120   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
121   EXPECT_EQ(*wifiAsyncData.cookie, firstCookie);
122   waitForEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
123 
124   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
125       Setting::WIFI_AVAILABLE, false /* enabled */);
126 
127   constexpr uint32_t secondCookie = 0x2020;
128   sendEventToNanoapp(app, SCAN_REQUEST, secondCookie);
129   waitForEvent(SCAN_REQUEST, &success);
130   EXPECT_TRUE(success);
131 
132   waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
133   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_FUNCTION_DISABLED);
134   EXPECT_EQ(*wifiAsyncData.cookie, secondCookie);
135 
136   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
137       Setting::WIFI_AVAILABLE, true /* enabled */);
138   unloadNanoapp(app);
139 }
140 
TEST_F(WifiScanRequestQueueTestBase,WifiQueuedScanSettingChangeTest)141 TEST_F(WifiScanRequestQueueTestBase, WifiQueuedScanSettingChangeTest) {
142   struct WifiScanTestNanoappTwo : public WifiScanTestNanoapp {
143     uint64_t id = 0x1123456789abcdef;
144   };
145 
146   auto firstApp = loadNanoapp<WifiScanTestNanoapp>();
147   auto secondApp = loadNanoapp<WifiScanTestNanoappTwo>();
148 
149   constexpr uint32_t firstRequestCookie = 0x1010;
150   constexpr uint32_t secondRequestCookie = 0x2020;
151   bool success;
152   sendEventToNanoapp(firstApp, SCAN_REQUEST, firstRequestCookie);
153   waitForEvent(SCAN_REQUEST, &success);
154   EXPECT_TRUE(success);
155   sendEventToNanoapp(secondApp, SCAN_REQUEST, secondRequestCookie);
156   waitForEvent(SCAN_REQUEST, &success);
157   EXPECT_TRUE(success);
158 
159   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
160       Setting::WIFI_AVAILABLE, false /* enabled */);
161 
162   WifiAsyncData wifiAsyncData;
163   waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
164   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
165   EXPECT_EQ(*wifiAsyncData.cookie, firstRequestCookie);
166   waitForEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
167 
168   waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
169   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_FUNCTION_DISABLED);
170   EXPECT_EQ(*wifiAsyncData.cookie, secondRequestCookie);
171 
172   EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
173       Setting::WIFI_AVAILABLE, true /* enabled */);
174 
175   unloadNanoapp(firstApp);
176   unloadNanoapp(secondApp);
177 }
178 
TEST_F(WifiScanRequestQueueTestBase,WifiScanRejectRequestFromSameNanoapp)179 TEST_F(WifiScanRequestQueueTestBase, WifiScanRejectRequestFromSameNanoapp) {
180   auto app = loadNanoapp<WifiScanTestNanoapp>();
181 
182   constexpr uint32_t firstRequestCookie = 0x1010;
183   constexpr uint32_t secondRequestCookie = 0x2020;
184   bool success;
185   sendEventToNanoapp(app, SCAN_REQUEST, firstRequestCookie);
186   waitForEvent(SCAN_REQUEST, &success);
187   EXPECT_TRUE(success);
188   sendEventToNanoapp(app, SCAN_REQUEST, secondRequestCookie);
189   waitForEvent(SCAN_REQUEST, &success);
190   EXPECT_FALSE(success);
191 
192   WifiAsyncData wifiAsyncData;
193   waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
194   EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
195   EXPECT_EQ(*wifiAsyncData.cookie, firstRequestCookie);
196   waitForEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
197 
198   unloadNanoapp(app);
199 }
200 
TEST_F(WifiScanRequestQueueTestBase,WifiScanActiveScanFromDistinctNanoapps)201 TEST_F(WifiScanRequestQueueTestBase, WifiScanActiveScanFromDistinctNanoapps) {
202   CREATE_CHRE_TEST_EVENT(CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT,
203                          1);
204   CREATE_CHRE_TEST_EVENT(CONCURRENT_NANOAPP_READ_COOKIE, 2);
205 
206   struct AppCookies {
207     uint32_t sent = 0;
208     uint32_t received = 0;
209   };
210 
211   constexpr uint64_t kAppOneId = 0x0123456789000001;
212   constexpr uint64_t kAppTwoId = 0x0123456789000002;
213 
214   struct WifiScanTestConcurrentNanoappOne : public TestNanoapp {
215     uint32_t perms = NanoappPermissions::CHRE_PERMS_WIFI;
216     uint64_t id = kAppOneId;
217 
218     decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
219                                                    const void *eventData) {
220       constexpr uint8_t kExpectedReceiveAsyncResultCount = 2;
221       static uint8_t receivedCookieCount = 0;
222       static AppCookies appOneCookies;
223       static AppCookies appTwoCookies;
224 
225       // Retrieve cookies from different apps that have the same access to
226       // static storage due to inheritance.
227       AppCookies *appCookies =
228           chreGetAppId() == kAppTwoId ? &appTwoCookies : &appOneCookies;
229 
230       switch (eventType) {
231         case CHRE_EVENT_WIFI_ASYNC_RESULT: {
232           auto *event = static_cast<const chreAsyncResult *>(eventData);
233           if (event->errorCode == CHRE_ERROR_NONE) {
234             appCookies->received =
235                 *static_cast<const uint32_t *>(event->cookie);
236             ++receivedCookieCount;
237           } else {
238             LOGE("Received failed async result");
239           }
240 
241           if (receivedCookieCount == kExpectedReceiveAsyncResultCount) {
242             TestEventQueueSingleton::get()->pushEvent(
243                 CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT);
244           }
245           break;
246         }
247 
248         case CHRE_EVENT_TEST_EVENT: {
249           auto event = static_cast<const TestEvent *>(eventData);
250           bool success = false;
251           uint32_t expectedCookie;
252           switch (event->type) {
253             case SCAN_REQUEST:
254               appCookies->sent = *static_cast<uint32_t *>(event->data);
255               success = chreWifiRequestScanAsyncDefault(&(appCookies->sent));
256               TestEventQueueSingleton::get()->pushEvent(SCAN_REQUEST, success);
257               break;
258             case CONCURRENT_NANOAPP_READ_COOKIE:
259               TestEventQueueSingleton::get()->pushEvent(
260                   CONCURRENT_NANOAPP_READ_COOKIE, appCookies->received);
261               break;
262           }
263         }
264       };
265     };
266   };
267 
268   struct WifiScanTestConcurrentNanoappTwo
269       : public WifiScanTestConcurrentNanoappOne {
270     uint64_t id = kAppTwoId;
271   };
272 
273   auto appOne = loadNanoapp<WifiScanTestConcurrentNanoappOne>();
274   auto appTwo = loadNanoapp<WifiScanTestConcurrentNanoappTwo>();
275 
276   constexpr uint32_t kAppOneRequestCookie = 0x1010;
277   constexpr uint32_t kAppTwoRequestCookie = 0x2020;
278   bool success;
279   sendEventToNanoapp(appOne, SCAN_REQUEST, kAppOneRequestCookie);
280   waitForEvent(SCAN_REQUEST, &success);
281   EXPECT_TRUE(success);
282   sendEventToNanoapp(appTwo, SCAN_REQUEST, kAppTwoRequestCookie);
283   waitForEvent(SCAN_REQUEST, &success);
284   EXPECT_TRUE(success);
285 
286   waitForEvent(CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT);
287 
288   uint32_t receivedCookie;
289   sendEventToNanoapp(appOne, CONCURRENT_NANOAPP_READ_COOKIE);
290   waitForEvent(CONCURRENT_NANOAPP_READ_COOKIE, &receivedCookie);
291   EXPECT_EQ(kAppOneRequestCookie, receivedCookie);
292 
293   sendEventToNanoapp(appTwo, CONCURRENT_NANOAPP_READ_COOKIE);
294   waitForEvent(CONCURRENT_NANOAPP_READ_COOKIE, &receivedCookie);
295   EXPECT_EQ(kAppTwoRequestCookie, receivedCookie);
296 
297   unloadNanoapp(appOne);
298   unloadNanoapp(appTwo);
299 }
300 
301 }  // namespace
302 }  // namespace chre