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