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_WIFI;
     20 import static android.net.ConnectivityManager.getNetworkTypeName;
     21 import static android.net.ConnectivityManager.isNetworkTypeMobile;
     22 
     23 import android.content.Context;
     24 import android.net.wifi.WifiInfo;
     25 import android.net.wifi.WifiManager;
     26 import android.os.Build;
     27 import android.telephony.TelephonyManager;
     28 import android.util.Slog;
     29 
     30 import java.util.Objects;
     31 
     32 /**
     33  * Network definition that includes strong identity. Analogous to combining
     34  * {@link NetworkInfo} and an IMSI.
     35  *
     36  * @hide
     37  */
     38 public class NetworkIdentity implements Comparable<NetworkIdentity> {
     39     private static final String TAG = "NetworkIdentity";
     40 
     41     /**
     42      * When enabled, combine all {@link #mSubType} together under
     43      * {@link #SUBTYPE_COMBINED}.
     44      *
     45      * @deprecated we no longer offer to collect statistics on a per-subtype
     46      *             basis; this is always disabled.
     47      */
     48     @Deprecated
     49     public static final boolean COMBINE_SUBTYPE_ENABLED = true;
     50 
     51     public static final int SUBTYPE_COMBINED = -1;
     52 
     53     final int mType;
     54     final int mSubType;
     55     final String mSubscriberId;
     56     final String mNetworkId;
     57     final boolean mRoaming;
     58     final boolean mMetered;
     59 
     60     public NetworkIdentity(
     61             int type, int subType, String subscriberId, String networkId, boolean roaming,
     62             boolean metered) {
     63         mType = type;
     64         mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
     65         mSubscriberId = subscriberId;
     66         mNetworkId = networkId;
     67         mRoaming = roaming;
     68         mMetered = metered;
     69     }
     70 
     71     @Override
     72     public int hashCode() {
     73         return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered);
     74     }
     75 
     76     @Override
     77     public boolean equals(Object obj) {
     78         if (obj instanceof NetworkIdentity) {
     79             final NetworkIdentity ident = (NetworkIdentity) obj;
     80             return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
     81                     && Objects.equals(mSubscriberId, ident.mSubscriberId)
     82                     && Objects.equals(mNetworkId, ident.mNetworkId)
     83                     && mMetered == ident.mMetered;
     84         }
     85         return false;
     86     }
     87 
     88     @Override
     89     public String toString() {
     90         final StringBuilder builder = new StringBuilder("{");
     91         builder.append("type=").append(getNetworkTypeName(mType));
     92         builder.append(", subType=");
     93         if (COMBINE_SUBTYPE_ENABLED) {
     94             builder.append("COMBINED");
     95         } else if (ConnectivityManager.isNetworkTypeMobile(mType)) {
     96             builder.append(TelephonyManager.getNetworkTypeName(mSubType));
     97         } else {
     98             builder.append(mSubType);
     99         }
    100         if (mSubscriberId != null) {
    101             builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
    102         }
    103         if (mNetworkId != null) {
    104             builder.append(", networkId=").append(mNetworkId);
    105         }
    106         if (mRoaming) {
    107             builder.append(", ROAMING");
    108         }
    109         builder.append(", metered=").append(mMetered);
    110         return builder.append("}").toString();
    111     }
    112 
    113     public int getType() {
    114         return mType;
    115     }
    116 
    117     public int getSubType() {
    118         return mSubType;
    119     }
    120 
    121     public String getSubscriberId() {
    122         return mSubscriberId;
    123     }
    124 
    125     public String getNetworkId() {
    126         return mNetworkId;
    127     }
    128 
    129     public boolean getRoaming() {
    130         return mRoaming;
    131     }
    132 
    133     public boolean getMetered() {
    134         return mMetered;
    135     }
    136 
    137     /**
    138      * Scrub given IMSI on production builds.
    139      */
    140     public static String scrubSubscriberId(String subscriberId) {
    141         if ("eng".equals(Build.TYPE)) {
    142             return subscriberId;
    143         } else if (subscriberId != null) {
    144             // TODO: parse this as MCC+MNC instead of hard-coding
    145             return subscriberId.substring(0, Math.min(6, subscriberId.length())) + "...";
    146         } else {
    147             return "null";
    148         }
    149     }
    150 
    151     /**
    152      * Scrub given IMSI on production builds.
    153      */
    154     public static String[] scrubSubscriberId(String[] subscriberId) {
    155         if (subscriberId == null) return null;
    156         final String[] res = new String[subscriberId.length];
    157         for (int i = 0; i < res.length; i++) {
    158             res[i] = NetworkIdentity.scrubSubscriberId(subscriberId[i]);
    159         }
    160         return res;
    161     }
    162 
    163     /**
    164      * Build a {@link NetworkIdentity} from the given {@link NetworkState},
    165      * assuming that any mobile networks are using the current IMSI.
    166      */
    167     public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
    168         final int type = state.networkInfo.getType();
    169         final int subType = state.networkInfo.getSubtype();
    170 
    171         String subscriberId = null;
    172         String networkId = null;
    173         boolean roaming = false;
    174         boolean metered = false;
    175 
    176         if (isNetworkTypeMobile(type)) {
    177             if (state.subscriberId == null) {
    178                 Slog.w(TAG, "Active mobile network without subscriber!");
    179             }
    180 
    181             subscriberId = state.subscriberId;
    182             roaming = state.networkInfo.isRoaming();
    183 
    184             metered = !state.networkCapabilities.hasCapability(
    185                     NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
    186 
    187         } else if (type == TYPE_WIFI) {
    188             if (state.networkId != null) {
    189                 networkId = state.networkId;
    190             } else {
    191                 final WifiManager wifi = (WifiManager) context.getSystemService(
    192                         Context.WIFI_SERVICE);
    193                 final WifiInfo info = wifi.getConnectionInfo();
    194                 networkId = info != null ? info.getSSID() : null;
    195             }
    196         }
    197 
    198         return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered);
    199     }
    200 
    201     @Override
    202     public int compareTo(NetworkIdentity another) {
    203         int res = Integer.compare(mType, another.mType);
    204         if (res == 0) {
    205             res = Integer.compare(mSubType, another.mSubType);
    206         }
    207         if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
    208             res = mSubscriberId.compareTo(another.mSubscriberId);
    209         }
    210         if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
    211             res = mNetworkId.compareTo(another.mNetworkId);
    212         }
    213         if (res == 0) {
    214             res = Boolean.compare(mRoaming, another.mRoaming);
    215         }
    216         if (res == 0) {
    217             res = Boolean.compare(mMetered, another.mMetered);
    218         }
    219         return res;
    220     }
    221 }
    222