NetworkIdentity.java revision 6973634ce61ab7d4c1d51c70be6d51725b89e7b9
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
17package android.net;
18
19import static android.net.ConnectivityManager.TYPE_WIFI;
20import static android.net.ConnectivityManager.getNetworkTypeName;
21import static android.net.ConnectivityManager.isNetworkTypeMobile;
22
23import android.content.Context;
24import android.net.wifi.WifiInfo;
25import android.net.wifi.WifiManager;
26import android.os.Build;
27import android.telephony.TelephonyManager;
28import android.util.Slog;
29
30import 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 */
38public 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
59    public NetworkIdentity(
60            int type, int subType, String subscriberId, String networkId, boolean roaming) {
61        mType = type;
62        mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
63        mSubscriberId = subscriberId;
64        mNetworkId = networkId;
65        mRoaming = roaming;
66    }
67
68    @Override
69    public int hashCode() {
70        return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming);
71    }
72
73    @Override
74    public boolean equals(Object obj) {
75        if (obj instanceof NetworkIdentity) {
76            final NetworkIdentity ident = (NetworkIdentity) obj;
77            return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
78                    && Objects.equals(mSubscriberId, ident.mSubscriberId)
79                    && Objects.equals(mNetworkId, ident.mNetworkId);
80        }
81        return false;
82    }
83
84    @Override
85    public String toString() {
86        final StringBuilder builder = new StringBuilder("{");
87        builder.append("type=").append(getNetworkTypeName(mType));
88        builder.append(", subType=");
89        if (COMBINE_SUBTYPE_ENABLED) {
90            builder.append("COMBINED");
91        } else if (ConnectivityManager.isNetworkTypeMobile(mType)) {
92            builder.append(TelephonyManager.getNetworkTypeName(mSubType));
93        } else {
94            builder.append(mSubType);
95        }
96        if (mSubscriberId != null) {
97            builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
98        }
99        if (mNetworkId != null) {
100            builder.append(", networkId=").append(mNetworkId);
101        }
102        if (mRoaming) {
103            builder.append(", ROAMING");
104        }
105        return builder.append("}").toString();
106    }
107
108    public int getType() {
109        return mType;
110    }
111
112    public int getSubType() {
113        return mSubType;
114    }
115
116    public String getSubscriberId() {
117        return mSubscriberId;
118    }
119
120    public String getNetworkId() {
121        return mNetworkId;
122    }
123
124    public boolean getRoaming() {
125        return mRoaming;
126    }
127
128    /**
129     * Scrub given IMSI on production builds.
130     */
131    public static String scrubSubscriberId(String subscriberId) {
132        if ("eng".equals(Build.TYPE)) {
133            return subscriberId;
134        } else if (subscriberId != null) {
135            // TODO: parse this as MCC+MNC instead of hard-coding
136            return subscriberId.substring(0, Math.min(6, subscriberId.length())) + "...";
137        } else {
138            return "null";
139        }
140    }
141
142    /**
143     * Scrub given IMSI on production builds.
144     */
145    public static String[] scrubSubscriberId(String[] subscriberId) {
146        if (subscriberId == null) return null;
147        final String[] res = new String[subscriberId.length];
148        for (int i = 0; i < res.length; i++) {
149            res[i] = NetworkIdentity.scrubSubscriberId(subscriberId[i]);
150        }
151        return res;
152    }
153
154    /**
155     * Build a {@link NetworkIdentity} from the given {@link NetworkState},
156     * assuming that any mobile networks are using the current IMSI.
157     */
158    public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
159        final int type = state.networkInfo.getType();
160        final int subType = state.networkInfo.getSubtype();
161
162        String subscriberId = null;
163        String networkId = null;
164        boolean roaming = false;
165
166        if (isNetworkTypeMobile(type)) {
167            if (state.subscriberId == null) {
168                Slog.w(TAG, "Active mobile network without subscriber!");
169            }
170
171            subscriberId = state.subscriberId;
172            roaming = state.networkInfo.isRoaming();
173
174        } else if (type == TYPE_WIFI) {
175            if (state.networkId != null) {
176                networkId = state.networkId;
177            } else {
178                final WifiManager wifi = (WifiManager) context.getSystemService(
179                        Context.WIFI_SERVICE);
180                final WifiInfo info = wifi.getConnectionInfo();
181                networkId = info != null ? info.getSSID() : null;
182            }
183        }
184
185        return new NetworkIdentity(type, subType, subscriberId, networkId, roaming);
186    }
187
188    @Override
189    public int compareTo(NetworkIdentity another) {
190        int res = Integer.compare(mType, another.mType);
191        if (res == 0) {
192            res = Integer.compare(mSubType, another.mSubType);
193        }
194        if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
195            res = mSubscriberId.compareTo(another.mSubscriberId);
196        }
197        if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
198            res = mNetworkId.compareTo(another.mNetworkId);
199        }
200        if (res == 0) {
201            res = Boolean.compare(mRoaming, another.mRoaming);
202        }
203        return res;
204    }
205}
206