From: Jeff Sharkey Date: Wed, 4 Apr 2012 04:13:25 +0000 (-0700) Subject: Controls to set expensive (metered) networks. X-Git-Tag: android-x86-4.4-r1~1647^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=313f7d8c5759fd29a98c710ceb9339d27b8e62fa;p=android-x86%2Fpackages-apps-Settings.git Controls to set expensive (metered) networks. Add UI to change metered flag on NetworkPolicy, and support Wi-Fi policies per-SSID. Create Wi-Fi policies as needed, but leave cycle undefined. Only show and mutate mobile policies when SIM state is ready. Bug: 3001465, 3291052 Change-Id: I481a202fe0e68fc2f5adfd3b3a6f40347d2b168c --- diff --git a/res/menu/data_usage.xml b/res/menu/data_usage.xml index 4e938aa2ed..7847f3be9e 100644 --- a/res/menu/data_usage.xml +++ b/res/menu/data_usage.xml @@ -35,4 +35,7 @@ android:id="@+id/data_usage_menu_show_ethernet" android:title="@string/data_usage_menu_show_ethernet" android:checkable="true" /> + diff --git a/res/values/strings.xml b/res/values/strings.xml index d080d59bcc..1bf5763337 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3603,6 +3603,8 @@ Show Wi-Fi usage Show Ethernet usage + + Expensive networks Change cycle\u2026 @@ -3704,6 +3706,15 @@ %2$s: about %1$s used + + Expensive networks + + Select the networks for which data usage is expensive. Apps can be restricted from using these networks when in the background. Apps may also warn before using these networks for large downloads. + + Mobile networks + + Wi-Fi networks + Emergency call diff --git a/res/xml/data_usage_metered_prefs.xml b/res/xml/data_usage_metered_prefs.xml new file mode 100644 index 0000000000..7ec30592eb --- /dev/null +++ b/res/xml/data_usage_metered_prefs.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java index d398e0b6b8..656288a835 100644 --- a/src/com/android/settings/DataUsageSummary.java +++ b/src/com/android/settings/DataUsageSummary.java @@ -35,11 +35,12 @@ import static android.net.NetworkTemplate.buildTemplateEthernet; import static android.net.NetworkTemplate.buildTemplateMobile3gLower; import static android.net.NetworkTemplate.buildTemplateMobile4g; import static android.net.NetworkTemplate.buildTemplateMobileAll; -import static android.net.NetworkTemplate.buildTemplateWifi; +import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.TrafficStats.GB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.net.TrafficStats.UID_REMOVED; import static android.net.TrafficStats.UID_TETHERING; +import static android.telephony.TelephonyManager.SIM_STATE_READY; import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH; import static android.text.format.DateUtils.FORMAT_SHOW_DATE; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; @@ -83,6 +84,7 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserId; import android.preference.Preference; +import android.preference.PreferenceActivity; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -127,6 +129,7 @@ import com.android.internal.telephony.Phone; import com.android.settings.drawable.InsetBoundsDrawable; import com.android.settings.net.ChartData; import com.android.settings.net.ChartDataLoader; +import com.android.settings.net.DataUsageMeteredSettings; import com.android.settings.net.NetworkPolicyEditor; import com.android.settings.net.SummaryForAllUidLoader; import com.android.settings.net.UidDetail; @@ -144,8 +147,8 @@ import java.util.Locale; import libcore.util.Objects; /** - * Panel show data usage history across various networks, including options to - * inspect based on usage cycle and control through {@link NetworkPolicy}. + * Panel showing data usage history across various networks, including options + * to inspect based on usage cycle and control through {@link NetworkPolicy}. */ public class DataUsageSummary extends Fragment { private static final String TAG = "DataUsage"; @@ -180,7 +183,7 @@ public class DataUsageSummary extends Fragment { private INetworkManagementService mNetworkService; private INetworkStatsService mStatsService; - private INetworkPolicyManager mPolicyService; + private NetworkPolicyManager mPolicyManager; private ConnectivityManager mConnService; private static final String PREF_FILE = "data_usage"; @@ -253,19 +256,18 @@ public class DataUsageSummary extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + final Context context = getActivity(); mNetworkService = INetworkManagementService.Stub.asInterface( ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); mStatsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); - mPolicyService = INetworkPolicyManager.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); - mConnService = (ConnectivityManager) getActivity().getSystemService( - Context.CONNECTIVITY_SERVICE); + mPolicyManager = NetworkPolicyManager.from(context); + mConnService = ConnectivityManager.from(context); mPrefs = getActivity().getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); - mPolicyEditor = new NetworkPolicyEditor(mPolicyService); + mPolicyEditor = new NetworkPolicyEditor(mPolicyManager); mPolicyEditor.read(); mShowWifi = mPrefs.getBoolean(PREF_SHOW_WIFI, false); @@ -431,19 +433,19 @@ public class DataUsageSummary extends Fragment { final boolean appDetailMode = isAppDetailMode(); mMenuDataRoaming = menu.findItem(R.id.data_usage_menu_roaming); - mMenuDataRoaming.setVisible(hasMobileRadio(context) && !appDetailMode); + mMenuDataRoaming.setVisible(hasReadyMobileRadio(context) && !appDetailMode); mMenuDataRoaming.setChecked(getDataRoaming()); mMenuRestrictBackground = menu.findItem(R.id.data_usage_menu_restrict_background); - mMenuRestrictBackground.setVisible(hasMobileRadio(context) && !appDetailMode); - mMenuRestrictBackground.setChecked(getRestrictBackground()); + mMenuRestrictBackground.setVisible(hasReadyMobileRadio(context) && !appDetailMode); + mMenuRestrictBackground.setChecked(mPolicyManager.getRestrictBackground()); final MenuItem split4g = menu.findItem(R.id.data_usage_menu_split_4g); split4g.setVisible(hasMobile4gRadio(context) && !appDetailMode); split4g.setChecked(isMobilePolicySplit()); final MenuItem showWifi = menu.findItem(R.id.data_usage_menu_show_wifi); - if (hasWifiRadio(context) && hasMobileRadio(context)) { + if (hasWifiRadio(context) && hasReadyMobileRadio(context)) { showWifi.setVisible(!appDetailMode); showWifi.setChecked(mShowWifi); } else { @@ -452,13 +454,20 @@ public class DataUsageSummary extends Fragment { } final MenuItem showEthernet = menu.findItem(R.id.data_usage_menu_show_ethernet); - if (hasEthernet(context) && hasMobileRadio(context)) { + if (hasEthernet(context) && hasReadyMobileRadio(context)) { showEthernet.setVisible(!appDetailMode); showEthernet.setChecked(mShowEthernet); } else { showEthernet.setVisible(false); mShowEthernet = true; } + + final MenuItem metered = menu.findItem(R.id.data_usage_menu_metered); + if (hasReadyMobileRadio(context) || hasWifiRadio(context)) { + metered.setVisible(!appDetailMode); + } else { + metered.setVisible(false); + } } @Override @@ -505,6 +514,12 @@ public class DataUsageSummary extends Fragment { updateTabs(); return true; } + case R.id.data_usage_menu_metered: { + final PreferenceActivity activity = (PreferenceActivity) getActivity(); + activity.startPreferencePanel(DataUsageMeteredSettings.class.getCanonicalName(), null, + R.string.data_usage_metered_title, null, this, 0); + return true; + } } return false; } @@ -572,7 +587,7 @@ public class DataUsageSummary extends Fragment { if (mobileSplit && hasMobile4gRadio(context)) { mTabHost.addTab(buildTabSpec(TAB_3G, R.string.data_usage_tab_3g)); mTabHost.addTab(buildTabSpec(TAB_4G, R.string.data_usage_tab_4g)); - } else if (hasMobileRadio(context)) { + } else if (hasReadyMobileRadio(context)) { mTabHost.addTab(buildTabSpec(TAB_MOBILE, R.string.data_usage_tab_mobile)); } if (mShowWifi && hasWifiRadio(context)) { @@ -650,6 +665,9 @@ public class DataUsageSummary extends Fragment { mDataEnabledView.setVisibility(View.VISIBLE); + // TODO: remove mobile tabs when SIM isn't ready + final TelephonyManager tele = TelephonyManager.from(context); + if (TAB_MOBILE.equals(currentTab)) { setPreferenceTitle(mDataEnabledView, R.string.data_usage_enable_mobile); setPreferenceTitle(mDisableAtLimitView, R.string.data_usage_disable_mobile_limit); @@ -671,7 +689,7 @@ public class DataUsageSummary extends Fragment { // wifi doesn't have any controls mDataEnabledView.setVisibility(View.GONE); mDisableAtLimitView.setVisibility(View.GONE); - mTemplate = buildTemplateWifi(); + mTemplate = buildTemplateWifiWildcard(); } else if (TAB_ETHERNET.equals(currentTab)) { // ethernet doesn't have any controls @@ -755,8 +773,8 @@ public class DataUsageSummary extends Fragment { updateDetailData(); - if (UserId.isApp(appId) && !getRestrictBackground() && isBandwidthControlEnabled() - && hasMobileRadio(context)) { + if (UserId.isApp(appId) && !mPolicyManager.getRestrictBackground() + && isBandwidthControlEnabled() && hasReadyMobileRadio(context)) { setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background); setPreferenceSummary(mAppRestrictView, getString(R.string.data_usage_app_restrict_background_summary)); @@ -829,48 +847,22 @@ public class DataUsageSummary extends Fragment { mMenuDataRoaming.setChecked(enabled); } - private boolean getRestrictBackground() { - try { - return mPolicyService.getRestrictBackground(); - } catch (RemoteException e) { - Log.w(TAG, "problem talking with policy service: " + e); - return false; - } - } - - private void setRestrictBackground(boolean restrictBackground) { - if (LOGD) Log.d(TAG, "setRestrictBackground()"); - try { - mPolicyService.setRestrictBackground(restrictBackground); - mMenuRestrictBackground.setChecked(restrictBackground); - } catch (RemoteException e) { - Log.w(TAG, "problem talking with policy service: " + e); - } + public void setRestrictBackground(boolean restrictBackground) { + mPolicyManager.setRestrictBackground(restrictBackground); + mMenuRestrictBackground.setChecked(restrictBackground); } private boolean getAppRestrictBackground() { final int appId = mCurrentApp.appId; - final int uidPolicy; - try { - uidPolicy = mPolicyService.getAppPolicy(appId); - } catch (RemoteException e) { - // since we can't do much without policy, we bail hard. - throw new RuntimeException("problem reading network policy", e); - } - + final int uidPolicy = mPolicyManager.getAppPolicy(appId); return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0; } private void setAppRestrictBackground(boolean restrictBackground) { if (LOGD) Log.d(TAG, "setAppRestrictBackground()"); final int appId = mCurrentApp.appId; - try { - mPolicyService.setAppPolicy(appId, - restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE); - } catch (RemoteException e) { - throw new RuntimeException("unable to save policy", e); - } - + mPolicyManager.setAppPolicy(appId, + restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE); mAppRestrict.setChecked(restrictBackground); } @@ -1201,23 +1193,25 @@ public class DataUsageSummary extends Fragment { private boolean isMobilePolicySplit() { final Context context = getActivity(); - if (hasMobileRadio(context)) { - final String subscriberId = getActiveSubscriberId(context); - return mPolicyEditor.isMobilePolicySplit(subscriberId); + if (hasReadyMobileRadio(context)) { + final TelephonyManager tele = TelephonyManager.from(context); + return mPolicyEditor.isMobilePolicySplit(getActiveSubscriberId(context)); } else { return false; } } private void setMobilePolicySplit(boolean split) { - final String subscriberId = getActiveSubscriberId(getActivity()); - mPolicyEditor.setMobilePolicySplit(subscriberId, split); + final Context context = getActivity(); + if (hasReadyMobileRadio(context)) { + final TelephonyManager tele = TelephonyManager.from(context); + mPolicyEditor.setMobilePolicySplit(getActiveSubscriberId(context), split); + } } private static String getActiveSubscriberId(Context context) { - final TelephonyManager telephony = (TelephonyManager) context.getSystemService( - Context.TELEPHONY_SERVICE); - final String actualSubscriberId = telephony.getSubscriberId(); + final TelephonyManager tele = TelephonyManager.from(context); + final String actualSubscriberId = tele.getSubscriberId(); return SystemProperties.get(TEST_SUBSCRIBER_PROP, actualSubscriberId); } @@ -2048,22 +2042,24 @@ public class DataUsageSummary extends Fragment { } /** - * Test if device has a mobile data radio. + * Test if device has a mobile data radio with SIM in ready state. */ - private static boolean hasMobileRadio(Context context) { + public static boolean hasReadyMobileRadio(Context context) { if (TEST_RADIOS) { return SystemProperties.get(TEST_RADIOS_PROP).contains("mobile"); } - final ConnectivityManager conn = (ConnectivityManager) context.getSystemService( - Context.CONNECTIVITY_SERVICE); - return conn.isNetworkSupported(TYPE_MOBILE); + final ConnectivityManager conn = ConnectivityManager.from(context); + final TelephonyManager tele = TelephonyManager.from(context); + + // require both supported network and ready SIM + return conn.isNetworkSupported(TYPE_MOBILE) && tele.getSimState() == SIM_STATE_READY; } /** * Test if device has a mobile 4G data radio. */ - private static boolean hasMobile4gRadio(Context context) { + public static boolean hasMobile4gRadio(Context context) { if (!NetworkPolicyEditor.ENABLE_SPLIT_POLICIES) { return false; } @@ -2071,39 +2067,35 @@ public class DataUsageSummary extends Fragment { return SystemProperties.get(TEST_RADIOS_PROP).contains("4g"); } - final ConnectivityManager conn = (ConnectivityManager) context.getSystemService( - Context.CONNECTIVITY_SERVICE); - final TelephonyManager telephony = (TelephonyManager) context.getSystemService( - Context.TELEPHONY_SERVICE); + final ConnectivityManager conn = ConnectivityManager.from(context); + final TelephonyManager tele = TelephonyManager.from(context); final boolean hasWimax = conn.isNetworkSupported(TYPE_WIMAX); - final boolean hasLte = telephony.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE; + final boolean hasLte = tele.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE; return hasWimax || hasLte; } /** * Test if device has a Wi-Fi data radio. */ - private static boolean hasWifiRadio(Context context) { + public static boolean hasWifiRadio(Context context) { if (TEST_RADIOS) { return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi"); } - final ConnectivityManager conn = (ConnectivityManager) context.getSystemService( - Context.CONNECTIVITY_SERVICE); + final ConnectivityManager conn = ConnectivityManager.from(context); return conn.isNetworkSupported(TYPE_WIFI); } /** * Test if device has an ethernet network connection. */ - private static boolean hasEthernet(Context context) { + public static boolean hasEthernet(Context context) { if (TEST_RADIOS) { return SystemProperties.get(TEST_RADIOS_PROP).contains("ethernet"); } - final ConnectivityManager conn = (ConnectivityManager) context.getSystemService( - Context.CONNECTIVITY_SERVICE); + final ConnectivityManager conn = ConnectivityManager.from(context); return conn.isNetworkSupported(TYPE_ETHERNET); } @@ -2138,6 +2130,7 @@ public class DataUsageSummary extends Fragment { * Build string describing currently limited networks, which defines when * background data is restricted. */ + @Deprecated private CharSequence buildLimitedNetworksString() { final List limited = buildLimitedNetworksList(); @@ -2153,22 +2146,28 @@ public class DataUsageSummary extends Fragment { * Build list of currently limited networks, which defines when background * data is restricted. */ + @Deprecated private List buildLimitedNetworksList() { final Context context = getActivity(); - final String subscriberId = getActiveSubscriberId(context); // build combined list of all limited networks final ArrayList limited = Lists.newArrayList(); - if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobileAll(subscriberId))) { - limited.add(getText(R.string.data_usage_list_mobile)); - } - if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobile3gLower(subscriberId))) { - limited.add(getText(R.string.data_usage_tab_3g)); - } - if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobile4g(subscriberId))) { - limited.add(getText(R.string.data_usage_tab_4g)); + + final TelephonyManager tele = TelephonyManager.from(context); + if (tele.getSimState() == SIM_STATE_READY) { + final String subscriberId = getActiveSubscriberId(context); + if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobileAll(subscriberId))) { + limited.add(getText(R.string.data_usage_list_mobile)); + } + if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobile3gLower(subscriberId))) { + limited.add(getText(R.string.data_usage_tab_3g)); + } + if (mPolicyEditor.hasLimitedPolicy(buildTemplateMobile4g(subscriberId))) { + limited.add(getText(R.string.data_usage_tab_4g)); + } } - if (mPolicyEditor.hasLimitedPolicy(buildTemplateWifi())) { + + if (mPolicyEditor.hasLimitedPolicy(buildTemplateWifiWildcard())) { limited.add(getText(R.string.data_usage_tab_wifi)); } if (mPolicyEditor.hasLimitedPolicy(buildTemplateEthernet())) { diff --git a/src/com/android/settings/net/DataUsageMeteredSettings.java b/src/com/android/settings/net/DataUsageMeteredSettings.java new file mode 100644 index 0000000000..d069a7196a --- /dev/null +++ b/src/com/android/settings/net/DataUsageMeteredSettings.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2012 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.net; + +import static com.android.settings.DataUsageSummary.hasReadyMobileRadio; +import static com.android.settings.DataUsageSummary.hasWifiRadio; + +import android.content.Context; +import android.net.NetworkPolicy; +import android.net.NetworkPolicyManager; +import android.net.NetworkTemplate; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.telephony.TelephonyManager; + +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; + +/** + * Panel to configure {@link NetworkPolicy#metered} for networks. + */ +public class DataUsageMeteredSettings extends SettingsPreferenceFragment { + + private NetworkPolicyManager mPolicyManager; + private WifiManager mWifiManager; + + private NetworkPolicyEditor mPolicyEditor; + + private PreferenceCategory mMobileCategory; + private PreferenceCategory mWifiCategory; + + @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"); + + updateNetworks(context); + + } + + private void updateNetworks(Context context) { + if (hasReadyMobileRadio(context)) { + mMobileCategory.removeAll(); + mMobileCategory.addPreference(buildMobilePref(context)); + } else { + getPreferenceScreen().removePreference(mMobileCategory); + } + + if (hasWifiRadio(context)) { + mWifiCategory.removeAll(); + for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) { + if (config.SSID != null) { + mWifiCategory.addPreference(buildWifiPref(context, config)); + } + } + } else { + getPreferenceScreen().removePreference(mWifiCategory); + } + } + + private Preference buildMobilePref(Context context) { + final TelephonyManager tele = TelephonyManager.from(context); + final NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll( + tele.getSubscriberId()); + final MeteredPreference pref = new MeteredPreference(context, template); + pref.setTitle(tele.getNetworkOperatorName()); + return pref; + } + + private Preference buildWifiPref(Context context, WifiConfiguration config) { + final String networkId = removeDoubleQuotes(config.SSID); + final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(networkId); + final MeteredPreference pref = new MeteredPreference(context, template); + pref.setTitle(networkId); + return pref; + } + + private class MeteredPreference extends CheckBoxPreference { + private final NetworkTemplate mTemplate; + + public MeteredPreference(Context context, NetworkTemplate template) { + super(context); + mTemplate = template; + + setPersistent(false); + setChecked(mPolicyEditor.getPolicyMetered(mTemplate)); + } + + @Override + protected void notifyChanged() { + super.notifyChanged(); + mPolicyEditor.setPolicyMetered(mTemplate, isChecked()); + } + } + + + private static String removeDoubleQuotes(String string) { + final int length = string.length(); + if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) { + return string.substring(1, length - 1); + } + return string; + } + +} diff --git a/src/com/android/settings/net/NetworkPolicyEditor.java b/src/com/android/settings/net/NetworkPolicyEditor.java index 80fcdb5b9e..07a2afbdcb 100644 --- a/src/com/android/settings/net/NetworkPolicyEditor.java +++ b/src/com/android/settings/net/NetworkPolicyEditor.java @@ -16,6 +16,7 @@ package com.android.settings.net; +import static android.net.NetworkPolicy.CYCLE_NONE; import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; @@ -27,11 +28,10 @@ import static android.net.NetworkTemplate.buildTemplateMobile4g; import static android.net.NetworkTemplate.buildTemplateMobileAll; import static com.android.internal.util.Preconditions.checkNotNull; -import android.net.INetworkPolicyManager; import android.net.NetworkPolicy; +import android.net.NetworkPolicyManager; import android.net.NetworkTemplate; import android.os.AsyncTask; -import android.os.RemoteException; import android.text.format.Time; import com.android.internal.util.Objects; @@ -43,27 +43,23 @@ import java.util.HashSet; /** * Utility class to modify list of {@link NetworkPolicy}. Specifically knows - * about which policies can coexist. Not thread safe. + * about which policies can coexist. This editor offers thread safety when + * talking with {@link NetworkPolicyManager}. */ public class NetworkPolicyEditor { // TODO: be more robust when missing policies from service public static final boolean ENABLE_SPLIT_POLICIES = false; - private INetworkPolicyManager mPolicyService; + private NetworkPolicyManager mPolicyManager; private ArrayList mPolicies = Lists.newArrayList(); - public NetworkPolicyEditor(INetworkPolicyManager policyService) { - mPolicyService = checkNotNull(policyService); + public NetworkPolicyEditor(NetworkPolicyManager policyManager) { + mPolicyManager = checkNotNull(policyManager); } public void read() { - final NetworkPolicy[] policies; - try { - policies = mPolicyService.getNetworkPolicies(); - } catch (RemoteException e) { - throw new RuntimeException("problem reading policies", e); - } + final NetworkPolicy[] policies = mPolicyManager.getNetworkPolicies(); boolean modified = false; mPolicies.clear(); @@ -78,12 +74,6 @@ public class NetworkPolicyEditor { modified = true; } - // drop any WIFI policies that were defined - if (policy.template.getMatchRule() == MATCH_WIFI) { - modified = true; - continue; - } - mPolicies.add(policy); } @@ -109,11 +99,7 @@ public class NetworkPolicyEditor { } public void write(NetworkPolicy[] policies) { - try { - mPolicyService.setNetworkPolicies(policies); - } catch (RemoteException e) { - throw new RuntimeException("problem writing policies", e); - } + mPolicyManager.setNetworkPolicies(policies); } public boolean hasLimitedPolicy(NetworkTemplate template) { @@ -142,13 +128,24 @@ public class NetworkPolicyEditor { @Deprecated private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) { // TODO: move this into framework to share with NetworkPolicyManagerService - final Time time = new Time(); - time.setToNow(); - final int cycleDay = time.monthDay; - final String cycleTimezone = time.timezone; + final int cycleDay; + final String cycleTimezone; + final boolean metered; + + if (template.getMatchRule() == MATCH_WIFI) { + cycleDay = CYCLE_NONE; + cycleTimezone = Time.TIMEZONE_UTC; + metered = false; + } else { + final Time time = new Time(); + time.setToNow(); + cycleDay = time.monthDay; + cycleTimezone = time.timezone; + metered = true; + } return new NetworkPolicy(template, cycleDay, cycleTimezone, WARNING_DISABLED, - LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, false); + LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, metered, true); } public int getPolicyCycleDay(NetworkTemplate template) { @@ -188,6 +185,52 @@ public class NetworkPolicyEditor { writeAsync(); } + public boolean getPolicyMetered(NetworkTemplate template) { + final NetworkPolicy policy = getPolicy(template); + if (policy != null) { + return policy.metered; + } else { + return false; + } + } + + public void setPolicyMetered(NetworkTemplate template, boolean metered) { + boolean modified = false; + + NetworkPolicy policy = getPolicy(template); + if (metered) { + if (policy == null) { + policy = buildDefaultPolicy(template); + policy.metered = true; + policy.inferred = false; + mPolicies.add(policy); + modified = true; + } else if (!policy.metered) { + policy.metered = true; + policy.inferred = false; + modified = true; + } + + } else { + if (policy == null) { + // ignore when policy doesn't exist + } else if (policy.template.getMatchRule() == MATCH_WIFI + && policy.warningBytes == WARNING_DISABLED + && policy.limitBytes == LIMIT_DISABLED) { + // when WIFI goes unmetered, and no other warning/limit for + // policy, clean it up. + mPolicies.remove(policy); + modified = true; + } else if (policy.metered) { + policy.metered = false; + policy.inferred = false; + modified = true; + } + } + + if (modified) writeAsync(); + } + /** * Remove any split {@link NetworkPolicy}. */