blob: fd118f340119a956a81ac0524a0193bc2f847e43 [file] [log] [blame]
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001/*
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
Jeff Sharkey8fc27e82012-04-04 20:40:58 -070019import static android.net.ConnectivityManager.TYPE_WIFI;
20import static android.net.ConnectivityManager.getNetworkTypeName;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070021import static android.net.ConnectivityManager.isNetworkTypeMobile;
22
23import android.content.Context;
Jeff Sharkey8fc27e82012-04-04 20:40:58 -070024import android.net.wifi.WifiInfo;
25import android.net.wifi.WifiManager;
Jeff Sharkey02e21d62011-07-17 15:53:33 -070026import android.os.Build;
Makoto Onukida65a522017-01-13 10:23:30 -080027import android.service.NetworkIdentityProto;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070028import android.telephony.TelephonyManager;
Jeff Sharkey32566012014-12-02 18:30:14 -080029import android.util.Slog;
Makoto Onukida65a522017-01-13 10:23:30 -080030import android.util.proto.ProtoOutputStream;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070031
Kenny Roote6585b32013-12-13 12:00:26 -080032import java.util.Objects;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070033
34/**
35 * Network definition that includes strong identity. Analogous to combining
36 * {@link NetworkInfo} and an IMSI.
37 *
38 * @hide
39 */
Jeff Sharkey55a442e2014-11-18 18:22:21 -080040public class NetworkIdentity implements Comparable<NetworkIdentity> {
Jeff Sharkey32566012014-12-02 18:30:14 -080041 private static final String TAG = "NetworkIdentity";
42
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -070043 /**
44 * When enabled, combine all {@link #mSubType} together under
45 * {@link #SUBTYPE_COMBINED}.
Jeff Sharkey69736342014-12-08 14:50:12 -080046 *
47 * @deprecated we no longer offer to collect statistics on a per-subtype
48 * basis; this is always disabled.
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -070049 */
Jeff Sharkey69736342014-12-08 14:50:12 -080050 @Deprecated
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -070051 public static final boolean COMBINE_SUBTYPE_ENABLED = true;
52
53 public static final int SUBTYPE_COMBINED = -1;
54
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070055 final int mType;
56 final int mSubType;
57 final String mSubscriberId;
Jeff Sharkey8fc27e82012-04-04 20:40:58 -070058 final String mNetworkId;
Jeff Sharkey5dc0c262011-06-19 22:21:05 -070059 final boolean mRoaming;
Jack Yu66a6be32016-03-30 11:14:39 -070060 final boolean mMetered;
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +090061 final boolean mDefaultNetwork;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070062
Jeff Sharkey8fc27e82012-04-04 20:40:58 -070063 public NetworkIdentity(
Jack Yu66a6be32016-03-30 11:14:39 -070064 int type, int subType, String subscriberId, String networkId, boolean roaming,
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +090065 boolean metered, boolean defaultNetwork) {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -070066 mType = type;
67 mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
68 mSubscriberId = subscriberId;
69 mNetworkId = networkId;
70 mRoaming = roaming;
Jack Yu66a6be32016-03-30 11:14:39 -070071 mMetered = metered;
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +090072 mDefaultNetwork = defaultNetwork;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070073 }
74
75 @Override
76 public int hashCode() {
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +090077 return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered,
78 mDefaultNetwork);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070079 }
80
81 @Override
82 public boolean equals(Object obj) {
83 if (obj instanceof NetworkIdentity) {
84 final NetworkIdentity ident = (NetworkIdentity) obj;
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -070085 return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
Kenny Roote6585b32013-12-13 12:00:26 -080086 && Objects.equals(mSubscriberId, ident.mSubscriberId)
Jack Yu66a6be32016-03-30 11:14:39 -070087 && Objects.equals(mNetworkId, ident.mNetworkId)
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +090088 && mMetered == ident.mMetered
89 && mDefaultNetwork == ident.mDefaultNetwork;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070090 }
91 return false;
92 }
93
94 @Override
95 public String toString() {
Jeff Sharkey55a442e2014-11-18 18:22:21 -080096 final StringBuilder builder = new StringBuilder("{");
Jeff Sharkey8fc27e82012-04-04 20:40:58 -070097 builder.append("type=").append(getNetworkTypeName(mType));
98 builder.append(", subType=");
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -070099 if (COMBINE_SUBTYPE_ENABLED) {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700100 builder.append("COMBINED");
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -0700101 } else if (ConnectivityManager.isNetworkTypeMobile(mType)) {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700102 builder.append(TelephonyManager.getNetworkTypeName(mSubType));
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700103 } else {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700104 builder.append(mSubType);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700105 }
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700106 if (mSubscriberId != null) {
107 builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
108 }
109 if (mNetworkId != null) {
110 builder.append(", networkId=").append(mNetworkId);
111 }
112 if (mRoaming) {
113 builder.append(", ROAMING");
114 }
Jack Yu66a6be32016-03-30 11:14:39 -0700115 builder.append(", metered=").append(mMetered);
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +0900116 builder.append(", defaultNetwork=").append(mDefaultNetwork);
Jeff Sharkey55a442e2014-11-18 18:22:21 -0800117 return builder.append("}").toString();
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700118 }
119
Makoto Onukida65a522017-01-13 10:23:30 -0800120 public void writeToProto(ProtoOutputStream proto, long tag) {
121 final long start = proto.start(tag);
122
123 proto.write(NetworkIdentityProto.TYPE, mType);
124
125 // Not dumping mSubType, subtypes are no longer supported.
126
127 if (mSubscriberId != null) {
128 proto.write(NetworkIdentityProto.SUBSCRIBER_ID, scrubSubscriberId(mSubscriberId));
129 }
130 proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId);
131 proto.write(NetworkIdentityProto.ROAMING, mRoaming);
132 proto.write(NetworkIdentityProto.METERED, mMetered);
133
134 proto.end(start);
135 }
136
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700137 public int getType() {
138 return mType;
139 }
140
141 public int getSubType() {
142 return mSubType;
143 }
144
145 public String getSubscriberId() {
146 return mSubscriberId;
147 }
148
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700149 public String getNetworkId() {
150 return mNetworkId;
151 }
152
Jeff Sharkey5dc0c262011-06-19 22:21:05 -0700153 public boolean getRoaming() {
154 return mRoaming;
155 }
156
Jack Yu66a6be32016-03-30 11:14:39 -0700157 public boolean getMetered() {
158 return mMetered;
159 }
160
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +0900161 public boolean getDefaultNetwork() {
162 return mDefaultNetwork;
163 }
164
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700165 /**
Jeff Sharkey02e21d62011-07-17 15:53:33 -0700166 * Scrub given IMSI on production builds.
167 */
168 public static String scrubSubscriberId(String subscriberId) {
Jeff Sharkey5ab02432017-06-27 11:01:36 -0600169 if (Build.IS_ENG) {
Jeff Sharkey02e21d62011-07-17 15:53:33 -0700170 return subscriberId;
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700171 } else if (subscriberId != null) {
172 // TODO: parse this as MCC+MNC instead of hard-coding
173 return subscriberId.substring(0, Math.min(6, subscriberId.length())) + "...";
Jeff Sharkey02e21d62011-07-17 15:53:33 -0700174 } else {
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700175 return "null";
Jeff Sharkey02e21d62011-07-17 15:53:33 -0700176 }
177 }
178
179 /**
Jeff Sharkey32566012014-12-02 18:30:14 -0800180 * Scrub given IMSI on production builds.
181 */
182 public static String[] scrubSubscriberId(String[] subscriberId) {
183 if (subscriberId == null) return null;
184 final String[] res = new String[subscriberId.length];
185 for (int i = 0; i < res.length; i++) {
186 res[i] = NetworkIdentity.scrubSubscriberId(subscriberId[i]);
187 }
188 return res;
189 }
190
191 /**
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700192 * Build a {@link NetworkIdentity} from the given {@link NetworkState},
193 * assuming that any mobile networks are using the current IMSI.
194 */
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +0900195 public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state,
196 boolean defaultNetwork) {
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700197 final int type = state.networkInfo.getType();
198 final int subType = state.networkInfo.getSubtype();
199
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700200 String subscriberId = null;
201 String networkId = null;
Jeff Sharkey72f9c422017-10-27 17:22:59 -0600202 boolean roaming = !state.networkCapabilities.hasCapability(
203 NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
Stephen Chen25147872016-10-21 12:44:26 -0700204 boolean metered = !state.networkCapabilities.hasCapability(
205 NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700206
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700207 if (isNetworkTypeMobile(type)) {
Jeff Sharkey32566012014-12-02 18:30:14 -0800208 if (state.subscriberId == null) {
Jack Yubfd1d6e2016-08-23 16:09:36 -0700209 if (state.networkInfo.getState() != NetworkInfo.State.DISCONNECTED &&
210 state.networkInfo.getState() != NetworkInfo.State.UNKNOWN) {
211 Slog.w(TAG, "Active mobile network without subscriber! ni = "
212 + state.networkInfo);
213 }
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700214 }
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700215
Jeff Sharkey32566012014-12-02 18:30:14 -0800216 subscriberId = state.subscriberId;
Jeff Sharkey32566012014-12-02 18:30:14 -0800217
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700218 } else if (type == TYPE_WIFI) {
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700219 if (state.networkId != null) {
220 networkId = state.networkId;
221 } else {
222 final WifiManager wifi = (WifiManager) context.getSystemService(
223 Context.WIFI_SERVICE);
224 final WifiInfo info = wifi.getConnectionInfo();
225 networkId = info != null ? info.getSSID() : null;
226 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700227 }
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700228
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +0900229 return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered,
230 defaultNetwork);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700231 }
Jeff Sharkey55a442e2014-11-18 18:22:21 -0800232
233 @Override
234 public int compareTo(NetworkIdentity another) {
235 int res = Integer.compare(mType, another.mType);
236 if (res == 0) {
237 res = Integer.compare(mSubType, another.mSubType);
238 }
239 if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
240 res = mSubscriberId.compareTo(another.mSubscriberId);
241 }
242 if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
243 res = mNetworkId.compareTo(another.mNetworkId);
244 }
245 if (res == 0) {
246 res = Boolean.compare(mRoaming, another.mRoaming);
247 }
Jack Yu66a6be32016-03-30 11:14:39 -0700248 if (res == 0) {
249 res = Boolean.compare(mMetered, another.mMetered);
250 }
Lorenzo Colittid3e4a1e2018-01-19 01:12:04 +0900251 if (res == 0) {
252 res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork);
253 }
Jeff Sharkey55a442e2014-11-18 18:22:21 -0800254 return res;
255 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700256}