diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index 0a0eed20f3c..61cad39f2cb 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -132,6 +132,8 @@ public class TetherSettings extends RestrictedSettingsFragment super.onCreate(icicle); addPreferencesFromResource(R.xml.tether_prefs); + mFooterPreferenceMixin.createFooterPreference() + .setTitle(R.string.tethering_footer_info); mDataSaverBackend = new DataSaverBackend(getContext()); mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled(); diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java index 41dc78f2270..8eb1f61b82c 100644 --- a/src/com/android/settings/datausage/DataUsageSummary.java +++ b/src/com/android/settings/datausage/DataUsageSummary.java @@ -20,13 +20,18 @@ import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.INetworkStatsSession; +import android.net.NetworkPolicy; +import android.net.NetworkPolicyManager; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserManager; import android.provider.SearchIndexableResource; +import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.telephony.SubscriptionInfo; @@ -56,6 +61,7 @@ import java.util.List; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.NetworkPolicy.LIMIT_DISABLED; public class DataUsageSummary extends DataUsageBase implements Indexable, DataUsageEditController { @@ -68,6 +74,7 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs private static final String KEY_STATUS_HEADER = "status_header"; private static final String KEY_LIMIT_SUMMARY = "limit_summary"; private static final String KEY_RESTRICT_BACKGROUND = "restrict_background"; + private static final String KEY_NETWORK_RESTRICTIONS = "network_restrictions"; private DataUsageController mDataUsageController; private DataUsageInfoController mDataInfoController; @@ -75,6 +82,10 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs private Preference mLimitPreference; private NetworkTemplate mDefaultTemplate; private int mDataUsageTemplate; + private NetworkRestrictionsPreference mNetworkRestrcitionPreference; + private WifiManager mWifiManager; + private NetworkPolicyManager mPolicyManager; + private NetworkPolicyEditor mPolicyEditor; @Override protected int getHelpResource() { @@ -85,16 +96,21 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs public void onCreate(Bundle icicle) { super.onCreate(icicle); - boolean hasMobileData = hasMobileData(getContext()); - mDataUsageController = new DataUsageController(getContext()); + final Context context = getContext(); + mPolicyManager = NetworkPolicyManager.from(context); + mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + mPolicyEditor = new NetworkPolicyEditor(mPolicyManager); + + boolean hasMobileData = hasMobileData(context); + mDataUsageController = new DataUsageController(context); mDataInfoController = new DataUsageInfoController(); addPreferencesFromResource(R.xml.data_usage); - int defaultSubId = getDefaultSubscriptionId(getContext()); + int defaultSubId = getDefaultSubscriptionId(context); if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { hasMobileData = false; } - mDefaultTemplate = getDefaultTemplate(getContext(), defaultSubId); + mDefaultTemplate = getDefaultTemplate(context, defaultSubId); mSummaryPreference = (SummaryPreference) findPreference(KEY_STATUS_HEADER); if (!hasMobileData || !isAdmin()) { @@ -115,11 +131,11 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs removePreference(KEY_LIMIT_SUMMARY); mSummaryPreference.setSelectable(false); } - boolean hasWifiRadio = hasWifiRadio(getContext()); + boolean hasWifiRadio = hasWifiRadio(context); if (hasWifiRadio) { addWifiSection(); } - if (hasEthernet(getContext())) { + if (hasEthernet(context)) { addEthernetSection(); } mDataUsageTemplate = hasMobileData ? R.string.cell_data_template @@ -171,6 +187,8 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs TemplatePreferenceCategory category = (TemplatePreferenceCategory) inflatePreferences(R.xml.data_usage_wifi); category.setTemplate(NetworkTemplate.buildTemplateWifiWildcard(), 0, services); + mNetworkRestrcitionPreference = + (NetworkRestrictionsPreference) category.findPreference(KEY_NETWORK_RESTRICTIONS); } private void addEthernetSection() { @@ -259,6 +277,8 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs mLimitPreference.setSummary(null); } + updateNetworkRestrictionSummary(mNetworkRestrcitionPreference); + PreferenceScreen screen = getPreferenceScreen(); for (int i = 1; i < screen.getPreferenceCount(); i++) { ((TemplatePreferenceCategory) screen.getPreference(i)).pushTemplates(services); @@ -362,6 +382,39 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs } } + @VisibleForTesting + void updateNetworkRestrictionSummary(NetworkRestrictionsPreference preference) { + if (preference == null) { + return; + } + mPolicyEditor.read(); + int count = 0; + for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) { + if (isMetered(config)) { + count++; + } + } + preference.setSummary(getResources().getQuantityString( + R.plurals.network_restrictions_summary, count, count)); + } + + @VisibleForTesting + boolean isMetered(WifiConfiguration config) { + if (config.SSID == null) { + return false; + } + final String networkId = config.isPasspoint() ? config.providerFriendlyName : config.SSID; + final NetworkPolicy policy = + mPolicyEditor.getPolicyMaybeUnquoted(NetworkTemplate.buildTemplateWifi(networkId)); + if (policy == null) { + return false; + } + if (policy.limitBytes != LIMIT_DISABLED) { + return true; + } + return policy.metered; + } + private static class SummaryProvider implements SummaryLoader.SummaryProvider { diff --git a/src/com/android/settings/wifi/WifiApEnabler.java b/src/com/android/settings/wifi/WifiApEnabler.java index 760879e5d8e..8e577a4f6ad 100644 --- a/src/com/android/settings/wifi/WifiApEnabler.java +++ b/src/com/android/settings/wifi/WifiApEnabler.java @@ -28,7 +28,6 @@ import android.support.v14.preference.SwitchPreference; import com.android.settings.R; import com.android.settings.datausage.DataSaverBackend; -import com.android.settingslib.TetherUtil; import java.util.ArrayList; @@ -140,6 +139,8 @@ public class WifiApEnabler { updateConfigSummary(wifiConfig); } else if (wifiErrored) { mSwitch.setSummary(R.string.wifi_error); + } else { + mSwitch.setSummary(R.string.wifi_hotspot_off_subtext); } } diff --git a/src/com/android/settings/wifi/WifiSummaryUpdater.java b/src/com/android/settings/wifi/WifiSummaryUpdater.java index 533ee0750df..c0d44688266 100644 --- a/src/com/android/settings/wifi/WifiSummaryUpdater.java +++ b/src/com/android/settings/wifi/WifiSummaryUpdater.java @@ -26,6 +26,8 @@ import com.android.settings.R; import com.android.settings.widget.SummaryUpdater; import com.android.settingslib.wifi.WifiStatusTracker; +import static android.net.wifi.WifiInfo.removeDoubleQuotes; + /** * Helper class that listeners to wifi callback and notify client when there is update in * wifi summary info. @@ -78,7 +80,7 @@ public final class WifiSummaryUpdater extends SummaryUpdater { if (!mWifiTracker.connected) { return mContext.getString(R.string.disconnected); } - return mWifiTracker.ssid; + return removeDoubleQuotes(mWifiTracker.ssid); } } diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java index e8a2ee468e6..71d9ea11672 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java @@ -18,8 +18,15 @@ package com.android.settings.datausage; import android.content.Context; import android.net.ConnectivityManager; +import android.net.NetworkPolicy; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; + +import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settingslib.NetworkPolicyEditor; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -27,9 +34,17 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; +import org.robolectric.util.ReflectionHelpers; + +import java.util.ArrayList; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) @@ -57,4 +72,75 @@ public class DataUsageSummaryTest { boolean hasMobileData = DataUsageSummary.hasMobileData(mContext); assertThat(hasMobileData).isTrue(); } + + @Test + public void testUpdateNetworkRestrictionSummary_shouldSetSummary() { + final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary()); + final NetworkRestrictionsPreference preference = mock(NetworkRestrictionsPreference.class); + final NetworkPolicyEditor policyEditor = mock(NetworkPolicyEditor.class); + final WifiManager wifiManager = mock(WifiManager.class); + ReflectionHelpers.setField(dataUsageSummary, "mPolicyEditor", policyEditor); + ReflectionHelpers.setField(dataUsageSummary, "mWifiManager", wifiManager); + when(wifiManager.getConfiguredNetworks()).thenReturn(new ArrayList()); + doReturn(mContext.getResources()).when(dataUsageSummary).getResources(); + + dataUsageSummary.updateNetworkRestrictionSummary(preference); + + verify(preference).setSummary(mContext.getResources().getQuantityString( + R.plurals.network_restrictions_summary, 0, 0)); + } + + @Test + public void testIsMetered_noSsid_shouldReturnFalse() { + final DataUsageSummary dataUsageSummary = new DataUsageSummary(); + final NetworkPolicyEditor policyEditor = mock(NetworkPolicyEditor.class); + ReflectionHelpers.setField(dataUsageSummary, "mPolicyEditor", policyEditor); + WifiConfiguration config = mock(WifiConfiguration.class); + + assertThat(dataUsageSummary.isMetered(config)).isFalse(); + } + + @Test + public void testIsMetered_noNetworkPolicy_shouldReturnFalse() { + final DataUsageSummary dataUsageSummary = new DataUsageSummary(); + final NetworkPolicyEditor policyEditor = mock(NetworkPolicyEditor.class); + ReflectionHelpers.setField(dataUsageSummary, "mPolicyEditor", policyEditor); + WifiConfiguration config = mock(WifiConfiguration.class); + config.SSID = "network1"; + doReturn(null).when(policyEditor).getPolicyMaybeUnquoted(any()); + + assertThat(dataUsageSummary.isMetered(config)).isFalse(); + } + + @Test + public void testIsMetered_policyHasLimit_shouldReturnTrue() { + final DataUsageSummary dataUsageSummary = new DataUsageSummary(); + final NetworkPolicyEditor policyEditor = mock(NetworkPolicyEditor.class); + ReflectionHelpers.setField(dataUsageSummary, "mPolicyEditor", policyEditor); + WifiConfiguration config = mock(WifiConfiguration.class); + config.SSID = "network1"; + NetworkPolicy policy = mock(NetworkPolicy.class); + policy.limitBytes = 100; + doReturn(policy).when(policyEditor).getPolicyMaybeUnquoted(any()); + + assertThat(dataUsageSummary.isMetered(config)).isTrue(); + } + + @Test + public void testIsMetered_noPolicyLimit_shouldReturnMeteredValue() { + final DataUsageSummary dataUsageSummary = new DataUsageSummary(); + final NetworkPolicyEditor policyEditor = mock(NetworkPolicyEditor.class); + ReflectionHelpers.setField(dataUsageSummary, "mPolicyEditor", policyEditor); + WifiConfiguration config = mock(WifiConfiguration.class); + config.SSID = "network1"; + NetworkPolicy policy = mock(NetworkPolicy.class); + policy.limitBytes = NetworkPolicy.LIMIT_DISABLED; + doReturn(policy).when(policyEditor).getPolicyMaybeUnquoted(any()); + + policy.metered = true; + assertThat(dataUsageSummary.isMetered(config)).isTrue(); + + policy.metered = false; + assertThat(dataUsageSummary.isMetered(config)).isFalse(); + } }