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 package android.net.wifi.rtt.cts; 18 19 import static android.net.wifi.rtt.ResponderConfig.RESPONDER_AP; 20 21 import static org.junit.Assert.assertArrayEquals; 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertNotEquals; 25 import static org.junit.Assert.assertNotNull; 26 import static org.junit.Assert.assertNull; 27 import static org.junit.Assert.assertTrue; 28 import static org.junit.Assert.fail; 29 import static org.junit.Assume.assumeNotNull; 30 import static org.junit.Assume.assumeTrue; 31 import static org.mockito.Mockito.mock; 32 33 import android.net.MacAddress; 34 import android.net.wifi.OuiKeyedData; 35 import android.net.wifi.ScanResult; 36 import android.net.wifi.aware.PeerHandle; 37 import android.net.wifi.cts.WifiBuildCompat; 38 import android.net.wifi.cts.WifiFeature; 39 import android.net.wifi.rtt.PasnConfig; 40 import android.net.wifi.rtt.RangingRequest; 41 import android.net.wifi.rtt.RangingResult; 42 import android.net.wifi.rtt.ResponderConfig; 43 import android.net.wifi.rtt.ResponderLocation; 44 import android.net.wifi.rtt.SecureRangingConfig; 45 import android.net.wifi.rtt.WifiRttManager; 46 import android.os.Build; 47 import android.os.PersistableBundle; 48 import android.platform.test.annotations.AppModeFull; 49 import android.platform.test.annotations.RequiresFlagsEnabled; 50 51 import androidx.test.ext.junit.runners.AndroidJUnit4; 52 import androidx.test.filters.LargeTest; 53 import androidx.test.filters.SdkSuppress; 54 55 import com.android.compatibility.common.util.ApiTest; 56 import com.android.compatibility.common.util.DeviceReportLog; 57 import com.android.compatibility.common.util.ResultType; 58 import com.android.compatibility.common.util.ResultUnit; 59 import com.android.wifi.flags.Flags; 60 61 import org.junit.Test; 62 import org.junit.runner.RunWith; 63 64 import java.util.ArrayList; 65 import java.util.Arrays; 66 import java.util.List; 67 import java.util.concurrent.TimeUnit; 68 69 /** 70 * Wi-Fi RTT CTS test: range to all available Access Points which support IEEE 802.11mc. 71 */ 72 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 73 @LargeTest 74 @RunWith(AndroidJUnit4.class) 75 public class WifiRttTest extends TestBase { 76 // Number of scans to do while searching for APs supporting IEEE 802.11mc 77 private static final int NUM_SCANS_SEARCHING_FOR_IEEE80211MC_AP = 5; 78 79 // Number of RTT measurements per AP 80 private static final int NUM_OF_RTT_ITERATIONS = 10; 81 82 // Maximum failure rate of RTT measurements (percentage) 83 private static final int MAX_FAILURE_RATE_PERCENT = 20; 84 85 // Maximum variation from the average measurement (measures consistency) 86 private static final int MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM = 2000; 87 88 // Maximum failure rate of one-sided RTT measurements (percentage) 89 private static final int MAX_NON11MC_FAILURE_RATE_PERCENT = 40; 90 91 // Maximum non-8011mc variation from the average measurement (measures consistency) 92 private static final int MAX_NON11MC_VARIATION_FROM_AVERAGE_DISTANCE_MM = 4000; 93 94 // Minimum valid RSSI value 95 private static final int MIN_VALID_RSSI = -100; 96 97 // Valid Mac Address 98 private static final MacAddress MAC = MacAddress.fromString("00:01:02:03:04:05"); 99 100 // Interval between two ranging request. 101 private static final int INTERVAL_MS = 1000; 102 103 /** 104 * Test Wi-Fi RTT ranging operation using ScanResults in request: 105 * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc) 106 * - Perform N (constant) RTT operations 107 * - Validate: 108 * - Failure ratio < threshold (constant) 109 * - Result margin < threshold (constant) 110 */ 111 @Test testRangingToTest11mcApUsingScanResult()112 public void testRangingToTest11mcApUsingScanResult() throws InterruptedException { 113 // Scan for IEEE 802.11mc supporting APs 114 ScanResult testAp = getS11McScanResult(); 115 assertNotNull( 116 "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that " 117 + "your test setup includes them!", testAp); 118 // Perform RTT operations 119 RangingRequest.Builder builder = new RangingRequest.Builder(); 120 builder.addAccessPoint(testAp); 121 122 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 123 builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize()); 124 assertTrue(RangingRequest.getDefaultRttBurstSize() 125 >= RangingRequest.getMinRttBurstSize()); 126 assertTrue(RangingRequest.getDefaultRttBurstSize() 127 <= RangingRequest.getMaxRttBurstSize()); 128 } 129 130 RangingRequest request = builder.build(); 131 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 132 assertEquals(1, request.getRttResponders().size()); 133 } 134 range11mcApRequest(request, testAp); 135 } 136 137 /** 138 * Test Wi-Fi RTT ranging using ResponderConfig in the single responder RangingRequest API. 139 * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc) 140 * - Perform N (constant) RTT operations 141 * - Validate: 142 * - Failure ratio < threshold (constant) 143 * - Result margin < threshold (constant) 144 */ 145 @Test testRangingToTest11mcApUsingResponderConfig()146 public void testRangingToTest11mcApUsingResponderConfig() throws InterruptedException { 147 // Scan for IEEE 802.11mc supporting APs 148 ScanResult testAp = getS11McScanResult(); 149 assertNotNull( 150 "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that " 151 + "your test setup includes them!", testAp); 152 int preamble = ResponderConfig.fromScanResult(testAp).getPreamble(); 153 154 // Create a ResponderConfig from the builder API. 155 ResponderConfig.Builder responderBuilder = new ResponderConfig.Builder(); 156 ResponderConfig responder = responderBuilder 157 .setMacAddress(MacAddress.fromString(testAp.BSSID)) 158 .set80211mcSupported(testAp.is80211mcResponder()) 159 .setChannelWidth(testAp.channelWidth) 160 .setFrequencyMhz(testAp.frequency) 161 .setCenterFreq0Mhz(testAp.centerFreq0) 162 .setCenterFreq1Mhz(testAp.centerFreq1) 163 .setPreamble(preamble) 164 .setResponderType(RESPONDER_AP) 165 .build(); 166 167 // Validate ResponderConfig.Builder set method arguments match getter methods. 168 assertTrue(responder.getMacAddress().toString().equalsIgnoreCase(testAp.BSSID) 169 && responder.is80211mcSupported() == testAp.is80211mcResponder() 170 && responder.getChannelWidth() == testAp.channelWidth 171 && responder.getFrequencyMhz() == testAp.frequency 172 && responder.getCenterFreq0Mhz() == testAp.centerFreq0 173 && responder.getCenterFreq1Mhz() == testAp.centerFreq1 174 && responder.getPreamble() == preamble 175 && responder.getResponderType() == RESPONDER_AP); 176 177 // Perform RTT operations 178 RangingRequest.Builder builder = new RangingRequest.Builder(); 179 builder.addResponder(responder); 180 181 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 182 builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize()); 183 assertTrue(RangingRequest.getDefaultRttBurstSize() 184 >= RangingRequest.getMinRttBurstSize()); 185 assertTrue(RangingRequest.getDefaultRttBurstSize() 186 <= RangingRequest.getMaxRttBurstSize()); 187 } 188 189 RangingRequest request = builder.build(); 190 191 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 192 assertEquals(1, request.getRttResponders().size()); 193 } 194 range11mcApRequest(request, testAp); 195 } 196 197 /** 198 * Test Wi-Fi RTT ranging using ResponderConfig in the multi-Responder RangingRequest API. 199 * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc) 200 * - Perform N (constant) RTT operations 201 * - Validate: 202 * - Failure ratio < threshold (constant) 203 * - Result margin < threshold (constant) 204 */ 205 @Test testRangingToTest11mcApUsingListResponderConfig()206 public void testRangingToTest11mcApUsingListResponderConfig() throws InterruptedException { 207 // Scan for IEEE 802.11mc supporting APs 208 ScanResult testAp = getS11McScanResult(); 209 assertNotNull( 210 "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that " 211 + "your test setup includes them!", testAp); 212 ResponderConfig responder = ResponderConfig.fromScanResult(testAp); 213 // Perform RTT operations 214 RangingRequest.Builder builder = new RangingRequest.Builder(); 215 List<ResponderConfig> responders = new ArrayList<>(); 216 responders.add(responder); 217 builder.addResponders(responders); 218 219 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 220 builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize()); 221 assertTrue(RangingRequest.getDefaultRttBurstSize() 222 >= RangingRequest.getMinRttBurstSize()); 223 assertTrue(RangingRequest.getDefaultRttBurstSize() 224 <= RangingRequest.getMaxRttBurstSize()); 225 } 226 227 RangingRequest request = builder.build(); 228 229 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 230 assertEquals(1, request.getRttResponders().size()); 231 } 232 range11mcApRequest(request, testAp); 233 } 234 235 /** 236 * Utility method for validating 11mc ranging request. 237 * 238 * @param request the ranging request that is being tested 239 * @param testAp the original test scan result to provide feedback on failure conditions 240 */ range11mcApRequest(RangingRequest request, ScanResult testAp)241 private void range11mcApRequest(RangingRequest request, ScanResult testAp) 242 throws InterruptedException { 243 Thread.sleep(5000); 244 List<RangingResult> allResults = new ArrayList<>(); 245 int numFailures = 0; 246 int distanceSum = 0; 247 int distanceMin = 0; 248 int distanceMax = 0; 249 int[] statuses = new int[NUM_OF_RTT_ITERATIONS]; 250 int[] distanceMms = new int[NUM_OF_RTT_ITERATIONS]; 251 int[] distanceStdDevMms = new int[NUM_OF_RTT_ITERATIONS]; 252 int[] rssis = new int[NUM_OF_RTT_ITERATIONS]; 253 int[] numAttempted = new int[NUM_OF_RTT_ITERATIONS]; 254 int[] numSuccessful = new int[NUM_OF_RTT_ITERATIONS]; 255 int[] frequencies = new int[NUM_OF_RTT_ITERATIONS]; 256 int[] packetBws = new int[NUM_OF_RTT_ITERATIONS]; 257 long[] timestampsMs = new long[NUM_OF_RTT_ITERATIONS]; 258 byte[] lastLci = null; 259 byte[] lastLcr = null; 260 for (int i = 0; i < NUM_OF_RTT_ITERATIONS; ++i) { 261 ResultCallback callback = new ResultCallback(); 262 mWifiRttManager.startRanging(request, mExecutor, callback); 263 assertTrue("Wi-Fi RTT results: no callback on iteration " + i, 264 callback.waitForCallback()); 265 266 List<RangingResult> currentResults = callback.getResults(); 267 assertNotNull("Wi-Fi RTT results: null results (onRangingFailure) on iteration " + i, 268 currentResults); 269 assertEquals("Wi-Fi RTT results: unexpected # of results (expect 1) on iteration " + i, 270 1, currentResults.size()); 271 RangingResult result = currentResults.get(0); 272 assertEquals("Wi-Fi RTT results: invalid result (wrong BSSID) entry on iteration " + i, 273 result.getMacAddress().toString(), testAp.BSSID); 274 assertNull("Wi-Fi RTT results: invalid result (non-null PeerHandle) entry on iteration " 275 + i, result.getPeerHandle()); 276 277 allResults.add(result); 278 int status = result.getStatus(); 279 statuses[i] = status; 280 if (status == RangingResult.STATUS_SUCCESS) { 281 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 282 assertEquals( 283 "Wi-Fi RTT results: invalid result (wrong rttBurstSize) entry on " 284 + "iteration " 285 + i, 286 result.getNumAttemptedMeasurements(), 287 RangingRequest.getMaxRttBurstSize()); 288 assertTrue("Wi-Fi RTT results: should be a 802.11MC measurement", 289 result.is80211mcMeasurement()); 290 } 291 distanceSum += result.getDistanceMm(); 292 if (i == 0) { 293 distanceMin = result.getDistanceMm(); 294 distanceMax = result.getDistanceMm(); 295 } else { 296 distanceMin = Math.min(distanceMin, result.getDistanceMm()); 297 distanceMax = Math.max(distanceMax, result.getDistanceMm()); 298 } 299 300 assertTrue("Wi-Fi RTT results: invalid RSSI on iteration " + i, 301 result.getRssi() >= MIN_VALID_RSSI); 302 303 distanceMms[i - numFailures] = result.getDistanceMm(); 304 distanceStdDevMms[i - numFailures] = result.getDistanceStdDevMm(); 305 rssis[i - numFailures] = result.getRssi(); 306 numAttempted[i - numFailures] = result.getNumAttemptedMeasurements(); 307 numSuccessful[i - numFailures] = result.getNumSuccessfulMeasurements(); 308 timestampsMs[i - numFailures] = result.getRangingTimestampMillis(); 309 frequencies[i - numFailures] = result.getMeasurementChannelFrequencyMHz(); 310 packetBws[i - numFailures] = result.getMeasurementBandwidth(); 311 312 byte[] currentLci = result.getLci(); 313 byte[] currentLcr = result.getLcr(); 314 if (i - numFailures > 0) { 315 assertArrayEquals( 316 "Wi-Fi RTT results: invalid result (LCI mismatch) on iteration " + i, 317 currentLci, lastLci); 318 assertArrayEquals( 319 "Wi-Fi RTT results: invalid result (LCR mismatch) on iteration " + i, 320 currentLcr, lastLcr); 321 } 322 lastLci = currentLci; 323 lastLcr = currentLcr; 324 } else { 325 numFailures++; 326 } 327 // Sleep a while to avoid stress AP. 328 Thread.sleep(INTERVAL_MS); 329 } 330 331 // Save results to log 332 int numGoodResults = NUM_OF_RTT_ITERATIONS - numFailures; 333 DeviceReportLog reportLog = new DeviceReportLog(TAG, "testRangingToTestAp"); 334 reportLog.addValues("status_codes", statuses, ResultType.NEUTRAL, ResultUnit.NONE); 335 reportLog.addValues("distance_mm", Arrays.copyOf(distanceMms, numGoodResults), 336 ResultType.NEUTRAL, ResultUnit.NONE); 337 reportLog.addValues("distance_stddev_mm", Arrays.copyOf(distanceStdDevMms, numGoodResults), 338 ResultType.NEUTRAL, ResultUnit.NONE); 339 reportLog.addValues("rssi_dbm", Arrays.copyOf(rssis, numGoodResults), ResultType.NEUTRAL, 340 ResultUnit.NONE); 341 reportLog.addValues("num_attempted", Arrays.copyOf(numAttempted, numGoodResults), 342 ResultType.NEUTRAL, ResultUnit.NONE); 343 reportLog.addValues("num_successful", Arrays.copyOf(numSuccessful, numGoodResults), 344 ResultType.NEUTRAL, ResultUnit.NONE); 345 reportLog.addValues("timestamps", Arrays.copyOf(timestampsMs, numGoodResults), 346 ResultType.NEUTRAL, ResultUnit.NONE); 347 reportLog.addValues("frequencies", Arrays.copyOf(frequencies, numGoodResults), 348 ResultType.NEUTRAL, ResultUnit.NONE); 349 reportLog.addValues("packetBws", Arrays.copyOf(packetBws, numGoodResults), 350 ResultType.NEUTRAL, ResultUnit.NONE); 351 reportLog.submit(); 352 353 // Analyze results 354 assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures + ", ITERATIONS=" 355 + NUM_OF_RTT_ITERATIONS + ", AP=" + testAp, 356 numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100); 357 if (numFailures != NUM_OF_RTT_ITERATIONS) { 358 double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures); 359 assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation =" 360 + (distanceMax - distanceAvg), 361 (distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM); 362 assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation =" 363 + (distanceAvg - distanceMin), 364 (distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM); 365 for (int i = 0; i < numGoodResults; ++i) { 366 assertNotEquals("Number of attempted measurements is 0", 0, numAttempted[i]); 367 assertNotEquals("Number of successful measurements is 0", 0, numSuccessful[i]); 368 } 369 } 370 } 371 372 /** 373 * Utility method for validating 11az ranging request. 374 * 375 * @param request the ranging request that is being tested 376 * @param testAp the original test scan result to provide feedback on failure conditions 377 * @param isSecure whether the ranging is secure or not 378 */ range11azApRequest(RangingRequest request, ScanResult testAp, boolean isSecure)379 private void range11azApRequest(RangingRequest request, ScanResult testAp, boolean isSecure) 380 throws InterruptedException { 381 Thread.sleep(5000); 382 List<RangingResult> allResults = new ArrayList<>(); 383 int numFailures = 0; 384 int distanceSum = 0; 385 int distanceMin = 0; 386 int distanceMax = 0; 387 int[] statuses = new int[NUM_OF_RTT_ITERATIONS]; 388 int[] distanceMms = new int[NUM_OF_RTT_ITERATIONS]; 389 int[] distanceStdDevMms = new int[NUM_OF_RTT_ITERATIONS]; 390 int[] rssis = new int[NUM_OF_RTT_ITERATIONS]; 391 int[] numAttempted = new int[NUM_OF_RTT_ITERATIONS]; 392 int[] numSuccessful = new int[NUM_OF_RTT_ITERATIONS]; 393 int[] frequencies = new int[NUM_OF_RTT_ITERATIONS]; 394 int[] packetBws = new int[NUM_OF_RTT_ITERATIONS]; 395 long[] timestampsMs = new long[NUM_OF_RTT_ITERATIONS]; 396 int[] i2rTxLtfRepetitions = new int[NUM_OF_RTT_ITERATIONS]; 397 int[] r2iTxLtfRepetitions = new int[NUM_OF_RTT_ITERATIONS]; 398 int[] numRxSts = new int[NUM_OF_RTT_ITERATIONS]; 399 int[] numTxSts = new int[NUM_OF_RTT_ITERATIONS]; 400 long[] maxNtbMeasurementTime = new long[NUM_OF_RTT_ITERATIONS]; 401 long[] minNtbMeasurementTime = new long[NUM_OF_RTT_ITERATIONS]; 402 403 byte[] lastLci = null; 404 byte[] lastLcr = null; 405 for (int i = 0; i < NUM_OF_RTT_ITERATIONS; ++i) { 406 ResultCallback callback = new ResultCallback(); 407 mWifiRttManager.startRanging(request, mExecutor, callback); 408 assertTrue("Wi-Fi RTT results: no callback on iteration " + i, 409 callback.waitForCallback()); 410 411 List<RangingResult> currentResults = callback.getResults(); 412 assertNotNull("Wi-Fi RTT results: null results (onRangingFailure) on iteration " + i, 413 currentResults); 414 assertEquals("Wi-Fi RTT results: unexpected # of results (expect 1) on iteration " + i, 415 1, currentResults.size()); 416 RangingResult result = currentResults.get(0); 417 assertEquals("Wi-Fi RTT results: invalid result (wrong BSSID) entry on iteration " + i, 418 result.getMacAddress().toString(), testAp.BSSID); 419 assertNull("Wi-Fi RTT results: invalid result (non-null PeerHandle) entry on iteration " 420 + i, result.getPeerHandle()); 421 422 allResults.add(result); 423 int status = result.getStatus(); 424 statuses[i] = status; 425 if (status == RangingResult.STATUS_SUCCESS) { 426 assertTrue("Wi-Fi RTT results: should be a 802.11az measurement", 427 result.is80211azNtbMeasurement()); 428 if (isSecure) { 429 assertTrue("Ranging frames should be protected", 430 result.isRangingFrameProtected()); 431 assertTrue("Secure HE-LTF should be enabled", result.isSecureHeLtfEnabled()); 432 assertTrue("Ranging should be authenticated", result.isRangingAuthenticated()); 433 } 434 distanceSum += result.getDistanceMm(); 435 if (i == 0) { 436 distanceMin = result.getDistanceMm(); 437 distanceMax = result.getDistanceMm(); 438 } else { 439 distanceMin = Math.min(distanceMin, result.getDistanceMm()); 440 distanceMax = Math.max(distanceMax, result.getDistanceMm()); 441 } 442 443 assertTrue("Wi-Fi RTT results: invalid RSSI on iteration " + i, 444 result.getRssi() >= MIN_VALID_RSSI); 445 446 distanceMms[i - numFailures] = result.getDistanceMm(); 447 distanceStdDevMms[i - numFailures] = result.getDistanceStdDevMm(); 448 rssis[i - numFailures] = result.getRssi(); 449 numAttempted[i - numFailures] = result.getNumAttemptedMeasurements(); 450 numSuccessful[i - numFailures] = result.getNumSuccessfulMeasurements(); 451 timestampsMs[i - numFailures] = result.getRangingTimestampMillis(); 452 frequencies[i - numFailures] = result.getMeasurementChannelFrequencyMHz(); 453 packetBws[i - numFailures] = result.getMeasurementBandwidth(); 454 i2rTxLtfRepetitions[i - numFailures] = 455 result.get80211azInitiatorTxLtfRepetitionsCount(); 456 r2iTxLtfRepetitions[i - numFailures] = 457 result.get80211azResponderTxLtfRepetitionsCount(); 458 numRxSts[i - numFailures] = result.get80211azNumberOfRxSpatialStreams(); 459 numTxSts[i - numFailures] = result.get80211azNumberOfTxSpatialStreams(); 460 maxNtbMeasurementTime[i - numFailures] = 461 result.getMaxTimeBetweenNtbMeasurementsMicros(); 462 minNtbMeasurementTime[i - numFailures] = 463 result.getMinTimeBetweenNtbMeasurementsMicros(); 464 465 byte[] currentLci = result.getLci(); 466 byte[] currentLcr = result.getLcr(); 467 if (i - numFailures > 0) { 468 assertArrayEquals( 469 "Wi-Fi RTT results: invalid result (LCI mismatch) on iteration " + i, 470 currentLci, lastLci); 471 assertArrayEquals( 472 "Wi-Fi RTT results: invalid result (LCR mismatch) on iteration " + i, 473 currentLcr, lastLcr); 474 } 475 lastLci = currentLci; 476 lastLcr = currentLcr; 477 } else { 478 numFailures++; 479 } 480 long minWait = TimeUnit.MICROSECONDS.toMillis( 481 result.getMinTimeBetweenNtbMeasurementsMicros()); 482 if (isSecure && result.getPasnComebackCookie() != null) { 483 minWait = Math.max(minWait, result.getPasnComebackAfterMillis()); 484 } 485 // Wait for the minimum measurement time 486 Thread.sleep(minWait); 487 } 488 489 // Save results to log 490 int numGoodResults = NUM_OF_RTT_ITERATIONS - numFailures; 491 DeviceReportLog reportLog = new DeviceReportLog(TAG, "testRangingToTestAp"); 492 reportLog.addValues("status_codes", statuses, ResultType.NEUTRAL, ResultUnit.NONE); 493 reportLog.addValues("distance_mm", Arrays.copyOf(distanceMms, numGoodResults), 494 ResultType.NEUTRAL, ResultUnit.NONE); 495 reportLog.addValues("distance_stddev_mm", Arrays.copyOf(distanceStdDevMms, numGoodResults), 496 ResultType.NEUTRAL, ResultUnit.NONE); 497 reportLog.addValues("rssi_dbm", Arrays.copyOf(rssis, numGoodResults), ResultType.NEUTRAL, 498 ResultUnit.NONE); 499 reportLog.addValues("num_attempted", Arrays.copyOf(numAttempted, numGoodResults), 500 ResultType.NEUTRAL, ResultUnit.NONE); 501 reportLog.addValues("num_successful", Arrays.copyOf(numSuccessful, numGoodResults), 502 ResultType.NEUTRAL, ResultUnit.NONE); 503 reportLog.addValues("timestamps", Arrays.copyOf(timestampsMs, numGoodResults), 504 ResultType.NEUTRAL, ResultUnit.NONE); 505 reportLog.addValues("frequencies", Arrays.copyOf(frequencies, numGoodResults), 506 ResultType.NEUTRAL, ResultUnit.NONE); 507 reportLog.addValues("packetBws", Arrays.copyOf(packetBws, numGoodResults), 508 ResultType.NEUTRAL, ResultUnit.NONE); 509 reportLog.addValues("i2rTxLtfRepetitions", 510 Arrays.copyOf(i2rTxLtfRepetitions, numGoodResults), 511 ResultType.NEUTRAL, ResultUnit.NONE); 512 reportLog.addValues("r2iTxLtfRepetitions", 513 Arrays.copyOf(r2iTxLtfRepetitions, numGoodResults), 514 ResultType.NEUTRAL, ResultUnit.NONE); 515 reportLog.addValues("numRxSts", Arrays.copyOf(numRxSts, numGoodResults), 516 ResultType.NEUTRAL, ResultUnit.NONE); 517 reportLog.addValues("numTxSts", Arrays.copyOf(numRxSts, numGoodResults), 518 ResultType.NEUTRAL, ResultUnit.NONE); 519 reportLog.addValues("maxNtbMeasurementTime", 520 Arrays.copyOf(maxNtbMeasurementTime, numGoodResults), 521 ResultType.NEUTRAL, ResultUnit.NONE); 522 reportLog.addValues("minNtbMeasurementTime", 523 Arrays.copyOf(minNtbMeasurementTime, numGoodResults), 524 ResultType.NEUTRAL, ResultUnit.NONE); 525 reportLog.submit(); 526 527 // Analyze results 528 assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures + ", ITERATIONS=" 529 + NUM_OF_RTT_ITERATIONS + ", AP=" + testAp, 530 numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100); 531 if (numFailures != NUM_OF_RTT_ITERATIONS) { 532 double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures); 533 assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation =" 534 + (distanceMax - distanceAvg), 535 (distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM); 536 assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation =" 537 + (distanceAvg - distanceMin), 538 (distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM); 539 for (int i = 0; i < numGoodResults; ++i) { 540 assertNotEquals("Number of attempted measurements is 0", 0, numAttempted[i]); 541 assertNotEquals("Number of successful measurements is 0", 0, numSuccessful[i]); 542 } 543 } 544 } 545 546 /** 547 * Validate that when a request contains more range operations than allowed (by API) that we 548 * get an exception. 549 */ 550 @Test testRequestTooLarge()551 public void testRequestTooLarge() throws InterruptedException { 552 ScanResult testAp = getS11McScanResult(); 553 assertNotNull( 554 "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that " 555 + "your test setup includes them!", testAp); 556 557 RangingRequest.Builder builder = new RangingRequest.Builder(); 558 List<ScanResult> scanResults = new ArrayList<>(); 559 for (int i = 0; i < RangingRequest.getMaxPeers() - 2; ++i) { 560 scanResults.add(testAp); 561 } 562 builder.addAccessPoints(scanResults); 563 564 ScanResult testApNon80211mc = null; 565 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 566 testApNon80211mc = getLegacyScanResult(); 567 } 568 if (testApNon80211mc == null) { 569 builder.addAccessPoints(List.of(testAp, testAp, testAp)); 570 } else { 571 builder.addNon80211mcCapableAccessPoints(List.of(testApNon80211mc, testApNon80211mc, 572 testApNon80211mc)); 573 } 574 575 try { 576 mWifiRttManager.startRanging(builder.build(), mExecutor, new ResultCallback()); 577 } catch (IllegalArgumentException e) { 578 return; 579 } 580 581 fail("Did not receive expected IllegalArgumentException when tried to range to too " 582 + "many peers"); 583 } 584 585 /** 586 * Verify ResponderLocation API 587 */ 588 @Test testRangingToTestApWithResponderLocation()589 public void testRangingToTestApWithResponderLocation() throws InterruptedException { 590 // Scan for IEEE 802.11mc supporting APs 591 ScanResult testAp = getS11McScanResult(); 592 assertNotNull( 593 "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that " 594 + "your test setup includes them!", testAp); 595 596 // Perform RTT operations 597 RangingRequest request = new RangingRequest.Builder().addAccessPoint(testAp).build(); 598 ResultCallback callback = new ResultCallback(); 599 mWifiRttManager.startRanging(request, mExecutor, callback); 600 assertTrue("Wi-Fi RTT results: no callback! ", 601 callback.waitForCallback()); 602 603 RangingResult result = callback.getResults().get(0); 604 assertEquals("Ranging request not success", 605 result.getStatus(), RangingResult.STATUS_SUCCESS); 606 ResponderLocation responderLocation = result.getUnverifiedResponderLocation(); 607 if (responderLocation == null) { 608 return; 609 } 610 assertTrue("ResponderLocation is not valid", responderLocation.isLciSubelementValid()); 611 612 // Check LCI related APIs 613 int exceptionCount = 0; 614 int apiCount = 0; 615 try { 616 apiCount++; 617 responderLocation.getLatitudeUncertainty(); 618 } catch (IllegalStateException e) { 619 exceptionCount++; 620 } 621 try { 622 apiCount++; 623 responderLocation.getLatitude(); 624 } catch (IllegalStateException e) { 625 exceptionCount++; 626 } 627 try { 628 apiCount++; 629 responderLocation.getLongitudeUncertainty(); 630 } catch (IllegalStateException e) { 631 exceptionCount++; 632 } 633 try { 634 apiCount++; 635 responderLocation.getLongitude(); 636 } catch (IllegalStateException e) { 637 exceptionCount++; 638 } 639 try { 640 apiCount++; 641 responderLocation.getAltitudeType(); 642 } catch (IllegalStateException e) { 643 exceptionCount++; 644 } 645 try { 646 apiCount++; 647 responderLocation.getAltitudeUncertainty(); 648 } catch (IllegalStateException e) { 649 exceptionCount++; 650 } 651 try { 652 apiCount++; 653 responderLocation.getAltitude(); 654 } catch (IllegalStateException e) { 655 exceptionCount++; 656 } 657 try { 658 apiCount++; 659 responderLocation.getDatum(); 660 } catch (IllegalStateException e) { 661 exceptionCount++; 662 } 663 try { 664 apiCount++; 665 responderLocation.getRegisteredLocationAgreementIndication(); 666 } catch (IllegalStateException e) { 667 exceptionCount++; 668 } 669 try { 670 apiCount++; 671 responderLocation.getLciVersion(); 672 } catch (IllegalStateException e) { 673 exceptionCount++; 674 } 675 try { 676 apiCount++; 677 assertNotNull(responderLocation.toLocation()); 678 } catch (IllegalStateException e) { 679 exceptionCount++; 680 } 681 // If LCI is not valid, all APIs should throw exception, otherwise no exception. 682 assertEquals("Exception number should equal to API number", 683 responderLocation.isLciSubelementValid()? 0 : apiCount, exceptionCount); 684 685 // Verify ZaxisSubelement APIs 686 apiCount = 0; 687 exceptionCount = 0; 688 689 try { 690 apiCount++; 691 responderLocation.getExpectedToMove(); 692 } catch (IllegalStateException e) { 693 exceptionCount++; 694 } 695 696 try { 697 apiCount++; 698 responderLocation.getFloorNumber(); 699 } catch (IllegalStateException e) { 700 exceptionCount++; 701 } 702 703 try { 704 apiCount++; 705 responderLocation.getHeightAboveFloorMeters(); 706 } catch (IllegalStateException e) { 707 exceptionCount++; 708 } 709 710 try { 711 apiCount++; 712 responderLocation.getHeightAboveFloorUncertaintyMeters(); 713 } catch (IllegalStateException e) { 714 exceptionCount++; 715 } 716 // If Zaxis is not valid, all APIs should throw exception, otherwise no exception. 717 assertEquals("Exception number should equal to API number", 718 responderLocation.isZaxisSubelementValid() ? 0 : apiCount, exceptionCount); 719 // Verify civic location 720 if (responderLocation.toCivicLocationAddress() == null) { 721 assertNull(responderLocation.toCivicLocationSparseArray()); 722 } else { 723 assertNotNull(responderLocation.toCivicLocationSparseArray()); 724 } 725 // Verify map image 726 if (responderLocation.getMapImageUri() == null) { 727 assertNull(responderLocation.getMapImageMimeType()); 728 } else { 729 assertNotNull(responderLocation.getMapImageMimeType()); 730 } 731 boolean extraInfoOnAssociationIndication = 732 responderLocation.getExtraInfoOnAssociationIndication(); 733 assertNotNull("ColocatedBSSID list should be nonNull", 734 responderLocation.getColocatedBssids()); 735 } 736 737 /** 738 * Verify ranging request with aware peer Mac address and peer handle. 739 */ 740 @Test testAwareRttWithMacAddress()741 public void testAwareRttWithMacAddress() throws InterruptedException { 742 if (!WifiFeature.isAwareSupported(getContext())) { 743 return; 744 } 745 RangingRequest request = new RangingRequest.Builder() 746 .addWifiAwarePeer(MAC).build(); 747 ResultCallback callback = new ResultCallback(); 748 mWifiRttManager.startRanging(request, mExecutor, callback); 749 assertTrue("Wi-Fi RTT results: no callback", 750 callback.waitForCallback()); 751 List<RangingResult> rangingResults = callback.getResults(); 752 assertNotNull("Wi-Fi RTT results: null results", rangingResults); 753 assertEquals(1, rangingResults.size()); 754 assertEquals(RangingResult.STATUS_FAIL, rangingResults.get(0).getStatus()); 755 } 756 757 /** 758 * Verify ranging request with aware peer handle. 759 */ 760 @Test testAwareRttWithPeerHandle()761 public void testAwareRttWithPeerHandle() throws InterruptedException { 762 if (!WifiFeature.isAwareSupported(getContext())) { 763 return; 764 } 765 PeerHandle peerHandle = mock(PeerHandle.class); 766 RangingRequest request = new RangingRequest.Builder() 767 .addWifiAwarePeer(peerHandle).build(); 768 ResultCallback callback = new ResultCallback(); 769 mWifiRttManager.startRanging(request, mExecutor, callback); 770 assertTrue("Wi-Fi RTT results: no callback", 771 callback.waitForCallback()); 772 List<RangingResult> rangingResults = callback.getResults(); 773 assertNotNull("Wi-Fi RTT results: null results", rangingResults); 774 assertEquals("Invalid peerHandle should return 0 result", 0, rangingResults.size()); 775 } 776 777 /** 778 * Test Wi-Fi One-sided RTT ranging operation using ScanResult in request: 779 * - Scan for visible APs for the test AP (which do not support IEEE 802.11mc) and are operating 780 * - in the 5GHz band. 781 * - Perform N (constant) RTT operations 782 * - Remove outliers while insuring greater than 50% of the results still remain 783 * - Validate: 784 * - Failure ratio < threshold (constant) 785 * - Result margin < threshold (constant) 786 */ 787 @Test testRangingToTestNon11mcApUsingScanResult()788 public void testRangingToTestNon11mcApUsingScanResult() throws InterruptedException { 789 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 790 return; 791 } 792 793 // Scan for Non-IEEE 802.11mc supporting APs 794 ScanResult testAp = getLegacyScanResult(); 795 assertNotNull( 796 "Cannot find any test APs which are Non-IEEE 802.11mc - please verify that" 797 + " your test setup includes them!", testAp); 798 799 // Perform RTT operations 800 RangingRequest.Builder builder = new RangingRequest.Builder(); 801 builder.addNon80211mcCapableAccessPoint(testAp); 802 builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize()); 803 RangingRequest request = builder.build(); 804 805 // Perform the request 806 rangeNon11mcApRequest(request, testAp, MAX_NON11MC_VARIATION_FROM_AVERAGE_DISTANCE_MM); 807 } 808 809 /** 810 * Test Wi-Fi one-sided RTT ranging operation using ResponderConfig in request: 811 * - Scan for visible APs for the test AP (which do not support IEEE 802.11mc) and are operating 812 * - in the 5GHz band. 813 * - Perform N (constant) RTT operations 814 * - Remove outliers while insuring greater than 50% of the results still remain 815 * - Validate: 816 * - Failure ratio < threshold (constant) 817 * - Result margin < threshold (constant) 818 */ 819 @Test testRangingToTestNon11mcApUsingResponderConfig()820 public void testRangingToTestNon11mcApUsingResponderConfig() throws InterruptedException { 821 if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 822 return; 823 } 824 825 // Scan for Non-IEEE 802.11mc supporting APs 826 ScanResult testAp = getLegacyScanResult(); 827 assertNotNull( 828 "Cannot find any test APs which are Non-IEEE 802.11mc - please verify that" 829 + " your test setup includes them!", testAp); 830 831 ResponderConfig responder = ResponderConfig.fromScanResult(testAp); 832 833 // Perform RTT operations 834 RangingRequest.Builder builder = new RangingRequest.Builder(); 835 builder.addResponder(responder); 836 builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize()); 837 RangingRequest request = builder.build(); 838 839 840 841 // Perform the request 842 rangeNon11mcApRequest(request, testAp, MAX_NON11MC_VARIATION_FROM_AVERAGE_DISTANCE_MM); 843 } 844 845 /** 846 * Utility method for validating a ranging request to a non-80211mc AP. 847 * 848 * @param request the ranging request that is being tested 849 * @param testAp the original test scan result to provide feedback on failure conditions 850 */ rangeNon11mcApRequest(RangingRequest request, ScanResult testAp, int variationLimit)851 private void rangeNon11mcApRequest(RangingRequest request, ScanResult testAp, 852 int variationLimit) throws InterruptedException { 853 Thread.sleep(5000); 854 List<RangingResult> allResults = new ArrayList<>(); 855 int numFailures = 0; 856 int distanceSum = 0; 857 int distanceMin = 0; 858 int distanceMax = 0; 859 int[] statuses = new int[NUM_OF_RTT_ITERATIONS]; 860 int[] distanceMms = new int[NUM_OF_RTT_ITERATIONS]; 861 boolean[] distanceInclusionMap = new boolean[NUM_OF_RTT_ITERATIONS]; 862 int[] distanceStdDevMms = new int[NUM_OF_RTT_ITERATIONS]; 863 int[] rssis = new int[NUM_OF_RTT_ITERATIONS]; 864 int[] numAttempted = new int[NUM_OF_RTT_ITERATIONS]; 865 int[] numSuccessful = new int[NUM_OF_RTT_ITERATIONS]; 866 long[] timestampsMs = new long[NUM_OF_RTT_ITERATIONS]; 867 byte[] lastLci = null; 868 byte[] lastLcr = null; 869 for (int i = 0; i < NUM_OF_RTT_ITERATIONS; ++i) { 870 ResultCallback callback = new ResultCallback(); 871 mWifiRttManager.startRanging(request, mExecutor, callback); 872 assertTrue("Wi-Fi RTT results: no callback on iteration " + i, 873 callback.waitForCallback()); 874 875 List<RangingResult> currentResults = callback.getResults(); 876 assertNotNull( 877 "Wi-Fi RTT results: null results (onRangingFailure) on iteration " + i, 878 currentResults); 879 assertEquals( 880 "Wi-Fi RTT results: unexpected # of results (expect 1) on iteration " + i, 881 1, currentResults.size()); 882 RangingResult result = currentResults.get(0); 883 assertEquals( 884 "Wi-Fi RTT results: invalid result (wrong BSSID) entry on iteration " + i, 885 result.getMacAddress().toString(), testAp.BSSID); 886 887 assertNull( 888 "Wi-Fi RTT results: invalid result (non-null PeerHandle) entry on iteration " 889 + i, result.getPeerHandle()); 890 891 allResults.add(result); 892 int status = result.getStatus(); 893 statuses[i] = status; 894 if (status == RangingResult.STATUS_SUCCESS) { 895 assertFalse("Wi-Fi RTT results: should not be a 802.11MC measurement", 896 result.is80211mcMeasurement()); 897 distanceSum += result.getDistanceMm(); 898 899 assertTrue("Wi-Fi RTT results: invalid RSSI on iteration " + i, 900 result.getRssi() >= MIN_VALID_RSSI); 901 902 distanceMms[i - numFailures] = result.getDistanceMm(); 903 distanceStdDevMms[i - numFailures] = result.getDistanceStdDevMm(); 904 rssis[i - numFailures] = result.getRssi(); 905 // For one-sided RTT the number of packets attempted in a burst is not available, 906 // So we set the result to be the same as used in the request. 907 numAttempted[i - numFailures] = request.getRttBurstSize(); 908 numSuccessful[i - numFailures] = result.getNumSuccessfulMeasurements(); 909 timestampsMs[i - numFailures] = result.getRangingTimestampMillis(); 910 911 byte[] currentLci = result.getLci(); 912 byte[] currentLcr = result.getLcr(); 913 if (i - numFailures > 0) { 914 assertArrayEquals( 915 "Wi-Fi RTT results: invalid result (LCI mismatch) on iteration " + i, 916 currentLci, lastLci); 917 assertArrayEquals( 918 "Wi-Fi RTT results: invalid result (LCR mismatch) on iteration " + i, 919 currentLcr, lastLcr); 920 } 921 lastLci = currentLci; 922 lastLcr = currentLcr; 923 } else { 924 numFailures++; 925 } 926 // Sleep a while to avoid stress AP. 927 Thread.sleep(INTERVAL_MS); 928 } 929 // Save results to log 930 int numGoodResults = NUM_OF_RTT_ITERATIONS - numFailures; 931 DeviceReportLog reportLog = new DeviceReportLog(TAG, "testRangingToTestAp"); 932 reportLog.addValues("status_codes", statuses, ResultType.NEUTRAL, ResultUnit.NONE); 933 reportLog.addValues("distance_mm", Arrays.copyOf(distanceMms, numGoodResults), 934 ResultType.NEUTRAL, ResultUnit.NONE); 935 reportLog.addValues("distance_stddev_mm", 936 Arrays.copyOf(distanceStdDevMms, numGoodResults), 937 ResultType.NEUTRAL, ResultUnit.NONE); 938 reportLog.addValues("rssi_dbm", Arrays.copyOf(rssis, numGoodResults), 939 ResultType.NEUTRAL, 940 ResultUnit.NONE); 941 reportLog.addValues("num_attempted", Arrays.copyOf(numAttempted, numGoodResults), 942 ResultType.NEUTRAL, ResultUnit.NONE); 943 reportLog.addValues("num_successful", Arrays.copyOf(numSuccessful, numGoodResults), 944 ResultType.NEUTRAL, ResultUnit.NONE); 945 reportLog.addValues("timestamps", Arrays.copyOf(timestampsMs, numGoodResults), 946 ResultType.NEUTRAL, ResultUnit.NONE); 947 reportLog.submit(); 948 949 if (mCharacteristics != null && mCharacteristics.getBoolean(WifiRttManager 950 .CHARACTERISTICS_KEY_BOOLEAN_ONE_SIDED_RTT)) { 951 // Analyze results 952 assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures 953 + ", ITERATIONS=" 954 + NUM_OF_RTT_ITERATIONS + ", AP=" + testAp, 955 numFailures <= NUM_OF_RTT_ITERATIONS * MAX_NON11MC_FAILURE_RATE_PERCENT / 100); 956 } 957 958 if (numFailures != NUM_OF_RTT_ITERATIONS) { 959 // Calculate an initial average using all measurements to determine distance outliers 960 double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures); 961 // Now figure out the distance outliers and mark them in the distance inclusion map 962 int validDistances = 0; 963 for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) { 964 if (distanceMms[i] - variationLimit < distanceAvg) { 965 // Distances that are in range for the distribution are included in the map 966 distanceInclusionMap[i] = true; 967 validDistances++; 968 } else { 969 // Distances that are out of range for the distribution are excluded in the map 970 distanceInclusionMap[i] = false; 971 } 972 } 973 974 assertTrue("After fails+outlier removal greater that 50% distances must remain: " 975 + NUM_OF_RTT_ITERATIONS / 2, validDistances > NUM_OF_RTT_ITERATIONS / 2); 976 977 // Remove the distance outliers and find the new average, min and max. 978 distanceSum = 0; 979 distanceMax = Integer.MIN_VALUE; 980 distanceMin = Integer.MAX_VALUE; 981 for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) { 982 if (distanceInclusionMap[i]) { 983 distanceSum += distanceMms[i]; 984 distanceMin = Math.min(distanceMin, distanceMms[i]); 985 distanceMax = Math.max(distanceMax, distanceMms[i]); 986 } 987 } 988 distanceAvg = (double) distanceSum / validDistances; 989 assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation =" 990 + (distanceMax - distanceAvg), 991 (distanceMax - distanceAvg) <= variationLimit); 992 assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation =" 993 + (distanceAvg - distanceMin), 994 (distanceAvg - distanceMin) <= variationLimit); 995 for (int i = 0; i < numGoodResults; ++i) { 996 assertNotEquals("Number of attempted measurements is 0", 0, numAttempted[i]); 997 assertNotEquals("Number of successful measurements is 0", 0, numSuccessful[i]); 998 } 999 } 1000 1001 } 1002 1003 /** 1004 * Test RangingResult.Builder 1005 */ 1006 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1007 @Test 1008 @ApiTest(apis = { "android.net.wifi.rtt.RangingResult.Builder#setMacAddress", 1009 "android.net.wifi.rtt.RangingResult.Builder#setPeerHandle", 1010 "android.net.wifi.rtt.RangingResult.Builder#setStatus", 1011 "android.net.wifi.rtt.RangingResult.Builder#setDistanceMm", 1012 "android.net.wifi.rtt.RangingResult.Builder#setDistanceStdDevMm", 1013 "android.net.wifi.rtt.RangingResult.Builder#setLci", 1014 "android.net.wifi.rtt.RangingResult.Builder#setLcr", 1015 "android.net.wifi.rtt.RangingResult.Builder#setNumAttemptedMeasurements", 1016 "android.net.wifi.rtt.RangingResult.Builder#setNumSuccessfulMeasurements", 1017 "android.net.wifi.rtt.RangingResult.Builder#setRangingTimestampMillis", 1018 "android.net.wifi.rtt.RangingResult.Builder#setRssi", 1019 "android.net.wifi.rtt.RangingResult.Builder#setMeasurementChannelFrequencyMHz", 1020 "android.net.wifi.rtt.RangingResult.Builder#setMeasurementBandwidth", 1021 "android.net.wifi.rtt.RangingResult.Builder#set80211azNtbMeasurement", 1022 "android.net.wifi.rtt.RangingResult.Builder#set80211mcMeasurement", 1023 "android.net.wifi.rtt.RangingResult.Builder#set80211azInitiatorTxLtfRepetitionsCount", 1024 "android.net.wifi.rtt.RangingResult.Builder#set80211azResponderTxLtfRepetitionsCount", 1025 "android.net.wifi.rtt.RangingResult.Builder#set80211azNumberOfRxSpatialStreams", 1026 "android.net.wifi.rtt.RangingResult.Builder#set80211azNumberOfTxSpatialStreams", 1027 "android.net.wifi.rtt.RangingResult.Builder#setMinTimeBetweenNtbMeasurementsMicros", 1028 "android.net.wifi.rtt.RangingResult.Builder#setMaxTimeBetweenNtbMeasurementsMicros", 1029 "android.net.wifi.rtt.RangingResult.Builder#setUnverifiedResponderLocation", 1030 "android.net.wifi.rtt.RangingResult#Builder"}) testRangingResultBuilder()1031 public void testRangingResultBuilder() { 1032 byte[] lci = {1, 2, 3, 4}; 1033 byte[] lcr = {10, 20, 30, 40}; 1034 RangingResult rangingResult = new RangingResult.Builder() 1035 .setMacAddress(MacAddress.fromString("00:11:22:33:44:55")) 1036 .setPeerHandle(null) 1037 .setStatus(RangingResult.STATUS_SUCCESS) 1038 .setDistanceMm(100) 1039 .setDistanceStdDevMm(33) 1040 .setLci(lci) 1041 .setLcr(lcr) 1042 .setNumAttemptedMeasurements(10) 1043 .setNumSuccessfulMeasurements(5) 1044 .setRangingTimestampMillis(12345) 1045 .setRssi(-77) 1046 .setMeasurementChannelFrequencyMHz(5180) 1047 .setMeasurementBandwidth(ScanResult.CHANNEL_WIDTH_40MHZ) 1048 .set80211azNtbMeasurement(true) 1049 .set80211mcMeasurement(false) 1050 .set80211azInitiatorTxLtfRepetitionsCount(2) 1051 .set80211azResponderTxLtfRepetitionsCount(1) 1052 .set80211azNumberOfRxSpatialStreams(2) 1053 .set80211azNumberOfTxSpatialStreams(1) 1054 .setMinTimeBetweenNtbMeasurementsMicros(1000) 1055 .setMaxTimeBetweenNtbMeasurementsMicros(10000) 1056 .setUnverifiedResponderLocation(null) 1057 .build(); 1058 1059 assertEquals(MacAddress.fromString("00:11:22:33:44:55"), rangingResult.getMacAddress()); 1060 assertEquals(null, rangingResult.getPeerHandle()); 1061 assertEquals(RangingResult.STATUS_SUCCESS, rangingResult.getStatus()); 1062 assertEquals(100, rangingResult.getDistanceMm()); 1063 assertEquals(33, rangingResult.getDistanceStdDevMm()); 1064 assertArrayEquals(lci, rangingResult.getLci()); 1065 assertArrayEquals(lcr, rangingResult.getLcr()); 1066 assertEquals(10, rangingResult.getNumAttemptedMeasurements()); 1067 assertEquals(5, rangingResult.getNumSuccessfulMeasurements()); 1068 assertEquals(12345, rangingResult.getRangingTimestampMillis()); 1069 assertEquals(-77, rangingResult.getRssi()); 1070 assertEquals(5180, rangingResult.getMeasurementChannelFrequencyMHz()); 1071 assertEquals(ScanResult.CHANNEL_WIDTH_40MHZ, rangingResult.getMeasurementBandwidth()); 1072 assertTrue(rangingResult.is80211azNtbMeasurement()); 1073 assertFalse(rangingResult.is80211mcMeasurement()); 1074 assertEquals(2, rangingResult.get80211azInitiatorTxLtfRepetitionsCount()); 1075 assertEquals(1, rangingResult.get80211azResponderTxLtfRepetitionsCount()); 1076 assertEquals(2, rangingResult.get80211azNumberOfRxSpatialStreams()); 1077 assertEquals(1, rangingResult.get80211azNumberOfTxSpatialStreams()); 1078 assertEquals(1000, rangingResult.getMinTimeBetweenNtbMeasurementsMicros()); 1079 assertEquals(10000, rangingResult.getMaxTimeBetweenNtbMeasurementsMicros()); 1080 assertEquals(null, rangingResult.getUnverifiedResponderLocation()); 1081 try { 1082 rangingResult = new RangingResult.Builder() 1083 .setStatus(RangingResult.STATUS_SUCCESS) 1084 .setDistanceMm(100) 1085 .setDistanceStdDevMm(33) 1086 .build(); 1087 assertEquals(RangingResult.STATUS_SUCCESS, rangingResult.getStatus()); 1088 fail("RangeResult need MAC address or Peer handle"); 1089 } catch (IllegalArgumentException e) { 1090 1091 } 1092 } 1093 1094 /** 1095 * Test Secure RangingResult.Builder 1096 */ 1097 @RequiresFlagsEnabled(Flags.FLAG_SECURE_RANGING) 1098 @Test 1099 @ApiTest(apis = { "android.net.wifi.rtt.RangingResult.Builder#setRangingFrameProtected", 1100 "android.net.wifi.rtt.RangingResult.Builder#setRangingAuthenticated", 1101 "android.net.wifi.rtt.RangingResult#isRangingFrameProtected", 1102 "android.net.wifi.rtt.RangingResult#isRangingAuthenticated", 1103 "android.net.wifi.rtt.RangingResult#isSecureHeLtfEnabled"}) testSecureRangingResultBuilder()1104 public void testSecureRangingResultBuilder() { 1105 RangingResult rangingResult = new RangingResult.Builder() 1106 .setMacAddress(MacAddress.fromString("00:11:22:33:44:55")) 1107 .setRangingFrameProtected(true) 1108 .setRangingAuthenticated(true) 1109 .setSecureHeLtfEnabled(true) 1110 .setSecureHeLtfProtocolVersion(1) 1111 .build(); 1112 1113 assertEquals(MacAddress.fromString("00:11:22:33:44:55"), rangingResult.getMacAddress()); 1114 assertTrue(rangingResult.isRangingFrameProtected()); 1115 assertTrue(rangingResult.isRangingAuthenticated()); 1116 assertTrue(rangingResult.isSecureHeLtfEnabled()); 1117 assertEquals(1, rangingResult.getSecureHeLtfProtocolVersion()); 1118 } 1119 1120 /** 1121 * Test Wi-Fi RTT ranging operation using ScanResults in request: 1122 * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11az) 1123 * - Perform N (constant) RTT operations 1124 * - Validate: 1125 * - Failure ratio < threshold (constant) 1126 * - Result margin < threshold (constant) 1127 */ 1128 @Test 1129 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) testRangingToTest11azApUsingScanResult()1130 public void testRangingToTest11azApUsingScanResult() throws InterruptedException { 1131 assumeTrue(mCharacteristics != null && mCharacteristics.getBoolean( 1132 WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR)); 1133 ScanResult testAp = getS11AzScanResult(); 1134 assertNotNull("Cannot find any test APs which support RTT / IEEE 802.11az" 1135 + " - please verify that your test setup includes them!", testAp); 1136 RangingRequest.Builder builder = new RangingRequest.Builder(); 1137 builder.addAccessPoint(testAp); 1138 RangingRequest request = builder.build(); 1139 range11azApRequest(request, testAp, false); 1140 } 1141 1142 /* 1143 * Test that vendor data can be set and retrieved properly in RangingRequest and RangingResult. 1144 */ 1145 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1146 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 1147 codeName = "VanillaIceCream") 1148 @Test testRangingRequestVendorData()1149 public void testRangingRequestVendorData() { 1150 // Default value should be an empty list 1151 RangingRequest emptyRequest = new RangingRequest.Builder().build(); 1152 assertNotNull(emptyRequest.getVendorData()); 1153 assertTrue(emptyRequest.getVendorData().isEmpty()); 1154 1155 RangingResult emptyResult = new RangingResult.Builder().setMacAddress(MAC).build(); 1156 assertNotNull(emptyResult.getVendorData()); 1157 assertTrue(emptyResult.getVendorData().isEmpty()); 1158 1159 // Set and get vendor data 1160 OuiKeyedData vendorDataElement = 1161 new OuiKeyedData.Builder(0x00aabbcc, new PersistableBundle()).build(); 1162 List<OuiKeyedData> vendorData = Arrays.asList(vendorDataElement); 1163 1164 RangingRequest requestWithData = new RangingRequest.Builder() 1165 .setVendorData(vendorData) 1166 .build(); 1167 assertTrue(vendorData.equals(requestWithData.getVendorData())); 1168 1169 RangingResult resultWithData = new RangingResult.Builder() 1170 .setMacAddress(MAC) 1171 .setVendorData(vendorData) 1172 .build(); 1173 assertTrue(vendorData.equals(resultWithData.getVendorData())); 1174 } 1175 1176 /** 1177 * Test Wi-Fi RTT ranging using ResponderConfig in the single responder RangingRequest API. 1178 * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11az) 1179 * - Perform N (constant) RTT operations 1180 * - Validate: 1181 * - Failure ratio < threshold (constant) 1182 * - Result margin < threshold (constant) 1183 */ 1184 @Test 1185 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1186 @ApiTest(apis = {"android.net.wifi.rtt.ResponderConfig.Builder#set80211azNtbSupported", 1187 "android.net.wifi.rtt.ResponderConfig#is80211azNtbSupported"}) testRangingToTest11azApUsingResponderConfig()1188 public void testRangingToTest11azApUsingResponderConfig() throws InterruptedException { 1189 assumeTrue(mCharacteristics != null && mCharacteristics.getBoolean( 1190 WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR)); 1191 // Scan for IEEE 802.11az supporting APs 1192 ScanResult testAp = getS11AzScanResult(); 1193 assertNotNull( 1194 "Cannot find any test APs which support RTT / IEEE 802.11az - please verify that " 1195 + "your test setup includes them!", testAp); 1196 int preamble = ResponderConfig.fromScanResult(testAp).getPreamble(); 1197 1198 // Create a ResponderConfig from the builder API. 1199 ResponderConfig.Builder responderBuilder = new ResponderConfig.Builder(); 1200 ResponderConfig responder = responderBuilder 1201 .setMacAddress(MacAddress.fromString(testAp.BSSID)) 1202 .set80211azNtbSupported(testAp.is80211azNtbResponder()) 1203 .setChannelWidth(testAp.channelWidth) 1204 .setFrequencyMhz(testAp.frequency) 1205 .setCenterFreq0Mhz(testAp.centerFreq0) 1206 .setCenterFreq1Mhz(testAp.centerFreq1) 1207 .setPreamble(preamble) 1208 .setResponderType(RESPONDER_AP) 1209 .build(); 1210 1211 // Validate ResponderConfig.Builder set method arguments match getter methods. 1212 assertTrue(responder.getMacAddress().toString().equalsIgnoreCase(testAp.BSSID) 1213 && responder.is80211azNtbSupported() == testAp.is80211azNtbResponder() 1214 && responder.getChannelWidth() == testAp.channelWidth 1215 && responder.getFrequencyMhz() == testAp.frequency 1216 && responder.getCenterFreq0Mhz() == testAp.centerFreq0 1217 && responder.getCenterFreq1Mhz() == testAp.centerFreq1 1218 && responder.getPreamble() == preamble 1219 && responder.getResponderType() == RESPONDER_AP); 1220 1221 // Perform RTT operations 1222 RangingRequest.Builder builder = new RangingRequest.Builder(); 1223 builder.addResponder(responder); 1224 1225 RangingRequest request = builder.build(); 1226 1227 if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) { 1228 assertEquals(1, request.getRttResponders().size()); 1229 } 1230 range11azApRequest(request, testAp, false); 1231 } 1232 1233 /** 1234 * Test Wi-Fi RTT secure ranging operation using ScanResults in request: 1235 * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11az secure 1236 * ranging) 1237 * - Perform N (constant) RTT operations 1238 * - Validate: 1239 * - Failure ratio < threshold (constant) 1240 * - Result margin < threshold (constant) 1241 */ 1242 @Test 1243 @RequiresFlagsEnabled(Flags.FLAG_SECURE_RANGING) 1244 @ApiTest(apis = {"android.net.wifi.rtt.ResponderConfig.Builder#set80211azNtbSupported", 1245 "android.net.wifi.rtt.ResponderConfig#is80211azNtbSupported"}) testSecureRangingToTest11azApUsingScanResult()1246 public void testSecureRangingToTest11azApUsingScanResult() throws InterruptedException { 1247 // Check Device capabilities 1248 assumeNotNull(mCharacteristics); 1249 assumeTrue(mCharacteristics.getBoolean( 1250 WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR)); 1251 assumeTrue(mCharacteristics.getBoolean( 1252 WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_RANGING_FRAME_PROTECTION_SUPPORTED)); 1253 assumeTrue(mCharacteristics.getBoolean( 1254 WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_SECURE_HE_LTF_SUPPORTED)); 1255 assertTrue(mCharacteristics.getInt( 1256 WifiRttManager.CHARACTERISTICS_KEY_INT_MAX_SUPPORTED_SECURE_HE_LTF_PROTO_VERSION) 1257 >= 0); 1258 1259 // Check for responder 1260 ScanResult testAp = getS11AzSecureScanResult(); 1261 assertNotNull("Cannot find any test APs which support IEEE 802.11az Secure Ranging" 1262 + " - please verify that your test setup includes them!", testAp); 1263 RangingRequest.Builder builder = new RangingRequest.Builder(); 1264 builder.addAccessPoint(testAp); 1265 RangingRequest request = builder.build(); 1266 1267 // Validate responder configuration 1268 assertEquals(1, request.getRttResponders().size()); 1269 ResponderConfig responderConfig = request.getRttResponders().getFirst(); 1270 SecureRangingConfig secureRangingConfig = responderConfig.getSecureRangingConfig(); 1271 assertNotNull(secureRangingConfig); 1272 assertTrue(secureRangingConfig.isSecureHeLtfEnabled()); 1273 assumeTrue(secureRangingConfig.isRangingFrameProtectionEnabled()); 1274 PasnConfig pasnConfig = secureRangingConfig.getPasnConfig(); 1275 assertNotNull(pasnConfig); 1276 assertTrue(pasnConfig.getBaseAkms() != PasnConfig.AKM_NONE); 1277 assertTrue(pasnConfig.getCiphers() != PasnConfig.CIPHER_NONE); 1278 assertNotNull(pasnConfig.getWifiSsid()); 1279 1280 range11azApRequest(request, testAp, true); 1281 } 1282 } 1283 1284