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