138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu/*
238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * Copyright (C) 2011 The Android Open Source Project
338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu *
438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * Licensed under the Apache License, Version 2.0 (the "License");
538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * you may not use this file except in compliance with the License.
638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * You may obtain a copy of the License at
738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu *
838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu *      http://www.apache.org/licenses/LICENSE-2.0
938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu *
1038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * Unless required by applicable law or agreed to in writing, software
1138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * distributed under the License is distributed on an "AS IS" BASIS,
1238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * See the License for the specific language governing permissions and
1438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * limitations under the License.
1538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu */
1638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
1738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liupackage com.android.settingslib;
1838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
1938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport static android.net.NetworkPolicy.CYCLE_NONE;
2038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport static android.net.NetworkPolicy.LIMIT_DISABLED;
2138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport static android.net.NetworkPolicy.SNOOZE_NEVER;
2238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport static android.net.NetworkPolicy.WARNING_DISABLED;
2338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport static android.net.NetworkTemplate.MATCH_WIFI;
2438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport static com.android.internal.util.Preconditions.checkNotNull;
2538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
2638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport android.net.NetworkPolicy;
2738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport android.net.NetworkPolicyManager;
2838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport android.net.NetworkTemplate;
2938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport android.net.wifi.WifiInfo;
3038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport android.os.AsyncTask;
3138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport android.text.TextUtils;
3238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport android.text.format.Time;
3338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
3438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport com.google.android.collect.Lists;
3538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
3638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liuimport java.util.ArrayList;
3738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
3838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu/**
3938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * Utility class to modify list of {@link NetworkPolicy}. Specifically knows
4038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * about which policies can coexist. This editor offers thread safety when
4138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * talking with {@link NetworkPolicyManager}.
4238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu *
4338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu * @hide
4438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu */
4538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liupublic class NetworkPolicyEditor {
4638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    // TODO: be more robust when missing policies from service
4738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
4838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public static final boolean ENABLE_SPLIT_POLICIES = false;
4938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
5038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    private NetworkPolicyManager mPolicyManager;
5138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    private ArrayList<NetworkPolicy> mPolicies = Lists.newArrayList();
5238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
5338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public NetworkPolicyEditor(NetworkPolicyManager policyManager) {
5438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        mPolicyManager = checkNotNull(policyManager);
5538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
5638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
5738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public void read() {
5838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy[] policies = mPolicyManager.getNetworkPolicies();
5938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
6038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        boolean modified = false;
6138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        mPolicies.clear();
6238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        for (NetworkPolicy policy : policies) {
6338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            // TODO: find better place to clamp these
6438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            if (policy.limitBytes < -1) {
6538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy.limitBytes = LIMIT_DISABLED;
6638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                modified = true;
6738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            }
6838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            if (policy.warningBytes < -1) {
6938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy.warningBytes = WARNING_DISABLED;
7038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                modified = true;
7138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            }
7238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
7338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            mPolicies.add(policy);
7438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
7538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
7638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        // when we cleaned policies above, write back changes
7738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (modified) writeAsync();
7838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
7938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
8038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public void writeAsync() {
8138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        // TODO: consider making more robust by passing through service
8238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy[] policies = mPolicies.toArray(new NetworkPolicy[mPolicies.size()]);
8338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        new AsyncTask<Void, Void, Void>() {
8438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            @Override
8538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            protected Void doInBackground(Void... params) {
8638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                write(policies);
8738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                return null;
8838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            }
8938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }.execute();
9038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
9138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
9238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public void write(NetworkPolicy[] policies) {
9338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        mPolicyManager.setNetworkPolicies(policies);
9438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
9538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
9638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public boolean hasLimitedPolicy(NetworkTemplate template) {
9738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy policy = getPolicy(template);
9838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        return policy != null && policy.limitBytes != LIMIT_DISABLED;
9938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
10038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
10138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public NetworkPolicy getOrCreatePolicy(NetworkTemplate template) {
10238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        NetworkPolicy policy = getPolicy(template);
10338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (policy == null) {
10438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            policy = buildDefaultPolicy(template);
10538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            mPolicies.add(policy);
10638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
10738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        return policy;
10838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
10938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
11038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public NetworkPolicy getPolicy(NetworkTemplate template) {
11138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        for (NetworkPolicy policy : mPolicies) {
11238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            if (policy.template.equals(template)) {
11338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                return policy;
11438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            }
11538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
11638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        return null;
11738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
11838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
11938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public NetworkPolicy getPolicyMaybeUnquoted(NetworkTemplate template) {
12038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        NetworkPolicy policy = getPolicy(template);
12138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (policy != null) {
12238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            return policy;
12338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        } else {
12438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            return getPolicy(buildUnquotedNetworkTemplate(template));
12538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
12638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
12738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
12838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    @Deprecated
12938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) {
13038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        // TODO: move this into framework to share with NetworkPolicyManagerService
13138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final int cycleDay;
13238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final String cycleTimezone;
13338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final boolean metered;
13438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
13538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (template.getMatchRule() == MATCH_WIFI) {
13638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            cycleDay = CYCLE_NONE;
13738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            cycleTimezone = Time.TIMEZONE_UTC;
13838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            metered = false;
13938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        } else {
14038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            final Time time = new Time();
14138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            time.setToNow();
14238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            cycleDay = time.monthDay;
14338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            cycleTimezone = time.timezone;
14438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            metered = true;
14538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
14638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
14738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        return new NetworkPolicy(template, cycleDay, cycleTimezone, WARNING_DISABLED,
14838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, metered, true);
14938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
15038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
15138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public int getPolicyCycleDay(NetworkTemplate template) {
15238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy policy = getPolicy(template);
15338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        return (policy != null) ? policy.cycleDay : -1;
15438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
15538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
15638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public void setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone) {
15738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy policy = getOrCreatePolicy(template);
15838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.cycleDay = cycleDay;
15938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.cycleTimezone = cycleTimezone;
16038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.inferred = false;
16138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.clearSnooze();
16238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        writeAsync();
16338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
16438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
16538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public long getPolicyWarningBytes(NetworkTemplate template) {
16638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy policy = getPolicy(template);
16738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        return (policy != null) ? policy.warningBytes : WARNING_DISABLED;
16838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
16938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
17038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) {
17138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy policy = getOrCreatePolicy(template);
17238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.warningBytes = warningBytes;
17338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.inferred = false;
17438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.clearSnooze();
17538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        writeAsync();
17638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
17738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
17838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public long getPolicyLimitBytes(NetworkTemplate template) {
17938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy policy = getPolicy(template);
18038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        return (policy != null) ? policy.limitBytes : LIMIT_DISABLED;
18138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
18238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
18338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) {
18438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy policy = getOrCreatePolicy(template);
18538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.limitBytes = limitBytes;
18638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.inferred = false;
18738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        policy.clearSnooze();
18838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        writeAsync();
18938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
19038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
19138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public boolean getPolicyMetered(NetworkTemplate template) {
19238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        NetworkPolicy policy = getPolicy(template);
19338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (policy != null) {
19438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            return policy.metered;
19538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        } else {
19638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            return false;
19738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
19838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
19938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
20038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    public void setPolicyMetered(NetworkTemplate template, boolean metered) {
20138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        boolean modified = false;
20238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
20338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        NetworkPolicy policy = getPolicy(template);
20438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (metered) {
20538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            if (policy == null) {
20638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy = buildDefaultPolicy(template);
20738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy.metered = true;
20838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy.inferred = false;
20938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                mPolicies.add(policy);
21038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                modified = true;
21138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            } else if (!policy.metered) {
21238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy.metered = true;
21338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy.inferred = false;
21438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                modified = true;
21538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            }
21638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
21738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        } else {
21838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            if (policy == null) {
21938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                // ignore when policy doesn't exist
22038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            } else if (policy.metered) {
22138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy.metered = false;
22238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                policy.inferred = false;
22338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                modified = true;
22438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            }
22538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
22638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
22738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        // Remove legacy unquoted policies while we're here
22838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkTemplate unquoted = buildUnquotedNetworkTemplate(template);
22938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final NetworkPolicy unquotedPolicy = getPolicy(unquoted);
23038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (unquotedPolicy != null) {
23138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            mPolicies.remove(unquotedPolicy);
23238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            modified = true;
23338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
23438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
23538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (modified) writeAsync();
23638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
23738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu
23838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    /**
23938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu     * Build a revised {@link NetworkTemplate} that matches the same rule, but
24038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu     * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work
24138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu     * around legacy bugs.
24238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu     */
24338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) {
24438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (template == null) return null;
24538e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final String networkId = template.getNetworkId();
24638e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        final String strippedNetworkId = WifiInfo.removeDoubleQuotes(networkId);
24738e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        if (!TextUtils.equals(strippedNetworkId, networkId)) {
24838e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            return new NetworkTemplate(
24938e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu                    template.getMatchRule(), template.getSubscriberId(), strippedNetworkId);
25038e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        } else {
25138e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu            return null;
25238e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu        }
25338e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu    }
25438e932b37aea8d2f6866c3c879afa188587bcde3Wei Liu}
255