summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff Sharkey <jsharkey@android.com> 2017-07-12 10:50:42 -0600
committer Jeff Sharkey <jsharkey@android.com> 2017-07-14 11:46:31 -0600
commit43d2a1700b6eb1d804924c6a1e5e0161a13a5348 (patch)
treee82fcf03e39350a21e97b768a02bca70fa083a2b
parent183f9ac26302e1f677df8d698c1f7c570bb22014 (diff)
Move "metered" persistence to WifiConfiguration.
For a long time we've had a nasty tangled dependency between Wi-Fi and NPMS, since they both persisted different details for configured networks. As part of preparing for new carrier data plan APIs, move the tracking of meteredness over to WifiConfiguration. This also cleans up how meteredness is communicated through NetworkAgents to rely completely on NET_CAPABILITY_NOT_METERED by removing the metered flag on NetworkInfo, which has caused confusion and staleness. Migrates any existing user-configured metered networks over to WifiConfiguration once the device finishes booting. Remove support for NetworkQuotaInfo, since this information can no longer be made available to apps. Frustratingly, some apps are using it, so keep the object around returning stub values, and shame them in the logs. Bug: 63391323 Test: builds, boots, Wi-Fi policy is upgraded Exempt-From-Owner-Approval: Bug 63673347 Change-Id: I64f865ddeb65cfcd330f8d2a847368abdf960a07
-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;
}