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