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