diff --git a/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml index 5d5958d534e..257533f0cc9 100644 --- a/res/xml/wifi_network_details_fragment.xml +++ b/res/xml/wifi_network_details_fragment.xml @@ -82,8 +82,12 @@ + android:selectable="false"> + + diff --git a/src/com/android/settings/wifi/WifiDetailPreference.java b/src/com/android/settings/wifi/WifiDetailPreference.java index 6d34ad1c68f..b62df56671f 100644 --- a/src/com/android/settings/wifi/WifiDetailPreference.java +++ b/src/com/android/settings/wifi/WifiDetailPreference.java @@ -19,6 +19,7 @@ package com.android.settings.wifi; import android.content.Context; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceViewHolder; +import android.text.TextUtils; import android.util.AttributeSet; import android.widget.TextView; @@ -37,6 +38,7 @@ public class WifiDetailPreference extends Preference { } public void setDetailText(String text) { + if (TextUtils.equals(mDetailText, text)) return; mDetailText = text; notifyChanged(); } diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java index a5d922da82f..b22d7027dd6 100644 --- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java +++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java @@ -27,6 +27,7 @@ import android.graphics.drawable.Drawable; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.IpPrefix; +import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkBadging; @@ -67,6 +68,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.List; import java.util.StringJoiner; +import java.util.stream.Collectors; /** * Controller for logic pertaining to displaying Wifi information for the @@ -100,7 +102,9 @@ public class WifiDetailPreferenceController extends PreferenceController impleme @VisibleForTesting static final String KEY_DNS_PREF = "dns"; @VisibleForTesting - static final String KEY_IPV6_ADDRESS_CATEGORY = "ipv6_details_category"; + static final String KEY_IPV6_CATEGORY = "ipv6_category"; + @VisibleForTesting + static final String KEY_IPV6_ADDRESSES_PREF = "ipv6_addresses"; private AccessPoint mAccessPoint; private final ConnectivityManagerWrapper mConnectivityManagerWrapper; @@ -133,8 +137,9 @@ public class WifiDetailPreferenceController extends PreferenceController impleme private WifiDetailPreference mGatewayPref; private WifiDetailPreference mSubnetPref; private WifiDetailPreference mDnsPref; + private PreferenceCategory mIpv6Category; + private Preference mIpv6AddressPref; - private PreferenceCategory mIpv6AddressCategory; private final IntentFilter mFilter; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -241,8 +246,8 @@ public class WifiDetailPreferenceController extends PreferenceController impleme mSubnetPref = (WifiDetailPreference) screen.findPreference(KEY_SUBNET_MASK_PREF); mDnsPref = (WifiDetailPreference) screen.findPreference(KEY_DNS_PREF); - mIpv6AddressCategory = - (PreferenceCategory) screen.findPreference(KEY_IPV6_ADDRESS_CATEGORY); + mIpv6Category = (PreferenceCategory) screen.findPreference(KEY_IPV6_CATEGORY); + mIpv6AddressPref = (Preference) screen.findPreference(KEY_IPV6_ADDRESSES_PREF); mSecurityPref.setDetailText(mAccessPoint.getSecurityString(false /* concise */)); mForgetButton = (Button) mButtonsPref.findViewById(R.id.left_button); @@ -315,8 +320,6 @@ public class WifiDetailPreferenceController extends PreferenceController impleme mFrequencyPref.setDetailText(band); updateIpLayerInfo(); - mButtonsPref.setVisible(mForgetButton.getVisibility() == View.VISIBLE - || mSignInButton.getVisibility() == View.VISIBLE); } private void exitActivity() { @@ -348,74 +351,69 @@ public class WifiDetailPreferenceController extends PreferenceController impleme mSignalStrengthPref.setDetailText(mSignalStr[summarySignalLevel]); } + private void updatePreference(WifiDetailPreference pref, String detailText) { + if (!TextUtils.isEmpty(detailText)) { + pref.setDetailText(detailText); + pref.setVisible(true); + } else { + pref.setVisible(false); + } + } + private void updateIpLayerInfo() { mSignInButton.setVisibility(canSignIntoNetwork() ? View.VISIBLE : View.INVISIBLE); - - // Reset all fields - mIpv6AddressCategory.removeAll(); - mIpv6AddressCategory.setVisible(false); - mIpAddressPref.setVisible(false); - mSubnetPref.setVisible(false); - mGatewayPref.setVisible(false); - mDnsPref.setVisible(false); + mButtonsPref.setVisible(mForgetButton.getVisibility() == View.VISIBLE + || mSignInButton.getVisibility() == View.VISIBLE); if (mNetwork == null || mLinkProperties == null) { + mIpAddressPref.setVisible(false); + mSubnetPref.setVisible(false); + mGatewayPref.setVisible(false); + mDnsPref.setVisible(false); + mIpv6Category.setVisible(false); return; } - List addresses = mLinkProperties.getAddresses(); - // Set IPv4 and IPv6 addresses - for (int i = 0; i < addresses.size(); i++) { - InetAddress addr = addresses.get(i); - if (addr instanceof Inet4Address) { - mIpAddressPref.setDetailText(addr.getHostAddress()); - mIpAddressPref.setVisible(true); - } else if (addr instanceof Inet6Address) { - String ip = addr.getHostAddress(); - Preference pref = new Preference(mPrefContext); - pref.setKey(ip); - pref.setTitle(ip); - pref.setSelectable(false); - mIpv6AddressCategory.addPreference(pref); - mIpv6AddressCategory.setVisible(true); - } - } - - // Set up IPv4 gateway and subnet mask - String gateway = null; + // Find IPv4 and IPv6 addresses. + String ipv4Address = null; String subnet = null; + StringJoiner ipv6Addresses = new StringJoiner("\n"); + + for (LinkAddress addr : mLinkProperties.getLinkAddresses()) { + if (addr.getAddress() instanceof Inet4Address) { + ipv4Address = addr.getAddress().getHostAddress(); + subnet = ipv4PrefixLengthToSubnetMask(addr.getPrefixLength()); + } else if (addr.getAddress() instanceof Inet6Address) { + ipv6Addresses.add(addr.getAddress().getHostAddress()); + } + } + + // Find IPv4 default gateway. + String gateway = null; for (RouteInfo routeInfo : mLinkProperties.getRoutes()) { - if (routeInfo.hasGateway() && routeInfo.getGateway() instanceof Inet4Address) { + if (routeInfo.isIPv4Default() && routeInfo.hasGateway()) { gateway = routeInfo.getGateway().getHostAddress(); - } - IpPrefix ipPrefix = routeInfo.getDestination(); - if (ipPrefix != null && ipPrefix.getAddress() instanceof Inet4Address - && ipPrefix.getPrefixLength() > 0) { - subnet = ipv4PrefixLengthToSubnetMask(ipPrefix.getPrefixLength()); + break; } } - if (!TextUtils.isEmpty(subnet)) { - mSubnetPref.setDetailText(subnet); - mSubnetPref.setVisible(true); - } + // Find IPv4 DNS addresses. + String dnsServers = mLinkProperties.getDnsServers().stream() + .filter(Inet4Address.class::isInstance) + .map(InetAddress::getHostAddress) + .collect(Collectors.joining(",")); - if (!TextUtils.isEmpty(gateway)) { - mGatewayPref.setDetailText(gateway); - mGatewayPref.setVisible(true); - } + // Update UI. + updatePreference(mIpAddressPref, ipv4Address); + updatePreference(mSubnetPref, subnet); + updatePreference(mGatewayPref, gateway); + updatePreference(mDnsPref, dnsServers); - // Set IPv4 DNS addresses - StringJoiner stringJoiner = new StringJoiner(","); - for (InetAddress dnsServer : mLinkProperties.getDnsServers()) { - if (dnsServer instanceof Inet4Address) { - stringJoiner.add(dnsServer.getHostAddress()); - } - } - String dnsText = stringJoiner.toString(); - if (!dnsText.isEmpty()) { - mDnsPref.setDetailText(dnsText); - mDnsPref.setVisible(true); + if (ipv6Addresses.length() > 0) { + mIpv6AddressPref.setSummary(ipv6Addresses.toString()); + mIpv6Category.setVisible(true); + } else { + mIpv6Category.setVisible(false); } } diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java index 14556185089..17801b1bc85 100644 --- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java @@ -79,7 +79,9 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @@ -119,7 +121,8 @@ public class WifiDetailPreferenceControllerTest { @Mock private WifiDetailPreference mockSubnetPref; @Mock private WifiDetailPreference mockDnsPref; @Mock private Button mockForgetButton; - @Mock private PreferenceCategory mockIpv6AddressCategory; + @Mock private PreferenceCategory mockIpv6Category; + @Mock private WifiDetailPreference mockIpv6AddressesPref; @Captor private ArgumentCaptor mCallbackCaptor; @Captor private ArgumentCaptor mForgetClickListener; @@ -211,8 +214,6 @@ public class WifiDetailPreferenceControllerTest { when(mockFragment.getActivity()).thenReturn(mockActivity); - when(mockIpv6AddressCategory.addPreference(mIpv6AddressCaptor.capture())).thenReturn(true); - setupMockedPreferenceScreen(); mController = newWifiDetailPreferenceController(); } @@ -258,8 +259,10 @@ public class WifiDetailPreferenceControllerTest { .thenReturn(mockSubnetPref); when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_DNS_PREF)) .thenReturn(mockDnsPref); - when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IPV6_ADDRESS_CATEGORY)) - .thenReturn(mockIpv6AddressCategory); + when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IPV6_CATEGORY)) + .thenReturn(mockIpv6Category); + when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IPV6_ADDRESSES_PREF)) + .thenReturn(mockIpv6AddressesPref); } @Test @@ -414,17 +417,17 @@ public class WifiDetailPreferenceControllerTest { @Test public void noLinkProperties_allIpDetailsHidden() { when(mockConnectivityManager.getLinkProperties(mockNetwork)).thenReturn(null); - reset(mockIpv6AddressCategory, mockIpAddressPref, mockSubnetPref, mockGatewayPref, + reset(mockIpv6Category, mockIpAddressPref, mockSubnetPref, mockGatewayPref, mockDnsPref); mController.displayPreference(mockScreen); - verify(mockIpv6AddressCategory).setVisible(false); + verify(mockIpv6Category).setVisible(false); verify(mockIpAddressPref).setVisible(false); verify(mockSubnetPref).setVisible(false); verify(mockGatewayPref).setVisible(false); verify(mockDnsPref).setVisible(false); - verify(mockIpv6AddressCategory, never()).setVisible(true); + verify(mockIpv6Category, never()).setVisible(true); verify(mockIpAddressPref, never()).setVisible(true); verify(mockSubnetPref, never()).setVisible(true); verify(mockGatewayPref, never()).setVisible(true); @@ -442,23 +445,11 @@ public class WifiDetailPreferenceControllerTest { mCallbackCaptor.getValue().onLinkPropertiesChanged(mockNetwork, new LinkProperties(lp)); } - // Check that all IP information is deleted before being redrawn. - // TODO: switch the code to redrawing in place and remove this method. - private void verifyIpLayerInfoCleared(InOrder inOrder) { - inOrder.verify(mockIpv6AddressCategory).removeAll(); - inOrder.verify(mockIpv6AddressCategory).setVisible(false); - inOrder.verify(mockIpAddressPref).setVisible(false); - inOrder.verify(mockSubnetPref).setVisible(false); - inOrder.verify(mockGatewayPref).setVisible(false); - inOrder.verify(mockDnsPref).setVisible(false); - } - private void verifyDisplayedIpv6Addresses(InOrder inOrder, LinkAddress... addresses) { - for (LinkAddress l: addresses) { - inOrder.verify(mockIpv6AddressCategory).addPreference(mIpv6AddressCaptor.capture()); - assertThat(mIpv6AddressCaptor.getValue().getTitle()).isEqualTo(asString(l)); - } - inOrder.verify(mockIpv6AddressCategory).setVisible(true); + String text = Arrays.stream(addresses) + .map(address -> asString(address)) + .collect(Collectors.joining("\n")); + inOrder.verify(mockIpv6AddressesPref).setSummary(text); } @Test @@ -467,25 +458,23 @@ public class WifiDetailPreferenceControllerTest { mController.onResume(); InOrder inOrder = inOrder(mockIpAddressPref, mockGatewayPref, mockSubnetPref, - mockDnsPref, mockIpv6AddressCategory); + mockDnsPref, mockIpv6Category, mockIpv6AddressesPref); LinkProperties lp = new LinkProperties(); lp.addLinkAddress(Constants.IPV6_LINKLOCAL); updateLinkProperties(lp); - verifyIpLayerInfoCleared(inOrder); verifyDisplayedIpv6Addresses(inOrder, Constants.IPV6_LINKLOCAL); + inOrder.verify(mockIpv6Category).setVisible(true); lp.addRoute(Constants.IPV4_DEFAULT); updateLinkProperties(lp); - verifyIpLayerInfoCleared(inOrder); inOrder.verify(mockGatewayPref).setDetailText(Constants.IPV4_GATEWAY.getHostAddress()); inOrder.verify(mockGatewayPref).setVisible(true); lp.addLinkAddress(Constants.IPV4_ADDR); lp.addRoute(Constants.IPV4_SUBNET); updateLinkProperties(lp); - verifyIpLayerInfoCleared(inOrder); inOrder.verify(mockIpAddressPref).setDetailText(asString(Constants.IPV4_ADDR)); inOrder.verify(mockIpAddressPref).setVisible(true); inOrder.verify(mockSubnetPref).setDetailText("255.255.255.128"); @@ -494,7 +483,6 @@ public class WifiDetailPreferenceControllerTest { lp.addLinkAddress(Constants.IPV6_GLOBAL1); lp.addLinkAddress(Constants.IPV6_GLOBAL2); updateLinkProperties(lp); - verifyIpLayerInfoCleared(inOrder); verifyDisplayedIpv6Addresses(inOrder, Constants.IPV6_LINKLOCAL, Constants.IPV6_GLOBAL1, @@ -502,7 +490,6 @@ public class WifiDetailPreferenceControllerTest { lp.removeLinkAddress(Constants.IPV6_GLOBAL1); updateLinkProperties(lp); - verifyIpLayerInfoCleared(inOrder); verifyDisplayedIpv6Addresses(inOrder, Constants.IPV6_LINKLOCAL, Constants.IPV6_GLOBAL2); @@ -630,11 +617,13 @@ public class WifiDetailPreferenceControllerTest { mController.displayPreference(mockScreen); List addrs = mIpv6AddressCaptor.getAllValues(); - assertThat(addrs.size()).isEqualTo(3); - assertThat((String) addrs.get(0).getTitle()).isEqualTo(asString(Constants.IPV6_LINKLOCAL)); - assertThat((String) addrs.get(1).getTitle()).isEqualTo(asString(Constants.IPV6_GLOBAL1)); - assertThat((String) addrs.get(2).getTitle()).isEqualTo(asString(Constants.IPV6_GLOBAL2)); + String expectedAddresses = String.join("\n", + asString(Constants.IPV6_LINKLOCAL), + asString(Constants.IPV6_GLOBAL1), + asString(Constants.IPV6_GLOBAL2)); + + verify(mockIpv6AddressesPref).setSummary(expectedAddresses); } @Test @@ -643,7 +632,7 @@ public class WifiDetailPreferenceControllerTest { mController.displayPreference(mockScreen); - assertThat(mockIpv6AddressCategory.isSelectable()).isFalse(); + assertThat(mockIpv6AddressesPref.isSelectable()).isFalse(); } @Test