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