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_BLUETOOTH; 20 import static android.net.ConnectivityManager.TYPE_ETHERNET; 21 import static android.net.ConnectivityManager.TYPE_MOBILE; 22 import static android.net.ConnectivityManager.TYPE_PROXY; 23 import static android.net.ConnectivityManager.TYPE_WIFI; 24 import static android.net.ConnectivityManager.TYPE_WIFI_P2P; 25 import static android.net.ConnectivityManager.TYPE_WIMAX; 26 import static android.net.NetworkIdentity.OEM_NONE; 27 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; 28 import static android.net.NetworkStats.DEFAULT_NETWORK_NO; 29 import static android.net.NetworkStats.DEFAULT_NETWORK_YES; 30 import static android.net.NetworkStats.METERED_ALL; 31 import static android.net.NetworkStats.METERED_NO; 32 import static android.net.NetworkStats.METERED_YES; 33 import static android.net.NetworkStats.ROAMING_ALL; 34 import static android.net.NetworkStats.ROAMING_NO; 35 import static android.net.NetworkStats.ROAMING_YES; 36 import static android.net.wifi.WifiInfo.sanitizeSsid; 37 38 import android.annotation.NonNull; 39 import android.annotation.Nullable; 40 import android.compat.annotation.UnsupportedAppUsage; 41 import android.os.Build; 42 import android.os.Parcel; 43 import android.os.Parcelable; 44 import android.telephony.Annotation.NetworkType; 45 import android.telephony.TelephonyManager; 46 import android.text.TextUtils; 47 import android.util.BackupUtils; 48 import android.util.Log; 49 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.util.ArrayUtils; 52 import com.android.net.module.util.NetworkIdentityUtils; 53 54 import java.io.ByteArrayOutputStream; 55 import java.io.DataInputStream; 56 import java.io.DataOutputStream; 57 import java.io.IOException; 58 import java.util.Arrays; 59 import java.util.Collection; 60 import java.util.HashSet; 61 import java.util.List; 62 import java.util.Objects; 63 64 /** 65 * Predicate used to match {@link NetworkIdentity}, usually when collecting 66 * statistics. (It should probably have been named {@code NetworkPredicate}.) 67 * 68 * @hide 69 */ 70 public class NetworkTemplate implements Parcelable { 71 private static final String TAG = "NetworkTemplate"; 72 73 /** 74 * Current Version of the Backup Serializer. 75 */ 76 private static final int BACKUP_VERSION = 1; 77 78 public static final int MATCH_MOBILE = 1; 79 public static final int MATCH_WIFI = 4; 80 public static final int MATCH_ETHERNET = 5; 81 public static final int MATCH_MOBILE_WILDCARD = 6; 82 public static final int MATCH_WIFI_WILDCARD = 7; 83 public static final int MATCH_BLUETOOTH = 8; 84 public static final int MATCH_PROXY = 9; 85 public static final int MATCH_CARRIER = 10; 86 87 /** 88 * Value of the match rule of the subscriberId to match networks with specific subscriberId. 89 */ 90 public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0; 91 /** 92 * Value of the match rule of the subscriberId to match networks with any subscriberId which 93 * includes null and non-null. 94 */ 95 public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1; 96 97 /** 98 * Wi-Fi Network ID is never supposed to be null (if it is, it is a bug that 99 * should be fixed), so it's not possible to want to match null vs 100 * non-null. Therefore it's fine to use null as a sentinel for Network ID. 101 */ 102 public static final String WIFI_NETWORKID_ALL = null; 103 104 /** 105 * Include all network types when filtering. This is meant to merge in with the 106 * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. 107 * 108 * @hide 109 */ 110 public static final int NETWORK_TYPE_ALL = -1; 111 /** 112 * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is 113 * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along 114 * with NR state as connected. This should not be overlapped with any of the 115 * {@code TelephonyManager.NETWORK_TYPE_*} constants. 116 * 117 * @hide 118 */ 119 public static final int NETWORK_TYPE_5G_NSA = -2; 120 121 /** 122 * Value to match both OEM managed and unmanaged networks (all networks). 123 * @hide 124 */ 125 public static final int OEM_MANAGED_ALL = -1; 126 /** 127 * Value to match networks which are not OEM managed. 128 * @hide 129 */ 130 public static final int OEM_MANAGED_NO = OEM_NONE; 131 /** 132 * Value to match any OEM managed network. 133 * @hide 134 */ 135 public static final int OEM_MANAGED_YES = -2; 136 isKnownMatchRule(final int rule)137 private static boolean isKnownMatchRule(final int rule) { 138 switch (rule) { 139 case MATCH_MOBILE: 140 case MATCH_WIFI: 141 case MATCH_ETHERNET: 142 case MATCH_MOBILE_WILDCARD: 143 case MATCH_WIFI_WILDCARD: 144 case MATCH_BLUETOOTH: 145 case MATCH_PROXY: 146 case MATCH_CARRIER: 147 return true; 148 149 default: 150 return false; 151 } 152 } 153 154 private static boolean sForceAllNetworkTypes = false; 155 156 /** 157 * Results in matching against all mobile network types. 158 * 159 * <p>See {@link #matchesMobile} and {@link matchesMobileWildcard}. 160 */ 161 @VisibleForTesting forceAllNetworkTypes()162 public static void forceAllNetworkTypes() { 163 sForceAllNetworkTypes = true; 164 } 165 166 /** Resets the affect of {@link #forceAllNetworkTypes}. */ 167 @VisibleForTesting resetForceAllNetworkTypes()168 public static void resetForceAllNetworkTypes() { 169 sForceAllNetworkTypes = false; 170 } 171 172 /** 173 * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with 174 * the given IMSI. 175 */ 176 @UnsupportedAppUsage buildTemplateMobileAll(String subscriberId)177 public static NetworkTemplate buildTemplateMobileAll(String subscriberId) { 178 return new NetworkTemplate(MATCH_MOBILE, subscriberId, null); 179 } 180 181 /** 182 * Template to match cellular networks with the given IMSI and {@code ratType}. 183 * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering. 184 * See {@code TelephonyManager.NETWORK_TYPE_*}. 185 */ buildTemplateMobileWithRatType(@ullable String subscriberId, @NetworkType int ratType)186 public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, 187 @NetworkType int ratType) { 188 if (TextUtils.isEmpty(subscriberId)) { 189 return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, 190 METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, 191 SUBSCRIBER_ID_MATCH_RULE_EXACT); 192 } 193 return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, 194 METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, 195 SUBSCRIBER_ID_MATCH_RULE_EXACT); 196 } 197 198 /** 199 * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, 200 * regardless of IMSI. 201 */ 202 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) buildTemplateMobileWildcard()203 public static NetworkTemplate buildTemplateMobileWildcard() { 204 return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); 205 } 206 207 /** 208 * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks, 209 * regardless of SSID. 210 */ 211 @UnsupportedAppUsage buildTemplateWifiWildcard()212 public static NetworkTemplate buildTemplateWifiWildcard() { 213 // TODO: Consider replace this with MATCH_WIFI with NETWORK_ID_ALL 214 // and SUBSCRIBER_ID_MATCH_RULE_ALL. 215 return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null); 216 } 217 218 @Deprecated 219 @UnsupportedAppUsage buildTemplateWifi()220 public static NetworkTemplate buildTemplateWifi() { 221 return buildTemplateWifiWildcard(); 222 } 223 224 /** 225 * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the 226 * given SSID. 227 */ buildTemplateWifi(@onNull String networkId)228 public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) { 229 Objects.requireNonNull(networkId); 230 return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */, 231 new String[] { null } /* matchSubscriberIds */, 232 networkId, METERED_ALL, ROAMING_ALL, 233 DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, 234 SUBSCRIBER_ID_MATCH_RULE_ALL); 235 } 236 237 /** 238 * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID, 239 * and IMSI. 240 * 241 * Call with {@link #WIFI_NETWORKID_ALL} for {@code networkId} to get result regardless of SSID. 242 */ buildTemplateWifi(@ullable String networkId, @Nullable String subscriberId)243 public static NetworkTemplate buildTemplateWifi(@Nullable String networkId, 244 @Nullable String subscriberId) { 245 return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId }, 246 networkId, METERED_ALL, ROAMING_ALL, 247 DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, 248 SUBSCRIBER_ID_MATCH_RULE_EXACT); 249 } 250 251 /** 252 * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style 253 * networks together. 254 */ 255 @UnsupportedAppUsage buildTemplateEthernet()256 public static NetworkTemplate buildTemplateEthernet() { 257 return new NetworkTemplate(MATCH_ETHERNET, null, null); 258 } 259 260 /** 261 * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style 262 * networks together. 263 */ buildTemplateBluetooth()264 public static NetworkTemplate buildTemplateBluetooth() { 265 return new NetworkTemplate(MATCH_BLUETOOTH, null, null); 266 } 267 268 /** 269 * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style 270 * networks together. 271 */ buildTemplateProxy()272 public static NetworkTemplate buildTemplateProxy() { 273 return new NetworkTemplate(MATCH_PROXY, null, null); 274 } 275 276 /** 277 * Template to match all metered carrier networks with the given IMSI. 278 */ buildTemplateCarrierMetered(@onNull String subscriberId)279 public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) { 280 Objects.requireNonNull(subscriberId); 281 return new NetworkTemplate(MATCH_CARRIER, subscriberId, 282 new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL, 283 DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, 284 SUBSCRIBER_ID_MATCH_RULE_EXACT); 285 } 286 287 private final int mMatchRule; 288 private final String mSubscriberId; 289 290 /** 291 * Ugh, templates are designed to target a single subscriber, but we might 292 * need to match several "merged" subscribers. These are the subscribers 293 * that should be considered to match this template. 294 * <p> 295 * Since the merge set is dynamic, it should <em>not</em> be persisted or 296 * used for determining equality. 297 */ 298 private final String[] mMatchSubscriberIds; 299 300 private final String mNetworkId; 301 302 // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. 303 private final int mMetered; 304 private final int mRoaming; 305 private final int mDefaultNetwork; 306 private final int mSubType; 307 private final int mSubscriberIdMatchRule; 308 309 // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}. 310 private final int mOemManaged; 311 checkValidSubscriberIdMatchRule()312 private void checkValidSubscriberIdMatchRule() { 313 switch (mMatchRule) { 314 case MATCH_MOBILE: 315 case MATCH_CARRIER: 316 // MOBILE and CARRIER templates must always specify a subscriber ID. 317 if (mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { 318 throw new IllegalArgumentException("Invalid SubscriberIdMatchRule" 319 + "on match rule: " + getMatchRuleName(mMatchRule)); 320 } 321 return; 322 default: 323 return; 324 } 325 } 326 327 @UnsupportedAppUsage NetworkTemplate(int matchRule, String subscriberId, String networkId)328 public NetworkTemplate(int matchRule, String subscriberId, String networkId) { 329 this(matchRule, subscriberId, new String[] { subscriberId }, networkId); 330 } 331 NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId)332 public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, 333 String networkId) { 334 this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, 335 DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, 336 SUBSCRIBER_ID_MATCH_RULE_EXACT); 337 } 338 339 // TODO: Remove it after updating all of the caller. NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId, int metered, int roaming, int defaultNetwork, int subType, int oemManaged)340 public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, 341 String networkId, int metered, int roaming, int defaultNetwork, int subType, 342 int oemManaged) { 343 this(matchRule, subscriberId, matchSubscriberIds, networkId, metered, roaming, 344 defaultNetwork, subType, oemManaged, SUBSCRIBER_ID_MATCH_RULE_EXACT); 345 } 346 NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId, int metered, int roaming, int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule)347 public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, 348 String networkId, int metered, int roaming, int defaultNetwork, int subType, 349 int oemManaged, int subscriberIdMatchRule) { 350 mMatchRule = matchRule; 351 mSubscriberId = subscriberId; 352 // TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when 353 // mSubscriberId is null 354 mMatchSubscriberIds = matchSubscriberIds; 355 mNetworkId = networkId; 356 mMetered = metered; 357 mRoaming = roaming; 358 mDefaultNetwork = defaultNetwork; 359 mSubType = subType; 360 mOemManaged = oemManaged; 361 mSubscriberIdMatchRule = subscriberIdMatchRule; 362 checkValidSubscriberIdMatchRule(); 363 if (!isKnownMatchRule(matchRule)) { 364 Log.e(TAG, "Unknown network template rule " + matchRule 365 + " will not match any identity."); 366 } 367 } 368 NetworkTemplate(Parcel in)369 private NetworkTemplate(Parcel in) { 370 mMatchRule = in.readInt(); 371 mSubscriberId = in.readString(); 372 mMatchSubscriberIds = in.createStringArray(); 373 mNetworkId = in.readString(); 374 mMetered = in.readInt(); 375 mRoaming = in.readInt(); 376 mDefaultNetwork = in.readInt(); 377 mSubType = in.readInt(); 378 mOemManaged = in.readInt(); 379 mSubscriberIdMatchRule = in.readInt(); 380 } 381 382 @Override writeToParcel(Parcel dest, int flags)383 public void writeToParcel(Parcel dest, int flags) { 384 dest.writeInt(mMatchRule); 385 dest.writeString(mSubscriberId); 386 dest.writeStringArray(mMatchSubscriberIds); 387 dest.writeString(mNetworkId); 388 dest.writeInt(mMetered); 389 dest.writeInt(mRoaming); 390 dest.writeInt(mDefaultNetwork); 391 dest.writeInt(mSubType); 392 dest.writeInt(mOemManaged); 393 dest.writeInt(mSubscriberIdMatchRule); 394 } 395 396 @Override describeContents()397 public int describeContents() { 398 return 0; 399 } 400 401 @Override toString()402 public String toString() { 403 final StringBuilder builder = new StringBuilder("NetworkTemplate: "); 404 builder.append("matchRule=").append(getMatchRuleName(mMatchRule)); 405 if (mSubscriberId != null) { 406 builder.append(", subscriberId=").append( 407 NetworkIdentityUtils.scrubSubscriberId(mSubscriberId)); 408 } 409 if (mMatchSubscriberIds != null) { 410 builder.append(", matchSubscriberIds=").append( 411 Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds))); 412 } 413 if (mNetworkId != null) { 414 builder.append(", networkId=").append(mNetworkId); 415 } 416 if (mMetered != METERED_ALL) { 417 builder.append(", metered=").append(NetworkStats.meteredToString(mMetered)); 418 } 419 if (mRoaming != ROAMING_ALL) { 420 builder.append(", roaming=").append(NetworkStats.roamingToString(mRoaming)); 421 } 422 if (mDefaultNetwork != DEFAULT_NETWORK_ALL) { 423 builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString( 424 mDefaultNetwork)); 425 } 426 if (mSubType != NETWORK_TYPE_ALL) { 427 builder.append(", subType=").append(mSubType); 428 } 429 if (mOemManaged != OEM_MANAGED_ALL) { 430 builder.append(", oemManaged=").append(mOemManaged); 431 } 432 builder.append(", subscriberIdMatchRule=") 433 .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule)); 434 return builder.toString(); 435 } 436 437 @Override hashCode()438 public int hashCode() { 439 return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, 440 mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule); 441 } 442 443 @Override equals(@ullable Object obj)444 public boolean equals(@Nullable Object obj) { 445 if (obj instanceof NetworkTemplate) { 446 final NetworkTemplate other = (NetworkTemplate) obj; 447 return mMatchRule == other.mMatchRule 448 && Objects.equals(mSubscriberId, other.mSubscriberId) 449 && Objects.equals(mNetworkId, other.mNetworkId) 450 && mMetered == other.mMetered 451 && mRoaming == other.mRoaming 452 && mDefaultNetwork == other.mDefaultNetwork 453 && mSubType == other.mSubType 454 && mOemManaged == other.mOemManaged 455 && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule; 456 } 457 return false; 458 } 459 subscriberIdMatchRuleToString(int rule)460 private String subscriberIdMatchRuleToString(int rule) { 461 switch (rule) { 462 case SUBSCRIBER_ID_MATCH_RULE_EXACT: 463 return "EXACT_MATCH"; 464 case SUBSCRIBER_ID_MATCH_RULE_ALL: 465 return "ALL"; 466 default: 467 return "Unknown rule " + rule; 468 } 469 } 470 isMatchRuleMobile()471 public boolean isMatchRuleMobile() { 472 switch (mMatchRule) { 473 case MATCH_MOBILE: 474 case MATCH_MOBILE_WILDCARD: 475 return true; 476 default: 477 return false; 478 } 479 } 480 isPersistable()481 public boolean isPersistable() { 482 switch (mMatchRule) { 483 case MATCH_MOBILE_WILDCARD: 484 case MATCH_WIFI_WILDCARD: 485 return false; 486 case MATCH_CARRIER: 487 return mSubscriberId != null; 488 case MATCH_WIFI: 489 if (Objects.equals(mNetworkId, WIFI_NETWORKID_ALL) 490 && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { 491 return false; 492 } 493 return true; 494 default: 495 return true; 496 } 497 } 498 499 @UnsupportedAppUsage getMatchRule()500 public int getMatchRule() { 501 return mMatchRule; 502 } 503 504 @UnsupportedAppUsage getSubscriberId()505 public String getSubscriberId() { 506 return mSubscriberId; 507 } 508 getNetworkId()509 public String getNetworkId() { 510 return mNetworkId; 511 } 512 getSubscriberIdMatchRule()513 public int getSubscriberIdMatchRule() { 514 return mSubscriberIdMatchRule; 515 } 516 getMeteredness()517 public int getMeteredness() { 518 return mMetered; 519 } 520 521 /** 522 * Test if given {@link NetworkIdentity} matches this template. 523 */ matches(NetworkIdentity ident)524 public boolean matches(NetworkIdentity ident) { 525 if (!matchesMetered(ident)) return false; 526 if (!matchesRoaming(ident)) return false; 527 if (!matchesDefaultNetwork(ident)) return false; 528 if (!matchesOemNetwork(ident)) return false; 529 530 switch (mMatchRule) { 531 case MATCH_MOBILE: 532 return matchesMobile(ident); 533 case MATCH_WIFI: 534 return matchesWifi(ident); 535 case MATCH_ETHERNET: 536 return matchesEthernet(ident); 537 case MATCH_MOBILE_WILDCARD: 538 return matchesMobileWildcard(ident); 539 case MATCH_WIFI_WILDCARD: 540 return matchesWifiWildcard(ident); 541 case MATCH_BLUETOOTH: 542 return matchesBluetooth(ident); 543 case MATCH_PROXY: 544 return matchesProxy(ident); 545 case MATCH_CARRIER: 546 return matchesCarrier(ident); 547 default: 548 // We have no idea what kind of network template we are, so we 549 // just claim not to match anything. 550 return false; 551 } 552 } 553 matchesMetered(NetworkIdentity ident)554 private boolean matchesMetered(NetworkIdentity ident) { 555 return (mMetered == METERED_ALL) 556 || (mMetered == METERED_YES && ident.mMetered) 557 || (mMetered == METERED_NO && !ident.mMetered); 558 } 559 matchesRoaming(NetworkIdentity ident)560 private boolean matchesRoaming(NetworkIdentity ident) { 561 return (mRoaming == ROAMING_ALL) 562 || (mRoaming == ROAMING_YES && ident.mRoaming) 563 || (mRoaming == ROAMING_NO && !ident.mRoaming); 564 } 565 matchesDefaultNetwork(NetworkIdentity ident)566 private boolean matchesDefaultNetwork(NetworkIdentity ident) { 567 return (mDefaultNetwork == DEFAULT_NETWORK_ALL) 568 || (mDefaultNetwork == DEFAULT_NETWORK_YES && ident.mDefaultNetwork) 569 || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork); 570 } 571 matchesOemNetwork(NetworkIdentity ident)572 private boolean matchesOemNetwork(NetworkIdentity ident) { 573 return (mOemManaged == OEM_MANAGED_ALL) 574 || (mOemManaged == OEM_MANAGED_YES 575 && ident.mOemManaged != OEM_NONE) 576 || (mOemManaged == ident.mOemManaged); 577 } 578 matchesCollapsedRatType(NetworkIdentity ident)579 private boolean matchesCollapsedRatType(NetworkIdentity ident) { 580 return mSubType == NETWORK_TYPE_ALL 581 || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType); 582 } 583 584 /** 585 * Check if this template matches {@code subscriberId}. Returns true if this 586 * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a 587 * {@code mMatchSubscriberIds} array that contains {@code subscriberId}. 588 */ matchesSubscriberId(@ullable String subscriberId)589 public boolean matchesSubscriberId(@Nullable String subscriberId) { 590 return mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL 591 || ArrayUtils.contains(mMatchSubscriberIds, subscriberId); 592 } 593 594 /** 595 * Check if network with matching SSID. Returns true when the SSID matches, or when 596 * {@code mNetworkId} is {@code WIFI_NETWORKID_ALL}. 597 */ matchesWifiNetworkId(@ullable String networkId)598 private boolean matchesWifiNetworkId(@Nullable String networkId) { 599 return Objects.equals(mNetworkId, WIFI_NETWORKID_ALL) 600 || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId)); 601 } 602 603 /** 604 * Check if mobile network with matching IMSI. 605 */ matchesMobile(NetworkIdentity ident)606 private boolean matchesMobile(NetworkIdentity ident) { 607 if (ident.mType == TYPE_WIMAX) { 608 // TODO: consider matching against WiMAX subscriber identity 609 return true; 610 } else { 611 // Only metered mobile network would be matched regardless of metered filter. 612 // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650. 613 // TODO: Respect metered filter and remove mMetered condition. 614 return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) 615 && !ArrayUtils.isEmpty(mMatchSubscriberIds) 616 && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) 617 && matchesCollapsedRatType(ident); 618 } 619 } 620 621 /** 622 * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types. 623 * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}. 624 * 625 * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. 626 */ 627 // TODO: 1. Consider move this to TelephonyManager if used by other modules. 628 // 2. Consider make this configurable. 629 // 3. Use TelephonyManager APIs when available. getCollapsedRatType(int ratType)630 public static int getCollapsedRatType(int ratType) { 631 switch (ratType) { 632 case TelephonyManager.NETWORK_TYPE_GPRS: 633 case TelephonyManager.NETWORK_TYPE_GSM: 634 case TelephonyManager.NETWORK_TYPE_EDGE: 635 case TelephonyManager.NETWORK_TYPE_IDEN: 636 case TelephonyManager.NETWORK_TYPE_CDMA: 637 case TelephonyManager.NETWORK_TYPE_1xRTT: 638 return TelephonyManager.NETWORK_TYPE_GSM; 639 case TelephonyManager.NETWORK_TYPE_EVDO_0: 640 case TelephonyManager.NETWORK_TYPE_EVDO_A: 641 case TelephonyManager.NETWORK_TYPE_EVDO_B: 642 case TelephonyManager.NETWORK_TYPE_EHRPD: 643 case TelephonyManager.NETWORK_TYPE_UMTS: 644 case TelephonyManager.NETWORK_TYPE_HSDPA: 645 case TelephonyManager.NETWORK_TYPE_HSUPA: 646 case TelephonyManager.NETWORK_TYPE_HSPA: 647 case TelephonyManager.NETWORK_TYPE_HSPAP: 648 case TelephonyManager.NETWORK_TYPE_TD_SCDMA: 649 return TelephonyManager.NETWORK_TYPE_UMTS; 650 case TelephonyManager.NETWORK_TYPE_LTE: 651 case TelephonyManager.NETWORK_TYPE_IWLAN: 652 return TelephonyManager.NETWORK_TYPE_LTE; 653 case TelephonyManager.NETWORK_TYPE_NR: 654 return TelephonyManager.NETWORK_TYPE_NR; 655 // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. 656 case NetworkTemplate.NETWORK_TYPE_5G_NSA: 657 return NetworkTemplate.NETWORK_TYPE_5G_NSA; 658 default: 659 return TelephonyManager.NETWORK_TYPE_UNKNOWN; 660 } 661 } 662 663 /** 664 * Return all supported collapsed RAT types that could be returned by 665 * {@link #getCollapsedRatType(int)}. 666 */ 667 @NonNull getAllCollapsedRatTypes()668 public static final int[] getAllCollapsedRatTypes() { 669 final int[] ratTypes = TelephonyManager.getAllNetworkTypes(); 670 final HashSet<Integer> collapsedRatTypes = new HashSet<>(); 671 for (final int ratType : ratTypes) { 672 collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); 673 } 674 // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and 675 // it is not in TelephonyManager#NETWORK_TYPE_* constants. 676 // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. 677 collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA)); 678 // Ensure that unknown type is returned. 679 collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); 680 return toIntArray(collapsedRatTypes); 681 } 682 683 @NonNull toIntArray(@onNull Collection<Integer> list)684 private static int[] toIntArray(@NonNull Collection<Integer> list) { 685 final int[] array = new int[list.size()]; 686 int i = 0; 687 for (final Integer item : list) { 688 array[i++] = item; 689 } 690 return array; 691 } 692 693 /** 694 * Check if matches Wi-Fi network template. 695 */ matchesWifi(NetworkIdentity ident)696 private boolean matchesWifi(NetworkIdentity ident) { 697 switch (ident.mType) { 698 case TYPE_WIFI: 699 return matchesSubscriberId(ident.mSubscriberId) 700 && matchesWifiNetworkId(ident.mNetworkId); 701 default: 702 return false; 703 } 704 } 705 706 /** 707 * Check if matches Ethernet network template. 708 */ matchesEthernet(NetworkIdentity ident)709 private boolean matchesEthernet(NetworkIdentity ident) { 710 if (ident.mType == TYPE_ETHERNET) { 711 return true; 712 } 713 return false; 714 } 715 716 /** 717 * Check if matches carrier network. The carrier networks means it includes the subscriberId. 718 */ matchesCarrier(NetworkIdentity ident)719 private boolean matchesCarrier(NetworkIdentity ident) { 720 return ident.mSubscriberId != null 721 && !ArrayUtils.isEmpty(mMatchSubscriberIds) 722 && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); 723 } 724 matchesMobileWildcard(NetworkIdentity ident)725 private boolean matchesMobileWildcard(NetworkIdentity ident) { 726 if (ident.mType == TYPE_WIMAX) { 727 return true; 728 } else { 729 return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) 730 && matchesCollapsedRatType(ident); 731 } 732 } 733 matchesWifiWildcard(NetworkIdentity ident)734 private boolean matchesWifiWildcard(NetworkIdentity ident) { 735 switch (ident.mType) { 736 case TYPE_WIFI: 737 case TYPE_WIFI_P2P: 738 return true; 739 default: 740 return false; 741 } 742 } 743 744 /** 745 * Check if matches Bluetooth network template. 746 */ matchesBluetooth(NetworkIdentity ident)747 private boolean matchesBluetooth(NetworkIdentity ident) { 748 if (ident.mType == TYPE_BLUETOOTH) { 749 return true; 750 } 751 return false; 752 } 753 754 /** 755 * Check if matches Proxy network template. 756 */ matchesProxy(NetworkIdentity ident)757 private boolean matchesProxy(NetworkIdentity ident) { 758 return ident.mType == TYPE_PROXY; 759 } 760 getMatchRuleName(int matchRule)761 private static String getMatchRuleName(int matchRule) { 762 switch (matchRule) { 763 case MATCH_MOBILE: 764 return "MOBILE"; 765 case MATCH_WIFI: 766 return "WIFI"; 767 case MATCH_ETHERNET: 768 return "ETHERNET"; 769 case MATCH_MOBILE_WILDCARD: 770 return "MOBILE_WILDCARD"; 771 case MATCH_WIFI_WILDCARD: 772 return "WIFI_WILDCARD"; 773 case MATCH_BLUETOOTH: 774 return "BLUETOOTH"; 775 case MATCH_PROXY: 776 return "PROXY"; 777 case MATCH_CARRIER: 778 return "CARRIER"; 779 default: 780 return "UNKNOWN(" + matchRule + ")"; 781 } 782 } 783 784 /** 785 * Examine the given template and normalize if it refers to a "merged" 786 * mobile subscriber. We pick the "lowest" merged subscriber as the primary 787 * for key purposes, and expand the template to match all other merged 788 * subscribers. 789 * <p> 790 * For example, given an incoming template matching B, and the currently 791 * active merge set [A,B], we'd return a new template that primarily matches 792 * A, but also matches B. 793 * TODO: remove and use {@link #normalize(NetworkTemplate, List)}. 794 */ 795 @UnsupportedAppUsage normalize(NetworkTemplate template, String[] merged)796 public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) { 797 return normalize(template, Arrays.<String[]>asList(merged)); 798 } 799 800 /** 801 * Examine the given template and normalize if it refers to a "merged" 802 * mobile subscriber. We pick the "lowest" merged subscriber as the primary 803 * for key purposes, and expand the template to match all other merged 804 * subscribers. 805 * 806 * There can be multiple merged subscriberIds for multi-SIM devices. 807 * 808 * <p> 809 * For example, given an incoming template matching B, and the currently 810 * active merge set [A,B], we'd return a new template that primarily matches 811 * A, but also matches B. 812 */ normalize(NetworkTemplate template, List<String[]> mergedList)813 public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) { 814 if (!template.isMatchRuleMobile()) return template; 815 816 for (String[] merged : mergedList) { 817 if (ArrayUtils.contains(merged, template.mSubscriberId)) { 818 // Requested template subscriber is part of the merge group; return 819 // a template that matches all merged subscribers. 820 return new NetworkTemplate(template.mMatchRule, merged[0], merged, 821 template.mNetworkId); 822 } 823 } 824 825 return template; 826 } 827 828 @UnsupportedAppUsage 829 public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() { 830 @Override 831 public NetworkTemplate createFromParcel(Parcel in) { 832 return new NetworkTemplate(in); 833 } 834 835 @Override 836 public NetworkTemplate[] newArray(int size) { 837 return new NetworkTemplate[size]; 838 } 839 }; 840 getBytesForBackup()841 public byte[] getBytesForBackup() throws IOException { 842 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 843 DataOutputStream out = new DataOutputStream(baos); 844 845 out.writeInt(BACKUP_VERSION); 846 847 out.writeInt(mMatchRule); 848 BackupUtils.writeString(out, mSubscriberId); 849 BackupUtils.writeString(out, mNetworkId); 850 851 return baos.toByteArray(); 852 } 853 getNetworkTemplateFromBackup(DataInputStream in)854 public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in) 855 throws IOException, BackupUtils.BadVersionException { 856 int version = in.readInt(); 857 if (version < 1 || version > BACKUP_VERSION) { 858 throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); 859 } 860 861 int matchRule = in.readInt(); 862 String subscriberId = BackupUtils.readString(in); 863 String networkId = BackupUtils.readString(in); 864 865 if (!isKnownMatchRule(matchRule)) { 866 throw new BackupUtils.BadVersionException( 867 "Restored network template contains unknown match rule " + matchRule); 868 } 869 870 return new NetworkTemplate(matchRule, subscriberId, networkId); 871 } 872 } 873