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