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.annotation.SystemApi.Client.MODULE_LIBRARIES; 20 import static android.net.ConnectivityManager.TYPE_BLUETOOTH; 21 import static android.net.ConnectivityManager.TYPE_ETHERNET; 22 import static android.net.ConnectivityManager.TYPE_MOBILE; 23 import static android.net.ConnectivityManager.TYPE_PROXY; 24 import static android.net.ConnectivityManager.TYPE_WIFI; 25 import static android.net.ConnectivityManager.TYPE_WIFI_P2P; 26 import static android.net.ConnectivityManager.TYPE_WIMAX; 27 import static android.net.NetworkIdentity.OEM_NONE; 28 import static android.net.NetworkIdentity.OEM_PAID; 29 import static android.net.NetworkIdentity.OEM_PRIVATE; 30 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; 31 import static android.net.NetworkStats.DEFAULT_NETWORK_NO; 32 import static android.net.NetworkStats.DEFAULT_NETWORK_YES; 33 import static android.net.NetworkStats.METERED_ALL; 34 import static android.net.NetworkStats.METERED_NO; 35 import static android.net.NetworkStats.METERED_YES; 36 import static android.net.NetworkStats.ROAMING_ALL; 37 import static android.net.NetworkStats.ROAMING_NO; 38 import static android.net.NetworkStats.ROAMING_YES; 39 40 import android.annotation.IntDef; 41 import android.annotation.NonNull; 42 import android.annotation.Nullable; 43 import android.annotation.SystemApi; 44 import android.app.usage.NetworkStatsManager; 45 import android.compat.annotation.UnsupportedAppUsage; 46 import android.net.wifi.WifiInfo; 47 import android.os.Build; 48 import android.os.Parcel; 49 import android.os.Parcelable; 50 import android.text.TextUtils; 51 import android.util.ArraySet; 52 53 import com.android.net.module.util.CollectionUtils; 54 import com.android.net.module.util.NetworkIdentityUtils; 55 import com.android.net.module.util.NetworkStatsUtils; 56 57 import java.lang.annotation.Retention; 58 import java.lang.annotation.RetentionPolicy; 59 import java.util.Arrays; 60 import java.util.Comparator; 61 import java.util.List; 62 import java.util.Objects; 63 import java.util.Set; 64 import java.util.SortedSet; 65 import java.util.TreeSet; 66 67 /** 68 * Predicate used to match {@link NetworkIdentity}, usually when collecting 69 * statistics. (It should probably have been named {@code NetworkPredicate}.) 70 * 71 * @hide 72 */ 73 @SystemApi(client = MODULE_LIBRARIES) 74 public final class NetworkTemplate implements Parcelable { 75 /** @hide */ 76 @Retention(RetentionPolicy.SOURCE) 77 @IntDef(prefix = { "MATCH_" }, value = { 78 MATCH_MOBILE, 79 MATCH_WIFI, 80 MATCH_ETHERNET, 81 MATCH_BLUETOOTH, 82 MATCH_PROXY, 83 MATCH_CARRIER, 84 }) 85 public @interface TemplateMatchRule{} 86 87 /** Match rule to match cellular networks with given Subscriber Ids. */ 88 public static final int MATCH_MOBILE = 1; 89 /** Match rule to match wifi networks. */ 90 public static final int MATCH_WIFI = 4; 91 /** Match rule to match ethernet networks. */ 92 public static final int MATCH_ETHERNET = 5; 93 /** 94 * Match rule to match all cellular networks. 95 * 96 * @hide 97 */ 98 public static final int MATCH_MOBILE_WILDCARD = 6; 99 /** 100 * Match rule to match all wifi networks. 101 * 102 * @hide 103 */ 104 public static final int MATCH_WIFI_WILDCARD = 7; 105 /** Match rule to match bluetooth networks. */ 106 public static final int MATCH_BLUETOOTH = 8; 107 /** 108 * Match rule to match networks with {@link ConnectivityManager#TYPE_PROXY} as the legacy 109 * network type. 110 */ 111 public static final int MATCH_PROXY = 9; 112 /** 113 * Match rule to match all networks with subscriberId inside the template. Some carriers 114 * may offer non-cellular networks like WiFi, which will be matched by this rule. 115 */ 116 public static final int MATCH_CARRIER = 10; 117 118 // TODO: Remove this and replace all callers with WIFI_NETWORK_KEY_ALL. 119 /** @hide */ 120 public static final String WIFI_NETWORKID_ALL = null; 121 122 /** 123 * Wi-Fi Network Key is never supposed to be null (if it is, it is a bug that 124 * should be fixed), so it's not possible to want to match null vs 125 * non-null. Therefore it's fine to use null as a sentinel for Wifi Network Key. 126 * 127 * @hide 128 */ 129 public static final String WIFI_NETWORK_KEY_ALL = WIFI_NETWORKID_ALL; 130 131 /** 132 * Include all network types when filtering. This is meant to merge in with the 133 * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. 134 */ 135 public static final int NETWORK_TYPE_ALL = -1; 136 137 /** @hide */ 138 @Retention(RetentionPolicy.SOURCE) 139 @IntDef(prefix = { "OEM_MANAGED_" }, value = { 140 OEM_MANAGED_ALL, 141 OEM_MANAGED_NO, 142 OEM_MANAGED_YES, 143 OEM_MANAGED_PAID, 144 OEM_MANAGED_PRIVATE 145 }) 146 public @interface OemManaged{} 147 148 /** 149 * Value to match both OEM managed and unmanaged networks (all networks). 150 */ 151 public static final int OEM_MANAGED_ALL = -1; 152 /** 153 * Value to match networks which are not OEM managed. 154 */ 155 public static final int OEM_MANAGED_NO = OEM_NONE; 156 /** 157 * Value to match any OEM managed network. 158 */ 159 public static final int OEM_MANAGED_YES = -2; 160 /** 161 * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}. 162 */ 163 public static final int OEM_MANAGED_PAID = OEM_PAID; 164 /** 165 * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}. 166 */ 167 public static final int OEM_MANAGED_PRIVATE = OEM_PRIVATE; 168 isKnownMatchRule(final int rule)169 private static boolean isKnownMatchRule(final int rule) { 170 switch (rule) { 171 case MATCH_MOBILE: 172 case MATCH_WIFI: 173 case MATCH_ETHERNET: 174 case MATCH_MOBILE_WILDCARD: 175 case MATCH_WIFI_WILDCARD: 176 case MATCH_BLUETOOTH: 177 case MATCH_PROXY: 178 case MATCH_CARRIER: 179 return true; 180 181 default: 182 return false; 183 } 184 } 185 186 /** 187 * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with 188 * the given IMSI. 189 * 190 * @hide 191 */ 192 @UnsupportedAppUsage buildTemplateMobileAll(String subscriberId)193 public static NetworkTemplate buildTemplateMobileAll(String subscriberId) { 194 return new NetworkTemplate(MATCH_MOBILE, subscriberId, null); 195 } 196 197 /** 198 * Template to match cellular networks with the given IMSI, {@code ratType} and 199 * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when 200 * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}. 201 * 202 * @hide 203 */ buildTemplateMobileWithRatType(@ullable String subscriberId, int ratType, int metered)204 public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, 205 int ratType, int metered) { 206 if (TextUtils.isEmpty(subscriberId)) { 207 return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */, 208 null /* matchSubscriberIds */, 209 new String[0] /* matchWifiNetworkKeys */, metered, ROAMING_ALL, 210 DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, 211 NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); 212 } 213 return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[] { subscriberId }, 214 new String[0] /* matchWifiNetworkKeys */, 215 metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, 216 NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); 217 } 218 219 /** 220 * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, 221 * regardless of IMSI. 222 * 223 * @hide 224 */ 225 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) buildTemplateMobileWildcard()226 public static NetworkTemplate buildTemplateMobileWildcard() { 227 return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); 228 } 229 230 /** 231 * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks, 232 * regardless of key of the wifi network. 233 * 234 * @hide 235 */ 236 @UnsupportedAppUsage buildTemplateWifiWildcard()237 public static NetworkTemplate buildTemplateWifiWildcard() { 238 // TODO: Consider replace this with MATCH_WIFI with NETWORK_ID_ALL 239 // and SUBSCRIBER_ID_MATCH_RULE_ALL. 240 return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null); 241 } 242 243 /** @hide */ 244 @Deprecated 245 @UnsupportedAppUsage buildTemplateWifi()246 public static NetworkTemplate buildTemplateWifi() { 247 return buildTemplateWifiWildcard(); 248 } 249 250 /** 251 * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the 252 * given key of the wifi network. 253 * 254 * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()} 255 * to know details about the key. 256 * @hide 257 */ buildTemplateWifi(@onNull String wifiNetworkKey)258 public static NetworkTemplate buildTemplateWifi(@NonNull String wifiNetworkKey) { 259 Objects.requireNonNull(wifiNetworkKey); 260 return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */, 261 new String[] { null } /* matchSubscriberIds */, 262 new String[] { wifiNetworkKey }, METERED_ALL, ROAMING_ALL, 263 DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, 264 NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL); 265 } 266 267 /** 268 * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given 269 * key of the wifi network and IMSI. 270 * 271 * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless 272 * of key of the wifi network. 273 * 274 * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()} 275 * to know details about the key. 276 * @param subscriberId the IMSI associated to this wifi network. 277 * 278 * @hide 279 */ buildTemplateWifi(@ullable String wifiNetworkKey, @Nullable String subscriberId)280 public static NetworkTemplate buildTemplateWifi(@Nullable String wifiNetworkKey, 281 @Nullable String subscriberId) { 282 return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId }, 283 wifiNetworkKey != null 284 ? new String[] { wifiNetworkKey } : new String[0], 285 METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, 286 NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); 287 } 288 289 /** 290 * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style 291 * networks together. 292 * 293 * @hide 294 */ 295 @UnsupportedAppUsage buildTemplateEthernet()296 public static NetworkTemplate buildTemplateEthernet() { 297 return new NetworkTemplate(MATCH_ETHERNET, null, null); 298 } 299 300 /** 301 * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style 302 * networks together. 303 * 304 * @hide 305 */ buildTemplateBluetooth()306 public static NetworkTemplate buildTemplateBluetooth() { 307 return new NetworkTemplate(MATCH_BLUETOOTH, null, null); 308 } 309 310 /** 311 * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style 312 * networks together. 313 * 314 * @hide 315 */ buildTemplateProxy()316 public static NetworkTemplate buildTemplateProxy() { 317 return new NetworkTemplate(MATCH_PROXY, null, null); 318 } 319 320 /** 321 * Template to match all metered carrier networks with the given IMSI. 322 * 323 * @hide 324 */ buildTemplateCarrierMetered(@onNull String subscriberId)325 public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) { 326 Objects.requireNonNull(subscriberId); 327 return new NetworkTemplate(MATCH_CARRIER, subscriberId, 328 new String[] { subscriberId }, 329 new String[0] /* matchWifiNetworkKeys */, 330 METERED_YES, ROAMING_ALL, 331 DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, 332 NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); 333 } 334 335 private final int mMatchRule; 336 private final String mSubscriberId; 337 338 /** 339 * Ugh, templates are designed to target a single subscriber, but we might 340 * need to match several "merged" subscribers. These are the subscribers 341 * that should be considered to match this template. 342 * <p> 343 * Since the merge set is dynamic, it should <em>not</em> be persisted or 344 * used for determining equality. 345 */ 346 private final String[] mMatchSubscriberIds; 347 348 @NonNull 349 private final String[] mMatchWifiNetworkKeys; 350 351 // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. 352 private final int mMetered; 353 private final int mRoaming; 354 private final int mDefaultNetwork; 355 private final int mRatType; 356 /** 357 * The subscriber Id match rule defines how the template should match networks with 358 * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail. 359 */ 360 private final int mSubscriberIdMatchRule; 361 362 // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}. 363 private final int mOemManaged; 364 checkValidSubscriberIdMatchRule(int matchRule, int subscriberIdMatchRule)365 private static void checkValidSubscriberIdMatchRule(int matchRule, int subscriberIdMatchRule) { 366 switch (matchRule) { 367 case MATCH_MOBILE: 368 case MATCH_CARRIER: 369 // MOBILE and CARRIER templates must always specify a subscriber ID. 370 if (subscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL) { 371 throw new IllegalArgumentException("Invalid SubscriberIdMatchRule " 372 + "on match rule: " + getMatchRuleName(matchRule)); 373 } 374 return; 375 default: 376 return; 377 } 378 } 379 380 /** @hide */ 381 // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S) 382 @UnsupportedAppUsage NetworkTemplate(int matchRule, String subscriberId, String wifiNetworkKey)383 public NetworkTemplate(int matchRule, String subscriberId, String wifiNetworkKey) { 384 this(matchRule, subscriberId, new String[] { subscriberId }, wifiNetworkKey); 385 } 386 387 /** @hide */ NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String wifiNetworkKey)388 public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, 389 String wifiNetworkKey) { 390 // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates 391 // to metered networks. It is now possible to match mobile with any meteredness, but 392 // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this 393 //constructor passes METERED_YES for these types. 394 this(matchRule, subscriberId, matchSubscriberIds, 395 wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0], 396 (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD 397 || matchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL, 398 ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, 399 OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); 400 } 401 402 /** @hide */ 403 // TODO: Remove it after updating all of the caller. NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int ratType, int oemManaged)404 public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, 405 String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int ratType, 406 int oemManaged) { 407 this(matchRule, subscriberId, matchSubscriberIds, 408 wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0], 409 metered, roaming, defaultNetwork, ratType, oemManaged, 410 NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); 411 } 412 413 /** @hide */ NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String[] matchWifiNetworkKeys, int metered, int roaming, int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule)414 public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, 415 String[] matchWifiNetworkKeys, int metered, int roaming, 416 int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) { 417 Objects.requireNonNull(matchWifiNetworkKeys); 418 mMatchRule = matchRule; 419 mSubscriberId = subscriberId; 420 // TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when 421 // mSubscriberId is null 422 mMatchSubscriberIds = matchSubscriberIds; 423 mMatchWifiNetworkKeys = matchWifiNetworkKeys; 424 mMetered = metered; 425 mRoaming = roaming; 426 mDefaultNetwork = defaultNetwork; 427 mRatType = ratType; 428 mOemManaged = oemManaged; 429 mSubscriberIdMatchRule = subscriberIdMatchRule; 430 checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule); 431 if (!isKnownMatchRule(matchRule)) { 432 throw new IllegalArgumentException("Unknown network template rule " + matchRule 433 + " will not match any identity."); 434 } 435 } 436 NetworkTemplate(Parcel in)437 private NetworkTemplate(Parcel in) { 438 mMatchRule = in.readInt(); 439 mSubscriberId = in.readString(); 440 mMatchSubscriberIds = in.createStringArray(); 441 mMatchWifiNetworkKeys = in.createStringArray(); 442 mMetered = in.readInt(); 443 mRoaming = in.readInt(); 444 mDefaultNetwork = in.readInt(); 445 mRatType = in.readInt(); 446 mOemManaged = in.readInt(); 447 mSubscriberIdMatchRule = in.readInt(); 448 } 449 450 @Override writeToParcel(@onNull Parcel dest, int flags)451 public void writeToParcel(@NonNull Parcel dest, int flags) { 452 dest.writeInt(mMatchRule); 453 dest.writeString(mSubscriberId); 454 dest.writeStringArray(mMatchSubscriberIds); 455 dest.writeStringArray(mMatchWifiNetworkKeys); 456 dest.writeInt(mMetered); 457 dest.writeInt(mRoaming); 458 dest.writeInt(mDefaultNetwork); 459 dest.writeInt(mRatType); 460 dest.writeInt(mOemManaged); 461 dest.writeInt(mSubscriberIdMatchRule); 462 } 463 464 @Override describeContents()465 public int describeContents() { 466 return 0; 467 } 468 469 @Override toString()470 public String toString() { 471 final StringBuilder builder = new StringBuilder("NetworkTemplate: "); 472 builder.append("matchRule=").append(getMatchRuleName(mMatchRule)); 473 if (mSubscriberId != null) { 474 builder.append(", subscriberId=").append( 475 NetworkIdentityUtils.scrubSubscriberId(mSubscriberId)); 476 } 477 if (mMatchSubscriberIds != null) { 478 builder.append(", matchSubscriberIds=").append( 479 Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds))); 480 } 481 builder.append(", matchWifiNetworkKeys=").append(Arrays.toString(mMatchWifiNetworkKeys)); 482 if (mMetered != METERED_ALL) { 483 builder.append(", metered=").append(NetworkStats.meteredToString(mMetered)); 484 } 485 if (mRoaming != ROAMING_ALL) { 486 builder.append(", roaming=").append(NetworkStats.roamingToString(mRoaming)); 487 } 488 if (mDefaultNetwork != DEFAULT_NETWORK_ALL) { 489 builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString( 490 mDefaultNetwork)); 491 } 492 if (mRatType != NETWORK_TYPE_ALL) { 493 builder.append(", ratType=").append(mRatType); 494 } 495 if (mOemManaged != OEM_MANAGED_ALL) { 496 builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged)); 497 } 498 builder.append(", subscriberIdMatchRule=") 499 .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule)); 500 return builder.toString(); 501 } 502 503 @Override hashCode()504 public int hashCode() { 505 return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys), 506 mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, mSubscriberIdMatchRule); 507 } 508 509 @Override equals(@ullable Object obj)510 public boolean equals(@Nullable Object obj) { 511 if (obj instanceof NetworkTemplate) { 512 final NetworkTemplate other = (NetworkTemplate) obj; 513 return mMatchRule == other.mMatchRule 514 && Objects.equals(mSubscriberId, other.mSubscriberId) 515 && mMetered == other.mMetered 516 && mRoaming == other.mRoaming 517 && mDefaultNetwork == other.mDefaultNetwork 518 && mRatType == other.mRatType 519 && mOemManaged == other.mOemManaged 520 && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule 521 && Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys); 522 } 523 return false; 524 } 525 subscriberIdMatchRuleToString(int rule)526 private static String subscriberIdMatchRuleToString(int rule) { 527 switch (rule) { 528 case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT: 529 return "EXACT_MATCH"; 530 case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL: 531 return "ALL"; 532 default: 533 return "Unknown rule " + rule; 534 } 535 } 536 537 /** @hide */ isMatchRuleMobile()538 public boolean isMatchRuleMobile() { 539 switch (mMatchRule) { 540 case MATCH_MOBILE: 541 case MATCH_MOBILE_WILDCARD: 542 return true; 543 default: 544 return false; 545 } 546 } 547 548 /** 549 * Get match rule of the template. See {@code MATCH_*}. 550 */ 551 @UnsupportedAppUsage getMatchRule()552 public int getMatchRule() { 553 // Wildcard rules are not exposed. For external callers, convert wildcard rules to 554 // exposed rules before returning. 555 switch (mMatchRule) { 556 case MATCH_MOBILE_WILDCARD: 557 return MATCH_MOBILE; 558 case MATCH_WIFI_WILDCARD: 559 return MATCH_WIFI; 560 default: 561 return mMatchRule; 562 } 563 } 564 565 /** 566 * Get subscriber Id of the template. 567 * @hide 568 */ 569 @Nullable 570 @UnsupportedAppUsage getSubscriberId()571 public String getSubscriberId() { 572 return mSubscriberId; 573 } 574 575 /** 576 * Get set of subscriber Ids of the template. 577 */ 578 @NonNull getSubscriberIds()579 public Set<String> getSubscriberIds() { 580 return new ArraySet<>(Arrays.asList(mMatchSubscriberIds)); 581 } 582 583 /** 584 * Get the set of Wifi Network Keys of the template. 585 * See {@link WifiInfo#getNetworkKey()}. 586 */ 587 @NonNull getWifiNetworkKeys()588 public Set<String> getWifiNetworkKeys() { 589 return new ArraySet<>(Arrays.asList(mMatchWifiNetworkKeys)); 590 } 591 592 /** @hide */ 593 // TODO: Remove this and replace all callers with {@link #getWifiNetworkKeys()}. 594 @Nullable getNetworkId()595 public String getNetworkId() { 596 return getWifiNetworkKeys().isEmpty() ? null : getWifiNetworkKeys().iterator().next(); 597 } 598 599 /** 600 * Get meteredness filter of the template. 601 */ 602 @NetworkStats.Meteredness getMeteredness()603 public int getMeteredness() { 604 return mMetered; 605 } 606 607 /** 608 * Get roaming filter of the template. 609 */ 610 @NetworkStats.Roaming getRoaming()611 public int getRoaming() { 612 return mRoaming; 613 } 614 615 /** 616 * Get the default network status filter of the template. 617 */ 618 @NetworkStats.DefaultNetwork getDefaultNetworkStatus()619 public int getDefaultNetworkStatus() { 620 return mDefaultNetwork; 621 } 622 623 /** 624 * Get the Radio Access Technology(RAT) type filter of the template. 625 */ getRatType()626 public int getRatType() { 627 return mRatType; 628 } 629 630 /** 631 * Get the OEM managed filter of the template. See {@code OEM_MANAGED_*} or 632 * {@code android.net.NetworkIdentity#OEM_*}. 633 */ 634 @OemManaged getOemManaged()635 public int getOemManaged() { 636 return mOemManaged; 637 } 638 639 /** 640 * Test if given {@link NetworkIdentity} matches this template. 641 * 642 * @hide 643 */ 644 @SystemApi(client = MODULE_LIBRARIES) matches(@onNull NetworkIdentity ident)645 public boolean matches(@NonNull NetworkIdentity ident) { 646 Objects.requireNonNull(ident); 647 if (!matchesMetered(ident)) return false; 648 if (!matchesRoaming(ident)) return false; 649 if (!matchesDefaultNetwork(ident)) return false; 650 if (!matchesOemNetwork(ident)) return false; 651 652 switch (mMatchRule) { 653 case MATCH_MOBILE: 654 return matchesMobile(ident); 655 case MATCH_WIFI: 656 return matchesWifi(ident); 657 case MATCH_ETHERNET: 658 return matchesEthernet(ident); 659 case MATCH_MOBILE_WILDCARD: 660 return matchesMobileWildcard(ident); 661 case MATCH_WIFI_WILDCARD: 662 return matchesWifiWildcard(ident); 663 case MATCH_BLUETOOTH: 664 return matchesBluetooth(ident); 665 case MATCH_PROXY: 666 return matchesProxy(ident); 667 case MATCH_CARRIER: 668 return matchesCarrier(ident); 669 default: 670 // We have no idea what kind of network template we are, so we 671 // just claim not to match anything. 672 return false; 673 } 674 } 675 matchesMetered(NetworkIdentity ident)676 private boolean matchesMetered(NetworkIdentity ident) { 677 return (mMetered == METERED_ALL) 678 || (mMetered == METERED_YES && ident.mMetered) 679 || (mMetered == METERED_NO && !ident.mMetered); 680 } 681 matchesRoaming(NetworkIdentity ident)682 private boolean matchesRoaming(NetworkIdentity ident) { 683 return (mRoaming == ROAMING_ALL) 684 || (mRoaming == ROAMING_YES && ident.mRoaming) 685 || (mRoaming == ROAMING_NO && !ident.mRoaming); 686 } 687 matchesDefaultNetwork(NetworkIdentity ident)688 private boolean matchesDefaultNetwork(NetworkIdentity ident) { 689 return (mDefaultNetwork == DEFAULT_NETWORK_ALL) 690 || (mDefaultNetwork == DEFAULT_NETWORK_YES && ident.mDefaultNetwork) 691 || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork); 692 } 693 matchesOemNetwork(NetworkIdentity ident)694 private boolean matchesOemNetwork(NetworkIdentity ident) { 695 return (mOemManaged == OEM_MANAGED_ALL) 696 || (mOemManaged == OEM_MANAGED_YES 697 && ident.mOemManaged != OEM_NONE) 698 || (mOemManaged == ident.mOemManaged); 699 } 700 matchesCollapsedRatType(NetworkIdentity ident)701 private boolean matchesCollapsedRatType(NetworkIdentity ident) { 702 return mRatType == NETWORK_TYPE_ALL 703 || NetworkStatsManager.getCollapsedRatType(mRatType) 704 == NetworkStatsManager.getCollapsedRatType(ident.mRatType); 705 } 706 707 /** 708 * Check if this template matches {@code subscriberId}. Returns true if this 709 * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a 710 * {@code mMatchSubscriberIds} array that contains {@code subscriberId}. 711 * 712 * @hide 713 */ matchesSubscriberId(@ullable String subscriberId)714 public boolean matchesSubscriberId(@Nullable String subscriberId) { 715 return mSubscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL 716 || CollectionUtils.contains(mMatchSubscriberIds, subscriberId); 717 } 718 719 /** 720 * Check if network matches key of the wifi network. 721 * Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is 722 * empty. 723 * 724 * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()} 725 * to know details about the key. 726 */ matchesWifiNetworkKey(@onNull String wifiNetworkKey)727 private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) { 728 Objects.requireNonNull(wifiNetworkKey); 729 return CollectionUtils.isEmpty(mMatchWifiNetworkKeys) 730 || CollectionUtils.contains(mMatchWifiNetworkKeys, wifiNetworkKey); 731 } 732 733 /** 734 * Check if mobile network matches IMSI. 735 */ matchesMobile(NetworkIdentity ident)736 private boolean matchesMobile(NetworkIdentity ident) { 737 if (ident.mType == TYPE_WIMAX) { 738 // TODO: consider matching against WiMAX subscriber identity 739 return true; 740 } else { 741 return ident.mType == TYPE_MOBILE && !CollectionUtils.isEmpty(mMatchSubscriberIds) 742 && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) 743 && matchesCollapsedRatType(ident); 744 } 745 } 746 747 /** 748 * Check if matches Wi-Fi network template. 749 */ matchesWifi(NetworkIdentity ident)750 private boolean matchesWifi(NetworkIdentity ident) { 751 switch (ident.mType) { 752 case TYPE_WIFI: 753 return matchesSubscriberId(ident.mSubscriberId) 754 && matchesWifiNetworkKey(ident.mWifiNetworkKey); 755 default: 756 return false; 757 } 758 } 759 760 /** 761 * Check if matches Ethernet network template. 762 */ matchesEthernet(NetworkIdentity ident)763 private boolean matchesEthernet(NetworkIdentity ident) { 764 if (ident.mType == TYPE_ETHERNET) { 765 return true; 766 } 767 return false; 768 } 769 770 /** 771 * Check if matches carrier network. The carrier networks means it includes the subscriberId. 772 */ matchesCarrier(NetworkIdentity ident)773 private boolean matchesCarrier(NetworkIdentity ident) { 774 return ident.mSubscriberId != null 775 && !CollectionUtils.isEmpty(mMatchSubscriberIds) 776 && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); 777 } 778 matchesMobileWildcard(NetworkIdentity ident)779 private boolean matchesMobileWildcard(NetworkIdentity ident) { 780 if (ident.mType == TYPE_WIMAX) { 781 return true; 782 } else { 783 return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident); 784 } 785 } 786 matchesWifiWildcard(NetworkIdentity ident)787 private boolean matchesWifiWildcard(NetworkIdentity ident) { 788 switch (ident.mType) { 789 case TYPE_WIFI: 790 case TYPE_WIFI_P2P: 791 return true; 792 default: 793 return false; 794 } 795 } 796 797 /** 798 * Check if matches Bluetooth network template. 799 */ matchesBluetooth(NetworkIdentity ident)800 private boolean matchesBluetooth(NetworkIdentity ident) { 801 if (ident.mType == TYPE_BLUETOOTH) { 802 return true; 803 } 804 return false; 805 } 806 807 /** 808 * Check if matches Proxy network template. 809 */ matchesProxy(NetworkIdentity ident)810 private boolean matchesProxy(NetworkIdentity ident) { 811 return ident.mType == TYPE_PROXY; 812 } 813 getMatchRuleName(int matchRule)814 private static String getMatchRuleName(int matchRule) { 815 switch (matchRule) { 816 case MATCH_MOBILE: 817 return "MOBILE"; 818 case MATCH_WIFI: 819 return "WIFI"; 820 case MATCH_ETHERNET: 821 return "ETHERNET"; 822 case MATCH_MOBILE_WILDCARD: 823 return "MOBILE_WILDCARD"; 824 case MATCH_WIFI_WILDCARD: 825 return "WIFI_WILDCARD"; 826 case MATCH_BLUETOOTH: 827 return "BLUETOOTH"; 828 case MATCH_PROXY: 829 return "PROXY"; 830 case MATCH_CARRIER: 831 return "CARRIER"; 832 default: 833 return "UNKNOWN(" + matchRule + ")"; 834 } 835 } 836 getOemManagedNames(int oemManaged)837 private static String getOemManagedNames(int oemManaged) { 838 switch (oemManaged) { 839 case OEM_MANAGED_ALL: 840 return "OEM_MANAGED_ALL"; 841 case OEM_MANAGED_NO: 842 return "OEM_MANAGED_NO"; 843 case OEM_MANAGED_YES: 844 return "OEM_MANAGED_YES"; 845 default: 846 return NetworkIdentity.getOemManagedNames(oemManaged); 847 } 848 } 849 850 /** 851 * Examine the given template and normalize it. 852 * We pick the "lowest" merged subscriber as the primary 853 * for key purposes, and expand the template to match all other merged 854 * subscribers. 855 * <p> 856 * For example, given an incoming template matching B, and the currently 857 * active merge set [A,B], we'd return a new template that primarily matches 858 * A, but also matches B. 859 * TODO: remove and use {@link #normalize(NetworkTemplate, List)}. 860 * 861 * @hide 862 */ 863 @UnsupportedAppUsage normalize(NetworkTemplate template, String[] merged)864 public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) { 865 return normalize(template, Arrays.<String[]>asList(merged)); 866 } 867 868 /** 869 * Examine the given template and normalize it. 870 * We pick the "lowest" merged subscriber as the primary 871 * for key purposes, and expand the template to match all other merged 872 * subscribers. 873 * 874 * There can be multiple merged subscriberIds for multi-SIM devices. 875 * 876 * <p> 877 * For example, given an incoming template matching B, and the currently 878 * active merge set [A,B], we'd return a new template that primarily matches 879 * A, but also matches B. 880 * 881 * @hide 882 */ 883 // TODO: @SystemApi when ready. normalize(NetworkTemplate template, List<String[]> mergedList)884 public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) { 885 // Now there are several types of network which uses SubscriberId to store network 886 // information. For instances: 887 // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network. 888 // The TYPE_CARRIER means that the network associate to specific carrier network. 889 890 if (template.mSubscriberId == null) return template; 891 892 for (String[] merged : mergedList) { 893 if (CollectionUtils.contains(merged, template.mSubscriberId)) { 894 // Requested template subscriber is part of the merge group; return 895 // a template that matches all merged subscribers. 896 final String[] matchWifiNetworkKeys = template.mMatchWifiNetworkKeys; 897 return new NetworkTemplate(template.mMatchRule, merged[0], merged, 898 CollectionUtils.isEmpty(matchWifiNetworkKeys) 899 ? null : matchWifiNetworkKeys[0]); 900 } 901 } 902 903 return template; 904 } 905 906 @UnsupportedAppUsage 907 public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() { 908 @Override 909 public NetworkTemplate createFromParcel(Parcel in) { 910 return new NetworkTemplate(in); 911 } 912 913 @Override 914 public NetworkTemplate[] newArray(int size) { 915 return new NetworkTemplate[size]; 916 } 917 }; 918 919 /** 920 * Builder class for NetworkTemplate. 921 */ 922 public static final class Builder { 923 private final int mMatchRule; 924 // Use a SortedSet to provide a deterministic order when fetching the first one. 925 @NonNull 926 private final SortedSet<String> mMatchSubscriberIds = 927 new TreeSet<>(Comparator.nullsFirst(Comparator.naturalOrder())); 928 @NonNull 929 private final SortedSet<String> mMatchWifiNetworkKeys = new TreeSet<>(); 930 931 // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. 932 private int mMetered; 933 private int mRoaming; 934 private int mDefaultNetwork; 935 private int mRatType; 936 937 // Bitfield containing OEM network properties {@code NetworkIdentity#OEM_*}. 938 private int mOemManaged; 939 940 /** 941 * Creates a new Builder with given match rule to construct NetworkTemplate objects. 942 * 943 * @param matchRule the match rule of the template, see {@code MATCH_*}. 944 */ Builder(@emplateMatchRule final int matchRule)945 public Builder(@TemplateMatchRule final int matchRule) { 946 assertRequestableMatchRule(matchRule); 947 // Initialize members with default values. 948 mMatchRule = matchRule; 949 mMetered = METERED_ALL; 950 mRoaming = ROAMING_ALL; 951 mDefaultNetwork = DEFAULT_NETWORK_ALL; 952 mRatType = NETWORK_TYPE_ALL; 953 mOemManaged = OEM_MANAGED_ALL; 954 } 955 956 /** 957 * Set the Subscriber Ids. Calling this function with an empty set represents 958 * the intention of matching any Subscriber Ids. 959 * 960 * @param subscriberIds the list of Subscriber Ids. 961 * @return this builder. 962 */ 963 @NonNull setSubscriberIds(@onNull Set<String> subscriberIds)964 public Builder setSubscriberIds(@NonNull Set<String> subscriberIds) { 965 Objects.requireNonNull(subscriberIds); 966 mMatchSubscriberIds.clear(); 967 mMatchSubscriberIds.addAll(subscriberIds); 968 return this; 969 } 970 971 /** 972 * Set the Wifi Network Keys. Calling this function with an empty set represents 973 * the intention of matching any Wifi Network Key. 974 * 975 * @param wifiNetworkKeys the list of Wifi Network Key, 976 * see {@link WifiInfo#getNetworkKey()}. 977 * Or an empty list to match all networks. 978 * Note that {@code getNetworkKey()} might get null key 979 * when wifi disconnects. However, the caller should never invoke 980 * this function with a null Wifi Network Key since such statistics 981 * never exists. 982 * @return this builder. 983 */ 984 @NonNull setWifiNetworkKeys(@onNull Set<String> wifiNetworkKeys)985 public Builder setWifiNetworkKeys(@NonNull Set<String> wifiNetworkKeys) { 986 Objects.requireNonNull(wifiNetworkKeys); 987 for (String key : wifiNetworkKeys) { 988 if (key == null) { 989 throw new IllegalArgumentException("Null is not a valid key"); 990 } 991 } 992 mMatchWifiNetworkKeys.clear(); 993 mMatchWifiNetworkKeys.addAll(wifiNetworkKeys); 994 return this; 995 } 996 997 /** 998 * Set the meteredness filter. 999 * 1000 * @param metered the meteredness filter. 1001 * @return this builder. 1002 */ 1003 @NonNull setMeteredness(@etworkStats.Meteredness int metered)1004 public Builder setMeteredness(@NetworkStats.Meteredness int metered) { 1005 mMetered = metered; 1006 return this; 1007 } 1008 1009 /** 1010 * Set the roaming filter. 1011 * 1012 * @param roaming the roaming filter. 1013 * @return this builder. 1014 */ 1015 @NonNull setRoaming(@etworkStats.Roaming int roaming)1016 public Builder setRoaming(@NetworkStats.Roaming int roaming) { 1017 mRoaming = roaming; 1018 return this; 1019 } 1020 1021 /** 1022 * Set the default network status filter. 1023 * 1024 * @param defaultNetwork the default network status filter. 1025 * @return this builder. 1026 */ 1027 @NonNull setDefaultNetworkStatus(@etworkStats.DefaultNetwork int defaultNetwork)1028 public Builder setDefaultNetworkStatus(@NetworkStats.DefaultNetwork int defaultNetwork) { 1029 mDefaultNetwork = defaultNetwork; 1030 return this; 1031 } 1032 1033 /** 1034 * Set the Radio Access Technology(RAT) type filter. 1035 * 1036 * @param ratType the Radio Access Technology(RAT) type filter. Use 1037 * {@link #NETWORK_TYPE_ALL} to include all network types when filtering. 1038 * See {@code TelephonyManager.NETWORK_TYPE_*}. 1039 * @return this builder. 1040 */ 1041 @NonNull setRatType(int ratType)1042 public Builder setRatType(int ratType) { 1043 // Input will be validated with the match rule when building the template. 1044 mRatType = ratType; 1045 return this; 1046 } 1047 1048 /** 1049 * Set the OEM managed filter. 1050 * 1051 * @param oemManaged the match rule to match different type of OEM managed network or 1052 * unmanaged networks. See {@code OEM_MANAGED_*}. 1053 * @return this builder. 1054 */ 1055 @NonNull setOemManaged(@emManaged int oemManaged)1056 public Builder setOemManaged(@OemManaged int oemManaged) { 1057 mOemManaged = oemManaged; 1058 return this; 1059 } 1060 1061 /** 1062 * Check whether the match rule is requestable. 1063 * 1064 * @param matchRule the target match rule to be checked. 1065 */ assertRequestableMatchRule(final int matchRule)1066 private static void assertRequestableMatchRule(final int matchRule) { 1067 if (!isKnownMatchRule(matchRule) 1068 || matchRule == MATCH_PROXY 1069 || matchRule == MATCH_MOBILE_WILDCARD 1070 || matchRule == MATCH_WIFI_WILDCARD) { 1071 throw new IllegalArgumentException("Invalid match rule: " 1072 + getMatchRuleName(matchRule)); 1073 } 1074 } 1075 assertRequestableParameters()1076 private void assertRequestableParameters() { 1077 validateWifiNetworkKeys(); 1078 // TODO: Check all the input are legitimate. 1079 } 1080 validateWifiNetworkKeys()1081 private void validateWifiNetworkKeys() { 1082 if (mMatchRule != MATCH_WIFI && !mMatchWifiNetworkKeys.isEmpty()) { 1083 throw new IllegalArgumentException("Trying to build non wifi match rule: " 1084 + mMatchRule + " with wifi network keys"); 1085 } 1086 } 1087 1088 /** 1089 * For backward compatibility, deduce match rule to a wildcard match rule 1090 * if the Subscriber Ids are empty. 1091 */ getWildcardDeducedMatchRule()1092 private int getWildcardDeducedMatchRule() { 1093 if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) { 1094 return MATCH_MOBILE_WILDCARD; 1095 } else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty() 1096 && mMatchWifiNetworkKeys.isEmpty()) { 1097 return MATCH_WIFI_WILDCARD; 1098 } 1099 return mMatchRule; 1100 } 1101 1102 /** 1103 * Builds the instance of the NetworkTemplate. 1104 * 1105 * @return the built instance of NetworkTemplate. 1106 */ 1107 @NonNull build()1108 public NetworkTemplate build() { 1109 assertRequestableParameters(); 1110 final int subscriberIdMatchRule = mMatchSubscriberIds.isEmpty() 1111 ? NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL 1112 : NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT; 1113 return new NetworkTemplate(getWildcardDeducedMatchRule(), 1114 mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(), 1115 mMatchSubscriberIds.toArray(new String[0]), 1116 mMatchWifiNetworkKeys.toArray(new String[0]), mMetered, mRoaming, 1117 mDefaultNetwork, mRatType, mOemManaged, subscriberIdMatchRule); 1118 } 1119 } 1120 } 1121