WifiDetailPreferenceControllerTest.java revision 28dee1f08640c66febadf0354555f032e8b0a3bd
1/* 2 * Copyright (C) 2017 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.settings.wifi.details; 17 18import static com.google.common.truth.Truth.assertThat; 19 20import static org.mockito.ArgumentMatchers.anyInt; 21import static org.mockito.ArgumentMatchers.anyString; 22import static org.mockito.ArgumentMatchers.eq; 23import static org.mockito.ArgumentMatchers.nullable; 24import static org.mockito.Matchers.any; 25import static org.mockito.Mockito.doNothing; 26import static org.mockito.Mockito.doReturn; 27import static org.mockito.Mockito.inOrder; 28import static org.mockito.Mockito.never; 29import static org.mockito.Mockito.reset; 30import static org.mockito.Mockito.spy; 31import static org.mockito.Mockito.times; 32import static org.mockito.Mockito.verify; 33import static org.mockito.Mockito.when; 34 35import android.app.Activity; 36import android.arch.lifecycle.LifecycleOwner; 37import android.content.ComponentName; 38import android.content.Context; 39import android.content.Intent; 40import android.graphics.drawable.ColorDrawable; 41import android.graphics.drawable.Drawable; 42import android.net.ConnectivityManager; 43import android.net.ConnectivityManager.NetworkCallback; 44import android.net.IpPrefix; 45import android.net.LinkAddress; 46import android.net.LinkProperties; 47import android.net.Network; 48import android.net.NetworkCapabilities; 49import android.net.NetworkInfo; 50import android.net.NetworkRequest; 51import android.net.RouteInfo; 52import android.net.wifi.WifiConfiguration; 53import android.net.wifi.WifiInfo; 54import android.net.wifi.WifiManager; 55import android.os.Handler; 56import android.provider.Settings; 57import android.support.v7.preference.Preference; 58import android.support.v7.preference.PreferenceCategory; 59import android.support.v7.preference.PreferenceScreen; 60import android.view.View; 61import android.view.View.OnClickListener; 62import android.widget.ImageView; 63 64import com.android.internal.logging.nano.MetricsProto; 65import com.android.settings.R; 66import com.android.settings.TestConfig; 67import com.android.settings.applications.LayoutPreference; 68import com.android.settings.testutils.SettingsRobolectricTestRunner; 69import com.android.settings.testutils.shadow.ShadowBidiFormatter; 70import com.android.settings.testutils.shadow.ShadowDevicePolicyManagerWrapper; 71import com.android.settings.testutils.shadow.ShadowEntityHeaderController; 72import com.android.settings.testutils.shadow.ShadowPackageManagerWrapper; 73import com.android.settings.widget.ActionButtonPreference; 74import com.android.settings.widget.ActionButtonPreferenceTest; 75import com.android.settings.widget.EntityHeaderController; 76import com.android.settings.wifi.WifiDetailPreference; 77import com.android.settings.wrapper.ConnectivityManagerWrapper; 78import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 79import com.android.settingslib.core.lifecycle.Lifecycle; 80import com.android.settingslib.wifi.AccessPoint; 81 82import org.junit.Before; 83import org.junit.Test; 84import org.junit.runner.RunWith; 85import org.mockito.Answers; 86import org.mockito.ArgumentCaptor; 87import org.mockito.Captor; 88import org.mockito.InOrder; 89import org.mockito.Mock; 90import org.mockito.MockitoAnnotations; 91import org.robolectric.RuntimeEnvironment; 92import org.robolectric.annotation.Config; 93 94import java.net.Inet4Address; 95import java.net.InetAddress; 96import java.net.UnknownHostException; 97import java.util.Arrays; 98import java.util.List; 99import java.util.stream.Collectors; 100 101@RunWith(SettingsRobolectricTestRunner.class) 102@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, 103 shadows = { 104 ShadowDevicePolicyManagerWrapper.class, 105 ShadowEntityHeaderController.class, 106 ShadowPackageManagerWrapper.class, 107 ShadowBidiFormatter.class 108 }) 109public class WifiDetailPreferenceControllerTest { 110 111 private static final int LEVEL = 1; 112 private static final int RSSI = -55; 113 private static final int LINK_SPEED = 123; 114 private static final String MAC_ADDRESS = WifiInfo.DEFAULT_MAC_ADDRESS; 115 private static final String SECURITY = "None"; 116 117 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 118 private PreferenceScreen mockScreen; 119 120 @Mock private AccessPoint mockAccessPoint; 121 @Mock private Activity mockActivity; 122 @Mock private ConnectivityManager mockConnectivityManager; 123 @Mock private ConnectivityManagerWrapper mockConnectivityManagerWrapper; 124 @Mock private Network mockNetwork; 125 @Mock private NetworkInfo mockNetworkInfo; 126 @Mock private WifiConfiguration mockWifiConfig; 127 @Mock private WifiInfo mockWifiInfo; 128 @Mock private WifiNetworkDetailsFragment mockFragment; 129 @Mock private WifiManager mockWifiManager; 130 @Mock private MetricsFeatureProvider mockMetricsFeatureProvider; 131 @Mock private WifiDetailPreferenceController.IconInjector mockIconInjector; 132 133 @Mock (answer = Answers.RETURNS_DEEP_STUBS) 134 private EntityHeaderController mockHeaderController; 135 @Mock (answer = Answers.RETURNS_DEEP_STUBS) 136 private LayoutPreference mockHeaderLayoutPreference; 137 @Mock private ImageView mockHeaderIcon; 138 139 @Mock private ActionButtonPreference mockButtonsPref; 140 @Mock private WifiDetailPreference mockSignalStrengthPref; 141 @Mock private WifiDetailPreference mockLinkSpeedPref; 142 @Mock private WifiDetailPreference mockFrequencyPref; 143 @Mock private WifiDetailPreference mockSecurityPref; 144 @Mock private WifiDetailPreference mockMacAddressPref; 145 @Mock private WifiDetailPreference mockIpAddressPref; 146 @Mock private WifiDetailPreference mockGatewayPref; 147 @Mock private WifiDetailPreference mockSubnetPref; 148 @Mock private WifiDetailPreference mockDnsPref; 149 @Mock private PreferenceCategory mockIpv6Category; 150 @Mock private WifiDetailPreference mockIpv6AddressesPref; 151 152 @Captor private ArgumentCaptor<NetworkCallback> mCallbackCaptor; 153 @Captor private ArgumentCaptor<View.OnClickListener> mForgetClickListener; 154 @Captor private ArgumentCaptor<Preference> mIpv6AddressCaptor; 155 156 private Context mContext; 157 private Lifecycle mLifecycle; 158 private LifecycleOwner mLifecycleOwner; 159 private LinkProperties mLinkProperties; 160 private WifiDetailPreferenceController mController; 161 162 // This class exists so that these values can be made static final. They can't be static final 163 // members of the test class, because any attempt to call IpPrefix or RouteInfo constructors 164 // during static initialization of the test class results in NoSuchMethorError being thrown 165 // when the test is run. 166 private static class Constants { 167 static final int IPV4_PREFIXLEN = 25; 168 static final LinkAddress IPV4_ADDR; 169 static final Inet4Address IPV4_GATEWAY; 170 static final RouteInfo IPV4_DEFAULT; 171 static final RouteInfo IPV4_SUBNET; 172 static final LinkAddress IPV6_LINKLOCAL; 173 static final LinkAddress IPV6_GLOBAL1; 174 static final LinkAddress IPV6_GLOBAL2; 175 static final InetAddress IPV4_DNS1; 176 static final InetAddress IPV4_DNS2; 177 static final InetAddress IPV6_DNS; 178 179 private static LinkAddress ipv6LinkAddress(String addr) throws UnknownHostException { 180 return new LinkAddress(InetAddress.getByName(addr), 64); 181 } 182 183 private static LinkAddress ipv4LinkAddress(String addr, int prefixlen) 184 throws UnknownHostException { 185 return new LinkAddress(InetAddress.getByName(addr), prefixlen); 186 } 187 188 static { 189 try { 190 // We create our test constants in these roundabout ways because the robolectric 191 // shadows don't contain NetworkUtils.parseNumericAddress and other utility methods, 192 // so the easy ways to do things fail with NoSuchMethodError. 193 IPV4_ADDR = ipv4LinkAddress("192.0.2.2", IPV4_PREFIXLEN); 194 IPV4_GATEWAY = (Inet4Address) InetAddress.getByName("192.0.2.127"); 195 196 final Inet4Address any4 = (Inet4Address) InetAddress.getByName("0.0.0.0"); 197 IpPrefix subnet = new IpPrefix(IPV4_ADDR.getAddress(), IPV4_PREFIXLEN); 198 IPV4_SUBNET = new RouteInfo(subnet, any4); 199 IPV4_DEFAULT = new RouteInfo(new IpPrefix(any4, 0), IPV4_GATEWAY); 200 201 IPV6_LINKLOCAL = ipv6LinkAddress("fe80::211:25ff:fef8:7cb2%1"); 202 IPV6_GLOBAL1 = ipv6LinkAddress("2001:db8:1::211:25ff:fef8:7cb2"); 203 IPV6_GLOBAL2 = ipv6LinkAddress("2001:db8:1::3dfe:8902:f98f:739d"); 204 205 IPV4_DNS1 = InetAddress.getByName("8.8.8.8"); 206 IPV4_DNS2 = InetAddress.getByName("8.8.4.4"); 207 IPV6_DNS = InetAddress.getByName("2001:4860:4860::64"); 208 } catch (UnknownHostException e) { 209 throw new RuntimeException("Invalid hardcoded IP addresss: " + e); 210 } 211 } 212 } 213 214 @Before 215 public void setUp() { 216 MockitoAnnotations.initMocks(this); 217 218 mContext = spy(RuntimeEnvironment.application); 219 mLifecycleOwner = () -> mLifecycle; 220 mLifecycle = new Lifecycle(mLifecycleOwner); 221 222 when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfig); 223 when(mockAccessPoint.getLevel()).thenReturn(LEVEL); 224 when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY); 225 226 when(mockConnectivityManagerWrapper.getConnectivityManager()) 227 .thenReturn(mockConnectivityManager); 228 when(mockConnectivityManager.getNetworkInfo(any(Network.class))) 229 .thenReturn(mockNetworkInfo); 230 doNothing().when(mockConnectivityManagerWrapper).registerNetworkCallback( 231 nullable(NetworkRequest.class), mCallbackCaptor.capture(), nullable(Handler.class)); 232 mockButtonsPref = ActionButtonPreferenceTest.createMock(); 233 when(mockButtonsPref.setButton1OnClickListener(mForgetClickListener.capture())) 234 .thenReturn(mockButtonsPref); 235 236 when(mockWifiInfo.getLinkSpeed()).thenReturn(LINK_SPEED); 237 when(mockWifiInfo.getRssi()).thenReturn(RSSI); 238 when(mockWifiInfo.getMacAddress()).thenReturn(MAC_ADDRESS); 239 when(mockWifiManager.getConnectionInfo()).thenReturn(mockWifiInfo); 240 241 when(mockWifiManager.getCurrentNetwork()).thenReturn(mockNetwork); 242 mLinkProperties = new LinkProperties(); 243 when(mockConnectivityManager.getLinkProperties(mockNetwork)).thenReturn(mLinkProperties); 244 245 when(mockFragment.getActivity()).thenReturn(mockActivity); 246 247 ShadowEntityHeaderController.setUseMock(mockHeaderController); 248 // builder pattern 249 when(mockHeaderController.setRecyclerView(mockFragment.getListView(), mLifecycle)) 250 .thenReturn(mockHeaderController); 251 when(mockHeaderController.setSummary(anyString())).thenReturn(mockHeaderController); 252 when(mockIconInjector.getIcon(anyInt())).thenReturn(new ColorDrawable()); 253 254 setupMockedPreferenceScreen(); 255 mController = newWifiDetailPreferenceController(); 256 } 257 258 private WifiDetailPreferenceController newWifiDetailPreferenceController() { 259 return new WifiDetailPreferenceController( 260 mockAccessPoint, 261 mockConnectivityManagerWrapper, 262 mContext, 263 mockFragment, 264 null, // Handler 265 mLifecycle, 266 mockWifiManager, 267 mockMetricsFeatureProvider, 268 mockIconInjector); 269 } 270 271 private void setupMockedPreferenceScreen() { 272 when(mockScreen.getPreferenceManager().getContext()).thenReturn(mContext); 273 274 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_HEADER)) 275 .thenReturn(mockHeaderLayoutPreference); 276 when(mockHeaderLayoutPreference.findViewById(R.id.entity_header_icon)) 277 .thenReturn(mockHeaderIcon); 278 279 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_BUTTONS_PREF)) 280 .thenReturn(mockButtonsPref); 281 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SIGNAL_STRENGTH_PREF)) 282 .thenReturn(mockSignalStrengthPref); 283 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_LINK_SPEED)) 284 .thenReturn(mockLinkSpeedPref); 285 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_FREQUENCY_PREF)) 286 .thenReturn(mockFrequencyPref); 287 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SECURITY_PREF)) 288 .thenReturn(mockSecurityPref); 289 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_MAC_ADDRESS_PREF)) 290 .thenReturn(mockMacAddressPref); 291 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IP_ADDRESS_PREF)) 292 .thenReturn(mockIpAddressPref); 293 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_GATEWAY_PREF)) 294 .thenReturn(mockGatewayPref); 295 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SUBNET_MASK_PREF)) 296 .thenReturn(mockSubnetPref); 297 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_DNS_PREF)) 298 .thenReturn(mockDnsPref); 299 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IPV6_CATEGORY)) 300 .thenReturn(mockIpv6Category); 301 when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IPV6_ADDRESSES_PREF)) 302 .thenReturn(mockIpv6AddressesPref); 303 } 304 305 private void displayAndResume() { 306 mController.displayPreference(mockScreen); 307 mController.onResume(); 308 } 309 310 @Test 311 public void isAvailable_shouldAlwaysReturnTrue() { 312 mController.displayPreference(mockScreen); 313 314 assertThat(mController.isAvailable()).isTrue(); 315 } 316 317 @Test 318 public void securityPreference_stringShouldBeSet() { 319 displayAndResume(); 320 321 verify(mockSecurityPref).setDetailText(SECURITY); 322 } 323 324 @Test 325 public void latestWifiInfo_shouldBeFetchedInDisplayPreference() { 326 displayAndResume(); 327 328 verify(mockWifiManager, times(1)).getConnectionInfo(); 329 } 330 331 @Test 332 public void latestNetworkInfo_shouldBeFetchedInDisplayPreference() { 333 displayAndResume(); 334 335 verify(mockConnectivityManager, times(1)).getNetworkInfo(any(Network.class)); 336 } 337 338 @Test 339 public void networkCallback_shouldBeRegisteredOnResume() { 340 displayAndResume(); 341 342 verify(mockConnectivityManagerWrapper, times(1)).registerNetworkCallback( 343 nullable(NetworkRequest.class), mCallbackCaptor.capture(), nullable(Handler.class)); 344 } 345 346 @Test 347 public void networkCallback_shouldBeUnregisteredOnPause() { 348 displayAndResume(); 349 mController.onPause(); 350 351 verify(mockConnectivityManager, times(1)).unregisterNetworkCallback( 352 mCallbackCaptor.getValue()); 353 } 354 355 @Test 356 public void entityHeader_shouldHaveIconSet() { 357 Drawable expectedIcon = mockIconInjector.getIcon(LEVEL); 358 359 displayAndResume(); 360 361 verify(mockHeaderController).setIcon(expectedIcon); 362 } 363 364 @Test 365 public void entityHeader_shouldHaveLabelSetToSsid() { 366 String label = "ssid"; 367 when(mockAccessPoint.getSsidStr()).thenReturn(label); 368 369 displayAndResume(); 370 371 verify(mockHeaderController).setLabel(label); 372 } 373 374 @Test 375 public void entityHeader_shouldHaveSummarySet() { 376 String summary = "summary"; 377 when(mockAccessPoint.getSettingsSummary()).thenReturn(summary); 378 379 displayAndResume(); 380 381 verify(mockHeaderController).setSummary(summary); 382 } 383 384 @Test 385 public void signalStrengthPref_shouldHaveIconSet() { 386 displayAndResume(); 387 388 verify(mockSignalStrengthPref).setIcon(any(Drawable.class)); 389 } 390 391 @Test 392 public void signalStrengthPref_shouldHaveDetailTextSet() { 393 String expectedStrength = 394 mContext.getResources().getStringArray(R.array.wifi_signal)[LEVEL]; 395 396 displayAndResume(); 397 398 verify(mockSignalStrengthPref).setDetailText(expectedStrength); 399 } 400 401 @Test 402 public void linkSpeedPref_shouldHaveDetailTextSet() { 403 String expectedLinkSpeed = mContext.getString(R.string.link_speed, LINK_SPEED); 404 405 displayAndResume(); 406 407 verify(mockLinkSpeedPref).setDetailText(expectedLinkSpeed); 408 } 409 410 @Test 411 public void linkSpeedPref_shouldNotShowIfNotSet() { 412 when(mockWifiInfo.getLinkSpeed()).thenReturn(-1); 413 414 displayAndResume(); 415 416 verify(mockLinkSpeedPref).setVisible(false); 417 } 418 419 @Test 420 public void macAddressPref_shouldHaveDetailTextSet() { 421 displayAndResume(); 422 423 verify(mockMacAddressPref).setDetailText(MAC_ADDRESS); 424 } 425 426 @Test 427 public void ipAddressPref_shouldHaveDetailTextSet() { 428 mLinkProperties.addLinkAddress(Constants.IPV4_ADDR); 429 430 displayAndResume(); 431 432 verify(mockIpAddressPref).setDetailText(Constants.IPV4_ADDR.getAddress().getHostAddress()); 433 } 434 435 @Test 436 public void gatewayAndSubnet_shouldHaveDetailTextSet() { 437 mLinkProperties.addLinkAddress(Constants.IPV4_ADDR); 438 mLinkProperties.addRoute(Constants.IPV4_DEFAULT); 439 mLinkProperties.addRoute(Constants.IPV4_SUBNET); 440 441 displayAndResume(); 442 443 verify(mockSubnetPref).setDetailText("255.255.255.128"); 444 verify(mockGatewayPref).setDetailText("192.0.2.127"); 445 } 446 447 @Test 448 public void dnsServersPref_shouldHaveDetailTextSet() throws UnknownHostException { 449 mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[]{8,8,4,4})); 450 mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[]{8,8,8,8})); 451 mLinkProperties.addDnsServer(Constants.IPV6_DNS); 452 453 displayAndResume(); 454 455 verify(mockDnsPref).setDetailText( 456 "8.8.4.4\n" + 457 "8.8.8.8\n" + 458 Constants.IPV6_DNS.getHostAddress()); 459 } 460 461 @Test 462 public void noCurrentNetwork_shouldFinishActivity() { 463 // If WifiManager#getCurrentNetwork() returns null, then the network is neither connected 464 // nor connecting and WifiStateMachine has not reached L2ConnectedState. 465 when(mockWifiManager.getCurrentNetwork()).thenReturn(null); 466 467 displayAndResume(); 468 469 verify(mockActivity).finish(); 470 } 471 472 @Test 473 public void noLinkProperties_allIpDetailsHidden() { 474 when(mockConnectivityManager.getLinkProperties(mockNetwork)).thenReturn(null); 475 reset(mockIpv6Category, mockIpAddressPref, mockSubnetPref, mockGatewayPref, 476 mockDnsPref); 477 478 displayAndResume(); 479 480 verify(mockIpv6Category).setVisible(false); 481 verify(mockIpAddressPref).setVisible(false); 482 verify(mockSubnetPref).setVisible(false); 483 verify(mockGatewayPref).setVisible(false); 484 verify(mockDnsPref).setVisible(false); 485 verify(mockIpv6Category, never()).setVisible(true); 486 verify(mockIpAddressPref, never()).setVisible(true); 487 verify(mockSubnetPref, never()).setVisible(true); 488 verify(mockGatewayPref, never()).setVisible(true); 489 verify(mockDnsPref, never()).setVisible(true); 490 } 491 492 // Convenience method to convert a LinkAddress to a string without a prefix length. 493 private String asString(LinkAddress l) { 494 return l.getAddress().getHostAddress(); 495 } 496 497 // Pretend that the NetworkCallback was triggered with a new copy of lp. We need to create a 498 // new copy because the code only updates if !mLinkProperties.equals(lp). 499 private void updateLinkProperties(LinkProperties lp) { 500 mCallbackCaptor.getValue().onLinkPropertiesChanged(mockNetwork, new LinkProperties(lp)); 501 } 502 503 private void updateNetworkCapabilities(NetworkCapabilities nc) { 504 mCallbackCaptor.getValue().onCapabilitiesChanged(mockNetwork, new NetworkCapabilities(nc)); 505 } 506 507 private NetworkCapabilities makeNetworkCapabilities() { 508 NetworkCapabilities nc = new NetworkCapabilities(); 509 nc.clearAll(); 510 nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); 511 return nc; 512 } 513 514 private void verifyDisplayedIpv6Addresses(InOrder inOrder, LinkAddress... addresses) { 515 String text = Arrays.stream(addresses) 516 .map(address -> asString(address)) 517 .collect(Collectors.joining("\n")); 518 inOrder.verify(mockIpv6AddressesPref).setSummary(text); 519 } 520 521 @Test 522 public void onLinkPropertiesChanged_updatesFields() { 523 displayAndResume(); 524 525 InOrder inOrder = inOrder(mockIpAddressPref, mockGatewayPref, mockSubnetPref, 526 mockDnsPref, mockIpv6Category, mockIpv6AddressesPref); 527 528 LinkProperties lp = new LinkProperties(); 529 530 lp.addLinkAddress(Constants.IPV6_LINKLOCAL); 531 updateLinkProperties(lp); 532 verifyDisplayedIpv6Addresses(inOrder, Constants.IPV6_LINKLOCAL); 533 inOrder.verify(mockIpv6Category).setVisible(true); 534 535 lp.addRoute(Constants.IPV4_DEFAULT); 536 updateLinkProperties(lp); 537 inOrder.verify(mockGatewayPref).setDetailText(Constants.IPV4_GATEWAY.getHostAddress()); 538 inOrder.verify(mockGatewayPref).setVisible(true); 539 540 lp.addLinkAddress(Constants.IPV4_ADDR); 541 lp.addRoute(Constants.IPV4_SUBNET); 542 updateLinkProperties(lp); 543 inOrder.verify(mockIpAddressPref).setDetailText(asString(Constants.IPV4_ADDR)); 544 inOrder.verify(mockIpAddressPref).setVisible(true); 545 inOrder.verify(mockSubnetPref).setDetailText("255.255.255.128"); 546 inOrder.verify(mockSubnetPref).setVisible(true); 547 548 lp.addLinkAddress(Constants.IPV6_GLOBAL1); 549 lp.addLinkAddress(Constants.IPV6_GLOBAL2); 550 updateLinkProperties(lp); 551 verifyDisplayedIpv6Addresses(inOrder, 552 Constants.IPV6_LINKLOCAL, 553 Constants.IPV6_GLOBAL1, 554 Constants.IPV6_GLOBAL2); 555 556 lp.removeLinkAddress(Constants.IPV6_GLOBAL1); 557 updateLinkProperties(lp); 558 verifyDisplayedIpv6Addresses(inOrder, 559 Constants.IPV6_LINKLOCAL, 560 Constants.IPV6_GLOBAL2); 561 562 lp.addDnsServer(Constants.IPV6_DNS); 563 updateLinkProperties(lp); 564 inOrder.verify(mockDnsPref).setDetailText(Constants.IPV6_DNS.getHostAddress()); 565 inOrder.verify(mockDnsPref).setVisible(true); 566 567 lp.addDnsServer(Constants.IPV4_DNS1); 568 lp.addDnsServer(Constants.IPV4_DNS2); 569 updateLinkProperties(lp); 570 inOrder.verify(mockDnsPref).setDetailText( 571 Constants.IPV6_DNS.getHostAddress() + "\n" + 572 Constants.IPV4_DNS1.getHostAddress() + "\n" + 573 Constants.IPV4_DNS2.getHostAddress()); 574 inOrder.verify(mockDnsPref).setVisible(true); 575 } 576 577 @Test 578 public void onCapabilitiesChanged_callsRefreshIfNecessary() { 579 NetworkCapabilities nc = makeNetworkCapabilities(); 580 when(mockConnectivityManager.getNetworkCapabilities(mockNetwork)) 581 .thenReturn(new NetworkCapabilities(nc)); 582 583 String summary = "Connected, no Internet"; 584 when(mockAccessPoint.getSettingsSummary()).thenReturn(summary); 585 586 InOrder inOrder = inOrder(mockHeaderController); 587 displayAndResume(); 588 inOrder.verify(mockHeaderController).setSummary(summary); 589 590 // Check that an irrelevant capability update does not update the access point summary, as 591 // doing so could cause unnecessary jank... 592 summary = "Connected"; 593 when(mockAccessPoint.getSettingsSummary()).thenReturn(summary); 594 updateNetworkCapabilities(nc); 595 inOrder.verify(mockHeaderController, never()).setSummary(any(CharSequence.class)); 596 597 // ... but that if the network validates, then we do refresh. 598 nc.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); 599 updateNetworkCapabilities(nc); 600 inOrder.verify(mockHeaderController).setSummary(summary); 601 602 summary = "Connected, no Internet"; 603 when(mockAccessPoint.getSettingsSummary()).thenReturn(summary); 604 605 // Another irrelevant update won't cause the UI to refresh... 606 updateNetworkCapabilities(nc); 607 inOrder.verify(mockHeaderController, never()).setSummary(any(CharSequence.class)); 608 609 // ... but if the network is no longer validated, then we display "connected, no Internet". 610 nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); 611 updateNetworkCapabilities(nc); 612 inOrder.verify(mockHeaderController).setSummary(summary); 613 } 614 615 @Test 616 public void canForgetNetwork_noNetwork() { 617 when(mockAccessPoint.getConfig()).thenReturn(null); 618 619 mController = newWifiDetailPreferenceController(); 620 displayAndResume(); 621 622 verify(mockButtonsPref).setButton1Visible(false); 623 } 624 625 @Test 626 public void canForgetNetwork_ephemeral() { 627 when(mockWifiInfo.isEphemeral()).thenReturn(true); 628 when(mockAccessPoint.getConfig()).thenReturn(null); 629 630 displayAndResume(); 631 632 verify(mockButtonsPref).setButton1Visible(true); 633 } 634 635 @Test 636 public void canForgetNetwork_saved() { 637 displayAndResume(); 638 639 verify(mockButtonsPref).setButton1Visible(true); 640 } 641 642 @Test 643 public void canForgetNetwork_lockedDown() { 644 lockDownNetwork(); 645 646 displayAndResume(); 647 648 verify(mockButtonsPref).setButton1Visible(false); 649 } 650 651 @Test 652 public void canModifyNetwork_saved() { 653 assertThat(mController.canModifyNetwork()).isTrue(); 654 } 655 656 @Test 657 public void canModifyNetwork_lockedDown() { 658 lockDownNetwork(); 659 660 assertThat(mController.canModifyNetwork()).isFalse(); 661 } 662 663 /** 664 * Pretends that current network is locked down by device owner. 665 */ 666 private void lockDownNetwork() { 667 final int doUserId = 123; 668 final int doUid = 1234; 669 String doPackage = "some.package"; 670 671 mockWifiConfig.creatorUid = doUid; 672 ComponentName doComponent = new ComponentName(doPackage, "some.Class"); 673 ShadowPackageManagerWrapper.setPackageUidAsUser(doPackage, doUserId, doUid); 674 ShadowDevicePolicyManagerWrapper.setDeviceOComponentName(doComponent); 675 ShadowDevicePolicyManagerWrapper.setDeviceOwnerUserId(doUserId); 676 677 Settings.Global.putInt(mContext.getContentResolver(), 678 Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 1); 679 } 680 681 @Test 682 public void forgetNetwork_ephemeral() { 683 String ssid = "ssid"; 684 when(mockWifiInfo.isEphemeral()).thenReturn(true); 685 when(mockWifiInfo.getSSID()).thenReturn(ssid); 686 687 displayAndResume(); 688 mForgetClickListener.getValue().onClick(null); 689 690 verify(mockWifiManager).disableEphemeralNetwork(ssid); 691 verify(mockMetricsFeatureProvider) 692 .action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET); 693 } 694 695 @Test 696 public void forgetNetwork_saved() { 697 mockWifiConfig.networkId = 5; 698 699 mController.displayPreference(mockScreen); 700 mForgetClickListener.getValue().onClick(null); 701 702 verify(mockWifiManager).forget(mockWifiConfig.networkId, null); 703 verify(mockMetricsFeatureProvider) 704 .action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET); 705 } 706 707 @Test 708 public void networkStateChangedIntent_shouldRefetchInfo() { 709 displayAndResume(); 710 711 verify(mockConnectivityManager, times(1)).getNetworkInfo(any(Network.class)); 712 verify(mockWifiManager, times(1)).getConnectionInfo(); 713 714 mContext.sendBroadcast(new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)); 715 716 verify(mockConnectivityManager, times(2)).getNetworkInfo(any(Network.class)); 717 verify(mockWifiManager, times(2)).getConnectionInfo(); 718 } 719 720 @Test 721 public void rssiChangedIntent_shouldRefetchInfo() { 722 displayAndResume(); 723 724 verify(mockConnectivityManager, times(1)).getNetworkInfo(any(Network.class)); 725 verify(mockWifiManager, times(1)).getConnectionInfo(); 726 727 mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION)); 728 729 verify(mockConnectivityManager, times(2)).getNetworkInfo(any(Network.class)); 730 verify(mockWifiManager, times(2)).getConnectionInfo(); 731 } 732 733 @Test 734 public void networkDisconnectedState_shouldFinishActivity() { 735 displayAndResume(); 736 737 when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(null); 738 mContext.sendBroadcast(new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION)); 739 740 verify(mockActivity).finish(); 741 } 742 743 @Test 744 public void networkOnLost_shouldFinishActivity() { 745 displayAndResume(); 746 747 mCallbackCaptor.getValue().onLost(mockNetwork); 748 749 verify(mockActivity).finish(); 750 } 751 752 @Test 753 public void ipv6AddressPref_shouldHaveHostAddressTextSet() { 754 mLinkProperties.addLinkAddress(Constants.IPV6_LINKLOCAL); 755 mLinkProperties.addLinkAddress(Constants.IPV6_GLOBAL1); 756 mLinkProperties.addLinkAddress(Constants.IPV6_GLOBAL2); 757 758 displayAndResume(); 759 760 List <Preference> addrs = mIpv6AddressCaptor.getAllValues(); 761 762 String expectedAddresses = String.join("\n", 763 asString(Constants.IPV6_LINKLOCAL), 764 asString(Constants.IPV6_GLOBAL1), 765 asString(Constants.IPV6_GLOBAL2)); 766 767 verify(mockIpv6AddressesPref).setSummary(expectedAddresses); 768 } 769 770 @Test 771 public void ipv6AddressPref_shouldNotBeSelectable() { 772 mLinkProperties.addLinkAddress(Constants.IPV6_GLOBAL2); 773 774 displayAndResume(); 775 776 assertThat(mockIpv6AddressesPref.isSelectable()).isFalse(); 777 } 778 779 @Test 780 public void captivePortal_shouldShowSignInButton() { 781 InOrder inOrder = inOrder(mockButtonsPref); 782 783 displayAndResume(); 784 785 inOrder.verify(mockButtonsPref).setButton2Visible(false); 786 787 NetworkCapabilities nc = makeNetworkCapabilities(); 788 updateNetworkCapabilities(nc); 789 inOrder.verify(mockButtonsPref).setButton2Visible(false); 790 791 nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); 792 updateNetworkCapabilities(nc); 793 inOrder.verify(mockButtonsPref).setButton2Visible(true); 794 795 nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); 796 updateNetworkCapabilities(nc); 797 inOrder.verify(mockButtonsPref).setButton2Visible(false); 798 } 799 800 @Test 801 public void testSignInButton_shouldStartCaptivePortalApp() { 802 displayAndResume(); 803 804 ArgumentCaptor<OnClickListener> captor = ArgumentCaptor.forClass(OnClickListener.class); 805 verify(mockButtonsPref).setButton2OnClickListener(captor.capture()); 806 captor.getValue().onClick(null); 807 verify(mockConnectivityManagerWrapper).startCaptivePortalApp(mockNetwork); 808 verify(mockMetricsFeatureProvider) 809 .action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_SIGNIN); 810 } 811 812 @Test 813 public void testRefreshRssiViews_shouldNotUpdateIfLevelIsSame() { 814 displayAndResume(); 815 816 mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION)); 817 818 verify(mockAccessPoint, times(2)).getLevel(); 819 verify(mockIconInjector, times(1)).getIcon(anyInt()); 820 } 821 @Test 822 public void testRefreshRssiViews_shouldUpdateOnLevelChange() { 823 displayAndResume(); 824 825 when(mockAccessPoint.getLevel()).thenReturn(0); 826 mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION)); 827 828 verify(mockAccessPoint, times(2)).getLevel(); 829 verify(mockIconInjector, times(2)).getIcon(anyInt()); 830 } 831} 832