summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/ConnectivityManager.java10
-rw-r--r--core/java/android/net/INetworkPolicyManager.aidl2
-rw-r--r--core/java/android/net/NetworkInfo.java32
-rw-r--r--core/java/android/net/NetworkPolicy.java2
-rw-r--r--core/java/android/net/NetworkPolicyManager.java11
-rw-r--r--core/java/android/net/NetworkQuotaInfo.java26
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java48
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java8
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java17
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java43
-rw-r--r--services/core/java/com/android/server/job/controllers/ConnectivityController.java40
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java225
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java134
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java70
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java8
15 files changed, 227 insertions, 449 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2979cd8a5dba..7a1d85c93de0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1720,14 +1720,8 @@ public class ConnectivityManager {
// ignored
}
- /**
- * Return quota status for the current active network, or {@code null} if no
- * network is active. Quota status can change rapidly, so these values
- * shouldn't be cached.
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ /** {@hide} */
+ @Deprecated
public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
try {
return mService.getActiveNetworkQuotaInfo();
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 63bbd96bd01d..7b1e61e6dea1 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -63,9 +63,9 @@ interface INetworkPolicyManager {
int getRestrictBackgroundByCaller();
void setDeviceIdleMode(boolean enabled);
+ void setWifiMeteredOverride(String networkId, int meteredOverride);
NetworkQuotaInfo getNetworkQuotaInfo(in NetworkState state);
- boolean isNetworkMetered(in NetworkState state);
void factoryReset(String subscriber);
}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 84c32bec8ef7..818aa211625d 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -16,8 +16,8 @@
package android.net;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
@@ -121,7 +121,6 @@ public class NetworkInfo implements Parcelable {
private boolean mIsFailover;
private boolean mIsAvailable;
private boolean mIsRoaming;
- private boolean mIsMetered;
/**
* @hide
@@ -154,7 +153,6 @@ public class NetworkInfo implements Parcelable {
mIsFailover = source.mIsFailover;
mIsAvailable = source.mIsAvailable;
mIsRoaming = source.mIsRoaming;
- mIsMetered = source.mIsMetered;
}
}
}
@@ -327,31 +325,6 @@ public class NetworkInfo implements Parcelable {
}
/**
- * Returns if this network is metered. A network is classified as metered
- * when the user is sensitive to heavy data usage on that connection due to
- * monetary costs, data limitations or battery/performance issues. You
- * should check this before doing large data transfers, and warn the user or
- * delay the operation until another network is available.
- *
- * @return {@code true} if large transfers should be avoided, otherwise
- * {@code false}.
- * @hide
- */
- public boolean isMetered() {
- synchronized (this) {
- return mIsMetered;
- }
- }
-
- /** {@hide} */
- @VisibleForTesting
- public void setMetered(boolean isMetered) {
- synchronized (this) {
- mIsMetered = isMetered;
- }
- }
-
- /**
* Reports the current coarse-grained state of the network.
* @return the coarse-grained state
*/
@@ -434,7 +407,6 @@ public class NetworkInfo implements Parcelable {
append(", failover: ").append(mIsFailover).
append(", available: ").append(mIsAvailable).
append(", roaming: ").append(mIsRoaming).
- append(", metered: ").append(mIsMetered).
append("]");
return builder.toString();
}
@@ -457,7 +429,6 @@ public class NetworkInfo implements Parcelable {
dest.writeInt(mIsFailover ? 1 : 0);
dest.writeInt(mIsAvailable ? 1 : 0);
dest.writeInt(mIsRoaming ? 1 : 0);
- dest.writeInt(mIsMetered ? 1 : 0);
dest.writeString(mReason);
dest.writeString(mExtraInfo);
}
@@ -476,7 +447,6 @@ public class NetworkInfo implements Parcelable {
netInfo.mIsFailover = in.readInt() != 0;
netInfo.mIsAvailable = in.readInt() != 0;
netInfo.mIsRoaming = in.readInt() != 0;
- netInfo.mIsMetered = in.readInt() != 0;
netInfo.mReason = in.readString();
netInfo.mExtraInfo = in.readString();
return netInfo;
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 9870e7b6fa0c..58306675d2c7 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -52,7 +52,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
public long limitBytes;
public long lastWarningSnooze;
public long lastLimitSnooze;
- public boolean metered;
+ @Deprecated public boolean metered;
public boolean inferred;
private static final long DEFAULT_MTU = 1500;
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 4d94a55cd0c4..fc96004e7dcb 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -26,6 +26,8 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.DebugUtils;
@@ -400,4 +402,13 @@ public class NetworkPolicyManager {
public static boolean isProcStateAllowedWhileOnRestrictBackground(int procState) {
return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
}
+
+ public static String resolveNetworkId(WifiConfiguration config) {
+ return WifiInfo.removeDoubleQuotes(config.isPasspoint()
+ ? config.providerFriendlyName : config.SSID);
+ }
+
+ public static String resolveNetworkId(String ssid) {
+ return WifiInfo.removeDoubleQuotes(ssid);
+ }
}
diff --git a/core/java/android/net/NetworkQuotaInfo.java b/core/java/android/net/NetworkQuotaInfo.java
index 1725ed7b015e..b95f1d983180 100644
--- a/core/java/android/net/NetworkQuotaInfo.java
+++ b/core/java/android/net/NetworkQuotaInfo.java
@@ -20,41 +20,32 @@ import android.os.Parcel;
import android.os.Parcelable;
/**
- * Information about quota status on a specific network.
- *
+ * @deprecated nobody should be using this, but keep it around returning stub
+ * values to prevent app crashes.
* @hide
*/
+@Deprecated
public class NetworkQuotaInfo implements Parcelable {
- private final long mEstimatedBytes;
- private final long mSoftLimitBytes;
- private final long mHardLimitBytes;
-
public static final long NO_LIMIT = -1;
/** {@hide} */
- public NetworkQuotaInfo(long estimatedBytes, long softLimitBytes, long hardLimitBytes) {
- mEstimatedBytes = estimatedBytes;
- mSoftLimitBytes = softLimitBytes;
- mHardLimitBytes = hardLimitBytes;
+ public NetworkQuotaInfo() {
}
/** {@hide} */
public NetworkQuotaInfo(Parcel in) {
- mEstimatedBytes = in.readLong();
- mSoftLimitBytes = in.readLong();
- mHardLimitBytes = in.readLong();
}
public long getEstimatedBytes() {
- return mEstimatedBytes;
+ return 0;
}
public long getSoftLimitBytes() {
- return mSoftLimitBytes;
+ return NO_LIMIT;
}
public long getHardLimitBytes() {
- return mHardLimitBytes;
+ return NO_LIMIT;
}
@Override
@@ -64,9 +55,6 @@ public class NetworkQuotaInfo implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeLong(mEstimatedBytes);
- out.writeLong(mSoftLimitBytes);
- out.writeLong(mHardLimitBytes);
}
public static final Creator<NetworkQuotaInfo> CREATOR = new Creator<NetworkQuotaInfo>() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
index 2e77f4264de6..3640bfa4b23a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
+++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
@@ -21,6 +21,7 @@ import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkTemplate.MATCH_WIFI;
+
import static com.android.internal.util.Preconditions.checkNotNull;
import android.net.NetworkPolicy;
@@ -204,53 +205,6 @@ public class NetworkPolicyEditor {
writeAsync();
}
- public boolean getPolicyMetered(NetworkTemplate template) {
- NetworkPolicy policy = getPolicy(template);
- if (policy != null) {
- return policy.metered;
- } else {
- return false;
- }
- }
-
- public void setPolicyMetered(NetworkTemplate template, boolean metered) {
- boolean modified = false;
-
- NetworkPolicy policy = getPolicy(template);
- if (metered) {
- if (policy == null) {
- policy = buildDefaultPolicy(template);
- policy.metered = true;
- policy.inferred = false;
- mPolicies.add(policy);
- modified = true;
- } else if (!policy.metered) {
- policy.metered = true;
- policy.inferred = false;
- modified = true;
- }
-
- } else {
- if (policy == null) {
- // ignore when policy doesn't exist
- } else if (policy.metered) {
- policy.metered = false;
- policy.inferred = false;
- modified = true;
- }
- }
-
- // Remove legacy unquoted policies while we're here
- final NetworkTemplate unquoted = buildUnquotedNetworkTemplate(template);
- final NetworkPolicy unquotedPolicy = getPolicy(unquoted);
- if (unquotedPolicy != null) {
- mPolicies.remove(unquotedPolicy);
- modified = true;
- }
-
- if (modified) writeAsync();
- }
-
/**
* Build a revised {@link NetworkTemplate} that matches the same rule, but
* with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index ec4141518f82..7bbc598a0a0e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -552,15 +552,11 @@ public class AccessPoint implements Comparable<AccessPoint> {
}
/**
- * Returns if the network is marked metered. Metering can be marked through its config in
- * {@link WifiConfiguration}, after connection in {@link WifiInfo}, or from a score config in
- * {@link ScoredNetwork}.
+ * Returns if the network should be considered metered.
*/
public boolean isMetered() {
return mIsScoredNetworkMetered
- || (mConfig != null && mConfig.meteredHint)
- || (mInfo != null && mInfo.getMeteredHint()
- || (mNetworkInfo != null && mNetworkInfo.isMetered()));
+ || WifiConfiguration.isMetered(mConfig, mInfo);
}
public NetworkInfo getNetworkInfo() {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index c08dd6ed97cd..aed027002939 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -298,23 +298,6 @@ public class AccessPointTest {
}
@Test
- public void testIsMetered_returnTrueWhenNetworkInfoIsMetered() {
- WifiConfiguration configuration = createWifiConfiguration();
-
- NetworkInfo networkInfo =
- new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
- networkInfo.setMetered(true);
- AccessPoint accessPoint = new AccessPoint(mContext, configuration);
- WifiInfo wifiInfo = new WifiInfo();
- wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
- wifiInfo.setBSSID(configuration.BSSID);
- wifiInfo.setNetworkId(configuration.networkId);
- accessPoint.update(configuration, wifiInfo, networkInfo);
-
- assertThat(accessPoint.isMetered()).isTrue();
- }
-
- @Test
public void testIsMetered_returnTrueWhenScoredNetworkIsMetered() {
AccessPoint ap = createAccessPointWithScanResultCache();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a2e74b6a3812..8200289a76b2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1036,8 +1036,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* Apply any relevant filters to {@link NetworkState} for the given UID. For
* example, this may mark the network as {@link DetailedState#BLOCKED} based
- * on {@link #isNetworkWithLinkPropertiesBlocked}, or
- * {@link NetworkInfo#isMetered()} based on network policies.
+ * on {@link #isNetworkWithLinkPropertiesBlocked}.
*/
private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) {
if (state == null || state.networkInfo == null || state.linkProperties == null) return;
@@ -1048,15 +1047,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (mLockdownTracker != null) {
mLockdownTracker.augmentNetworkInfo(state.networkInfo);
}
-
- // TODO: apply metered state closer to NetworkAgentInfo
- final long token = Binder.clearCallingIdentity();
- try {
- state.networkInfo.setMetered(mPolicyManager.isNetworkMetered(state));
- } catch (RemoteException e) {
- } finally {
- Binder.restoreCallingIdentity(token);
- }
}
/**
@@ -1326,30 +1316,24 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
@Override
+ @Deprecated
public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
- enforceAccessPermission();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- final NetworkState state = getUnfilteredActiveNetworkState(uid);
- if (state.networkInfo != null) {
- try {
- return mPolicyManager.getNetworkQuotaInfo(state);
- } catch (RemoteException e) {
- }
- }
- return null;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ Log.w(TAG, "Shame on UID " + Binder.getCallingUid()
+ + " for calling the hidden API getNetworkQuotaInfo(). Shame!");
+ return new NetworkQuotaInfo();
}
@Override
public boolean isActiveNetworkMetered() {
enforceAccessPermission();
- final NetworkInfo info = getActiveNetworkInfo();
- return (info != null) ? info.isMetered() : false;
+ final NetworkCapabilities caps = getNetworkCapabilities(getActiveNetwork());
+ if (caps != null) {
+ return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ } else {
+ // Always return the most conservative value
+ return true;
+ }
}
private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
@@ -2759,7 +2743,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
enforceAccessPermission();
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
- if (nai != null && !nai.networkInfo.isMetered()) {
+ if (nai != null && nai.networkCapabilities
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED;
}
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 17c89282f280..78367fe97a54 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -85,7 +85,7 @@ public final class ConnectivityController extends StateController implements
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
if (jobStatus.hasConnectivityConstraint()) {
- updateConstraintsSatisfied(jobStatus, null);
+ updateConstraintsSatisfied(jobStatus);
mTrackedJobs.add(jobStatus);
jobStatus.setTrackingController(JobStatus.TRACKING_CONNECTIVITY);
}
@@ -99,23 +99,25 @@ public final class ConnectivityController extends StateController implements
}
}
- private boolean updateConstraintsSatisfied(JobStatus jobStatus,
- NetworkCapabilities capabilities) {
+ private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
final int jobUid = jobStatus.getSourceUid();
final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobUid, ignoreBlocked);
- if (capabilities == null) {
- final Network network = mConnManager.getActiveNetworkForUid(jobUid, ignoreBlocked);
- capabilities = mConnManager.getNetworkCapabilities(network);
- }
+ final Network network = mConnManager.getActiveNetworkForUid(jobUid, ignoreBlocked);
+ final NetworkCapabilities capabilities = (network != null)
+ ? mConnManager.getNetworkCapabilities(network) : null;
- final boolean validated = capabilities != null
+ final boolean validated = (capabilities != null)
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
- final boolean connected = info != null && info.isConnected();
+ final boolean connected = (info != null) && info.isConnected();
final boolean connectionUsable = connected && validated;
- final boolean metered = connected && info.isMetered();
- final boolean unmetered = connected && !info.isMetered();
- final boolean notRoaming = connected && !info.isRoaming();
+
+ final boolean metered = connected && (capabilities != null)
+ && !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ final boolean unmetered = connected && (capabilities != null)
+ && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ final boolean notRoaming = connected && (info != null)
+ && !info.isRoaming();
boolean changed = false;
changed |= jobStatus.setConnectivityConstraintSatisfied(connectionUsable);
@@ -148,13 +150,13 @@ public final class ConnectivityController extends StateController implements
* @param uid only update jobs belonging to this UID, or {@code -1} to
* update all tracked jobs.
*/
- private void updateTrackedJobs(int uid, NetworkCapabilities capabilities) {
+ private void updateTrackedJobs(int uid) {
synchronized (mLock) {
boolean changed = false;
for (int i = mTrackedJobs.size()-1; i >= 0; i--) {
final JobStatus js = mTrackedJobs.valueAt(i);
if (uid == -1 || uid == js.getSourceUid()) {
- changed |= updateConstraintsSatisfied(js, capabilities);
+ changed |= updateConstraintsSatisfied(js);
}
}
if (changed) {
@@ -187,7 +189,7 @@ public final class ConnectivityController extends StateController implements
if (DEBUG) {
Slog.v(TAG, "onCapabilitiesChanged() : " + networkCapabilities);
}
- updateTrackedJobs(-1, networkCapabilities);
+ updateTrackedJobs(-1);
}
@Override
@@ -195,7 +197,7 @@ public final class ConnectivityController extends StateController implements
if (DEBUG) {
Slog.v(TAG, "Network lost");
}
- updateTrackedJobs(-1, null);
+ updateTrackedJobs(-1);
}
};
@@ -205,7 +207,7 @@ public final class ConnectivityController extends StateController implements
if (DEBUG) {
Slog.v(TAG, "Uid rules changed for " + uid);
}
- updateTrackedJobs(uid, null);
+ updateTrackedJobs(uid);
}
@Override
@@ -218,7 +220,7 @@ public final class ConnectivityController extends StateController implements
if (DEBUG) {
Slog.v(TAG, "Background restriction change to " + restrictBackground);
}
- updateTrackedJobs(-1, null);
+ updateTrackedJobs(-1);
}
@Override
@@ -226,7 +228,7 @@ public final class ConnectivityController extends StateController implements
if (DEBUG) {
Slog.v(TAG, "Uid policy changed for " + uid);
}
- updateTrackedJobs(uid, null);
+ updateTrackedJobs(uid);
}
};
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index b6af07677d61..8b8811e252c0 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -18,7 +18,6 @@ package com.android.server.net;
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
-import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.READ_PHONE_STATE;
@@ -33,9 +32,6 @@ import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLE
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIMAX;
-import static android.net.ConnectivityManager.isNetworkTypeMobile;
-import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -46,13 +42,13 @@ import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
+import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
+import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
-import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
@@ -60,6 +56,7 @@ import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
+import static android.net.NetworkPolicyManager.resolveNetworkId;
import static android.net.NetworkPolicyManager.uidPoliciesToString;
import static android.net.NetworkPolicyManager.uidRulesToString;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
@@ -68,16 +65,9 @@ import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.TrafficStats.MB_IN_BYTES;
-import static android.net.wifi.WifiManager.CHANGE_REASON_ADDED;
-import static android.net.wifi.WifiManager.CHANGE_REASON_REMOVED;
-import static android.net.wifi.WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION;
-import static android.net.wifi.WifiManager.EXTRA_CHANGE_REASON;
-import static android.net.wifi.WifiManager.EXTRA_NETWORK_INFO;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION;
-import static android.net.wifi.WifiManager.EXTRA_WIFI_INFO;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
-import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
+import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.internal.util.ArrayUtils.appendInt;
@@ -127,15 +117,12 @@ import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.LinkProperties;
import android.net.NetworkIdentity;
-import android.net.NetworkInfo;
import android.net.NetworkPolicy;
import android.net.NetworkQuotaInfo;
import android.net.NetworkState;
import android.net.NetworkTemplate;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
@@ -147,6 +134,7 @@ import android.os.MessageQueue.IdleHandler;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -190,8 +178,8 @@ import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
-
import com.android.server.power.BatterySaverPolicy.ServiceType;
+
import libcore.io.IoUtils;
import com.google.android.collect.Lists;
@@ -212,8 +200,8 @@ import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
import java.util.Calendar;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -756,15 +744,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter,
MANAGE_NETWORK_POLICY, mHandler);
- // listen for configured wifi networks to be removed
- final IntentFilter wifiConfigFilter =
- new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION);
- mContext.registerReceiver(mWifiConfigReceiver, wifiConfigFilter, null, mHandler);
-
- // listen for wifi state changes to catch metered hint
- final IntentFilter wifiStateFilter = new IntentFilter(
- WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
+ // listen for configured wifi networks to be loaded
+ final IntentFilter wifiFilter =
+ new IntentFilter(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
+ mContext.registerReceiver(mWifiReceiver, wifiFilter, null, mHandler);
// listen for carrier config changes to update data cycle information
final IntentFilter carrierConfigFilter = new IntentFilter(
@@ -960,80 +943,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
};
/**
- * Receiver that watches for {@link WifiConfiguration} to be changed.
- */
- final private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // on background handler thread, and verified CONNECTIVITY_INTERNAL
- // permission above.
-
- final int reason = intent.getIntExtra(EXTRA_CHANGE_REASON, CHANGE_REASON_ADDED);
- if (reason == CHANGE_REASON_REMOVED) {
- final WifiConfiguration config = intent.getParcelableExtra(
- EXTRA_WIFI_CONFIGURATION);
- if (config.SSID != null) {
- final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(config.SSID);
- synchronized (mUidRulesFirstLock) {
- synchronized (mNetworkPoliciesSecondLock) {
- if (mNetworkPolicy.containsKey(template)) {
- mNetworkPolicy.remove(template);
- writePolicyAL();
- }
- }
- }
- }
- }
- }
- };
-
- /**
- * Receiver that watches {@link WifiInfo} state changes to infer metered
- * state. Ignores hints when policy is user-defined.
+ * Receiver that watches for {@link WifiConfiguration} to be loaded so that
+ * we can perform upgrade logic.
*/
- final private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
+ final private BroadcastReceiver mWifiReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- // on background handler thread, and verified CONNECTIVITY_INTERNAL
- // permission above.
-
- // ignore when not connected
- final NetworkInfo netInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
- if (!netInfo.isConnected()) return;
-
- final WifiInfo info = intent.getParcelableExtra(EXTRA_WIFI_INFO);
- final boolean meteredHint = info.getMeteredHint();
-
- final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(info.getSSID());
synchronized (mUidRulesFirstLock) {
synchronized (mNetworkPoliciesSecondLock) {
- NetworkPolicy policy = mNetworkPolicy.get(template);
- if (policy == null && meteredHint) {
- // policy doesn't exist, and AP is hinting that it's
- // metered: create an inferred policy.
- policy = newWifiPolicy(template, meteredHint);
- addNetworkPolicyAL(policy);
-
- } else if (policy != null && policy.inferred) {
- // policy exists, and was inferred: update its current
- // metered state.
- policy.metered = meteredHint;
-
- // since this is inferred for each wifi session, just update
- // rules without persisting.
- updateNetworkRulesNL();
- }
+ upgradeWifiMeteredOverrideAL();
}
}
+ // Only need to perform upgrade logic once
+ mContext.unregisterReceiver(this);
}
};
- static NetworkPolicy newWifiPolicy(NetworkTemplate template, boolean metered) {
- return new NetworkPolicy(template, CYCLE_NONE, Time.TIMEZONE_UTC,
- WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER,
- metered, true);
- }
-
/**
* Observer that watches for {@link INetworkManagementService} alerts.
*/
@@ -1905,7 +1830,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
lastLimitSnooze, metered, inferred));
}
-
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
final int policy = readIntAttribute(in, ATTR_POLICY);
@@ -1991,6 +1915,40 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ /**
+ * Perform upgrade step of moving any user-defined meterness overrides over
+ * into {@link WifiConfiguration}.
+ */
+ private void upgradeWifiMeteredOverrideAL() {
+ boolean modified = false;
+ final WifiManager wm = mContext.getSystemService(WifiManager.class);
+ final List<WifiConfiguration> configs = wm.getConfiguredNetworks();
+ for (int i = 0; i < mNetworkPolicy.size(); ) {
+ final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
+ if (policy.template.getMatchRule() == NetworkTemplate.MATCH_WIFI
+ && !policy.inferred) {
+ mNetworkPolicy.removeAt(i);
+ modified = true;
+
+ final String networkId = resolveNetworkId(policy.template.getNetworkId());
+ for (WifiConfiguration config : configs) {
+ if (Objects.equals(resolveNetworkId(config), networkId)) {
+ Slog.d(TAG, "Found network " + networkId + "; upgrading metered hint");
+ config.meteredOverride = policy.metered
+ ? WifiConfiguration.METERED_OVERRIDE_METERED
+ : WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
+ wm.updateNetwork(config);
+ }
+ }
+ } else {
+ i++;
+ }
+ }
+ if (modified) {
+ writePolicyAL();
+ }
+ }
+
void writePolicyAL() {
if (LOGV) Slog.v(TAG, "writePolicyAL()");
@@ -2495,81 +2453,30 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- private NetworkPolicy findPolicyForNetworkNL(NetworkIdentity ident) {
- for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
- NetworkPolicy policy = mNetworkPolicy.valueAt(i);
- if (policy.template.matches(ident)) {
- return policy;
- }
- }
- return null;
- }
-
@Override
- public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
- mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
-
- // only returns usage summary, so we don't require caller to have
- // READ_NETWORK_USAGE_HISTORY.
+ public void setWifiMeteredOverride(String networkId, int meteredOverride) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
final long token = Binder.clearCallingIdentity();
try {
- return getNetworkQuotaInfoUnchecked(state);
+ final WifiManager wm = mContext.getSystemService(WifiManager.class);
+ final List<WifiConfiguration> configs = wm.getConfiguredNetworks();
+ for (WifiConfiguration config : configs) {
+ if (Objects.equals(resolveNetworkId(config), networkId)) {
+ config.meteredOverride = meteredOverride;
+ wm.updateNetwork(config);
+ }
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
}
- private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
- final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
-
- final NetworkPolicy policy;
- synchronized (mNetworkPoliciesSecondLock) {
- policy = findPolicyForNetworkNL(ident);
- }
-
- if (policy == null || !policy.hasCycle()) {
- // missing policy means we can't derive useful quota info
- return null;
- }
-
- final long currentTime = currentTimeMillis();
-
- // find total bytes used under policy
- final long start = computeLastCycleBoundary(currentTime, policy);
- final long end = currentTime;
- final long totalBytes = getTotalBytes(policy.template, start, end);
-
- // report soft and hard limits under policy
- final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
- : NetworkQuotaInfo.NO_LIMIT;
- final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
- : NetworkQuotaInfo.NO_LIMIT;
-
- return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
- }
-
@Override
- public boolean isNetworkMetered(NetworkState state) {
- if (state.networkInfo == null) {
- return false;
- }
-
- final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
-
- final NetworkPolicy policy;
- synchronized (mNetworkPoliciesSecondLock) {
- policy = findPolicyForNetworkNL(ident);
- }
-
- if (policy != null) {
- return policy.metered;
- } else {
- final int type = state.networkInfo.getType();
- if ((isNetworkTypeMobile(type) && ident.getMetered()) || type == TYPE_WIMAX) {
- return true;
- }
- return false;
- }
+ @Deprecated
+ public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
+ Log.w(TAG, "Shame on UID " + Binder.getCallingUid()
+ + " for calling the hidden API getNetworkQuotaInfo(). Shame!");
+ return new NetworkQuotaInfo();
}
@Override
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index 8ced1c22020b..b65b9d7749b2 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -19,26 +19,17 @@ package com.android.server.net;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.wifi.WifiInfo.removeDoubleQuotes;
-
-import static com.android.server.net.NetworkPolicyManagerService.newWifiPolicy;
-import static com.android.server.net.NetworkPolicyManagerService.TAG;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
import android.content.Context;
import android.net.INetworkPolicyManager;
-import android.net.NetworkPolicy;
-import android.net.NetworkTemplate;
+import android.net.NetworkPolicyManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.RemoteException;
import android.os.ShellCommand;
-import android.util.Log;
+
+import java.io.PrintWriter;
+import java.util.List;
class NetworkPolicyManagerShellCommand extends ShellCommand {
@@ -90,7 +81,7 @@ class NetworkPolicyManagerShellCommand extends ShellCommand {
pw.println(" Adds a UID to the blacklist for restrict background usage.");
pw.println(" get restrict-background");
pw.println(" Gets the global restrict background usage status.");
- pw.println(" list wifi-networks [BOOLEAN]");
+ pw.println(" list wifi-networks [true|false]");
pw.println(" Lists all saved wifi networks and whether they are metered or not.");
pw.println(" If a boolean argument is passed, filters just the metered (or unmetered)");
pw.println(" networks.");
@@ -102,7 +93,7 @@ class NetworkPolicyManagerShellCommand extends ShellCommand {
pw.println(" Removes a UID from the whitelist for restrict background usage.");
pw.println(" remove restrict-background-blacklist UID");
pw.println(" Removes a UID from the blacklist for restrict background usage.");
- pw.println(" set metered-network ID BOOLEAN");
+ pw.println(" set metered-network ID [undefined|true|false]");
pw.println(" Toggles whether the given wi-fi network is metered.");
pw.println(" set restrict-background BOOLEAN");
pw.println(" Sets the global restrict background usage status.");
@@ -276,107 +267,60 @@ class NetworkPolicyManagerShellCommand extends ShellCommand {
return resetUidPolicy("not blacklisted", POLICY_REJECT_METERED_BACKGROUND);
}
- private int listWifiNetworks() throws RemoteException {
+ private int listWifiNetworks() {
final PrintWriter pw = getOutPrintWriter();
final String arg = getNextArg();
- final Boolean filter = arg == null ? null : Boolean.valueOf(arg);
- for (NetworkPolicy policy : getWifiPolicies()) {
- if (filter != null && filter.booleanValue() != policy.metered) {
- continue;
+ final int match;
+ if (arg == null) {
+ match = WifiConfiguration.METERED_OVERRIDE_NONE;
+ } else if (Boolean.parseBoolean(arg)) {
+ match = WifiConfiguration.METERED_OVERRIDE_METERED;
+ } else {
+ match = WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
+ }
+
+ final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+ for (WifiConfiguration config : configs) {
+ if (arg == null || config.meteredOverride == match) {
+ pw.print(NetworkPolicyManager.resolveNetworkId(config));
+ pw.print(';');
+ pw.println(overrideToString(config.meteredOverride));
}
- pw.print(getNetworkId(policy));
- pw.print(';');
- pw.println(policy.metered);
}
return 0;
}
private int setMeteredWifiNetwork() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
- final String id = getNextArg();
- if (id == null) {
- pw.println("Error: didn't specify ID");
+ final String networkId = getNextArg();
+ if (networkId == null) {
+ pw.println("Error: didn't specify networkId");
return -1;
}
final String arg = getNextArg();
if (arg == null) {
- pw.println("Error: didn't specify BOOLEAN");
+ pw.println("Error: didn't specify meteredOverride");
return -1;
}
- final boolean metered = Boolean.valueOf(arg);
- final NetworkPolicy[] policies = mInterface.getNetworkPolicies(null);
- boolean changed = false;
- // First try to find a policy with such id
- for (NetworkPolicy policy : policies) {
- if (policy.template.isMatchRuleMobile() || policy.metered == metered) {
- continue;
- }
- final String networkId = getNetworkId(policy);
- if (id.equals(networkId)) {
- Log.i(TAG, "Changing " + networkId + " metered status to " + metered);
- policy.metered = metered;
- changed = true;
- }
- }
- if (changed) {
- mInterface.setNetworkPolicies(policies);
- return 0;
- }
- // Policy not found: check if there is a saved wi-fi with such id.
- for (WifiConfiguration config : mWifiManager.getConfiguredNetworks()) {
- final String ssid = removeDoubleQuotes(config.SSID);
- if (id.equals(ssid)) {
- final NetworkPolicy policy = newPolicy(ssid);
- policy.metered = true;
- Log.i(TAG, "Creating new policy for " + ssid + ": " + policy);
- final NetworkPolicy[] newPolicies = new NetworkPolicy[policies.length + 1];
- System.arraycopy(policies, 0, newPolicies, 0, policies.length);
- newPolicies[newPolicies.length - 1] = policy;
- mInterface.setNetworkPolicies(newPolicies);
- return 0;
- }
- }
- pw.print("Error: didn't find network with SSID "); pw.println(id);
+ mInterface.setWifiMeteredOverride(NetworkPolicyManager.resolveNetworkId(networkId),
+ stringToOverride(arg));
return -1;
}
- private List<NetworkPolicy> getWifiPolicies() throws RemoteException {
- // First gets a list of saved wi-fi networks.
- final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
- final int size = configs != null ? configs.size() : 0;
- final Set<String> ssids = new HashSet<>(size);
- if (configs != null) {
- for (WifiConfiguration config : configs) {
- ssids.add(removeDoubleQuotes(config.SSID));
- }
- }
-
- // Then gets the saved policies.
- final NetworkPolicy[] policies = mInterface.getNetworkPolicies(null);
- final List<NetworkPolicy> wifiPolicies = new ArrayList<NetworkPolicy>(policies.length);
- for (NetworkPolicy policy: policies) {
- if (!policy.template.isMatchRuleMobile()) {
- wifiPolicies.add(policy);
- final String netId = getNetworkId(policy);
- ssids.remove(netId);
- }
- }
- // Finally, creates new default policies for saved WI-FIs not policied yet.
- for (String ssid : ssids) {
- final NetworkPolicy policy = newPolicy(ssid);
- wifiPolicies.add(policy);
+ private static String overrideToString(int override) {
+ switch (override) {
+ case WifiConfiguration.METERED_OVERRIDE_METERED: return "true";
+ case WifiConfiguration.METERED_OVERRIDE_NOT_METERED: return "false";
+ default: return "none";
}
- return wifiPolicies;
}
- private NetworkPolicy newPolicy(String ssid) {
- final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(ssid);
- final NetworkPolicy policy = newWifiPolicy(template, false);
- return policy;
- }
-
- private String getNetworkId(NetworkPolicy policy) {
- return removeDoubleQuotes(policy.template.getNetworkId());
+ private static int stringToOverride(String override) {
+ switch (override) {
+ case "true": return WifiConfiguration.METERED_OVERRIDE_METERED;
+ case "false": return WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
+ default: return WifiConfiguration.METERED_OVERRIDE_NONE;
+ }
}
private int getNextBooleanArg() {
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e7fbe4fe55fc..13d54abdd005 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -245,6 +245,7 @@ public class WifiConfiguration implements Parcelable {
* (e.g., {@code 01a243f405}).
*/
public String SSID;
+
/**
* When set, this network configuration entry should only be used when
* associating with the AP having the specified BSSID. The value is
@@ -740,22 +741,58 @@ public class WifiConfiguration implements Parcelable {
}
/**
+ * Indicates if the creator of this configuration has expressed that it
+ * should be considered metered.
+ *
+ * @see #isMetered(WifiConfiguration, WifiInfo)
* @hide
- * A hint about whether or not the network represented by this WifiConfiguration
- * is metered. This is hinted at via the meteredHint bit on DHCP results set in
- * {@link com.android.server.wifi.WifiStateMachine}, or via a network score in
- * {@link com.android.server.wifi.ExternalScoreEvaluator}.
*/
@SystemApi
public boolean meteredHint;
+ /** {@hide} */
+ public static final int METERED_OVERRIDE_NONE = 0;
+ /** {@hide} */
+ public static final int METERED_OVERRIDE_METERED = 1;
+ /** {@hide} */
+ public static final int METERED_OVERRIDE_NOT_METERED = 2;
+
+ /**
+ * Indicates if the end user has expressed an explicit opinion about the
+ * meteredness of this network, such as through the Settings app.
+ * <p>
+ * This should always override any values from {@link #meteredHint} or
+ * {@link WifiInfo#getMeteredHint()}.
+ *
+ * @see #isMetered(WifiConfiguration, WifiInfo)
+ * @hide
+ */
+ public int meteredOverride = METERED_OVERRIDE_NONE;
+
/**
+ * Blend together all the various opinions to decide if the given network
+ * should be considered metered or not.
+ *
* @hide
- * Indicates if a user has specified the WifiConfiguration to be metered. Users
- * can toggle if a network is metered within Settings -> Data Usage -> Network
- * Restrictions.
*/
- public boolean meteredOverride;
+ public static boolean isMetered(WifiConfiguration config, WifiInfo info) {
+ boolean metered = false;
+ if (info != null && info.getMeteredHint()) {
+ metered = true;
+ }
+ if (config != null && config.meteredHint) {
+ metered = true;
+ }
+ if (config != null
+ && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) {
+ metered = true;
+ }
+ if (config != null
+ && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) {
+ metered = false;
+ }
+ return metered;
+ }
/**
* @hide
@@ -1426,7 +1463,7 @@ public class WifiConfiguration implements Parcelable {
didSelfAdd = false;
ephemeral = false;
meteredHint = false;
- meteredOverride = false;
+ meteredOverride = METERED_OVERRIDE_NONE;
useExternalScores = false;
validatedInternetAccess = false;
mIpConfiguration = new IpConfiguration();
@@ -1520,23 +1557,24 @@ public class WifiConfiguration implements Parcelable {
sbuf.append(this.numNoInternetAccessReports).append("\n");
}
if (this.updateTime != null) {
- sbuf.append("update ").append(this.updateTime).append("\n");
+ sbuf.append(" update ").append(this.updateTime).append("\n");
}
if (this.creationTime != null) {
- sbuf.append("creation").append(this.creationTime).append("\n");
+ sbuf.append(" creation ").append(this.creationTime).append("\n");
}
if (this.didSelfAdd) sbuf.append(" didSelfAdd");
if (this.selfAdded) sbuf.append(" selfAdded");
if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess");
if (this.ephemeral) sbuf.append(" ephemeral");
if (this.meteredHint) sbuf.append(" meteredHint");
- if (this.meteredOverride) sbuf.append(" meteredOverride");
if (this.useExternalScores) sbuf.append(" useExternalScores");
if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess
- || this.ephemeral || this.meteredHint || this.meteredOverride
- || this.useExternalScores) {
+ || this.ephemeral || this.meteredHint || this.useExternalScores) {
sbuf.append("\n");
}
+ if (this.meteredOverride != METERED_OVERRIDE_NONE) {
+ sbuf.append(" meteredOverride ").append(meteredOverride).append("\n");
+ }
sbuf.append(" KeyMgmt:");
for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
if (this.allowedKeyManagement.get(k)) {
@@ -2062,7 +2100,7 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
dest.writeInt(ephemeral ? 1 : 0);
dest.writeInt(meteredHint ? 1 : 0);
- dest.writeInt(meteredOverride ? 1 : 0);
+ dest.writeInt(meteredOverride);
dest.writeInt(useExternalScores ? 1 : 0);
dest.writeInt(creatorUid);
dest.writeInt(lastConnectUid);
@@ -2129,7 +2167,7 @@ public class WifiConfiguration implements Parcelable {
config.isLegacyPasspointConfig = in.readInt() != 0;
config.ephemeral = in.readInt() != 0;
config.meteredHint = in.readInt() != 0;
- config.meteredOverride = in.readInt() != 0;
+ config.meteredOverride = in.readInt();
config.useExternalScores = in.readInt() != 0;
config.creatorUid = in.readInt();
config.lastConnectUid = in.readInt();
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index e48f7bdb27ee..bd253562c15e 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -459,7 +459,13 @@ public class WifiInfo implements Parcelable {
return mMacAddress != null && !DEFAULT_MAC_ADDRESS.equals(mMacAddress);
}
- /** {@hide} */
+ /**
+ * Indicates if we've dynamically detected this active network connection as
+ * being metered.
+ *
+ * @see WifiConfiguration#isMetered(WifiConfiguration, WifiInfo)
+ * @hide
+ */
public void setMeteredHint(boolean meteredHint) {
mMeteredHint = meteredHint;
}