Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f35dd41d authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Controls to set expensive (metered) networks."

parents 0bcb7c1e 313f7d8c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -35,4 +35,7 @@
        android:id="@+id/data_usage_menu_show_ethernet"
        android:title="@string/data_usage_menu_show_ethernet"
        android:checkable="true" />
    <item
        android:id="@+id/data_usage_menu_metered"
        android:title="@string/data_usage_menu_metered" />
</menu>
+11 −0
Original line number Diff line number Diff line
@@ -3609,6 +3609,8 @@
    <string name="data_usage_menu_show_wifi">Show Wi-Fi usage</string>
    <!-- Title for checkbox menu option to show Ethernet data usage. [CHAR LIMIT=32] -->
    <string name="data_usage_menu_show_ethernet">Show Ethernet usage</string>
    <!-- Title for menu option to configure expensive networks. [CHAR LIMIT=32] -->
    <string name="data_usage_menu_metered">Expensive networks</string>
    <!-- Title for option to change data usage cycle day. [CHAR LIMIT=32] -->
    <string name="data_usage_change_cycle">Change cycle\u2026</string>
    <!-- Body of dialog prompting user to change numerical day of month that data usage cycle should reset. [CHAR LIMIT=64] -->
@@ -3710,6 +3712,15 @@
    <!-- Label displaying total network data transferred during a specific time period. [CHAR LIMIT=64] -->
    <string name="data_usage_total_during_range"><xliff:g id="range" example="Jul 1 - Jul 31">%2$s</xliff:g>: about <xliff:g id="total" example="128KB">%1$s</xliff:g> used</string>

    <!-- Dialog title for selecting paid networks. [CHAR LIMIT=25] -->
    <string name="data_usage_metered_title">Expensive networks</string>
    <!-- Dialog body for selecting paid networks. [CHAR LIMIT=NONE] -->
    <string name="data_usage_metered_body">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.</string>
    <!-- Header for list of mobile networks. [CHAR LIMIT=32] -->
    <string name="data_usage_metered_mobile">Mobile networks</string>
    <!-- Header for list of Wi-Fi networks. [CHAR LIMIT=32] -->
    <string name="data_usage_metered_wifi">Wi-Fi networks</string>

    <!-- Button at the bottom of the CryptKeeper screen to make an emergency call. -->
    <string name="cryptkeeper_emergency_call">Emergency call</string>
    <!-- Button at the bottom of the CryptKeeper screen that lets the user return to a call -->
+34 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <Preference
        android:summary="@string/data_usage_metered_body"
        android:persistent="false"
        android:selectable="false" />

    <PreferenceCategory
        android:key="mobile"
        android:title="@string/data_usage_metered_mobile"
        android:persistent="false" />

    <PreferenceCategory
        android:key="wifi"
        android:title="@string/data_usage_metered_wifi"
        android:persistent="false" />

</PreferenceScreen>
+84 −85
Original line number Diff line number Diff line
@@ -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);
    public void setRestrictBackground(boolean restrictBackground) {
        mPolicyManager.setRestrictBackground(restrictBackground);
        mMenuRestrictBackground.setChecked(restrictBackground);
        } catch (RemoteException e) {
            Log.w(TAG, "problem talking with policy service: " + e);
        }
    }

    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,
        mPolicyManager.setAppPolicy(appId,
                restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
        } catch (RemoteException e) {
            throw new RuntimeException("unable to save policy", e);
        }

        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<CharSequence> limited = buildLimitedNetworksList();

@@ -2153,12 +2146,16 @@ public class DataUsageSummary extends Fragment {
     * Build list of currently limited networks, which defines when background
     * data is restricted.
     */
    @Deprecated
    private List<CharSequence> buildLimitedNetworksList() {
        final Context context = getActivity();
        final String subscriberId = getActiveSubscriberId(context);

        // build combined list of all limited networks
        final ArrayList<CharSequence> limited = Lists.newArrayList();

        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));
            }
@@ -2168,7 +2165,9 @@ public class DataUsageSummary extends Fragment {
            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())) {
+133 −0
Original line number Diff line number Diff line
/*
 * 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;
    }

}
Loading