Move "metered" persistence to WifiConfiguration.

For a long time we've had a nasty tangled dependency between Wi-Fi
and NPMS, since they both persisted different details for configured
networks.  As part of preparing for new carrier data plan APIs, move
the tracking of meteredness over to WifiConfiguration.

We've never really supported "unmetered" mobile networks inside the
framework, so remove the option to configure those flags.

Replace MeteredPreference.notifyChanged() with explicit listener
to avoid confusing an invalidation pass as expression of user intent
to change metered values.

Bug: 63391323
Test: builds, boots, Wi-Fi policy is upgraded
Exempt-From-Owner-Approval: No owner was found for changed files.
Change-Id: If8a6e12650d1d060a729ed1a80f07ebb65e0ffd7
This commit is contained in:
Jeff Sharkey
2017-07-12 10:56:57 -06:00
parent a7b04ed692
commit dc09269c81
4 changed files with 53 additions and 162 deletions

View File

@@ -5715,6 +5715,13 @@
<!-- Body text prompting user to enable Wi-Fi to configure metered networks. [CHAR LIMIT=64] --> <!-- Body text prompting user to enable Wi-Fi to configure metered networks. [CHAR LIMIT=64] -->
<string name="data_usage_metered_wifi_disabled">To select metered networks, turn Wi\u2011Fi on.</string> <string name="data_usage_metered_wifi_disabled">To select metered networks, turn Wi\u2011Fi on.</string>
<!-- Option for indicating that a network being metered (expensive) should be determined automatically. [CHAR LIMIT=32] -->
<string name="data_usage_metered_auto">Automatic</string>
<!-- Option for indicating that a network is metered (expensive). [CHAR LIMIT=32] -->
<string name="data_usage_metered_yes">Metered</string>
<!-- Option for indicating that a network is not metered (inexpensive). [CHAR LIMIT=32] -->
<string name="data_usage_metered_no">Not metered</string>
<!-- Disclaimer string for data usage measured by device. [CHAR LIMIT=80] --> <!-- Disclaimer string for data usage measured by device. [CHAR LIMIT=80] -->
<string name="data_usage_disclaimer">Carrier data accounting may differ from your device.</string> <string name="data_usage_disclaimer">Carrier data accounting may differ from your device.</string>

View File

@@ -14,19 +14,21 @@
package com.android.settings.datausage; package com.android.settings.datausage;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
import static com.android.settings.datausage.DataUsageSummary.hasWifiRadio;
import android.app.backup.BackupManager; import android.app.backup.BackupManager;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager; import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory; import android.support.v7.preference.PreferenceCategory;
import android.telephony.TelephonyManager; import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
@@ -39,18 +41,11 @@ import com.android.settingslib.NetworkPolicyEditor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
import static com.android.settings.datausage.DataUsageList.hasReadyMobileRadio;
import static com.android.settings.datausage.DataUsageSummary.hasWifiRadio;
/** /**
* Panel to configure {@link NetworkPolicy#metered} for networks. * Panel to configure {@link WifiConfiguration#meteredOverride}.
*/ */
public class DataUsageMeteredSettings extends SettingsPreferenceFragment implements Indexable { public class DataUsageMeteredSettings extends SettingsPreferenceFragment implements Indexable {
private static final boolean SHOW_MOBILE_CATEGORY = false;
private NetworkPolicyManager mPolicyManager; private NetworkPolicyManager mPolicyManager;
private WifiManager mWifiManager; private WifiManager mWifiManager;
@@ -85,18 +80,14 @@ public class DataUsageMeteredSettings extends SettingsPreferenceFragment impleme
} }
private void updateNetworks(Context context) { private void updateNetworks(Context context) {
if (SHOW_MOBILE_CATEGORY && hasReadyMobileRadio(context)) { getPreferenceScreen().removePreference(mMobileCategory);
mMobileCategory.removeAll();
mMobileCategory.addPreference(buildMobilePref(context));
} else {
getPreferenceScreen().removePreference(mMobileCategory);
}
mWifiCategory.removeAll(); mWifiCategory.removeAll();
if (hasWifiRadio(context) && mWifiManager.isWifiEnabled()) { if (hasWifiRadio(context) && mWifiManager.isWifiEnabled()) {
for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) { for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) {
if (config.SSID != null) { final Preference pref = new MeteredPreference(getPrefContext(), config);
mWifiCategory.addPreference(buildWifiPref(config)); if (!TextUtils.isEmpty(pref.getTitle())) {
mWifiCategory.addPreference(pref);
} }
} }
} else { } else {
@@ -104,57 +95,40 @@ public class DataUsageMeteredSettings extends SettingsPreferenceFragment impleme
} }
} }
private Preference buildMobilePref(Context context) { private class MeteredPreference extends DropDownPreference {
final TelephonyManager tele = TelephonyManager.from(context); private final WifiConfiguration mConfig;
final NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(
tele.getSubscriberId());
final MeteredPreference pref = new MeteredPreference(getPrefContext(), template);
pref.setTitle(tele.getNetworkOperatorName());
return pref;
}
private Preference buildWifiPref(WifiConfiguration config) { public MeteredPreference(Context context, WifiConfiguration config) {
final String networkId = config.isPasspoint() ?
config.providerFriendlyName : config.SSID;
final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(networkId);
final MeteredPreference pref = new MeteredPreference(getPrefContext(), template);
pref.setTitle(removeDoubleQuotes(networkId));
return pref;
}
private class MeteredPreference extends SwitchPreference {
private final NetworkTemplate mTemplate;
private boolean mBinding;
public MeteredPreference(Context context, NetworkTemplate template) {
super(context); super(context);
mTemplate = template; mConfig = config;
setPersistent(false); setPersistent(false);
setEntries(new CharSequence[] {
getString(R.string.data_usage_metered_auto),
getString(R.string.data_usage_metered_yes),
getString(R.string.data_usage_metered_no),
});
setEntryValues(new CharSequence[] {
Integer.toString(WifiConfiguration.METERED_OVERRIDE_NONE),
Integer.toString(WifiConfiguration.METERED_OVERRIDE_METERED),
Integer.toString(WifiConfiguration.METERED_OVERRIDE_NOT_METERED),
});
setValue(Integer.toString(mConfig.meteredOverride));
setTitle(NetworkPolicyManager.resolveNetworkId(mConfig));
setSummary(getEntries()[mConfig.meteredOverride]);
mBinding = true; setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
final NetworkPolicy policy = mPolicyEditor.getPolicyMaybeUnquoted(template); @Override
if (policy != null) { public boolean onPreferenceChange(Preference preference, Object newValue) {
if (policy.limitBytes != LIMIT_DISABLED) { mConfig.meteredOverride = Integer.parseInt((String) newValue);
setChecked(true); setSummary(getEntries()[mConfig.meteredOverride]);
setEnabled(false);
} else { mWifiManager.updateNetwork(mConfig);
setChecked(policy.metered); // Stage the backup of the SettingsProvider package which backs this up
BackupManager.dataChanged("com.android.providers.settings");
return true;
} }
} else { });
setChecked(false);
}
mBinding = false;
}
@Override
protected void notifyChanged() {
super.notifyChanged();
if (!mBinding) {
mPolicyEditor.setPolicyMetered(mTemplate, isChecked());
// Stage the backup of the SettingsProvider package which backs this up
BackupManager.dataChanged("com.android.providers.settings");
}
} }
} }
@@ -180,21 +154,6 @@ public class DataUsageMeteredSettings extends SettingsPreferenceFragment impleme
data.screenTitle = res.getString(R.string.data_usage_menu_metered); data.screenTitle = res.getString(R.string.data_usage_menu_metered);
result.add(data); result.add(data);
if (SHOW_MOBILE_CATEGORY && hasReadyMobileRadio(context)) {
// Mobile networks category
data = new SearchIndexableRaw(context);
data.title = res.getString(R.string.data_usage_metered_mobile);
data.screenTitle = res.getString(R.string.data_usage_menu_metered);
result.add(data);
final TelephonyManager tele = TelephonyManager.from(context);
data = new SearchIndexableRaw(context);
data.title = tele.getNetworkOperatorName();
data.screenTitle = res.getString(R.string.data_usage_menu_metered);
result.add(data);
}
// Wi-Fi networks category // Wi-Fi networks category
data = new SearchIndexableRaw(context); data = new SearchIndexableRaw(context);
data.title = res.getString(R.string.data_usage_metered_wifi); data.title = res.getString(R.string.data_usage_metered_wifi);
@@ -227,12 +186,8 @@ public class DataUsageMeteredSettings extends SettingsPreferenceFragment impleme
@Override @Override
public List<String> getNonIndexableKeys(Context context) { public List<String> getNonIndexableKeys(Context context) {
final List<String> result = super.getNonIndexableKeys(context); final List<String> result = super.getNonIndexableKeys(context);
if (!SHOW_MOBILE_CATEGORY || !hasReadyMobileRadio(context)) { result.add("mobile");
result.add("mobile");
}
return result; return result;
} }
}; };
} }

View File

@@ -14,13 +14,15 @@
package com.android.settings.datausage; package com.android.settings.datausage;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_WIFI;
import android.app.Activity; import android.app.Activity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.INetworkStatsSession; import android.net.INetworkStatsSession;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager; import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate; import android.net.NetworkTemplate;
import android.net.TrafficStats; import android.net.TrafficStats;
@@ -46,6 +48,7 @@ import android.text.style.RelativeSizeSpan;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SummaryPreference; import com.android.settings.SummaryPreference;
@@ -55,13 +58,10 @@ import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable; import com.android.settings.search.Indexable;
import com.android.settingslib.NetworkPolicyEditor; import com.android.settingslib.NetworkPolicyEditor;
import com.android.settingslib.net.DataUsageController; import com.android.settingslib.net.DataUsageController;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; 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 { public class DataUsageSummary extends DataUsageBase implements Indexable, DataUsageEditController {
static final boolean LOGD = false; static final boolean LOGD = false;
@@ -403,7 +403,7 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
mPolicyEditor.read(); mPolicyEditor.read();
int count = 0; int count = 0;
for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) { for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) {
if (isMetered(config)) { if (WifiConfiguration.isMetered(config, null)) {
count++; count++;
} }
} }
@@ -411,23 +411,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
R.plurals.network_restrictions_summary, count, count)); 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 private static class SummaryProvider
implements SummaryLoader.SummaryProvider { implements SummaryLoader.SummaryProvider {

View File

@@ -94,60 +94,6 @@ public class DataUsageSummaryTest {
R.plurals.network_restrictions_summary, 0, 0)); 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();
}
@Test @Test
public void testNonIndexableKeys_existInXmlLayout() { public void testNonIndexableKeys_existInXmlLayout() {
final Context context = RuntimeEnvironment.application; final Context context = RuntimeEnvironment.application;