NetworkTemplate.java revision adca34a0d6b5955f0cbc931dd0834b25fe3759b9
11b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey/*
21b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project
31b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey *
41b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
51b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * you may not use this file except in compliance with the License.
61b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * You may obtain a copy of the License at
71b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey *
81b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
91b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey *
101b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
111b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
121b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * See the License for the specific language governing permissions and
141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * limitations under the License.
151b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey */
161b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
171b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeypackage android.net;
181b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_BLUETOOTH;
2002e21d6a5b5117d494777a36783909854854f751Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_ETHERNET;
211b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_WIFI;
223ca7481439c9b65a137d7705d0f4a16766529e75Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_WIFI_P2P;
231b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_WIMAX;
24d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkeyimport static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
252e4dce0dd24aa89ca6adf6559f13d3e342ff8558Jeff Sharkeyimport static android.net.wifi.WifiInfo.removeDoubleQuotes;
261b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
271b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
281b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
291b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
301b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.telephony.TelephonyManager.getNetworkClass;
31adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
32630a1712168f402653039e368259cb9480454fa8Jeff Sharkeyimport static com.android.internal.util.ArrayUtils.contains;
331b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
34630a1712168f402653039e368259cb9480454fa8Jeff Sharkeyimport android.content.res.Resources;
351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.os.Parcel;
361b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.os.Parcelable;
37adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport android.util.BackupUtils;
381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
398b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.VisibleForTesting;
403256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkeyimport com.android.internal.util.ArrayUtils;
411b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
42adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport java.io.ByteArrayOutputStream;
43adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport java.io.DataInputStream;
44adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport java.io.DataOutputStream;
45adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddyimport java.io.IOException;
463256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkeyimport java.util.Arrays;
4755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkeyimport java.util.Objects;
4855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey
491b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey/**
501b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * Template definition used to generically match {@link NetworkIdentity},
511b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * usually when collecting statistics.
521b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey *
531b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * @hide
541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey */
551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeypublic class NetworkTemplate implements Parcelable {
56adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    /**
57adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy     * Current Version of the Backup Serializer.
58adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy     */
59adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    private static final int BACKUP_VERSION = 1;
601b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
614e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static final int MATCH_MOBILE_ALL = 1;
626973634ce61ab7d4c1d51c70be6d51725b89e7b9Jeff Sharkey    @Deprecated
634e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static final int MATCH_MOBILE_3G_LOWER = 2;
646973634ce61ab7d4c1d51c70be6d51725b89e7b9Jeff Sharkey    @Deprecated
654e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static final int MATCH_MOBILE_4G = 3;
664e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static final int MATCH_WIFI = 4;
674e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static final int MATCH_ETHERNET = 5;
68234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    public static final int MATCH_MOBILE_WILDCARD = 6;
69234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    public static final int MATCH_WIFI_WILDCARD = 7;
7055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey    public static final int MATCH_BLUETOOTH = 8;
714e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey
721b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
73630a1712168f402653039e368259cb9480454fa8Jeff Sharkey     * Set of {@link NetworkInfo#getType()} that reflect data usage.
74630a1712168f402653039e368259cb9480454fa8Jeff Sharkey     */
75630a1712168f402653039e368259cb9480454fa8Jeff Sharkey    private static final int[] DATA_USAGE_NETWORK_TYPES;
76630a1712168f402653039e368259cb9480454fa8Jeff Sharkey
77630a1712168f402653039e368259cb9480454fa8Jeff Sharkey    static {
78630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        DATA_USAGE_NETWORK_TYPES = Resources.getSystem().getIntArray(
79630a1712168f402653039e368259cb9480454fa8Jeff Sharkey                com.android.internal.R.array.config_data_usage_network_types);
80630a1712168f402653039e368259cb9480454fa8Jeff Sharkey    }
81630a1712168f402653039e368259cb9480454fa8Jeff Sharkey
8270c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey    private static boolean sForceAllNetworkTypes = false;
8370c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey
848b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @VisibleForTesting
8570c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey    public static void forceAllNetworkTypes() {
8670c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey        sForceAllNetworkTypes = true;
8770c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey    }
8870c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey
89630a1712168f402653039e368259cb9480454fa8Jeff Sharkey    /**
908fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
918fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * the given IMSI.
921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
934e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
948fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId, null);
954e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    }
961b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
988fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
998fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * the given IMSI that roughly meet a "3G" definition, or lower.
1001b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
1018fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    @Deprecated
1024e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static NetworkTemplate buildTemplateMobile3gLower(String subscriberId) {
1038fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId, null);
1044e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    }
1051b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1061b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
1078fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
1088fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * the given IMSI that roughly meet a "4G" definition.
1091b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
1108fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    @Deprecated
1114e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static NetworkTemplate buildTemplateMobile4g(String subscriberId) {
1128fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null);
1134e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    }
1141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1151b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
116234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
117234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey     * regardless of IMSI.
118234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey     */
119234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    public static NetworkTemplate buildTemplateMobileWildcard() {
120234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey        return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
121234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    }
122234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey
123234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    /**
1248fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
1258fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * regardless of SSID.
1261b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
1278fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    public static NetworkTemplate buildTemplateWifiWildcard() {
128234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey        return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
1298fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    }
1308fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey
1318fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    @Deprecated
1324e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static NetworkTemplate buildTemplateWifi() {
1338fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        return buildTemplateWifiWildcard();
1348fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    }
1358fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey
1368fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    /**
1378fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
1388fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * given SSID.
1398fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     */
1408fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    public static NetworkTemplate buildTemplateWifi(String networkId) {
1418fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        return new NetworkTemplate(MATCH_WIFI, null, networkId);
1424e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    }
1431b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1444e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    /**
1454e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey     * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
1464e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey     * networks together.
1474e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey     */
1484e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    public static NetworkTemplate buildTemplateEthernet() {
1498fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        return new NetworkTemplate(MATCH_ETHERNET, null, null);
1504e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    }
1514e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey
15255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey    /**
15355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey     * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
15455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey     * networks together.
15555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey     */
15655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey    public static NetworkTemplate buildTemplateBluetooth() {
15755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey        return new NetworkTemplate(MATCH_BLUETOOTH, null, null);
15855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey    }
15955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey
1604e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    private final int mMatchRule;
1614e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    private final String mSubscriberId;
1623256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
1633256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    /**
1643256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * Ugh, templates are designed to target a single subscriber, but we might
1653256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * need to match several "merged" subscribers. These are the subscribers
1663256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * that should be considered to match this template.
1673256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * <p>
1683256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * Since the merge set is dynamic, it should <em>not</em> be persisted or
1693256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * used for determining equality.
1703256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     */
1713256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    private final String[] mMatchSubscriberIds;
1723256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
1738fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    private final String mNetworkId;
1741b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1758fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
1763256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
1773256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    }
1783256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
1793256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
1803256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            String networkId) {
1818fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        mMatchRule = matchRule;
1828fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        mSubscriberId = subscriberId;
1833256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        mMatchSubscriberIds = matchSubscriberIds;
1848fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        mNetworkId = networkId;
1851b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
1861b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1874e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    private NetworkTemplate(Parcel in) {
1881b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        mMatchRule = in.readInt();
1891b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        mSubscriberId = in.readString();
1903256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        mMatchSubscriberIds = in.createStringArray();
1918fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        mNetworkId = in.readString();
1921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
1931b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1948fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    @Override
1951b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public void writeToParcel(Parcel dest, int flags) {
1961b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        dest.writeInt(mMatchRule);
1971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        dest.writeString(mSubscriberId);
1983256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        dest.writeStringArray(mMatchSubscriberIds);
1998fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        dest.writeString(mNetworkId);
2001b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
2011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
2028fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    @Override
2031b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public int describeContents() {
2041b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return 0;
2051b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
2061b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
2071b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    @Override
2081b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public String toString() {
2098fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
2108fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
2118fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        if (mSubscriberId != null) {
2123256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            builder.append(", subscriberId=").append(
2133256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                    NetworkIdentity.scrubSubscriberId(mSubscriberId));
2143256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        }
2153256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        if (mMatchSubscriberIds != null) {
2163256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            builder.append(", matchSubscriberIds=").append(
2173256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                    Arrays.toString(NetworkIdentity.scrubSubscriberId(mMatchSubscriberIds)));
2188fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        }
2198fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        if (mNetworkId != null) {
2208fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            builder.append(", networkId=").append(mNetworkId);
2218fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        }
2228fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        return builder.toString();
2231b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
2241b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
2251b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    @Override
2261b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public int hashCode() {
227e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root        return Objects.hash(mMatchRule, mSubscriberId, mNetworkId);
2281b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
2291b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
2301b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    @Override
2311b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public boolean equals(Object obj) {
2321b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        if (obj instanceof NetworkTemplate) {
2331b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            final NetworkTemplate other = (NetworkTemplate) obj;
2341b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            return mMatchRule == other.mMatchRule
235e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root                    && Objects.equals(mSubscriberId, other.mSubscriberId)
236e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root                    && Objects.equals(mNetworkId, other.mNetworkId);
2371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
2381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return false;
2391b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
2401b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
2413256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    public boolean isMatchRuleMobile() {
2423256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        switch (mMatchRule) {
2433256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            case MATCH_MOBILE_3G_LOWER:
2443256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            case MATCH_MOBILE_4G:
2453256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            case MATCH_MOBILE_ALL:
2463256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            case MATCH_MOBILE_WILDCARD:
2473256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                return true;
2483256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            default:
2493256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                return false;
2503256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        }
2513256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    }
2523256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
2531b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public int getMatchRule() {
2541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return mMatchRule;
2551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
2561b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
2571b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public String getSubscriberId() {
2581b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return mSubscriberId;
2591b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
2601b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
2618fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    public String getNetworkId() {
2628fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        return mNetworkId;
2638fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    }
2648fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey
2651b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
266630a1712168f402653039e368259cb9480454fa8Jeff Sharkey     * Test if given {@link NetworkIdentity} matches this template.
2671b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
2681b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public boolean matches(NetworkIdentity ident) {
2691b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        switch (mMatchRule) {
2701b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case MATCH_MOBILE_ALL:
2711b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return matchesMobile(ident);
2721b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case MATCH_MOBILE_3G_LOWER:
2731b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return matchesMobile3gLower(ident);
2741b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case MATCH_MOBILE_4G:
2751b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return matchesMobile4g(ident);
2761b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case MATCH_WIFI:
2771b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return matchesWifi(ident);
2784e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            case MATCH_ETHERNET:
2794e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey                return matchesEthernet(ident);
280234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey            case MATCH_MOBILE_WILDCARD:
281234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey                return matchesMobileWildcard(ident);
282234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey            case MATCH_WIFI_WILDCARD:
283234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey                return matchesWifiWildcard(ident);
28455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey            case MATCH_BLUETOOTH:
28555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey                return matchesBluetooth(ident);
2861b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            default:
2871b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                throw new IllegalArgumentException("unknown network template");
2881b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
2891b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
2901b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
2911b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
292630a1712168f402653039e368259cb9480454fa8Jeff Sharkey     * Check if mobile network with matching IMSI.
2931b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
2941b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private boolean matchesMobile(NetworkIdentity ident) {
295630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        if (ident.mType == TYPE_WIMAX) {
296630a1712168f402653039e368259cb9480454fa8Jeff Sharkey            // TODO: consider matching against WiMAX subscriber identity
2971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            return true;
298630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        } else {
2993256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final boolean matchesType = (sForceAllNetworkTypes
3003256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                    || contains(DATA_USAGE_NETWORK_TYPES, ident.mType));
30156859f323c1e7da9d537478e080d73614b207376Jeff Sharkey            return matchesType && !ArrayUtils.isEmpty(mMatchSubscriberIds)
30256859f323c1e7da9d537478e080d73614b207376Jeff Sharkey                    && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
3031b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
3041b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
3051b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
3061b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
30702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey     * Check if mobile network classified 3G or lower with matching IMSI.
3081b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
3096973634ce61ab7d4c1d51c70be6d51725b89e7b9Jeff Sharkey    @Deprecated
3101b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private boolean matchesMobile3gLower(NetworkIdentity ident) {
311d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey        ensureSubtypeAvailable();
312630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        if (ident.mType == TYPE_WIMAX) {
313630a1712168f402653039e368259cb9480454fa8Jeff Sharkey            return false;
314630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        } else if (matchesMobile(ident)) {
3151b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            switch (getNetworkClass(ident.mSubType)) {
3161b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case NETWORK_CLASS_UNKNOWN:
3171b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case NETWORK_CLASS_2_G:
3181b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case NETWORK_CLASS_3_G:
3191b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    return true;
3201b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            }
3211b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
3221b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return false;
3231b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
3241b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
3251b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
326630a1712168f402653039e368259cb9480454fa8Jeff Sharkey     * Check if mobile network classified 4G with matching IMSI.
3271b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
3286973634ce61ab7d4c1d51c70be6d51725b89e7b9Jeff Sharkey    @Deprecated
3291b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private boolean matchesMobile4g(NetworkIdentity ident) {
330d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey        ensureSubtypeAvailable();
331630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        if (ident.mType == TYPE_WIMAX) {
332630a1712168f402653039e368259cb9480454fa8Jeff Sharkey            // TODO: consider matching against WiMAX subscriber identity
333630a1712168f402653039e368259cb9480454fa8Jeff Sharkey            return true;
334630a1712168f402653039e368259cb9480454fa8Jeff Sharkey        } else if (matchesMobile(ident)) {
3351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            switch (getNetworkClass(ident.mSubType)) {
3361b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case NETWORK_CLASS_4_G:
3371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    return true;
3381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            }
3391b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
3401b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return false;
3411b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
3421b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
3431b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
3441b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * Check if matches Wi-Fi network template.
3451b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
3461b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private boolean matchesWifi(NetworkIdentity ident) {
3473ca7481439c9b65a137d7705d0f4a16766529e75Jeff Sharkey        switch (ident.mType) {
3483ca7481439c9b65a137d7705d0f4a16766529e75Jeff Sharkey            case TYPE_WIFI:
349e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root                return Objects.equals(
3502e4dce0dd24aa89ca6adf6559f13d3e342ff8558Jeff Sharkey                        removeDoubleQuotes(mNetworkId), removeDoubleQuotes(ident.mNetworkId));
3513ca7481439c9b65a137d7705d0f4a16766529e75Jeff Sharkey            default:
3523ca7481439c9b65a137d7705d0f4a16766529e75Jeff Sharkey                return false;
3531b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
3541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
3551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
3564e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    /**
3574e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey     * Check if matches Ethernet network template.
3584e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey     */
3594e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    private boolean matchesEthernet(NetworkIdentity ident) {
3604e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey        if (ident.mType == TYPE_ETHERNET) {
3614e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            return true;
3624e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey        }
3634e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey        return false;
3644e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    }
3654e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey
366234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    private boolean matchesMobileWildcard(NetworkIdentity ident) {
367234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey        if (ident.mType == TYPE_WIMAX) {
368234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey            return true;
369234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey        } else {
37070c70530bd6793869736ec894498e4ebf5dc9b20Jeff Sharkey            return sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType);
371234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey        }
372234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    }
373234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey
374234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    private boolean matchesWifiWildcard(NetworkIdentity ident) {
375234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey        switch (ident.mType) {
376234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey            case TYPE_WIFI:
377234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey            case TYPE_WIFI_P2P:
378234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey                return true;
379234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey            default:
380234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey                return false;
381234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey        }
382234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey    }
383234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey
38455a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey    /**
38555a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey     * Check if matches Bluetooth network template.
38655a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey     */
38755a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey    private boolean matchesBluetooth(NetworkIdentity ident) {
38855a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey        if (ident.mType == TYPE_BLUETOOTH) {
38955a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey            return true;
39055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey        }
39155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey        return false;
39255a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey    }
39355a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey
3944e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey    private static String getMatchRuleName(int matchRule) {
3951b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        switch (matchRule) {
3961b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case MATCH_MOBILE_3G_LOWER:
3971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return "MOBILE_3G_LOWER";
3981b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case MATCH_MOBILE_4G:
3991b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return "MOBILE_4G";
4001b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case MATCH_MOBILE_ALL:
4011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return "MOBILE_ALL";
4021b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            case MATCH_WIFI:
4031b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return "WIFI";
4044e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            case MATCH_ETHERNET:
4054e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey                return "ETHERNET";
406234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey            case MATCH_MOBILE_WILDCARD:
407234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey                return "MOBILE_WILDCARD";
408234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey            case MATCH_WIFI_WILDCARD:
409234766a36af6214644fa8205202287084ca9cf93Jeff Sharkey                return "WIFI_WILDCARD";
41055a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey            case MATCH_BLUETOOTH:
41155a442e58262e253df965d652bd8219c8d1e72d3Jeff Sharkey                return "BLUETOOTH";
4121b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            default:
4131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return "UNKNOWN";
4141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
4151b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
4161b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
417d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey    private static void ensureSubtypeAvailable() {
418d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey        if (COMBINE_SUBTYPE_ENABLED) {
419d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey            throw new IllegalArgumentException(
420d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey                    "Unable to enforce 3G_LOWER template on combined data.");
421d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey        }
422d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey    }
423d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey
4243256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    /**
4253256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * Examine the given template and normalize if it refers to a "merged"
4263256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * mobile subscriber. We pick the "lowest" merged subscriber as the primary
4273256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * for key purposes, and expand the template to match all other merged
4283256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * subscribers.
4293256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * <p>
4303256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * For example, given an incoming template matching B, and the currently
4313256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * active merge set [A,B], we'd return a new template that primarily matches
4323256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * A, but also matches B.
4333256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     */
4343256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
4353256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) {
4363256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            // Requested template subscriber is part of the merge group; return
4373256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            // a template that matches all merged subscribers.
4383256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            return new NetworkTemplate(template.mMatchRule, merged[0], merged,
4393256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                    template.mNetworkId);
4403256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        } else {
4413256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            return template;
4423256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        }
4433256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    }
4443256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
4451b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
4468fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        @Override
4471b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        public NetworkTemplate createFromParcel(Parcel in) {
4481b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            return new NetworkTemplate(in);
4491b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
4501b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
4518fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        @Override
4521b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        public NetworkTemplate[] newArray(int size) {
4531b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            return new NetworkTemplate[size];
4541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
4551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    };
456adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
457adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    public byte[] getBytesForBackup() throws IOException {
458adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        ByteArrayOutputStream baos = new ByteArrayOutputStream();
459adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        DataOutputStream out = new DataOutputStream(baos);
460adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
461adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.writeInt(BACKUP_VERSION);
462adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
463adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        out.writeInt(mMatchRule);
464adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        BackupUtils.writeString(out, mSubscriberId);
465adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        BackupUtils.writeString(out, mNetworkId);
466adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
467adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        return baos.toByteArray();
468adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    }
469adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
470adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in)
471adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy            throws IOException, BackupUtils.BadVersionException {
472adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        int version = in.readInt();
473adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        if (version < 1 || version > BACKUP_VERSION) {
474adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy            throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
475adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        }
476adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
477adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        int matchRule = in.readInt();
478adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        String subscriberId = BackupUtils.readString(in);
479adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        String networkId = BackupUtils.readString(in);
480adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy
481adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy        return new NetworkTemplate(matchRule, subscriberId, networkId);
482adca34a0d6b5955f0cbc931dd0834b25fe3759b9Ritesh Reddy    }
4831b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey}
484