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