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