1 /*
2 * Copyright (C) 2018 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 <general_test/basic_wifi_test.h>
18
19 #include <algorithm>
20 #include <cinttypes>
21 #include <cmath>
22
23 #include <shared/macros.h>
24 #include <shared/send_message.h>
25 #include <shared/time_util.h>
26
27 #include "chre/util/nanoapp/log.h"
28 #include "chre/util/time.h"
29 #include "chre/util/unique_ptr.h"
30 #include "chre_api/chre.h"
31
32 using nanoapp_testing::sendSuccessToHost;
33
34 #define LOG_TAG "[BasicWifiTest]"
35
36 /*
37 * Test to check expected functionality of the CHRE WiFi APIs.
38 *
39 * 1. If scan monitor is not supported, skips to 3;
40 * otherwise enables scan monitor.
41 * 2. Checks async result of enabling scan monitor.
42 * 3. If on demand WiFi scan is not supported, skips to 5;
43 * otherwise sends default scan request.
44 * 4. Checks the result of on demand WiFi scan.
45 * 5. If scan monitor is supported then disables scan monitor;
46 * otherwise go to step 7.
47 * 6. Checks async result of disabling scan monitor.
48 * 7. If a scan has ever happened runs the ranging test; otherwise
49 * go to the end.
50 * 8. Checks the ranging test result.
51 * 9. end
52 */
53 namespace general_test {
54
55 namespace {
56
57 //! A fake/unused cookie to pass into the enable configure scan monitoring async
58 //! request.
59 constexpr uint32_t kEnableScanMonitoringCookie = 0x1337;
60
61 //! A fake/unused cookie to pass into the disable configure scan monitoring
62 //! async request.
63 constexpr uint32_t kDisableScanMonitoringCookie = 0x1338;
64
65 //! A fake/unused cookie to pass into request ranging async.
66 constexpr uint32_t kRequestRangingCookie = 0xefac;
67
68 //! A fake/unused cookie to pass into request scan async.
69 constexpr uint32_t kOnDemandScanCookie = 0xcafe;
70
71 //! Starting frequency of band 2.4 GHz
72 constexpr uint32_t kWifiBandStartFreq_2_4_GHz = 2407;
73
74 //! Starting frequency of band 5 GHz
75 constexpr uint32_t kWifiBandStartFreq_5_GHz = 5000;
76
77 //! Frequency of channel 14
78 constexpr uint32_t kWifiBandFreqOfChannel_14 = 2484;
79
80 //! The amount of time to allow between an operation timing out and the event
81 //! being deliverd to the test.
82 constexpr uint32_t kTimeoutWiggleRoomNs = 2 * chre::kOneSecondInNanoseconds;
83
84 // Number of seconds waited before retrying when an on demand wifi scan fails.
85 constexpr uint64_t kOnDemandScanTimeoutNs = 7 * chre::kOneSecondInNanoseconds;
86
87 /**
88 * Calls API testConfigureScanMonitorAsync. Sends fatal failure to host
89 * if API call fails.
90 *
91 * @param enable Set to true to enable monitoring scan results,
92 * false to disable.
93 * @param cookie An opaque value that will be included in the chreAsyncResult
94 * sent in relation to this request.
95 */
testConfigureScanMonitorAsync(bool enable,const void * cookie)96 void testConfigureScanMonitorAsync(bool enable, const void *cookie) {
97 LOGI("Starts scan monitor configure test: %s", enable ? "enable" : "disable");
98 if (!chreWifiConfigureScanMonitorAsync(enable, cookie)) {
99 if (enable) {
100 EXPECT_FAIL_RETURN("Failed to request to enable scan monitor.");
101 } else {
102 EXPECT_FAIL_RETURN("Failed to request to disable scan monitor.");
103 }
104 }
105 }
106
107 /**
108 * Calls API chreWifiRequestScanAsyncDefault. Sends fatal failure to host
109 * if API call fails.
110 */
testRequestScanAsync()111 void testRequestScanAsync() {
112 LOGI("Starts on demand scan test");
113 // Request a fresh scan to ensure the correct scan type is performed.
114 constexpr struct chreWifiScanParams kParams = {
115 /*.scanType=*/CHRE_WIFI_SCAN_TYPE_ACTIVE,
116 /*.maxScanAgeMs=*/0, // 0 seconds
117 /*.frequencyListLen=*/0,
118 /*.frequencyList=*/NULL,
119 /*.ssidListLen=*/0,
120 /*.ssidList=*/NULL,
121 /*.radioChainPref=*/CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT,
122 /*.channelSet=*/CHRE_WIFI_CHANNEL_SET_NON_DFS};
123 if (!chreWifiRequestScanAsync(&kParams, &kOnDemandScanCookie)) {
124 EXPECT_FAIL_RETURN("Failed to request for on-demand WiFi scan.");
125 }
126 }
127
128 /**
129 * Calls API chreWifiRequestRangingAsync. Sends fatal failure to host if the
130 * API call fails.
131 */
testRequestRangingAsync(const struct chreWifiScanResult * aps,uint8_t length)132 void testRequestRangingAsync(const struct chreWifiScanResult *aps,
133 uint8_t length) {
134 LOGI("Starts ranging test");
135 // Sending an array larger than CHRE_WIFI_RANGING_LIST_MAX_LEN will cause
136 // an immediate failure.
137 uint8_t targetLength =
138 std::min(length, static_cast<uint8_t>(CHRE_WIFI_RANGING_LIST_MAX_LEN));
139
140 auto targetList =
141 chre::MakeUniqueArray<struct chreWifiRangingTarget[]>(targetLength);
142 EXPECT_NE_OR_RETURN(targetList, nullptr,
143 "Failed to allocate array for issuing a ranging request");
144
145 // Save the last spot for any available RTT APs in case they didn't make it
146 // in the array earlier. This first loop allows non-RTT compatible APs as a
147 // way to test that the driver implementation will return failure for only
148 // those APs and success for valid RTT APs.
149 for (uint8_t i = 0; i < targetLength - 1; i++) {
150 chreWifiRangingTargetFromScanResult(&aps[i], &targetList[i]);
151 }
152
153 for (uint8_t i = targetLength - 1; i < length; i++) {
154 if ((aps[i].flags & CHRE_WIFI_SCAN_RESULT_FLAGS_IS_FTM_RESPONDER) ==
155 CHRE_WIFI_SCAN_RESULT_FLAGS_IS_FTM_RESPONDER ||
156 i == (length - 1)) {
157 chreWifiRangingTargetFromScanResult(&aps[i],
158 &targetList[targetLength - 1]);
159 break;
160 }
161 }
162
163 struct chreWifiRangingParams params = {.targetListLen = targetLength,
164 .targetList = targetList.get()};
165 if (!chreWifiRequestRangingAsync(¶ms, &kRequestRangingCookie)) {
166 EXPECT_FAIL_RETURN("Failed to request ranging for a list of WiFi scans.");
167 }
168 }
169
170 /**
171 * Validates primaryChannel and sends fatal failure to host if failing.
172 * 1. (primaryChannel - start frequecny) is a multiple of 5.
173 * 2. primaryChannelNumber is multiple of 5 and between [1, maxChannelNumber].
174 *
175 * @param primaryChannel primary channel of a WiFi scan result.
176 * @param startFrequency start frequency of band 2.4/5 GHz.
177 * @param maxChannelNumber max channel number of band 2.4/5 GHz.
178 */
validatePrimaryChannel(uint32_t primaryChannel,uint32_t startFrequency,uint8_t maxChannelNumber)179 void validatePrimaryChannel(uint32_t primaryChannel, uint32_t startFrequency,
180 uint8_t maxChannelNumber) {
181 if ((primaryChannel - startFrequency) % 5 != 0) {
182 LOGE("primaryChannel - %" PRIu32
183 " must be a multiple of 5,"
184 "got primaryChannel: %" PRIu32,
185 startFrequency, primaryChannel);
186 }
187
188 uint32_t primaryChannelNumber = (primaryChannel - startFrequency) / 5;
189 if (primaryChannelNumber < 1 || primaryChannelNumber > maxChannelNumber) {
190 LOGE("primaryChannelNumber must be between 1 and %" PRIu8
191 ","
192 "got primaryChannel: %" PRIu32,
193 maxChannelNumber, primaryChannel);
194 }
195 }
196
197 /**
198 * Validates primaryChannel for band 2.4/5 GHz.
199 *
200 * primaryChannelNumber of band 2.4 GHz is between 1 and 13,
201 * plus a special case for channel 14 (primaryChannel == 2484);
202 * primaryChannelNumber of band 5 GHz is between 1 and 200,
203 * ref: IEEE Std 802.11-2016, 19.3.15.2.
204 * Also, (primaryChannel - start frequecny) is a multiple of 5,
205 * except channel 14 of 2.4 GHz.
206 *
207 * @param result WiFi scan result.
208 */
validatePrimaryChannel(const chreWifiScanResult & result)209 void validatePrimaryChannel(const chreWifiScanResult &result) {
210 // channel 14 (primaryChannel = 2484) is not applicable for this test.
211 if (result.band == CHRE_WIFI_BAND_2_4_GHZ &&
212 result.primaryChannel != kWifiBandFreqOfChannel_14) {
213 validatePrimaryChannel(result.primaryChannel, kWifiBandStartFreq_2_4_GHz,
214 13);
215 } else if (result.band == CHRE_WIFI_BAND_5_GHZ) {
216 validatePrimaryChannel(result.primaryChannel, kWifiBandStartFreq_5_GHz,
217 200);
218 }
219 }
220
221 /**
222 * Validates centerFreqPrimary and centerFreqSecondary
223 * TODO(b/396133301): add test when channelWidth is 20, 40, 80, or 160 MHz
224 */
validateCenterFreq(const chreWifiScanResult & result)225 void validateCenterFreq(const chreWifiScanResult &result) {
226 if (result.channelWidth != CHRE_WIFI_CHANNEL_WIDTH_80_PLUS_80_MHZ &&
227 result.centerFreqSecondary != 0) {
228 // TODO(b/396133301): Format the centerFreqSecondary into the message
229 // after redesigning of EXPECT_FAIL_RETURN()
230 EXPECT_FAIL_RETURN(
231 "centerFreqSecondary must be 0 if channelWidth is not 80+80MHZ");
232 }
233 }
234
235 /**
236 * Validates that RSSI is within sane limits.
237 */
validateRssi(int8_t rssi)238 void validateRssi(int8_t rssi) {
239 // It's possible for WiFi RSSI to be positive if the phone is placed
240 // right next to a high-power AP (e.g. transmitting at 20 dBm),
241 // in which case RSSI will be < 20 dBm. Place a high threshold to check
242 // against values likely to be erroneous (36 dBm/4W).
243 EXPECT_LT_OR_RETURN(rssi, 36, "RSSI is greater than 36");
244 }
245
246 /**
247 * Validates that the amount of access points ranging was requested for matches
248 * the number of ranging results returned. Also, verifies that the BSSID of
249 * the each access point is present in the ranging results.
250 */
validateRangingEventArray(const struct chreWifiScanResult * results,size_t resultsSize,const struct chreWifiRangingEvent * event)251 void validateRangingEventArray(const struct chreWifiScanResult *results,
252 size_t resultsSize,
253 const struct chreWifiRangingEvent *event) {
254 size_t expectedArraySize = std::min(
255 resultsSize, static_cast<size_t>(CHRE_WIFI_RANGING_LIST_MAX_LEN));
256 EXPECT_EQ_OR_RETURN(
257 event->resultCount, expectedArraySize,
258 "RTT ranging result count was not the same as the requested target "
259 "list size");
260
261 uint8_t matchesFound = 0;
262
263 for (size_t i = 0; i < resultsSize; i++) {
264 for (size_t j = 0; j < expectedArraySize; j++) {
265 if (memcmp(results[i].bssid, event->results[j].macAddress,
266 CHRE_WIFI_BSSID_LEN) == 0) {
267 matchesFound++;
268 break;
269 }
270 }
271 }
272
273 EXPECT_EQ_OR_RETURN(
274 matchesFound, expectedArraySize,
275 "BSSID(s) from the ranging request were not found in the ranging result");
276 }
277
278 /**
279 * Validates the location configuration information returned by a ranging result
280 * is compliant with the formatting specified at @see chreWifiLci.
281 */
validateLci(const struct chreWifiRangingResult::chreWifiLci * lci)282 void validateLci(const struct chreWifiRangingResult::chreWifiLci *lci) {
283 // Per RFC 6225 2.3, there are 25 fractional bits and up to 9 integer bits
284 // used for lat / lng so verify that no bits outside those are used.
285 constexpr int64_t kMaxLat = INT64_C(90) << 25;
286 constexpr int64_t kMaxLng = INT64_C(180) << 25;
287 EXPECT_IN_RANGE_OR_RETURN(lci->latitude, -1 * kMaxLat, kMaxLat,
288 "LCI's latitude is outside the range of -90 to 90");
289 EXPECT_IN_RANGE_OR_RETURN(
290 lci->longitude, -1 * kMaxLng, kMaxLng,
291 "LCI's longitude is outside the range of -180 to 180");
292
293 // According to RFC 6225, values greater than 34 are reserved
294 constexpr uint8_t kMaxLatLngUncertainty = 34;
295 EXPECT_LE_OR_RETURN(lci->latitudeUncertainty, kMaxLatLngUncertainty,
296 "LCI's latitude uncertainty is greater than 34");
297 EXPECT_LE_OR_RETURN(lci->longitudeUncertainty, kMaxLatLngUncertainty,
298 "LCI's longitude uncertainty is greater than 34");
299
300 if (lci->altitudeType == CHRE_WIFI_LCI_ALTITUDE_TYPE_METERS) {
301 // Highest largely populated city in the world, El Alto, Bolivia, is 4300
302 // meters and the tallest building in the world is 828 meters so the upper
303 // bound for this range should be 5500 meters (contains some padding).
304 constexpr int32_t kMaxAltitudeMeters = 5500 << 8;
305
306 // Lowest largely populated city in the world, Baku, Azerbaijan, is 28
307 // meters below sea level so -100 meters should be a good lower bound.
308 constexpr int32_t kMinAltitudeMeters = (100 << 8) * -1;
309 EXPECT_IN_RANGE_OR_RETURN(
310 lci->altitude, kMinAltitudeMeters, kMaxAltitudeMeters,
311 "LCI's altitude is outside of the range of -25 to 500 meters");
312
313 // According to RFC 6225, values greater than 30 are reserved
314 constexpr uint8_t kMaxAltitudeUncertainty = 30;
315 EXPECT_LE_OR_RETURN(lci->altitudeUncertainty, kMaxAltitudeUncertainty,
316 "LCI's altitude certainty is greater than 30");
317 } else if (lci->altitudeType == CHRE_WIFI_LCI_ALTITUDE_TYPE_FLOORS) {
318 // Tallest building has 163 floors. Assume -5 to 100 floors is a sane range.
319 constexpr int32_t kMaxAltitudeFloors = 100 << 8;
320 constexpr int32_t kMinAltitudeFloors = (5 << 8) * -1;
321 EXPECT_IN_RANGE_OR_RETURN(
322 lci->altitude, kMinAltitudeFloors, kMaxAltitudeFloors,
323 "LCI's altitude is outside of the range of -5 to 100 floors");
324 } else if (lci->altitudeType != CHRE_WIFI_LCI_ALTITUDE_TYPE_UNKNOWN) {
325 EXPECT_FAIL_RETURN(
326 "LCI's altitude type was not unknown, floors, or meters");
327 }
328 }
329
330 } // anonymous namespace
331
BasicWifiTest()332 BasicWifiTest::BasicWifiTest() : Test(CHRE_API_VERSION_1_1) {}
333
setUp(uint32_t messageSize,const void *)334 void BasicWifiTest::setUp(uint32_t messageSize, const void * /* message */) {
335 if (messageSize != 0) {
336 EXPECT_FAIL_RETURN("Expected 0 byte message, got more bytes:",
337 &messageSize);
338 } else {
339 mWifiCapabilities = chreWifiGetCapabilities();
340 startScanMonitorTestStage();
341 }
342 }
343
handleEvent(uint32_t,uint16_t eventType,const void * eventData)344 void BasicWifiTest::handleEvent(uint32_t /* senderInstanceId */,
345 uint16_t eventType, const void *eventData) {
346 EXPECT_NE_OR_RETURN(eventData, nullptr, "Received null eventData");
347 LOGI("Received event type %" PRIu16, eventType);
348 switch (eventType) {
349 case CHRE_EVENT_WIFI_ASYNC_RESULT:
350 handleChreWifiAsyncEvent(static_cast<const chreAsyncResult *>(eventData));
351 break;
352 case CHRE_EVENT_WIFI_SCAN_RESULT: {
353 if (mScanMonitorEnabled && !mNextScanResultWasRequested) {
354 LOGI(
355 "Ignoring scan monitor scan result while waiting on requested scan"
356 " result");
357 break;
358 }
359
360 if (!scanEventExpected()) {
361 EXPECT_FAIL_RETURN("WiFi scan event received when not requested");
362 }
363 const auto *result = static_cast<const chreWifiScanEvent *>(eventData);
364 LOGI("Received wifi scan result, result count: %" PRIu8,
365 result->resultCount);
366
367 if (!isActiveWifiScanType(result)) {
368 LOGW("Received unexpected scan type %" PRIu8, result->scanType);
369 }
370
371 // The first chreWifiScanResult is expected to come immediately,
372 // but a long delay is possible if it's implemented incorrectly,
373 // e.g. the async result comes right away (before the scan is actually
374 // completed), then there's a long delay to the scan result.
375 constexpr uint64_t maxDelayNs = 100 * chre::kOneMillisecondInNanoseconds;
376 bool delayExceeded = (mStartTimestampNs != 0) &&
377 (chreGetTime() - mStartTimestampNs > maxDelayNs);
378 if (delayExceeded) {
379 EXPECT_FAIL_RETURN(
380 "Did not receive chreWifiScanResult within 100 milliseconds.");
381 }
382 // Do not reset mStartTimestampNs here, because it is used for the
383 // subsequent RTT ranging timestamp validation.
384 validateWifiScanEvent(result);
385 break;
386 }
387 case CHRE_EVENT_WIFI_RANGING_RESULT: {
388 if (!rangingEventExpected()) {
389 EXPECT_FAIL_RETURN("WiFi ranging event received when not requested");
390 }
391 const auto *result = static_cast<const chreWifiRangingEvent *>(eventData);
392 // Allow some wiggle room between the expected timeout and when the event
393 // would actually be delivered to the test.
394 if (mStartTimestampNs != 0 &&
395 chreGetTime() - mStartTimestampNs >
396 CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS + kTimeoutWiggleRoomNs) {
397 EXPECT_FAIL_RETURN(
398 "Did not receive chreWifiRangingEvent within the ranging timeout");
399 }
400 validateRangingEvent(result);
401 // Ensure timestamp is reset after everything is validated as it's used to
402 // validate the ranging event
403 mStartTimestampNs = 0;
404 mTestSuccessMarker.markStageAndSuccessOnFinish(
405 BASIC_WIFI_TEST_STAGE_SCAN_RTT);
406 break;
407 }
408 case CHRE_EVENT_TIMER: {
409 const uint32_t *timerHandle = static_cast<const uint32_t *>(eventData);
410 if (mScanTimeoutTimerHandle != CHRE_TIMER_INVALID &&
411 timerHandle == &mScanTimeoutTimerHandle) {
412 mScanTimeoutTimerHandle = CHRE_TIMER_INVALID;
413 startScanAsyncTestStage();
414 }
415 break;
416 }
417 default:
418 unexpectedEvent(eventType);
419 break;
420 }
421 }
422
handleChreWifiAsyncEvent(const chreAsyncResult * result)423 void BasicWifiTest::handleChreWifiAsyncEvent(const chreAsyncResult *result) {
424 if (!mCurrentWifiRequest.has_value()) {
425 EXPECT_FAIL_RETURN("Unexpected async result");
426 }
427 LOGI("Received a wifi async event. request type: %" PRIu8
428 " error code: %" PRIu8,
429 result->requestType, result->errorCode);
430 if (result->requestType == CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN) {
431 if (result->success) {
432 mNextScanResultWasRequested = true;
433 } else if (mNumScanRetriesRemaining > 0) {
434 LOGI("Wait for %" PRIu64 " seconds and try again",
435 kOnDemandScanTimeoutNs / chre::kOneSecondInNanoseconds);
436 mNumScanRetriesRemaining--;
437 mScanTimeoutTimerHandle = chreTimerSet(
438 /* duration= */ kOnDemandScanTimeoutNs, &mScanTimeoutTimerHandle,
439 /* oneShot= */ true);
440 return;
441 }
442 }
443 validateChreAsyncResult(result, mCurrentWifiRequest.value());
444 processChreWifiAsyncResult(result);
445 }
446
processChreWifiAsyncResult(const chreAsyncResult * result)447 void BasicWifiTest::processChreWifiAsyncResult(const chreAsyncResult *result) {
448 switch (result->requestType) {
449 case CHRE_WIFI_REQUEST_TYPE_RANGING:
450 // Reuse same start timestamp as the scan request since ranging fields
451 // may be retrieved automatically as part of that scan.
452 break;
453 case CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN:
454 LOGI("Wifi scan result validated");
455 if (mScanTimeoutTimerHandle != CHRE_TIMER_INVALID) {
456 chreTimerCancel(mScanTimeoutTimerHandle);
457 mScanTimeoutTimerHandle = CHRE_TIMER_INVALID;
458 }
459 break;
460 case CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR:
461 if (mCurrentWifiRequest->cookie == &kDisableScanMonitoringCookie) {
462 if (result->success) {
463 mScanMonitorEnabled = false;
464 }
465 mTestSuccessMarker.markStageAndSuccessOnFinish(
466 BASIC_WIFI_TEST_STAGE_SCAN_MONITOR);
467 mStartTimestampNs = chreGetTime();
468 startRangingAsyncTestStage();
469 } else {
470 if (result->success) {
471 mScanMonitorEnabled = true;
472 }
473 startScanAsyncTestStage();
474 }
475 break;
476 default:
477 EXPECT_FAIL_RETURN_UINT8("Received unexpected requestType %d",
478 result->requestType);
479 break;
480 }
481 }
482
isActiveWifiScanType(const chreWifiScanEvent * eventData)483 bool BasicWifiTest::isActiveWifiScanType(const chreWifiScanEvent *eventData) {
484 return (eventData->scanType == CHRE_WIFI_SCAN_TYPE_ACTIVE);
485 }
486
startScanMonitorTestStage()487 void BasicWifiTest::startScanMonitorTestStage() {
488 LOGI("startScanMonitorTestStage - Wifi capabilities: %" PRIu32,
489 mWifiCapabilities);
490 if (mWifiCapabilities & CHRE_WIFI_CAPABILITIES_SCAN_MONITORING) {
491 testConfigureScanMonitorAsync(true /* enable */,
492 &kEnableScanMonitoringCookie);
493 resetCurrentWifiRequest(&kEnableScanMonitoringCookie,
494 CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR,
495 CHRE_ASYNC_RESULT_TIMEOUT_NS);
496 } else {
497 mTestSuccessMarker.markStageAndSuccessOnFinish(
498 BASIC_WIFI_TEST_STAGE_SCAN_MONITOR);
499 startScanAsyncTestStage();
500 }
501 }
502
startScanAsyncTestStage()503 void BasicWifiTest::startScanAsyncTestStage() {
504 if (mWifiCapabilities & CHRE_WIFI_CAPABILITIES_ON_DEMAND_SCAN) {
505 testRequestScanAsync();
506 resetCurrentWifiRequest(&kOnDemandScanCookie,
507 CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN,
508 CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS);
509 } else if (mWifiCapabilities & CHRE_WIFI_CAPABILITIES_SCAN_MONITORING) {
510 mTestSuccessMarker.markStageAndSuccessOnFinish(
511 BASIC_WIFI_TEST_STAGE_SCAN_ASYNC);
512 testConfigureScanMonitorAsync(false /* enable */,
513 &kDisableScanMonitoringCookie);
514 resetCurrentWifiRequest(&kDisableScanMonitoringCookie,
515 CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR,
516 CHRE_ASYNC_RESULT_TIMEOUT_NS);
517 } else {
518 mTestSuccessMarker.markStageAndSuccessOnFinish(
519 BASIC_WIFI_TEST_STAGE_SCAN_ASYNC);
520 mStartTimestampNs = chreGetTime();
521 startRangingAsyncTestStage();
522 }
523 }
524
startRangingAsyncTestStage()525 void BasicWifiTest::startRangingAsyncTestStage() {
526 // If no scans were received, the test has nothing to range with so simply
527 // mark it as a success.
528 if (mWifiCapabilities & CHRE_WIFI_CAPABILITIES_RTT_RANGING &&
529 mLatestWifiScanResults.size() != 0) {
530 testRequestRangingAsync(mLatestWifiScanResults.data(),
531 mLatestWifiScanResults.size());
532 resetCurrentWifiRequest(&kRequestRangingCookie,
533 CHRE_WIFI_REQUEST_TYPE_RANGING,
534 CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS);
535 } else {
536 mTestSuccessMarker.markStageAndSuccessOnFinish(
537 BASIC_WIFI_TEST_STAGE_SCAN_RTT);
538 }
539 }
540
resetCurrentWifiRequest(const void * cookie,uint8_t requestType,uint64_t timeoutNs)541 void BasicWifiTest::resetCurrentWifiRequest(const void *cookie,
542 uint8_t requestType,
543 uint64_t timeoutNs) {
544 chreAsyncRequest request = {.cookie = cookie,
545 .requestType = requestType,
546 .requestTimeNs = chreGetTime(),
547 .timeoutNs = timeoutNs};
548 mCurrentWifiRequest = request;
549 }
550
validateWifiScanEvent(const chreWifiScanEvent * eventData)551 void BasicWifiTest::validateWifiScanEvent(const chreWifiScanEvent *eventData) {
552 if (eventData->version != CHRE_WIFI_SCAN_EVENT_VERSION) {
553 EXPECT_FAIL_RETURN_UINT8("Got unexpected scan event version %d",
554 eventData->version);
555 }
556
557 if (mNextExpectedIndex != eventData->eventIndex) {
558 LOGE("Expected index: %" PRIu32 ", received index: %" PRIu8,
559 mNextExpectedIndex, eventData->eventIndex);
560 EXPECT_FAIL_RETURN("Received out-of-order events");
561 }
562 mNextExpectedIndex++;
563
564 if (eventData->eventIndex == 0) {
565 mWiFiScanResultRemaining = eventData->resultTotal;
566 }
567 if (mWiFiScanResultRemaining < eventData->resultCount) {
568 LOGE("Remaining scan results %" PRIu32 ", received %" PRIu8,
569 mWiFiScanResultRemaining, eventData->resultCount);
570 EXPECT_FAIL_RETURN("Received too many WiFi scan results");
571 }
572 mWiFiScanResultRemaining -= eventData->resultCount;
573
574 validateWifiScanResult(eventData->resultCount, eventData->results);
575
576 // Save the latest results for future tests retaining old data if the new
577 // scan is empty (so the test has something to use).
578 if (eventData->resultCount > 0) {
579 mLatestWifiScanResults.copy_array(eventData->results,
580 eventData->resultCount);
581 }
582
583 LOGI("Remaining scan result is %" PRIu32, mWiFiScanResultRemaining);
584
585 if (mWiFiScanResultRemaining == 0) {
586 mNextExpectedIndex = 0;
587 mNextScanResultWasRequested = false;
588 mTestSuccessMarker.markStageAndSuccessOnFinish(
589 BASIC_WIFI_TEST_STAGE_SCAN_ASYNC);
590 if (mWifiCapabilities & CHRE_WIFI_CAPABILITIES_SCAN_MONITORING) {
591 testConfigureScanMonitorAsync(false /* enable */,
592 &kDisableScanMonitoringCookie);
593 resetCurrentWifiRequest(&kDisableScanMonitoringCookie,
594 CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR,
595 CHRE_ASYNC_RESULT_TIMEOUT_NS);
596 } else {
597 mStartTimestampNs = chreGetTime();
598 startRangingAsyncTestStage();
599 }
600 }
601 }
602
validateWifiScanResult(uint8_t count,const chreWifiScanResult * results)603 void BasicWifiTest::validateWifiScanResult(uint8_t count,
604 const chreWifiScanResult *results) {
605 for (uint8_t i = 0; i < count; ++i) {
606 if (results[i].ssidLen > CHRE_WIFI_SSID_MAX_LEN) {
607 EXPECT_FAIL_RETURN_UINT8("Got unexpected ssidLen %d", results[i].ssidLen);
608 }
609
610 // TODO: Enable fatal failures on band, RSSI, and primary channel
611 // validations when proper error waiver is implemented in CHQTS.
612 if (results[i].band != CHRE_WIFI_BAND_2_4_GHZ &&
613 results[i].band != CHRE_WIFI_BAND_5_GHZ) {
614 LOGE("Got unexpected band %d", results[i].band);
615 }
616
617 validateRssi(results[i].rssi);
618
619 validatePrimaryChannel(results[i]);
620 validateCenterFreq(results[i]);
621 }
622 }
623
validateRangingEvent(const chreWifiRangingEvent * eventData)624 void BasicWifiTest::validateRangingEvent(
625 const chreWifiRangingEvent *eventData) {
626 if (eventData->version != CHRE_WIFI_RANGING_EVENT_VERSION) {
627 EXPECT_FAIL_RETURN_UINT8("Got unexpected ranging event version %d",
628 eventData->version);
629 }
630
631 validateRangingEventArray(mLatestWifiScanResults.data(),
632 mLatestWifiScanResults.size(), eventData);
633
634 for (uint8_t i = 0; i < eventData->resultCount; i++) {
635 auto &result = eventData->results[i];
636 auto currentTime = chreGetTime();
637 if (result.timestamp < mStartTimestampNs ||
638 result.timestamp > currentTime) {
639 LOGE("Invalid Ranging result timestamp = %" PRIu64 " (%" PRIu64
640 ", %" PRIu64 "). Status = %" PRIu8,
641 result.timestamp, mStartTimestampNs, currentTime, result.status);
642 EXPECT_FAIL_RETURN("Invalid ranging result timestamp");
643 }
644
645 if (result.status != CHRE_WIFI_RANGING_STATUS_SUCCESS) {
646 if (result.rssi != 0 || result.distance != 0 ||
647 result.distanceStdDev != 0) {
648 EXPECT_FAIL_RETURN(
649 "Ranging result with failure status had non-zero state");
650 }
651 } else {
652 validateRssi(result.rssi);
653
654 // TODO(b/289432591): Use EXPECT_FAIL to check ranging distance
655 // results.
656 constexpr uint32_t kMaxDistanceMillimeters = 100 * 1000;
657 if (result.distance > kMaxDistanceMillimeters) {
658 LOGE("Ranging result was more than 100 meters away %" PRIu32,
659 result.distance);
660 }
661
662 constexpr uint32_t kMaxStdDevMillimeters = 10 * 1000;
663 if (result.distanceStdDev > kMaxStdDevMillimeters) {
664 LOGE("Ranging result distance stddev was more than 10 meters %" PRIu32,
665 result.distanceStdDev);
666 }
667
668 if (result.flags & CHRE_WIFI_RTT_RESULT_HAS_LCI) {
669 validateLci(&result.lci);
670 }
671 }
672 }
673 }
674
rangingEventExpected()675 bool BasicWifiTest::rangingEventExpected() {
676 return mTestSuccessMarker.isStageMarked(BASIC_WIFI_TEST_STAGE_SCAN_ASYNC) &&
677 !mTestSuccessMarker.isStageMarked(BASIC_WIFI_TEST_STAGE_SCAN_RTT);
678 }
679
scanEventExpected()680 bool BasicWifiTest::scanEventExpected() {
681 bool scanMonitoringFinished =
682 mTestSuccessMarker.isStageMarked(BASIC_WIFI_TEST_STAGE_SCAN_MONITOR);
683 bool onDemandScanFinished =
684 mTestSuccessMarker.isStageMarked(BASIC_WIFI_TEST_STAGE_SCAN_ASYNC);
685 if (mWifiCapabilities & CHRE_WIFI_CAPABILITIES_SCAN_MONITORING) {
686 return !scanMonitoringFinished && !onDemandScanFinished;
687 } else {
688 return scanMonitoringFinished && !onDemandScanFinished;
689 }
690 }
691
692 } // namespace general_test
693