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