diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index cb5a025278..7dd04c5d42 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -47,6 +47,7 @@ import android.os.Parcelable; import android.telephony.Annotation.NetworkType; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArraySet; import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkIdentityUtils; @@ -58,6 +59,9 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; /** * Predicate used to match {@link NetworkIdentity}, usually when collecting @@ -119,21 +123,31 @@ public final class NetworkTemplate implements Parcelable { public @interface SubscriberIdMatchRule{} /** * Value of the match rule of the subscriberId to match networks with specific subscriberId. + * + * @hide */ public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0; /** * Value of the match rule of the subscriberId to match networks with any subscriberId which * includes null and non-null. + * + * @hide */ public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1; - /** - * Wi-Fi Network ID is never supposed to be null (if it is, it is a bug that - * should be fixed), so it's not possible to want to match null vs - * non-null. Therefore it's fine to use null as a sentinel for Network ID. - */ + // TODO: Remove this and replace all callers with WIFI_NETWORK_KEY_ALL. + /** @hide */ public static final String WIFI_NETWORKID_ALL = null; + /** + * Wi-Fi Network Key is never supposed to be null (if it is, it is a bug that + * should be fixed), so it's not possible to want to match null vs + * non-null. Therefore it's fine to use null as a sentinel for Wifi Network Key. + * + * @hide + */ + public static final String WIFI_NETWORK_KEY_ALL = WIFI_NETWORKID_ALL; + /** * Include all network types when filtering. This is meant to merge in with the * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. @@ -278,7 +292,10 @@ public final class NetworkTemplate implements Parcelable { * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID, * and IMSI. * - * Call with {@link #WIFI_NETWORKID_ALL} for {@code networkId} to get result regardless of SSID. + * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code networkId} to get result regardless + * of SSID. + * + * @hide */ public static NetworkTemplate buildTemplateWifi(@Nullable String networkId, @Nullable String subscriberId) { @@ -345,6 +362,7 @@ public final class NetworkTemplate implements Parcelable { */ private final String[] mMatchSubscriberIds; + // TODO: Change variable name to match the Api surface. private final String mNetworkId; // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. @@ -361,14 +379,14 @@ public final class NetworkTemplate implements Parcelable { // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}. private final int mOemManaged; - private void checkValidSubscriberIdMatchRule() { - switch (mMatchRule) { + private static void checkValidSubscriberIdMatchRule(int matchRule, int subscriberIdMatchRule) { + switch (matchRule) { case MATCH_MOBILE: case MATCH_CARRIER: // MOBILE and CARRIER templates must always specify a subscriber ID. - if (mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { - throw new IllegalArgumentException("Invalid SubscriberIdMatchRule" - + "on match rule: " + getMatchRuleName(mMatchRule)); + if (subscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { + throw new IllegalArgumentException("Invalid SubscriberIdMatchRule " + + "on match rule: " + getMatchRuleName(matchRule)); } return; default: @@ -421,7 +439,7 @@ public final class NetworkTemplate implements Parcelable { mSubType = subType; mOemManaged = oemManaged; mSubscriberIdMatchRule = subscriberIdMatchRule; - checkValidSubscriberIdMatchRule(); + checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule); if (!isKnownMatchRule(matchRule)) { throw new IllegalArgumentException("Unknown network template rule " + matchRule + " will not match any identity."); @@ -519,7 +537,7 @@ public final class NetworkTemplate implements Parcelable { return false; } - private String subscriberIdMatchRuleToString(int rule) { + private static String subscriberIdMatchRuleToString(int rule) { switch (rule) { case SUBSCRIBER_ID_MATCH_RULE_EXACT: return "EXACT_MATCH"; @@ -555,7 +573,7 @@ public final class NetworkTemplate implements Parcelable { case MATCH_CARRIER: return mSubscriberId != null; case MATCH_WIFI: - if (Objects.equals(mNetworkId, WIFI_NETWORKID_ALL) + if (Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL) && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { return false; } @@ -570,7 +588,16 @@ public final class NetworkTemplate implements Parcelable { */ @UnsupportedAppUsage public int getMatchRule() { - return mMatchRule; + // Wildcard rules are not exposed. For external callers, convert wildcard rules to + // exposed rules before returning. + switch (mMatchRule) { + case MATCH_MOBILE_WILDCARD: + return MATCH_MOBILE; + case MATCH_WIFI_WILDCARD: + return MATCH_WIFI; + default: + return mMatchRule; + } } /** @@ -582,12 +609,33 @@ public final class NetworkTemplate implements Parcelable { return mSubscriberId; } + /** + * Get set of subscriber Ids of the template. + */ + @NonNull + public Set getSubscriberIds() { + return new ArraySet<>(Arrays.asList(mMatchSubscriberIds)); + } + + /** + * Get Wifi Network Key of the template. See {@link WifiInfo#getCurrentNetworkKey()}. + */ + @Nullable + public String getWifiNetworkKey() { + return mNetworkId; + } + + /** @hide */ + // TODO: Remove this and replace all callers with {@link #getWifiNetworkKey()}. + @Nullable public String getNetworkId() { return mNetworkId; } /** * Get Subscriber Id Match Rule of the template. + * + * @hide */ public int getSubscriberIdMatchRule() { return mSubscriberIdMatchRule; @@ -601,6 +649,38 @@ public final class NetworkTemplate implements Parcelable { return mMetered; } + /** + * Get roaming filter of the template. + */ + @NetworkStats.Roaming + public int getRoaming() { + return mRoaming; + } + + /** + * Get the default network status filter of the template. + */ + @NetworkStats.DefaultNetwork + public int getDefaultNetworkStatus() { + return mDefaultNetwork; + } + + /** + * Get the Radio Access Technology(RAT) type filter of the template. + */ + public int getRatType() { + return mSubType; + } + + /** + * Get the OEM managed filter of the template. See {@code OEM_MANAGED_*} or + * {@code android.net.NetworkIdentity#OEM_*}. + */ + @OemManaged + public int getOemManaged() { + return mOemManaged; + } + /** * Test if given {@link NetworkIdentity} matches this template. * @@ -680,10 +760,10 @@ public final class NetworkTemplate implements Parcelable { /** * Check if network with matching SSID. Returns true when the SSID matches, or when - * {@code mNetworkId} is {@code WIFI_NETWORKID_ALL}. + * {@code mNetworkId} is {@code WIFI_NETWORK_KEY_ALL}. */ private boolean matchesWifiNetworkId(@Nullable String networkId) { - return Objects.equals(mNetworkId, WIFI_NETWORKID_ALL) + return Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL) || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId)); } @@ -948,4 +1028,184 @@ public final class NetworkTemplate implements Parcelable { return new NetworkTemplate[size]; } }; + + /** + * Builder class for NetworkTemplate. + */ + public static final class Builder { + private final int mMatchRule; + // Use a SortedSet to provide a deterministic order when fetching the first one. + @NonNull + private final SortedSet mMatchSubscriberIds = new TreeSet<>(); + @Nullable + private String mWifiNetworkKey; + + // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. + private int mMetered; + private int mRoaming; + private int mDefaultNetwork; + private int mRatType; + + // Bitfield containing OEM network properties {@code NetworkIdentity#OEM_*}. + private int mOemManaged; + + /** + * Creates a new Builder with given match rule to construct NetworkTemplate objects. + * + * @param matchRule the match rule of the template, see {@code MATCH_*}. + */ + public Builder(@TemplateMatchRule final int matchRule) { + assertRequestableMatchRule(matchRule); + // Initialize members with default values. + mMatchRule = matchRule; + mWifiNetworkKey = WIFI_NETWORK_KEY_ALL; + mMetered = METERED_ALL; + mRoaming = ROAMING_ALL; + mDefaultNetwork = DEFAULT_NETWORK_ALL; + mRatType = NETWORK_TYPE_ALL; + mOemManaged = OEM_MANAGED_ALL; + } + + /** + * Set the Subscriber Ids. Calling this function with an empty set represents + * the intention of matching any Subscriber Ids. + * + * @param subscriberIds the list of Subscriber Ids. + * @return this builder. + */ + @NonNull + public Builder setSubscriberIds(@NonNull Set subscriberIds) { + Objects.requireNonNull(subscriberIds); + mMatchSubscriberIds.clear(); + mMatchSubscriberIds.addAll(subscriberIds); + return this; + } + + /** + * Set the Wifi Network Key. + * + * @param wifiNetworkKey the Wifi Network Key, see {@link WifiInfo#getCurrentNetworkKey()}. + * Or null to match all networks. + * @return this builder. + */ + @NonNull + public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) { + mWifiNetworkKey = wifiNetworkKey; + return this; + } + + /** + * Set the meteredness filter. + * + * @param metered the meteredness filter. + * @return this builder. + */ + @NonNull + public Builder setMeteredness(@NetworkStats.Meteredness int metered) { + mMetered = metered; + return this; + } + + /** + * Set the roaming filter. + * + * @param roaming the roaming filter. + * @return this builder. + */ + @NonNull + public Builder setRoaming(@NetworkStats.Roaming int roaming) { + mRoaming = roaming; + return this; + } + + /** + * Set the default network status filter. + * + * @param defaultNetwork the default network status filter. + * @return this builder. + */ + @NonNull + public Builder setDefaultNetworkStatus(@NetworkStats.DefaultNetwork int defaultNetwork) { + mDefaultNetwork = defaultNetwork; + return this; + } + + /** + * Set the Radio Access Technology(RAT) type filter. + * + * @param ratType the Radio Access Technology(RAT) type filter. Use + * {@link #NETWORK_TYPE_ALL} to include all network types when filtering. + * See {@code TelephonyManager.NETWORK_TYPE_*}. + * @return this builder. + */ + @NonNull + public Builder setRatType(@NetworkType int ratType) { + // Input will be validated with the match rule when building the template. + mRatType = ratType; + return this; + } + + /** + * Set the OEM managed filter. + * + * @param oemManaged the match rule to match different type of OEM managed network or + * unmanaged networks. See {@code OEM_MANAGED_*}. + * @return this builder. + */ + @NonNull + public Builder setOemManaged(@OemManaged int oemManaged) { + mOemManaged = oemManaged; + return this; + } + + /** + * Check whether the match rule is requestable. + * + * @param matchRule the target match rule to be checked. + */ + private static void assertRequestableMatchRule(final int matchRule) { + if (!isKnownMatchRule(matchRule) + || matchRule == MATCH_PROXY + || matchRule == MATCH_MOBILE_WILDCARD + || matchRule == MATCH_WIFI_WILDCARD) { + throw new IllegalArgumentException("Invalid match rule: " + + getMatchRuleName(matchRule)); + } + } + + private void assertRequestableParameters() { + // TODO: Check all the input are legitimate. + } + + /** + * For backward compatibility, deduce match rule to a wildcard match rule + * if the Subscriber Ids are empty. + */ + private int getWildcardDeducedMatchRule() { + if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) { + return MATCH_MOBILE_WILDCARD; + } else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty() + && mWifiNetworkKey == WIFI_NETWORK_KEY_ALL) { + return MATCH_WIFI_WILDCARD; + } + return mMatchRule; + } + + /** + * Builds the instance of the NetworkTemplate. + * + * @return the built instance of NetworkTemplate. + */ + @NonNull + public NetworkTemplate build() { + assertRequestableParameters(); + final int subscriberIdMatchRule = mMatchSubscriberIds.isEmpty() + ? SUBSCRIBER_ID_MATCH_RULE_ALL : SUBSCRIBER_ID_MATCH_RULE_EXACT; + return new NetworkTemplate(getWildcardDeducedMatchRule(), + mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(), + mMatchSubscriberIds.toArray(new String[0]), + mWifiNetworkKey, mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, + subscriberIdMatchRule); + } + } }