Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net;
     18 
     19 import static android.net.ConnectivityManager.TYPE_ETHERNET;
     20 import static android.net.ConnectivityManager.TYPE_WIFI;
     21 import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
     22 import static android.net.ConnectivityManager.TYPE_WIMAX;
     23 import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
     24 import static android.net.NetworkIdentity.scrubSubscriberId;
     25 import static android.net.wifi.WifiInfo.removeDoubleQuotes;
     26 import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
     27 import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
     28 import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
     29 import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
     30 import static android.telephony.TelephonyManager.getNetworkClass;
     31 import static com.android.internal.util.ArrayUtils.contains;
     32 
     33 import android.content.res.Resources;
     34 import android.os.Parcel;
     35 import android.os.Parcelable;
     36 
     37 import com.android.internal.annotations.VisibleForTesting;
     38 import com.android.internal.util.Objects;
     39 
     40 /**
     41  * Template definition used to generically match {@link NetworkIdentity},
     42  * usually when collecting statistics.
     43  *
     44  * @hide
     45  */
     46 public class NetworkTemplate implements Parcelable {
     47 
     48     public static final int MATCH_MOBILE_ALL = 1;
     49     public static final int MATCH_MOBILE_3G_LOWER = 2;
     50     public static final int MATCH_MOBILE_4G = 3;
     51     public static final int MATCH_WIFI = 4;
     52     public static final int MATCH_ETHERNET = 5;
     53     public static final int MATCH_MOBILE_WILDCARD = 6;
     54     public static final int MATCH_WIFI_WILDCARD = 7;
     55 
     56     /**
     57      * Set of {@link NetworkInfo#getType()} that reflect data usage.
     58      */
     59     private static final int[] DATA_USAGE_NETWORK_TYPES;
     60 
     61     static {
     62         DATA_USAGE_NETWORK_TYPES = Resources.getSystem().getIntArray(
     63                 com.android.internal.R.array.config_data_usage_network_types);
     64     }
     65 
     66     private static boolean sForceAllNetworkTypes = false;
     67 
     68     @VisibleForTesting
     69     public static void forceAllNetworkTypes() {
     70         sForceAllNetworkTypes = true;
     71     }
     72 
     73     /**
     74      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
     75      * the given IMSI.
     76      */
     77     public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
     78         return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId, null);
     79     }
     80 
     81     /**
     82      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
     83      * the given IMSI that roughly meet a "3G" definition, or lower.
     84      */
     85     @Deprecated
     86     public static NetworkTemplate buildTemplateMobile3gLower(String subscriberId) {
     87         return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId, null);
     88     }
     89 
     90     /**
     91      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
     92      * the given IMSI that roughly meet a "4G" definition.
     93      */
     94     @Deprecated
     95     public static NetworkTemplate buildTemplateMobile4g(String subscriberId) {
     96         return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null);
     97     }
     98 
     99     /**
    100      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
    101      * regardless of IMSI.
    102      */
    103     public static NetworkTemplate buildTemplateMobileWildcard() {
    104         return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
    105     }
    106 
    107     /**
    108      * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
    109      * regardless of SSID.
    110      */
    111     public static NetworkTemplate buildTemplateWifiWildcard() {
    112         return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
    113     }
    114 
    115     @Deprecated
    116     public static NetworkTemplate buildTemplateWifi() {
    117         return buildTemplateWifiWildcard();
    118     }
    119 
    120     /**
    121      * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
    122      * given SSID.
    123      */
    124     public static NetworkTemplate buildTemplateWifi(String networkId) {
    125         return new NetworkTemplate(MATCH_WIFI, null, networkId);
    126     }
    127 
    128     /**
    129      * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
    130      * networks together.
    131      */
    132     public static NetworkTemplate buildTemplateEthernet() {
    133         return new NetworkTemplate(MATCH_ETHERNET, null, null);
    134     }
    135 
    136     private final int mMatchRule;
    137     private final String mSubscriberId;
    138     private final String mNetworkId;
    139 
    140     public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
    141         mMatchRule = matchRule;
    142         mSubscriberId = subscriberId;
    143         mNetworkId = networkId;
    144     }
    145 
    146     private NetworkTemplate(Parcel in) {
    147         mMatchRule = in.readInt();
    148         mSubscriberId = in.readString();
    149         mNetworkId = in.readString();
    150     }
    151 
    152     @Override
    153     public void writeToParcel(Parcel dest, int flags) {
    154         dest.writeInt(mMatchRule);
    155         dest.writeString(mSubscriberId);
    156         dest.writeString(mNetworkId);
    157     }
    158 
    159     @Override
    160     public int describeContents() {
    161         return 0;
    162     }
    163 
    164     @Override
    165     public String toString() {
    166         final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
    167         builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
    168         if (mSubscriberId != null) {
    169             builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
    170         }
    171         if (mNetworkId != null) {
    172             builder.append(", networkId=").append(mNetworkId);
    173         }
    174         return builder.toString();
    175     }
    176 
    177     @Override
    178     public int hashCode() {
    179         return Objects.hashCode(mMatchRule, mSubscriberId, mNetworkId);
    180     }
    181 
    182     @Override
    183     public boolean equals(Object obj) {
    184         if (obj instanceof NetworkTemplate) {
    185             final NetworkTemplate other = (NetworkTemplate) obj;
    186             return mMatchRule == other.mMatchRule
    187                     && Objects.equal(mSubscriberId, other.mSubscriberId)
    188                     && Objects.equal(mNetworkId, other.mNetworkId);
    189         }
    190         return false;
    191     }
    192 
    193     public int getMatchRule() {
    194         return mMatchRule;
    195     }
    196 
    197     public String getSubscriberId() {
    198         return mSubscriberId;
    199     }
    200 
    201     public String getNetworkId() {
    202         return mNetworkId;
    203     }
    204 
    205     /**
    206      * Test if given {@link NetworkIdentity} matches this template.
    207      */
    208     public boolean matches(NetworkIdentity ident) {
    209         switch (mMatchRule) {
    210             case MATCH_MOBILE_ALL:
    211                 return matchesMobile(ident);
    212             case MATCH_MOBILE_3G_LOWER:
    213                 return matchesMobile3gLower(ident);
    214             case MATCH_MOBILE_4G:
    215                 return matchesMobile4g(ident);
    216             case MATCH_WIFI:
    217                 return matchesWifi(ident);
    218             case MATCH_ETHERNET:
    219                 return matchesEthernet(ident);
    220             case MATCH_MOBILE_WILDCARD:
    221                 return matchesMobileWildcard(ident);
    222             case MATCH_WIFI_WILDCARD:
    223                 return matchesWifiWildcard(ident);
    224             default:
    225                 throw new IllegalArgumentException("unknown network template");
    226         }
    227     }
    228 
    229     /**
    230      * Check if mobile network with matching IMSI.
    231      */
    232     private boolean matchesMobile(NetworkIdentity ident) {
    233         if (ident.mType == TYPE_WIMAX) {
    234             // TODO: consider matching against WiMAX subscriber identity
    235             return true;
    236         } else {
    237             return ((sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType))
    238                     && Objects.equal(mSubscriberId, ident.mSubscriberId));
    239         }
    240     }
    241 
    242     /**
    243      * Check if mobile network classified 3G or lower with matching IMSI.
    244      */
    245     private boolean matchesMobile3gLower(NetworkIdentity ident) {
    246         ensureSubtypeAvailable();
    247         if (ident.mType == TYPE_WIMAX) {
    248             return false;
    249         } else if (matchesMobile(ident)) {
    250             switch (getNetworkClass(ident.mSubType)) {
    251                 case NETWORK_CLASS_UNKNOWN:
    252                 case NETWORK_CLASS_2_G:
    253                 case NETWORK_CLASS_3_G:
    254                     return true;
    255             }
    256         }
    257         return false;
    258     }
    259 
    260     /**
    261      * Check if mobile network classified 4G with matching IMSI.
    262      */
    263     private boolean matchesMobile4g(NetworkIdentity ident) {
    264         ensureSubtypeAvailable();
    265         if (ident.mType == TYPE_WIMAX) {
    266             // TODO: consider matching against WiMAX subscriber identity
    267             return true;
    268         } else if (matchesMobile(ident)) {
    269             switch (getNetworkClass(ident.mSubType)) {
    270                 case NETWORK_CLASS_4_G:
    271                     return true;
    272             }
    273         }
    274         return false;
    275     }
    276 
    277     /**
    278      * Check if matches Wi-Fi network template.
    279      */
    280     private boolean matchesWifi(NetworkIdentity ident) {
    281         switch (ident.mType) {
    282             case TYPE_WIFI:
    283                 return Objects.equal(
    284                         removeDoubleQuotes(mNetworkId), removeDoubleQuotes(ident.mNetworkId));
    285             default:
    286                 return false;
    287         }
    288     }
    289 
    290     /**
    291      * Check if matches Ethernet network template.
    292      */
    293     private boolean matchesEthernet(NetworkIdentity ident) {
    294         if (ident.mType == TYPE_ETHERNET) {
    295             return true;
    296         }
    297         return false;
    298     }
    299 
    300     private boolean matchesMobileWildcard(NetworkIdentity ident) {
    301         if (ident.mType == TYPE_WIMAX) {
    302             return true;
    303         } else {
    304             return sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType);
    305         }
    306     }
    307 
    308     private boolean matchesWifiWildcard(NetworkIdentity ident) {
    309         switch (ident.mType) {
    310             case TYPE_WIFI:
    311             case TYPE_WIFI_P2P:
    312                 return true;
    313             default:
    314                 return false;
    315         }
    316     }
    317 
    318     private static String getMatchRuleName(int matchRule) {
    319         switch (matchRule) {
    320             case MATCH_MOBILE_3G_LOWER:
    321                 return "MOBILE_3G_LOWER";
    322             case MATCH_MOBILE_4G:
    323                 return "MOBILE_4G";
    324             case MATCH_MOBILE_ALL:
    325                 return "MOBILE_ALL";
    326             case MATCH_WIFI:
    327                 return "WIFI";
    328             case MATCH_ETHERNET:
    329                 return "ETHERNET";
    330             case MATCH_MOBILE_WILDCARD:
    331                 return "MOBILE_WILDCARD";
    332             case MATCH_WIFI_WILDCARD:
    333                 return "WIFI_WILDCARD";
    334             default:
    335                 return "UNKNOWN";
    336         }
    337     }
    338 
    339     private static void ensureSubtypeAvailable() {
    340         if (COMBINE_SUBTYPE_ENABLED) {
    341             throw new IllegalArgumentException(
    342                     "Unable to enforce 3G_LOWER template on combined data.");
    343         }
    344     }
    345 
    346     public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
    347         @Override
    348         public NetworkTemplate createFromParcel(Parcel in) {
    349             return new NetworkTemplate(in);
    350         }
    351 
    352         @Override
    353         public NetworkTemplate[] newArray(int size) {
    354             return new NetworkTemplate[size];
    355         }
    356     };
    357 }
    358