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; 18 19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.junit.Assert.assertArrayEquals; 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertFalse; 26 import static org.junit.Assert.assertNull; 27 import static org.junit.Assert.assertTrue; 28 import static org.mockito.Mockito.validateMockitoUsage; 29 30 import android.net.wifi.ScanResult.InformationElement; 31 import android.net.wifi.util.ScanResultUtil; 32 import android.os.Parcel; 33 34 import androidx.test.filters.SmallTest; 35 36 import com.android.dx.mockito.inline.extended.ExtendedMockito; 37 38 import org.junit.After; 39 import org.junit.Before; 40 import org.junit.Test; 41 import org.mockito.MockitoAnnotations; 42 import org.mockito.MockitoSession; 43 44 import java.util.List; 45 import java.util.stream.Collectors; 46 47 /** 48 * Unit tests for {@link android.net.wifi.WifiScanner}. 49 */ 50 @SmallTest 51 public class ScanResultTest { 52 public static final String TEST_SSID = "\"test_ssid\""; 53 public static final String TEST_SSID_NON_UTF_8 = "b9c8b8e8"; 54 public static final String TEST_BSSID = "04:ac:fe:45:34:10"; 55 public static final String TEST_CAPS = "CCMP"; 56 public static final int TEST_LEVEL = -56; 57 public static final int TEST_FREQUENCY = 2412; 58 public static final long TEST_TSF = 04660l; 59 public static final @WifiAnnotations.WifiStandard int TEST_WIFI_STANDARD = 60 ScanResult.WIFI_STANDARD_11AC; 61 public static final String TEST_IFACE_NAME = "test_ifname"; 62 63 /** 64 * Frequency to channel map. This include some frequencies used outside the US. 65 * Representing it using a vector (instead of map) for simplification. 66 */ 67 private static final int[] FREQUENCY_TO_CHANNEL_MAP = { 68 2412, WifiScanner.WIFI_BAND_24_GHZ, 1, 69 2417, WifiScanner.WIFI_BAND_24_GHZ, 2, 70 2422, WifiScanner.WIFI_BAND_24_GHZ, 3, 71 2427, WifiScanner.WIFI_BAND_24_GHZ, 4, 72 2432, WifiScanner.WIFI_BAND_24_GHZ, 5, 73 2437, WifiScanner.WIFI_BAND_24_GHZ, 6, 74 2442, WifiScanner.WIFI_BAND_24_GHZ, 7, 75 2447, WifiScanner.WIFI_BAND_24_GHZ, 8, 76 2452, WifiScanner.WIFI_BAND_24_GHZ, 9, 77 2457, WifiScanner.WIFI_BAND_24_GHZ, 10, 78 2462, WifiScanner.WIFI_BAND_24_GHZ, 11, 79 /* 12, 13 are only legitimate outside the US. */ 80 2467, WifiScanner.WIFI_BAND_24_GHZ, 12, 81 2472, WifiScanner.WIFI_BAND_24_GHZ, 13, 82 /* 14 is for Japan, DSSS and CCK only. */ 83 2484, WifiScanner.WIFI_BAND_24_GHZ, 14, 84 /* 34 valid in Japan. */ 85 5170, WifiScanner.WIFI_BAND_5_GHZ, 34, 86 5180, WifiScanner.WIFI_BAND_5_GHZ, 36, 87 5190, WifiScanner.WIFI_BAND_5_GHZ, 38, 88 5200, WifiScanner.WIFI_BAND_5_GHZ, 40, 89 5210, WifiScanner.WIFI_BAND_5_GHZ, 42, 90 5220, WifiScanner.WIFI_BAND_5_GHZ, 44, 91 5230, WifiScanner.WIFI_BAND_5_GHZ, 46, 92 5240, WifiScanner.WIFI_BAND_5_GHZ, 48, 93 5260, WifiScanner.WIFI_BAND_5_GHZ, 52, 94 5280, WifiScanner.WIFI_BAND_5_GHZ, 56, 95 5300, WifiScanner.WIFI_BAND_5_GHZ, 60, 96 5320, WifiScanner.WIFI_BAND_5_GHZ, 64, 97 5500, WifiScanner.WIFI_BAND_5_GHZ, 100, 98 5520, WifiScanner.WIFI_BAND_5_GHZ, 104, 99 5540, WifiScanner.WIFI_BAND_5_GHZ, 108, 100 5560, WifiScanner.WIFI_BAND_5_GHZ, 112, 101 5580, WifiScanner.WIFI_BAND_5_GHZ, 116, 102 /* 120, 124, 128 valid in Europe/Japan. */ 103 5600, WifiScanner.WIFI_BAND_5_GHZ, 120, 104 5620, WifiScanner.WIFI_BAND_5_GHZ, 124, 105 5640, WifiScanner.WIFI_BAND_5_GHZ, 128, 106 /* 132+ valid in US. */ 107 5660, WifiScanner.WIFI_BAND_5_GHZ, 132, 108 5680, WifiScanner.WIFI_BAND_5_GHZ, 136, 109 5700, WifiScanner.WIFI_BAND_5_GHZ, 140, 110 /* 144 is supported by a subset of WiFi chips. */ 111 5720, WifiScanner.WIFI_BAND_5_GHZ, 144, 112 5745, WifiScanner.WIFI_BAND_5_GHZ, 149, 113 5765, WifiScanner.WIFI_BAND_5_GHZ, 153, 114 5785, WifiScanner.WIFI_BAND_5_GHZ, 157, 115 5805, WifiScanner.WIFI_BAND_5_GHZ, 161, 116 5825, WifiScanner.WIFI_BAND_5_GHZ, 165, 117 5845, WifiScanner.WIFI_BAND_5_GHZ, 169, 118 5865, WifiScanner.WIFI_BAND_5_GHZ, 173, 119 /* Now some 6GHz channels */ 120 5955, WifiScanner.WIFI_BAND_6_GHZ, 1, 121 5935, WifiScanner.WIFI_BAND_6_GHZ, 2, 122 5970, WifiScanner.WIFI_BAND_6_GHZ, 4, 123 6110, WifiScanner.WIFI_BAND_6_GHZ, 32 124 }; 125 126 /** 127 * Setup before tests. 128 */ 129 @Before setUp()130 public void setUp() throws Exception { 131 MockitoAnnotations.initMocks(this); 132 } 133 134 /** 135 * Clean up after tests. 136 */ 137 @After cleanup()138 public void cleanup() { 139 validateMockitoUsage(); 140 } 141 142 /** 143 * Verify the logic that determines whether a frequency is PSC. 144 */ 145 @Test testIs6GHzPsc()146 public void testIs6GHzPsc() { 147 int test2G = 2412; 148 int test6GNonPsc = ScanResult.BAND_6_GHZ_PSC_START_MHZ 149 + ScanResult.BAND_6_GHZ_PSC_STEP_SIZE_MHZ - 20; 150 int test6GPsc = ScanResult.BAND_6_GHZ_PSC_START_MHZ 151 + ScanResult.BAND_6_GHZ_PSC_STEP_SIZE_MHZ; 152 assertFalse(ScanResult.is6GHzPsc(test2G)); 153 assertFalse(ScanResult.is6GHzPsc(test6GNonPsc)); 154 assertTrue(ScanResult.is6GHzPsc(test6GPsc)); 155 } 156 157 /** 158 * Verify parcel read/write for ScanResult. 159 */ 160 @Test verifyScanResultParcelWithoutRadioChainInfo()161 public void verifyScanResultParcelWithoutRadioChainInfo() throws Exception { 162 ScanResult writeScanResult = createScanResult(); 163 ScanResult readScanResult = parcelReadWrite(writeScanResult); 164 assertScanResultEquals(writeScanResult, readScanResult); 165 } 166 167 /** 168 * Verify parcel read/write for ScanResult with non-UTF-8 SSID. 169 */ 170 @Test verifyScanResultParcelWithNonUtf8Ssid()171 public void verifyScanResultParcelWithNonUtf8Ssid() throws Exception { 172 ScanResult writeScanResult = createScanResult(); 173 writeScanResult.setWifiSsid(WifiSsid.fromString(TEST_SSID_NON_UTF_8)); 174 ScanResult readScanResult = parcelReadWrite(writeScanResult); 175 assertScanResultEquals(writeScanResult, readScanResult); 176 } 177 178 179 /** 180 * Verify parcel read/write for ScanResult. 181 */ 182 @Test verifyScanResultParcelWithZeroRadioChainInfo()183 public void verifyScanResultParcelWithZeroRadioChainInfo() throws Exception { 184 ScanResult writeScanResult = createScanResult(); 185 writeScanResult.radioChainInfos = new ScanResult.RadioChainInfo[0]; 186 ScanResult readScanResult = parcelReadWrite(writeScanResult); 187 assertNull(readScanResult.radioChainInfos); 188 } 189 190 /** 191 * Verify parcel read/write for ScanResult. 192 */ 193 @Test verifyScanResultParcelWithRadioChainInfo()194 public void verifyScanResultParcelWithRadioChainInfo() throws Exception { 195 ScanResult writeScanResult = createScanResult(); 196 writeScanResult.radioChainInfos = new ScanResult.RadioChainInfo[2]; 197 writeScanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo(); 198 writeScanResult.radioChainInfos[0].id = 0; 199 writeScanResult.radioChainInfos[0].level = -45; 200 writeScanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo(); 201 writeScanResult.radioChainInfos[1].id = 1; 202 writeScanResult.radioChainInfos[1].level = -54; 203 ScanResult readScanResult = parcelReadWrite(writeScanResult); 204 assertScanResultEquals(writeScanResult, readScanResult); 205 } 206 207 /** 208 * Verify copy constructor for ScanResult. 209 */ 210 @Test verifyScanResultCopyWithoutRadioChainInfo()211 public void verifyScanResultCopyWithoutRadioChainInfo() throws Exception { 212 ScanResult scanResult = createScanResult(); 213 ScanResult copyScanResult = new ScanResult(scanResult); 214 assertScanResultEquals(scanResult, copyScanResult); 215 } 216 217 /** 218 * Verify copy constructor for ScanResult. 219 */ 220 @Test verifyScanResultCopyWithRadioChainInfo()221 public void verifyScanResultCopyWithRadioChainInfo() throws Exception { 222 ScanResult scanResult = createScanResult(); 223 scanResult.radioChainInfos = new ScanResult.RadioChainInfo[2]; 224 scanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo(); 225 scanResult.radioChainInfos[0].id = 0; 226 scanResult.radioChainInfos[0].level = -45; 227 scanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo(); 228 scanResult.radioChainInfos[1].id = 1; 229 scanResult.radioChainInfos[1].level = -54; 230 ScanResult copyScanResult = new ScanResult(scanResult); 231 assertScanResultEquals(scanResult, copyScanResult); 232 } 233 234 /** 235 * Verify parcel read/write for ScanResult with Information Element 236 */ 237 @Test verifyScanResultParcelWithInformationElement()238 public void verifyScanResultParcelWithInformationElement() throws Exception { 239 ScanResult writeScanResult = createScanResult(); 240 writeScanResult.informationElements = new ScanResult.InformationElement[2]; 241 writeScanResult.informationElements[0] = new ScanResult.InformationElement(); 242 writeScanResult.informationElements[0].id = InformationElement.EID_HT_OPERATION; 243 writeScanResult.informationElements[0].idExt = 0; 244 writeScanResult.informationElements[0].bytes = new byte[]{0x11, 0x22, 0x33}; 245 writeScanResult.informationElements[1] = new ScanResult.InformationElement(); 246 writeScanResult.informationElements[1].id = InformationElement.EID_EXTENSION_PRESENT; 247 writeScanResult.informationElements[1].idExt = InformationElement.EID_EXT_HE_OPERATION; 248 writeScanResult.informationElements[1].bytes = new byte[]{0x44, 0x55, 0x66}; 249 ScanResult readScanResult = new ScanResult(writeScanResult); 250 assertScanResultEquals(writeScanResult, readScanResult); 251 } 252 253 /** 254 * Verify toString for ScanResult. 255 */ 256 @Test verifyScanResultToStringWithoutRadioChainInfo()257 public void verifyScanResultToStringWithoutRadioChainInfo() throws Exception { 258 ScanResult scanResult = createScanResult(); 259 assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " 260 + "level: -56, frequency: 2412, timestamp: 2480, " 261 + "distance: 0(cm), distanceSd: 0(cm), " 262 + "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " 263 + "standard: 11ac, " 264 + "80211mcResponder: is not supported, " 265 + "80211azNtbResponder: is not supported, " 266 + "TWT Responder: no, " 267 + "Radio Chain Infos: null, interface name: test_ifname", scanResult.toString()); 268 } 269 270 /** 271 * Verify toString for ScanResult. 272 */ 273 @Test verifyScanResultToStringWithRadioChainInfo()274 public void verifyScanResultToStringWithRadioChainInfo() throws Exception { 275 ScanResult scanResult = createScanResult(); 276 scanResult.radioChainInfos = new ScanResult.RadioChainInfo[2]; 277 scanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo(); 278 scanResult.radioChainInfos[0].id = 0; 279 scanResult.radioChainInfos[0].level = -45; 280 scanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo(); 281 scanResult.radioChainInfos[1].id = 1; 282 scanResult.radioChainInfos[1].level = -54; 283 assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " 284 + "level: -56, frequency: 2412, timestamp: 2480, distance: 0(cm), " 285 + "distanceSd: 0(cm), " 286 + "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " 287 + "standard: 11ac, " 288 + "80211mcResponder: is not supported, " 289 + "80211azNtbResponder: is not supported, " 290 + "TWT Responder: no, " 291 + "Radio Chain Infos: [RadioChainInfo: id=0, level=-45, " 292 + "RadioChainInfo: id=1, level=-54], interface name: test_ifname", 293 scanResult.toString()); 294 } 295 296 /** 297 * Verify toString for ScanResult with non-UTF-8 SSID. 298 */ 299 @Test verifyScanResultToStringWithNonUtf8Ssid()300 public void verifyScanResultToStringWithNonUtf8Ssid() throws Exception { 301 ScanResult scanResult = createScanResult(); 302 scanResult.setWifiSsid(WifiSsid.fromString(TEST_SSID_NON_UTF_8)); 303 assertEquals("SSID: b9c8b8e8, BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " 304 + "level: -56, frequency: 2412, timestamp: 2480, " 305 + "distance: 0(cm), distanceSd: 0(cm), " 306 + "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " 307 + "standard: 11ac, " 308 + "80211mcResponder: is not supported, " 309 + "80211azNtbResponder: is not supported, " 310 + "TWT Responder: no, " 311 + "Radio Chain Infos: null, interface name: test_ifname", scanResult.toString()); 312 } 313 314 /** 315 * verify frequency to channel conversion for all possible frequencies. 316 */ 317 @Test convertFrequencyToChannel()318 public void convertFrequencyToChannel() throws Exception { 319 for (int i = 0; i < FREQUENCY_TO_CHANNEL_MAP.length; i += 3) { 320 assertEquals(FREQUENCY_TO_CHANNEL_MAP[i + 2], 321 ScanResult.convertFrequencyMhzToChannelIfSupported( 322 FREQUENCY_TO_CHANNEL_MAP[i])); 323 } 324 } 325 326 /** 327 * Verify frequency to channel conversion failed for an invalid frequency. 328 */ 329 @Test convertFrequencyToChannelWithInvalidFreq()330 public void convertFrequencyToChannelWithInvalidFreq() throws Exception { 331 assertEquals(-1, ScanResult.convertFrequencyMhzToChannelIfSupported(8000)); 332 } 333 334 /** 335 * Verify that getSecurityTypes returns the types derived from the generated security params 336 */ 337 @Test verifyGetSecurityTypesDerivedFromSecurityParams()338 public void verifyGetSecurityTypesDerivedFromSecurityParams() { 339 List<Integer> wifiConfigSecurityTypes = List.of( 340 WifiConfiguration.SECURITY_TYPE_OPEN, 341 WifiConfiguration.SECURITY_TYPE_WEP, 342 WifiConfiguration.SECURITY_TYPE_PSK, 343 WifiConfiguration.SECURITY_TYPE_EAP, 344 WifiConfiguration.SECURITY_TYPE_SAE, 345 WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT, 346 WifiConfiguration.SECURITY_TYPE_OWE, 347 WifiConfiguration.SECURITY_TYPE_WAPI_PSK, 348 WifiConfiguration.SECURITY_TYPE_WAPI_CERT, 349 WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE, 350 WifiConfiguration.SECURITY_TYPE_OSEN, 351 WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2, 352 WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3); 353 List<SecurityParams> securityParamsList = wifiConfigSecurityTypes.stream() 354 .map(SecurityParams::createSecurityParamsBySecurityType) 355 .collect(Collectors.toList()); 356 List<Integer> wifiInfoSecurityTypes = wifiConfigSecurityTypes.stream() 357 .map(WifiInfo::convertWifiConfigurationSecurityType) 358 .collect(Collectors.toList()); 359 360 MockitoSession session = 361 ExtendedMockito.mockitoSession().spyStatic(ScanResultUtil.class).startMocking(); 362 try { 363 ScanResult scanResult = new ScanResult(); 364 scanResult.capabilities = ""; 365 doReturn(securityParamsList).when( 366 () -> ScanResultUtil.generateSecurityParamsListFromScanResult(scanResult)); 367 assertThat(scanResult.getSecurityTypes()) 368 .asList().containsExactlyElementsIn(wifiInfoSecurityTypes); 369 } finally { 370 session.finishMocking(); 371 } 372 } 373 374 /** 375 * Write the provided {@link ScanResult} to a parcel and deserialize it. 376 */ parcelReadWrite(ScanResult writeResult)377 private static ScanResult parcelReadWrite(ScanResult writeResult) throws Exception { 378 Parcel parcel = Parcel.obtain(); 379 writeResult.writeToParcel(parcel, 0); 380 parcel.setDataPosition(0); // Rewind data position back to the beginning for read. 381 return ScanResult.CREATOR.createFromParcel(parcel); 382 } 383 createScanResult()384 private static ScanResult createScanResult() { 385 ScanResult result = new ScanResult(); 386 result.setWifiSsid(WifiSsid.fromString(TEST_SSID)); 387 result.BSSID = TEST_BSSID; 388 result.capabilities = TEST_CAPS; 389 result.level = TEST_LEVEL; 390 result.frequency = TEST_FREQUENCY; 391 result.timestamp = TEST_TSF; 392 result.setWifiStandard(TEST_WIFI_STANDARD); 393 result.ifaceName = TEST_IFACE_NAME; 394 395 return result; 396 } 397 assertScanResultEquals(ScanResult expected, ScanResult actual)398 private static void assertScanResultEquals(ScanResult expected, ScanResult actual) { 399 assertEquals(expected.SSID, actual.SSID); 400 assertEquals(expected.getWifiSsid(), actual.getWifiSsid()); 401 assertEquals(expected.BSSID, actual.BSSID); 402 assertEquals(expected.capabilities, actual.capabilities); 403 assertEquals(expected.level, actual.level); 404 assertEquals(expected.frequency, actual.frequency); 405 assertEquals(expected.timestamp, actual.timestamp); 406 assertEquals(expected.getWifiStandard(), actual.getWifiStandard()); 407 assertArrayEquals(expected.radioChainInfos, actual.radioChainInfos); 408 assertArrayEquals(expected.informationElements, actual.informationElements); 409 } 410 411 /** 412 * Test ScanResult.getBand() function. 413 */ 414 @Test testScanResultGetBand()415 public void testScanResultGetBand() throws Exception { 416 ScanResult scanResult = createScanResult(); 417 assertEquals(WifiScanner.WIFI_BAND_24_GHZ, scanResult.getBand()); 418 } 419 420 /** 421 * Test ScanResult.toBand() function. 422 */ 423 @Test testScanResultToBand()424 public void testScanResultToBand() throws Exception { 425 assertEquals(WifiScanner.WIFI_BAND_24_GHZ, ScanResult.toBand(TEST_FREQUENCY)); 426 } 427 428 /** 429 * Test ScanResult.getBandFromOpClass() function. 430 */ 431 @Test testScanResultGetBandFromOpCalss()432 public void testScanResultGetBandFromOpCalss() throws Exception { 433 assertEquals(WifiScanner.WIFI_BAND_24_GHZ, ScanResult.getBandFromOpClass(81, 11)); 434 assertEquals(WifiScanner.WIFI_BAND_UNSPECIFIED, ScanResult.getBandFromOpClass(81, 36)); 435 assertEquals(WifiScanner.WIFI_BAND_5_GHZ, ScanResult.getBandFromOpClass(120, 149)); 436 assertEquals(WifiScanner.WIFI_BAND_6_GHZ, ScanResult.getBandFromOpClass(131, 32)); 437 } 438 } 439