• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params, &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