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 android.content.IntentFilter; 20 import android.net.wifi.ScanResult; 21 import android.net.wifi.rtt.RangingRequest; 22 import android.net.wifi.rtt.RangingResult; 23 import android.net.wifi.rtt.WifiRttManager; 24 25 import com.android.compatibility.common.util.DeviceReportLog; 26 import com.android.compatibility.common.util.ResultType; 27 import com.android.compatibility.common.util.ResultUnit; 28 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.List; 32 33 /** 34 * Wi-Fi RTT CTS test: range to all available Access Points which support IEEE 802.11mc. 35 */ 36 public class WifiRttTest extends TestBase { 37 // Number of scans to do while searching for APs supporting IEEE 802.11mc 38 private static final int NUM_SCANS_SEARCHING_FOR_IEEE80211MC_AP = 2; 39 40 // Number of RTT measurements per AP 41 private static final int NUM_OF_RTT_ITERATIONS = 10; 42 43 // Maximum failure rate of RTT measurements (percentage) 44 private static final int MAX_FAILURE_RATE_PERCENT = 10; 45 46 // Maximum variation from the average measurement (measures consistency) 47 private static final int MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM = 1000; 48 49 // Minimum valid RSSI value 50 private static final int MIN_VALID_RSSI = -100; 51 52 /** 53 * Test Wi-Fi RTT ranging operation: 54 * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc) 55 * - Perform N (constant) RTT operations 56 * - Validate: 57 * - Failure ratio < threshold (constant) 58 * - Result margin < threshold (constant) 59 */ 60 public void testRangingToTestAp() throws InterruptedException { 61 if (!shouldTestWifiRtt(getContext())) { 62 return; 63 } 64 65 // Scan for IEEE 802.11mc supporting APs 66 ScanResult testAp = scanForTestAp(NUM_SCANS_SEARCHING_FOR_IEEE80211MC_AP); 67 assertTrue("Cannot find test AP", testAp != null); 68 69 // Perform RTT operations 70 RangingRequest request = new RangingRequest.Builder().addAccessPoint(testAp).build(); 71 List<RangingResult> allResults = new ArrayList<>(); 72 int numFailures = 0; 73 int distanceSum = 0; 74 int distanceMin = 0; 75 int distanceMax = 0; 76 int[] statuses = new int[NUM_OF_RTT_ITERATIONS]; 77 int[] distanceMms = new int[NUM_OF_RTT_ITERATIONS]; 78 int[] distanceStdDevMms = new int[NUM_OF_RTT_ITERATIONS]; 79 int[] rssis = new int[NUM_OF_RTT_ITERATIONS]; 80 int[] numAttempted = new int[NUM_OF_RTT_ITERATIONS]; 81 int[] numSuccessful = new int[NUM_OF_RTT_ITERATIONS]; 82 long[] timestampsMs = new long[NUM_OF_RTT_ITERATIONS]; 83 byte[] lastLci = null; 84 byte[] lastLcr = null; 85 for (int i = 0; i < NUM_OF_RTT_ITERATIONS; ++i) { 86 ResultCallback callback = new ResultCallback(); 87 mWifiRttManager.startRanging(request, mExecutor, callback); 88 assertTrue("Wi-Fi RTT results: no callback on iteration " + i, 89 callback.waitForCallback()); 90 91 List<RangingResult> currentResults = callback.getResults(); 92 assertTrue("Wi-Fi RTT results: null results (onRangingFailure) on iteration " + i, 93 currentResults != null); 94 assertTrue("Wi-Fi RTT results: unexpected # of results (expect 1) on iteration " + i, 95 currentResults.size() == 1); 96 RangingResult result = currentResults.get(0); 97 assertTrue("Wi-Fi RTT results: invalid result (wrong BSSID) entry on iteration " + i, 98 result.getMacAddress().toString().equals(testAp.BSSID)); 99 assertEquals( 100 "Wi-Fi RTT results: invalid result (non-null PeerHandle) entry on iteration " 101 + i, null, result.getPeerHandle()); 102 103 allResults.add(result); 104 int status = result.getStatus(); 105 statuses[i] = status; 106 if (status == RangingResult.STATUS_SUCCESS) { 107 distanceSum += result.getDistanceMm(); 108 if (i == 0) { 109 distanceMin = result.getDistanceMm(); 110 distanceMax = result.getDistanceMm(); 111 } else { 112 distanceMin = Math.min(distanceMin, result.getDistanceMm()); 113 distanceMax = Math.max(distanceMax, result.getDistanceMm()); 114 } 115 116 assertTrue("Wi-Fi RTT results: invalid RSSI on iteration " + i, 117 result.getRssi() >= MIN_VALID_RSSI); 118 119 distanceMms[i - numFailures] = result.getDistanceMm(); 120 distanceStdDevMms[i - numFailures] = result.getDistanceStdDevMm(); 121 rssis[i - numFailures] = result.getRssi(); 122 numAttempted[i - numFailures] = result.getNumAttemptedMeasurements(); 123 numSuccessful[i - numFailures] = result.getNumSuccessfulMeasurements(); 124 timestampsMs[i - numFailures] = result.getRangingTimestampMillis(); 125 126 byte[] currentLci = result.getLci(); 127 byte[] currentLcr = result.getLcr(); 128 if (i - numFailures > 0) { 129 assertTrue("Wi-Fi RTT results: invalid result (LCI mismatch) on iteration " + i, 130 Arrays.equals(currentLci, lastLci)); 131 assertTrue("Wi-Fi RTT results: invalid result (LCR mismatch) on iteration " + i, 132 Arrays.equals(currentLcr, lastLcr)); 133 } 134 lastLci = currentLci; 135 lastLcr = currentLcr; 136 } else { 137 numFailures++; 138 } 139 } 140 141 // Save results to log 142 int numGoodResults = NUM_OF_RTT_ITERATIONS - numFailures; 143 DeviceReportLog reportLog = new DeviceReportLog(TAG, "testRangingToTestAp"); 144 reportLog.addValues("status_codes", statuses, ResultType.NEUTRAL, ResultUnit.NONE); 145 reportLog.addValues("distance_mm", Arrays.copyOf(distanceMms, numGoodResults), 146 ResultType.NEUTRAL, ResultUnit.NONE); 147 reportLog.addValues("distance_stddev_mm", Arrays.copyOf(distanceStdDevMms, numGoodResults), 148 ResultType.NEUTRAL, ResultUnit.NONE); 149 reportLog.addValues("rssi_dbm", Arrays.copyOf(rssis, numGoodResults), ResultType.NEUTRAL, 150 ResultUnit.NONE); 151 reportLog.addValues("num_attempted", Arrays.copyOf(numAttempted, numGoodResults), 152 ResultType.NEUTRAL, ResultUnit.NONE); 153 reportLog.addValues("num_successful", Arrays.copyOf(numSuccessful, numGoodResults), 154 ResultType.NEUTRAL, ResultUnit.NONE); 155 reportLog.addValues("timestamps", Arrays.copyOf(timestampsMs, numGoodResults), 156 ResultType.NEUTRAL, ResultUnit.NONE); 157 reportLog.submit(); 158 159 // Analyze results 160 assertTrue("Wi-Fi RTT failure rate exceeds threshold", 161 numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100); 162 if (numFailures != NUM_OF_RTT_ITERATIONS) { 163 double distanceAvg = distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures); 164 assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold", 165 (distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM); 166 assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold", 167 (distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM); 168 for (int i = 0; i < numGoodResults; ++i) { 169 assertNotSame("Number of attempted measurements is 0", 0, numAttempted[i]); 170 assertNotSame("Number of successful measurements is 0", 0, numSuccessful[i]); 171 } 172 } 173 } 174 175 /** 176 * Validate that when a request contains more range operations than allowed (by API) that we 177 * get an exception. 178 */ 179 public void testRequestTooLarge() { 180 if (!shouldTestWifiRtt(getContext())) { 181 return; 182 } 183 184 ScanResult dummy = new ScanResult(); 185 dummy.BSSID = "00:01:02:03:04:05"; 186 187 RangingRequest.Builder builder = new RangingRequest.Builder(); 188 for (int i = 0; i < RangingRequest.getMaxPeers() - 2; ++i) { 189 builder.addAccessPoint(dummy); 190 } 191 192 List<ScanResult> scanResults = new ArrayList<>(); 193 scanResults.add(dummy); 194 scanResults.add(dummy); 195 scanResults.add(dummy); 196 197 builder.addAccessPoints(scanResults); 198 199 try { 200 mWifiRttManager.startRanging(builder.build(), mExecutor, new ResultCallback()); 201 } catch (IllegalArgumentException e) { 202 return; 203 } 204 205 assertTrue( 206 "Did not receive expected IllegalArgumentException when tried to range to too " 207 + "many peers", 208 false); 209 } 210 } 211