2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 import static android.net.ConnectivityManager.TYPE_WIFI;
20 import static android.net.ConnectivityManager.getNetworkTypeName;
21 import static android.net.ConnectivityManager.isNetworkTypeMobile;
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;
30 import java.util.Objects;
33 * Network definition that includes strong identity. Analogous to combining
34 * {@link NetworkInfo} and an IMSI.
38 public class NetworkIdentity implements Comparable<NetworkIdentity> {
39 private static final String TAG = "NetworkIdentity";
42 * When enabled, combine all {@link #mSubType} together under
43 * {@link #SUBTYPE_COMBINED}.
45 * @deprecated we no longer offer to collect statistics on a per-subtype
46 * basis; this is always disabled.
49 public static final boolean COMBINE_SUBTYPE_ENABLED = true;
51 public static final int SUBTYPE_COMBINED = -1;
55 final String mSubscriberId;
56 final String mNetworkId;
57 final boolean mRoaming;
58 final boolean mMetered;
60 public NetworkIdentity(
61 int type, int subType, String subscriberId, String networkId, boolean roaming,
64 mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
65 mSubscriberId = subscriberId;
66 mNetworkId = networkId;
72 public int hashCode() {
73 return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered);
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;
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));
98 builder.append(mSubType);
100 if (mSubscriberId != null) {
101 builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
103 if (mNetworkId != null) {
104 builder.append(", networkId=").append(mNetworkId);
107 builder.append(", ROAMING");
109 builder.append(", metered=").append(mMetered);
110 return builder.append("}").toString();
113 public int getType() {
117 public int getSubType() {
121 public String getSubscriberId() {
122 return mSubscriberId;
125 public String getNetworkId() {
129 public boolean getRoaming() {
133 public boolean getMetered() {
138 * Scrub given IMSI on production builds.
140 public static String scrubSubscriberId(String subscriberId) {
141 if ("eng".equals(Build.TYPE)) {
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())) + "...";
152 * Scrub given IMSI on production builds.
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]);
164 * Build a {@link NetworkIdentity} from the given {@link NetworkState},
165 * assuming that any mobile networks are using the current IMSI.
167 public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
168 final int type = state.networkInfo.getType();
169 final int subType = state.networkInfo.getSubtype();
171 String subscriberId = null;
172 String networkId = null;
173 boolean roaming = false;
174 boolean metered = false;
176 if (isNetworkTypeMobile(type)) {
177 if (state.subscriberId == null) {
178 Slog.w(TAG, "Active mobile network without subscriber!");
181 subscriberId = state.subscriberId;
182 roaming = state.networkInfo.isRoaming();
184 metered = !state.networkCapabilities.hasCapability(
185 NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
187 } else if (type == TYPE_WIFI) {
188 if (state.networkId != null) {
189 networkId = state.networkId;
191 final WifiManager wifi = (WifiManager) context.getSystemService(
192 Context.WIFI_SERVICE);
193 final WifiInfo info = wifi.getConnectionInfo();
194 networkId = info != null ? info.getSSID() : null;
198 return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered);
202 public int compareTo(NetworkIdentity another) {
203 int res = Integer.compare(mType, another.mType);
205 res = Integer.compare(mSubType, another.mSubType);
207 if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
208 res = mSubscriberId.compareTo(another.mSubscriberId);
210 if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
211 res = mNetworkId.compareTo(another.mNetworkId);
214 res = Boolean.compare(mRoaming, another.mRoaming);
217 res = Boolean.compare(mMetered, another.mMetered);