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(&params, &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