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