Add wifi metered controls in wifi settings.

1. Add it in wifi detail page
2. Add it in wifi dialog
2. Remove it in "Mobile network" page

Bug: 68030417
Test: RunSettingsRoboTests
Change-Id: I2e001c55f3c6c75a660e429732dfbece97b0ca9e
This commit is contained in:
jackqdyulei
2018-01-04 14:55:13 -08:00
parent 87f7a1be1e
commit 261c29c485
13 changed files with 250 additions and 202 deletions

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M11.8,10.9c-2.27,-0.59 -3,-1.2 -3,-2.15 0,-1.09 1.01,-1.85 2.7,-1.85 1.78,0 2.44,0.85 2.5,2.1h2.21c-0.07,-1.72 -1.12,-3.3 -3.21,-3.81V3h-3v2.16c-1.94,0.42 -3.5,1.68 -3.5,3.61 0,2.31 1.91,3.46 4.7,4.13 2.5,0.6 3,1.48 3,2.41 0,0.69 -0.49,1.79 -2.7,1.79 -2.06,0 -2.87,-0.92 -2.98,-2.1h-2.2c0.12,2.19 1.76,3.42 3.68,3.83V21h3v-2.15c1.95,-0.37 3.5,-1.5 3.5,-3.55 0,-2.84 -2.43,-3.81 -4.7,-4.4z"/>
</vector>

View File

@@ -316,6 +316,26 @@
android:orientation="vertical"
android:visibility="gone">
<LinearLayout android:id="@+id/metered_settings_fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/wifi_item">
<TextView android:id="@+id/metered_settings_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/wifi_item_label"
android:text="@string/data_usage_metered_yes" />
<Spinner android:id="@+id/metered_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/wifi_item_spinner"
android:prompt="@string/data_usage_metered_yes"
android:entries="@array/wifi_metered_entries"/>
</LinearLayout>
<LinearLayout android:id="@+id/proxy_settings_fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -1063,4 +1063,16 @@
<item>zen_mode_from_none</item>
</string-array>
<string-array name="wifi_metered_entries">
<item>Use network preference</item>
<item>Treat as metered</item>
<item>Treat as unmetered</item>
</string-array>
<string-array name="wifi_metered_values" translatable="false">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>

View File

@@ -27,11 +27,6 @@
android:key="wifi_data_usage"
android:title="@string/wifi_data_usage" />
<com.android.settings.datausage.NetworkRestrictionsPreference
android:key="network_restrictions"
android:title="@string/network_restrictions"
android:fragment="com.android.settings.datausage.DataUsageMeteredSettings" />
</com.android.settings.datausage.TemplatePreferenceCategory>
</PreferenceScreen>

View File

@@ -49,6 +49,13 @@
android:icon="@drawable/ic_security_lock_24dp"
android:title="@string/wifi_security"
android:selectable="false"/>
<DropDownPreference
android:key="metered"
android:icon="@drawable/ic_attach_money_black_24dp"
android:title="@string/data_usage_metered_yes"
android:entries="@array/wifi_metered_entries"
android:entryValues="@array/wifi_metered_values"/>
</PreferenceCategory>
<!-- Network Details -->

View File

@@ -1,150 +0,0 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.datausage;
import android.app.backup.BackupManager;
import android.content.Context;
import android.net.NetworkPolicyManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.NetworkPolicyEditor;
import java.util.Arrays;
import java.util.List;
/**
* Panel to configure {@link WifiConfiguration#meteredOverride}.
*/
public class DataUsageMeteredSettings extends SettingsPreferenceFragment implements Indexable {
private NetworkPolicyManager mPolicyManager;
private WifiManager mWifiManager;
private NetworkPolicyEditor mPolicyEditor;
private PreferenceCategory mMobileCategory;
private PreferenceCategory mWifiCategory;
private Preference mWifiDisabled;
@Override
public int getMetricsCategory() {
return MetricsEvent.NET_DATA_USAGE_METERED;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Context context = getActivity();
mPolicyManager = NetworkPolicyManager.from(context);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mPolicyEditor = new NetworkPolicyEditor(mPolicyManager);
mPolicyEditor.read();
addPreferencesFromResource(R.xml.data_usage_metered_prefs);
mMobileCategory = (PreferenceCategory) findPreference("mobile");
mWifiCategory = (PreferenceCategory) findPreference("wifi");
mWifiDisabled = findPreference("wifi_disabled");
updateNetworks(context);
}
private void updateNetworks(Context context) {
getPreferenceScreen().removePreference(mMobileCategory);
mWifiCategory.removeAll();
if (DataUsageUtils.hasWifiRadio(context) && mWifiManager.isWifiEnabled()) {
for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) {
final Preference pref = new MeteredPreference(getPrefContext(), config);
if (!TextUtils.isEmpty(pref.getTitle())) {
mWifiCategory.addPreference(pref);
}
}
} else {
mWifiCategory.addPreference(mWifiDisabled);
}
}
private class MeteredPreference extends DropDownPreference {
private final WifiConfiguration mConfig;
public MeteredPreference(Context context, WifiConfiguration config) {
super(context);
mConfig = config;
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]);
setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mConfig.meteredOverride = Integer.parseInt((String) newValue);
setSummary(getEntries()[mConfig.meteredOverride]);
mWifiManager.updateNetwork(mConfig);
// Stage the backup of the SettingsProvider package which backs this up
BackupManager.dataChanged("com.android.providers.settings");
return true;
}
});
}
}
/**
* For search
*/
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.data_usage_metered_prefs;
return Arrays.asList(sir);
}
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> result = super.getNonIndexableKeys(context);
result.add("mobile");
return result;
}
};
}

View File

@@ -77,8 +77,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
// Wifi keys
public static final String KEY_WIFI_USAGE_TITLE = "wifi_category";
public static final String KEY_WIFI_DATA_USAGE = "wifi_data_usage";
public static final String KEY_NETWORK_RESTRICTIONS = "network_restrictions";
private DataUsageController mDataUsageController;
private DataUsageInfoController mDataInfoController;
@@ -86,8 +84,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
private Preference mLimitPreference;
private NetworkTemplate mDefaultTemplate;
private int mDataUsageTemplate;
private NetworkRestrictionsPreference mNetworkRestrictionPreference;
private WifiManager mWifiManager;
private NetworkPolicyEditor mPolicyEditor;
@Override
@@ -101,7 +97,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
final Context context = getContext();
NetworkPolicyManager policyManager = NetworkPolicyManager.from(context);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mPolicyEditor = new NetworkPolicyEditor(policyManager);
boolean hasMobileData = DataUsageUtils.hasMobileData(context);
@@ -203,8 +198,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
TemplatePreferenceCategory category = (TemplatePreferenceCategory)
inflatePreferences(R.xml.data_usage_wifi);
category.setTemplate(NetworkTemplate.buildTemplateWifiWildcard(), 0, services);
mNetworkRestrictionPreference =
(NetworkRestrictionsPreference) category.findPreference(KEY_NETWORK_RESTRICTIONS);
}
private void addEthernetSection() {
@@ -293,8 +286,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
mLimitPreference.setSummary(null);
}
updateNetworkRestrictionSummary(mNetworkRestrictionPreference);
PreferenceScreen screen = getPreferenceScreen();
for (int i = 1; i < screen.getPreferenceCount(); i++) {
((TemplatePreferenceCategory) screen.getPreference(i)).pushTemplates(services);
@@ -321,22 +312,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
updateState();
}
@VisibleForTesting
void updateNetworkRestrictionSummary(NetworkRestrictionsPreference preference) {
if (preference == null) {
return;
}
mPolicyEditor.read();
int count = 0;
for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) {
if (WifiConfiguration.isMetered(config, null)) {
count++;
}
}
preference.setSummary(getResources().getQuantityString(
R.plurals.network_restrictions_summary, count, count));
}
private static class SummaryProvider
implements SummaryLoader.SummaryProvider {
@@ -409,7 +384,6 @@ public class DataUsageSummary extends DataUsageBase implements Indexable, DataUs
if (!DataUsageUtils.hasWifiRadio(context)) {
keys.add(KEY_WIFI_DATA_USAGE);
keys.add(KEY_NETWORK_RESTRICTIONS);
}
// This title is named Wifi, and will confuse users.

View File

@@ -36,7 +36,6 @@ import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragmentOld;
import com.android.settings.datausage.DataUsageMeteredSettings;
import com.android.settings.datausage.DataUsageSummary;
import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
@@ -110,7 +109,6 @@ public final class SearchIndexableResources {
addIndex(BluetoothSettings.class);
addIndex(SimSettings.class);
addIndex(DataUsageSummary.class);
addIndex(DataUsageMeteredSettings.class);
addIndex(ScreenZoomSettings.class);
addIndex(DisplaySettings.class);
addIndex(AmbientDisplaySettings.class);

View File

@@ -146,11 +146,11 @@ public class WifiConfigController implements TextWatcher,
private TextView mDns2View;
private Spinner mProxySettingsSpinner;
private Spinner mMeteredSettingsSpinner;
private TextView mProxyHostView;
private TextView mProxyPortView;
private TextView mProxyExclusionListView;
private TextView mProxyPacView;
private CheckBox mSharedCheckBox;
private IpAssignment mIpAssignment = IpAssignment.UNASSIGNED;
@@ -208,6 +208,7 @@ public class WifiConfigController implements TextWatcher,
mProxySettingsSpinner = (Spinner) mView.findViewById(R.id.proxy_settings);
mProxySettingsSpinner.setOnItemSelectedListener(this);
mSharedCheckBox = (CheckBox) mView.findViewById(R.id.shared);
mMeteredSettingsSpinner = mView.findViewById(R.id.metered_settings);
if (mAccessPoint == null) { // new network
mConfigUi.setTitle(R.string.wifi_add_network);
@@ -237,6 +238,7 @@ public class WifiConfigController implements TextWatcher,
boolean showAdvancedFields = false;
if (mAccessPoint.isSaved()) {
WifiConfiguration config = mAccessPoint.getConfig();
mMeteredSettingsSpinner.setSelection(config.meteredOverride);
if (config.getIpAssignment() == IpAssignment.STATIC) {
mIpSettingsSpinner.setSelection(STATIC_IP);
showAdvancedFields = true;
@@ -671,6 +673,9 @@ public class WifiConfigController implements TextWatcher,
config.setIpConfiguration(
new IpConfiguration(mIpAssignment, mProxySettings,
mStaticIpConfiguration, mHttpProxy));
if (mMeteredSettingsSpinner != null) {
config.meteredOverride = mMeteredSettingsSpinner.getSelectedItemPosition();
}
return config;
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi.details;
import android.app.backup.BackupManager;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
/**
* {@link AbstractPreferenceController} that controls whether the wifi network is metered or not
*/
public class WifiMeteredPreferenceController extends BasePreferenceController implements
Preference.OnPreferenceChangeListener {
private static final String KEY_WIFI_METERED = "metered";
private WifiConfiguration mWifiConfiguration;
private WifiManager mWifiManager;
public WifiMeteredPreferenceController(Context context, WifiConfiguration wifiConfiguration) {
super(context, KEY_WIFI_METERED);
mWifiConfiguration = wifiConfiguration;
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
@Override
public void updateState(Preference preference) {
final DropDownPreference dropDownPreference = (DropDownPreference) preference;
final int meteredOverride = getMeteredOverride();
dropDownPreference.setValue(Integer.toString(meteredOverride));
updateSummary(dropDownPreference, meteredOverride);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mWifiConfiguration.meteredOverride = Integer.parseInt((String) newValue);
mWifiManager.updateNetwork(mWifiConfiguration);
// Stage the backup of the SettingsProvider package which backs this up
BackupManager.dataChanged("com.android.providers.settings");
updateSummary((DropDownPreference) preference, getMeteredOverride());
return true;
}
@VisibleForTesting
int getMeteredOverride() {
// Wrap the meteredOverride since robolectric cannot recognize it
return mWifiConfiguration.meteredOverride;
}
private void updateSummary(DropDownPreference preference, int meteredOverride) {
preference.setSummary(preference.getEntries()[meteredOverride]);
}
}

View File

@@ -20,10 +20,13 @@ import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID;
import android.app.Dialog;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkPolicyManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.preference.DropDownPreference;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -122,6 +125,7 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
mWifiDetailPreferenceController = WifiDetailPreferenceController.newInstance(
mAccessPoint,
@@ -133,6 +137,9 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
context.getSystemService(WifiManager.class),
mMetricsFeatureProvider);
return new ArrayList<>(Collections.singletonList(mWifiDetailPreferenceController));
controllers.add(mWifiDetailPreferenceController);
controllers.add(new WifiMeteredPreferenceController(context, mAccessPoint.getConfig()));
return controllers;
}
}

View File

@@ -68,23 +68,6 @@ public class DataUsageSummaryTest {
when(mManager.isNetworkSupported(anyInt())).thenReturn(true);
}
@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<WifiConfiguration>());
doReturn(mContext.getResources()).when(dataUsageSummary).getResources();
dataUsageSummary.updateNetworkRestrictionSummary(preference);
verify(preference).setSummary(mContext.getResources().getQuantityString(
R.plurals.network_restrictions_summary, 0, 0));
}
@Test
@Config(shadows = {
SettingsShadowResources.class,

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi.details;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.support.v7.preference.DropDownPreference;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class WifiMeteredPreferenceControllerTest {
public static final int METERED_OVERRIDE_NONE = 0;
public static final int METERED_OVERRIDE_METERED = 1;
public static final int METERED_OVERRIDE_NOT_METERED = 2;
@Mock
private WifiConfiguration mWifiConfiguration;
private WifiMeteredPreferenceController mPreferenceController;
private Context mContext;
private DropDownPreference mDropDownPreference;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mPreferenceController = spy(
new WifiMeteredPreferenceController(mContext, mWifiConfiguration));
mDropDownPreference = new DropDownPreference(mContext);
mDropDownPreference.setEntries(R.array.wifi_metered_entries);
mDropDownPreference.setEntryValues(R.array.wifi_metered_values);
}
@Test
public void testUpdateState_wifiMetered_setCorrectValue() {
doReturn(METERED_OVERRIDE_METERED).when(mPreferenceController).getMeteredOverride();
mPreferenceController.updateState(mDropDownPreference);
assertThat(mDropDownPreference.getEntry()).isEqualTo("Treat as metered");
}
@Test
public void testUpdateState_wifiNotMetered_setCorrectValue() {
doReturn(METERED_OVERRIDE_NOT_METERED).when(mPreferenceController).getMeteredOverride();
mPreferenceController.updateState(mDropDownPreference);
assertThat(mDropDownPreference.getEntry()).isEqualTo("Treat as unmetered");
}
@Test
public void testUpdateState_wifiAuto_setCorrectValue() {
doReturn(METERED_OVERRIDE_NONE).when(mPreferenceController).getMeteredOverride();
mPreferenceController.updateState(mDropDownPreference);
assertThat(mDropDownPreference.getEntry()).isEqualTo("Use network preference");
}
}