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