1/* 2 * Copyright (C) 2016 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 */ 16package com.android.settingslib.wifi; 17 18import static com.google.common.truth.Truth.assertThat; 19import static com.google.common.truth.Truth.assertWithMessage; 20 21import static org.mockito.Mockito.any; 22import static org.mockito.Mockito.when; 23 24import android.content.Context; 25import android.net.ConnectivityManager; 26import android.net.NetworkInfo; 27import android.net.ScoredNetwork; 28import android.net.wifi.ScanResult; 29import android.net.wifi.WifiConfiguration; 30import android.net.wifi.WifiInfo; 31import android.net.wifi.WifiNetworkScoreCache; 32import android.net.wifi.WifiSsid; 33import android.net.wifi.hotspot2.PasspointConfiguration; 34import android.net.wifi.hotspot2.pps.HomeSp; 35import android.os.Bundle; 36import android.os.SystemClock; 37import android.support.test.InstrumentationRegistry; 38import android.support.test.filters.SmallTest; 39import android.support.test.runner.AndroidJUnit4; 40import android.text.SpannableString; 41import android.text.style.TtsSpan; 42 43import org.junit.Before; 44import org.junit.Test; 45import org.junit.runner.RunWith; 46import org.mockito.Mock; 47import org.mockito.MockitoAnnotations; 48 49import java.util.ArrayList; 50import java.util.Collections; 51 52@SmallTest 53@RunWith(AndroidJUnit4.class) 54public class AccessPointTest { 55 56 private static final String TEST_SSID = "test_ssid"; 57 private Context mContext; 58 @Mock private WifiNetworkScoreCache mWifiNetworkScoreCache; 59 60 @Before 61 public void setUp() { 62 MockitoAnnotations.initMocks(this); 63 mContext = InstrumentationRegistry.getTargetContext(); 64 } 65 66 @Test 67 public void testSsidIsTelephoneSpan() { 68 final Bundle bundle = new Bundle(); 69 bundle.putString("key_ssid", TEST_SSID); 70 final AccessPoint ap = new AccessPoint(InstrumentationRegistry.getTargetContext(), bundle); 71 final CharSequence ssid = ap.getSsid(); 72 73 assertThat(ssid instanceof SpannableString).isTrue(); 74 75 TtsSpan[] spans = ((SpannableString) ssid).getSpans(0, TEST_SSID.length(), TtsSpan.class); 76 77 assertThat(spans.length).isEqualTo(1); 78 assertThat(spans[0].getType()).isEqualTo(TtsSpan.TYPE_TELEPHONE); 79 } 80 81 @Test 82 public void testCopyAccessPoint_dataShouldMatch() { 83 WifiConfiguration configuration = createWifiConfiguration(); 84 configuration.meteredHint = true; 85 86 NetworkInfo networkInfo = 87 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE"); 88 AccessPoint originalAccessPoint = new AccessPoint(mContext, configuration); 89 WifiInfo wifiInfo = new WifiInfo(); 90 wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID)); 91 wifiInfo.setBSSID(configuration.BSSID); 92 originalAccessPoint.update(configuration, wifiInfo, networkInfo); 93 AccessPoint copy = new AccessPoint(mContext, originalAccessPoint); 94 95 assertThat(originalAccessPoint.getSsid().toString()).isEqualTo(copy.getSsid().toString()); 96 assertThat(originalAccessPoint.getBssid()).isEqualTo(copy.getBssid()); 97 assertThat(originalAccessPoint.getConfig()).isEqualTo(copy.getConfig()); 98 assertThat(originalAccessPoint.getSecurity()).isEqualTo(copy.getSecurity()); 99 assertThat(originalAccessPoint.isMetered()).isEqualTo(copy.isMetered()); 100 assertThat(originalAccessPoint.compareTo(copy) == 0).isTrue(); 101 } 102 103 @Test 104 public void testThatCopyAccessPoint_scanCacheShouldMatch() { 105 AccessPoint original = createAccessPointWithScanResultCache(); 106 assertThat(original.getRssi()).isEqualTo(4); 107 AccessPoint copy = new AccessPoint(mContext, createWifiConfiguration()); 108 assertThat(copy.getRssi()).isEqualTo(AccessPoint.UNREACHABLE_RSSI); 109 copy.copyFrom(original); 110 assertThat(original.getRssi()).isEqualTo(copy.getRssi()); 111 } 112 113 @Test 114 public void testCompareTo_GivesActiveBeforeInactive() { 115 AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build(); 116 AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build(); 117 118 assertSortingWorks(activeAp, inactiveAp); 119 } 120 121 @Test 122 public void testCompareTo_GivesReachableBeforeUnreachable() { 123 AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build(); 124 AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build(); 125 126 assertSortingWorks(nearAp, farAp); 127 } 128 129 @Test 130 public void testCompareTo_GivesSavedBeforeUnsaved() { 131 AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build(); 132 AccessPoint notSavedAp = new TestAccessPointBuilder(mContext).setSaved(false).build(); 133 134 assertSortingWorks(savedAp, notSavedAp); 135 } 136 137 //TODO: add tests for mRankingScore sort order if ranking is exposed 138 139 @Test 140 public void testCompareTo_GivesHighLevelBeforeLowLevel() { 141 final int highLevel = AccessPoint.SIGNAL_LEVELS - 1; 142 final int lowLevel = 1; 143 assertThat(highLevel).isGreaterThan(lowLevel); 144 145 AccessPoint strongAp = new TestAccessPointBuilder(mContext).setLevel(highLevel).build(); 146 AccessPoint weakAp = new TestAccessPointBuilder(mContext).setLevel(lowLevel).build(); 147 148 assertSortingWorks(strongAp, weakAp); 149 } 150 151 @Test 152 public void testCompareTo_GivesSsidAlphabetically() { 153 154 final String firstName = "AAAAAA"; 155 final String secondName = "zzzzzz"; 156 157 AccessPoint firstAp = new TestAccessPointBuilder(mContext).setSsid(firstName).build(); 158 AccessPoint secondAp = new TestAccessPointBuilder(mContext).setSsid(secondName).build(); 159 160 assertThat(firstAp.getSsidStr().compareToIgnoreCase(secondAp.getSsidStr()) < 0).isTrue(); 161 assertSortingWorks(firstAp, secondAp); 162 } 163 164 @Test 165 public void testCompareTo_AllSortingRulesCombined() { 166 167 AccessPoint active = new TestAccessPointBuilder(mContext).setActive(true).build(); 168 AccessPoint reachableAndMinLevel = new TestAccessPointBuilder(mContext) 169 .setReachable(true).build(); 170 AccessPoint saved = new TestAccessPointBuilder(mContext).setSaved(true).build(); 171 AccessPoint highLevelAndReachable = new TestAccessPointBuilder(mContext) 172 .setLevel(AccessPoint.SIGNAL_LEVELS - 1).build(); 173 AccessPoint firstName = new TestAccessPointBuilder(mContext).setSsid("a").build(); 174 AccessPoint lastname = new TestAccessPointBuilder(mContext).setSsid("z").build(); 175 176 ArrayList<AccessPoint> points = new ArrayList<AccessPoint>(); 177 points.add(lastname); 178 points.add(firstName); 179 points.add(highLevelAndReachable); 180 points.add(saved); 181 points.add(reachableAndMinLevel); 182 points.add(active); 183 184 Collections.sort(points); 185 assertThat(points.indexOf(active)).isLessThan(points.indexOf(reachableAndMinLevel)); 186 assertThat(points.indexOf(reachableAndMinLevel)).isLessThan(points.indexOf(saved)); 187 // note: the saved AP will not appear before highLevelAndReachable, 188 // because all APs with a signal level are reachable, 189 // and isReachable() takes higher sorting precedence than isSaved(). 190 assertThat(points.indexOf(saved)).isLessThan(points.indexOf(firstName)); 191 assertThat(points.indexOf(highLevelAndReachable)).isLessThan(points.indexOf(firstName)); 192 assertThat(points.indexOf(firstName)).isLessThan(points.indexOf(lastname)); 193 } 194 195 @Test 196 public void testRssiIsSetFromScanResults() { 197 AccessPoint ap = createAccessPointWithScanResultCache(); 198 int originalRssi = ap.getRssi(); 199 assertThat(originalRssi).isNotEqualTo(AccessPoint.UNREACHABLE_RSSI); 200 } 201 202 @Test 203 public void testGetRssiShouldReturnSetRssiValue() { 204 AccessPoint ap = createAccessPointWithScanResultCache(); 205 int originalRssi = ap.getRssi(); 206 int newRssi = originalRssi - 10; 207 ap.setRssi(newRssi); 208 assertThat(ap.getRssi()).isEqualTo(newRssi); 209 } 210 211 @Test 212 public void testUpdateWithScanResultShouldAverageRssi() { 213 String ssid = "ssid"; 214 int originalRssi = -65; 215 int newRssi = -80; 216 int expectedRssi = (originalRssi + newRssi) / 2; 217 AccessPoint ap = 218 new TestAccessPointBuilder(mContext).setSsid(ssid).setRssi(originalRssi).build(); 219 220 ScanResult scanResult = new ScanResult(); 221 scanResult.SSID = ssid; 222 scanResult.level = newRssi; 223 scanResult.BSSID = "bssid"; 224 scanResult.timestamp = SystemClock.elapsedRealtime() * 1000; 225 scanResult.capabilities = ""; 226 assertThat(ap.update(scanResult)).isTrue(); 227 228 assertThat(ap.getRssi()).isEqualTo(expectedRssi); 229 } 230 231 @Test 232 public void testCreateFromPasspointConfig() { 233 PasspointConfiguration config = new PasspointConfiguration(); 234 HomeSp homeSp = new HomeSp(); 235 homeSp.setFqdn("test.com"); 236 homeSp.setFriendlyName("Test Provider"); 237 config.setHomeSp(homeSp); 238 AccessPoint ap = new AccessPoint(mContext, config); 239 assertThat(ap.isPasspointConfig()).isTrue(); 240 } 241 242 @Test 243 public void testIsMetered_returnTrueWhenWifiConfigurationIsMetered() { 244 WifiConfiguration configuration = createWifiConfiguration(); 245 configuration.meteredHint = true; 246 247 NetworkInfo networkInfo = 248 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE"); 249 AccessPoint accessPoint = new AccessPoint(mContext, configuration); 250 WifiInfo wifiInfo = new WifiInfo(); 251 wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID)); 252 wifiInfo.setBSSID(configuration.BSSID); 253 wifiInfo.setNetworkId(configuration.networkId); 254 accessPoint.update(configuration, wifiInfo, networkInfo); 255 256 assertThat(accessPoint.isMetered()).isTrue(); 257 } 258 259 @Test 260 public void testIsMetered_returnTrueWhenWifiInfoIsMetered() { 261 WifiConfiguration configuration = createWifiConfiguration(); 262 263 NetworkInfo networkInfo = 264 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE"); 265 AccessPoint accessPoint = new AccessPoint(mContext, configuration); 266 WifiInfo wifiInfo = new WifiInfo(); 267 wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID)); 268 wifiInfo.setBSSID(configuration.BSSID); 269 wifiInfo.setNetworkId(configuration.networkId); 270 wifiInfo.setMeteredHint(true); 271 accessPoint.update(configuration, wifiInfo, networkInfo); 272 273 assertThat(accessPoint.isMetered()).isTrue(); 274 } 275 276 @Test 277 public void testIsMetered_returnTrueWhenNetworkInfoIsMetered() { 278 WifiConfiguration configuration = createWifiConfiguration(); 279 280 NetworkInfo networkInfo = 281 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE"); 282 networkInfo.setMetered(true); 283 AccessPoint accessPoint = new AccessPoint(mContext, configuration); 284 WifiInfo wifiInfo = new WifiInfo(); 285 wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID)); 286 wifiInfo.setBSSID(configuration.BSSID); 287 wifiInfo.setNetworkId(configuration.networkId); 288 accessPoint.update(configuration, wifiInfo, networkInfo); 289 290 assertThat(accessPoint.isMetered()).isTrue(); 291 } 292 293 @Test 294 public void testIsMetered_returnTrueWhenScoredNetworkIsMetered() { 295 AccessPoint ap = createAccessPointWithScanResultCache(); 296 297 when(mWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class))) 298 .thenReturn( 299 new ScoredNetwork( 300 null /* NetworkKey */, 301 null /* rssiCurve */, 302 true /* metered */)); 303 ap.update(mWifiNetworkScoreCache, false /* scoringUiEnabled */); 304 305 assertThat(ap.isMetered()).isTrue(); 306 } 307 308 @Test 309 public void testIsMetered_returnFalseByDefault() { 310 WifiConfiguration configuration = createWifiConfiguration(); 311 312 NetworkInfo networkInfo = 313 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE"); 314 AccessPoint accessPoint = new AccessPoint(mContext, configuration); 315 WifiInfo wifiInfo = new WifiInfo(); 316 wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID)); 317 wifiInfo.setBSSID(configuration.BSSID); 318 wifiInfo.setNetworkId(configuration.networkId); 319 accessPoint.update(configuration, wifiInfo, networkInfo); 320 321 assertThat(accessPoint.isMetered()).isFalse(); 322 } 323 324 private AccessPoint createAccessPointWithScanResultCache() { 325 Bundle bundle = new Bundle(); 326 ArrayList<ScanResult> scanResults = new ArrayList<>(); 327 for (int i = 0; i < 5; i++) { 328 ScanResult scanResult = new ScanResult(); 329 scanResult.level = i; 330 scanResult.BSSID = "bssid-" + i; 331 scanResult.timestamp = SystemClock.elapsedRealtime() * 1000; 332 scanResult.capabilities = ""; 333 scanResults.add(scanResult); 334 } 335 336 bundle.putParcelableArrayList("key_scanresultcache", scanResults); 337 return new AccessPoint(mContext, bundle); 338 } 339 340 private WifiConfiguration createWifiConfiguration() { 341 WifiConfiguration configuration = new WifiConfiguration(); 342 configuration.BSSID = "bssid"; 343 configuration.SSID = "ssid"; 344 configuration.networkId = 123; 345 return configuration; 346 } 347 348 /** 349 * Assert that the first AccessPoint appears after the second AccessPoint 350 * once sorting has been completed. 351 */ 352 private void assertSortingWorks(AccessPoint first, AccessPoint second) { 353 354 ArrayList<AccessPoint> points = new ArrayList<AccessPoint>(); 355 356 // add in reverse order so we can tell that sorting actually changed something 357 points.add(second); 358 points.add(first); 359 Collections.sort(points); 360 assertWithMessage( 361 String.format("After sorting: second AccessPoint should have higher array index " 362 + "than the first, but found indicies second '%s' and first '%s'.", 363 points.indexOf(second), points.indexOf(first))) 364 .that(points.indexOf(second)).isGreaterThan(points.indexOf(first)); 365 } 366 367 @Test 368 public void testBuilder_setActive() { 369 AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build(); 370 assertThat(activeAp.isActive()).isTrue(); 371 372 AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build(); 373 assertThat(inactiveAp.isActive()).isFalse(); 374 } 375 376 @Test 377 public void testBuilder_setReachable() { 378 AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build(); 379 assertThat(nearAp.isReachable()).isTrue(); 380 381 AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build(); 382 assertThat(farAp.isReachable()).isFalse(); 383 } 384 385 @Test 386 public void testBuilder_setSaved() { 387 AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build(); 388 assertThat(savedAp.isSaved()).isTrue(); 389 390 AccessPoint newAp = new TestAccessPointBuilder(mContext).setSaved(false).build(); 391 assertThat(newAp.isSaved()).isFalse(); 392 } 393 394 @Test 395 public void testBuilder_setLevel() { 396 AccessPoint testAp; 397 398 for (int i = 0; i < AccessPoint.SIGNAL_LEVELS; i++) { 399 testAp = new TestAccessPointBuilder(mContext).setLevel(i).build(); 400 assertThat(testAp.getLevel()).isEqualTo(i); 401 } 402 403 // numbers larger than the max level should be set to max 404 testAp = new TestAccessPointBuilder(mContext).setLevel(AccessPoint.SIGNAL_LEVELS).build(); 405 assertThat(testAp.getLevel()).isEqualTo(AccessPoint.SIGNAL_LEVELS - 1); 406 407 // numbers less than 0 should give level 0 408 testAp = new TestAccessPointBuilder(mContext).setLevel(-100).build(); 409 assertThat(testAp.getLevel()).isEqualTo(0); 410 } 411 412 @Test 413 public void testBuilder_settingReachableAfterLevelDoesNotAffectLevel() { 414 int level = 1; 415 assertThat(level).isLessThan(AccessPoint.SIGNAL_LEVELS - 1); 416 417 AccessPoint testAp = 418 new TestAccessPointBuilder(mContext).setLevel(level).setReachable(true).build(); 419 assertThat(testAp.getLevel()).isEqualTo(level); 420 } 421 422 @Test 423 public void testBuilder_setSsid() { 424 String name = "AmazingSsid!"; 425 AccessPoint namedAp = new TestAccessPointBuilder(mContext).setSsid(name).build(); 426 assertThat(namedAp.getSsidStr()).isEqualTo(name); 427 } 428 429 @Test 430 public void testBuilder_passpointConfig() { 431 String fqdn = "Test.com"; 432 String providerFriendlyName = "Test Provider"; 433 AccessPoint ap = new TestAccessPointBuilder(mContext).setFqdn(fqdn) 434 .setProviderFriendlyName(providerFriendlyName).build(); 435 assertThat(ap.isPasspointConfig()).isTrue(); 436 assertThat(ap.getPasspointFqdn()).isEqualTo(fqdn); 437 assertThat(ap.getConfigName()).isEqualTo(providerFriendlyName); 438 } 439 440 @Test 441 public void testUpdateNetworkInfo_returnsTrue() { 442 int networkId = 123; 443 int rssi = -55; 444 WifiConfiguration config = new WifiConfiguration(); 445 config.networkId = networkId; 446 WifiInfo wifiInfo = new WifiInfo(); 447 wifiInfo.setNetworkId(networkId); 448 wifiInfo.setRssi(rssi); 449 450 NetworkInfo networkInfo = 451 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", ""); 452 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", ""); 453 454 AccessPoint ap = new TestAccessPointBuilder(mContext) 455 .setNetworkInfo(networkInfo) 456 .setNetworkId(networkId) 457 .setRssi(rssi) 458 .setWifiInfo(wifiInfo) 459 .build(); 460 461 NetworkInfo newInfo = new NetworkInfo(networkInfo); 462 newInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", ""); 463 assertThat(ap.update(config, wifiInfo, newInfo)).isTrue(); 464 } 465 466 @Test 467 public void testUpdateNetworkInfoWithSameInfo_returnsFalse() { 468 int networkId = 123; 469 int rssi = -55; 470 WifiConfiguration config = new WifiConfiguration(); 471 config.networkId = networkId; 472 WifiInfo wifiInfo = new WifiInfo(); 473 wifiInfo.setNetworkId(networkId); 474 wifiInfo.setRssi(rssi); 475 476 NetworkInfo networkInfo = 477 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", ""); 478 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", ""); 479 480 AccessPoint ap = new TestAccessPointBuilder(mContext) 481 .setNetworkInfo(networkInfo) 482 .setNetworkId(networkId) 483 .setRssi(rssi) 484 .setWifiInfo(wifiInfo) 485 .build(); 486 487 NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values 488 assertThat(ap.update(config, wifiInfo, newInfo)).isFalse(); 489 } 490} 491