summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Felipe Leme <felipeal@google.com> 2016-03-22 14:53:13 -0700
committer Felipe Leme <felipeal@google.com> 2016-03-25 12:33:47 -0700
commit65be3025fd07d53137f5434794d1d1b3a0933aab (patch)
tree894e539a27506d88bb8e4644b27ffa97ba689116
parent4a2f9857c2759661a54d8705fb65e1ce500d1907 (diff)
Refactored NetworkManagerService to support Data Saver.
Netd provides 2 bandwidth control rules to restrict which uids can use metered networks: - bw_penalty_box is a blacklist-based firewall chain used to determine which uids do not have access to metered interfaces. - bw_happy_box is whitelist-based firewall chain used to determine which uids have access to metered interfaces. Currently, both NetworkManagerService (NMS) and NetworkPolicyManagerService (NPMS) uses just the bw_penalty_box rule, which makes turning Data Saver mode on / off too slow (since NPMS needs to build the bw_penalty_box on demand); this CL adds support for both rules on NMS, although NPMS doesn't take advantage of it yet (it will be refactored in a separate CL). BUG: 27127112 BUG: 26685616 Change-Id: Ib954574f7c86269fc9b4cf8ce4ba72ba5878c23d
-rw-r--r--core/java/android/os/INetworkManagementService.aidl4
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java129
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java34
4 files changed, 122 insertions, 47 deletions
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 100f6a165b1d..24a6cdf83b7a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -293,7 +293,9 @@ interface INetworkManagementService
/**
* Control network activity of a UID over interfaces with a quota limit.
*/
- void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces);
+ void setUidMeteredNetworkBlacklist(int uid, boolean enable);
+ void setUidMeteredNetworkWhitelist(int uid, boolean enable);
+ boolean setDataSaverModeEnabled(boolean enable);
void setUidCleartextNetworkPolicy(int uid, int policy);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 548b66284937..b8c5e63762e2 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -209,9 +209,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub
/** Set of interfaces with active alerts. */
@GuardedBy("mQuotaLock")
private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
- /** Set of UIDs with active reject rules. */
+ /** Set of UIDs blacklisted on metered networks. */
@GuardedBy("mQuotaLock")
- private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
+ private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
+ /** Set of UIDs whitelisted on metered networks. */
+ @GuardedBy("mQuotaLock")
+ private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
/** Set of UIDs with cleartext penalties. */
@GuardedBy("mQuotaLock")
private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
@@ -240,6 +243,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
@GuardedBy("mQuotaLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
+ @GuardedBy("mQuotaLock")
+ private boolean mDataSaverMode;
+
private Object mIdleTimerLock = new Object();
/** Set of interfaces with active idle timers. */
private static class IdleTimerParams {
@@ -561,6 +567,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
// push any existing quota or UID rules
synchronized (mQuotaLock) {
+
+ setDataSaverModeEnabled(mDataSaverMode);
+
int size = mActiveQuotas.size();
if (size > 0) {
if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
@@ -581,13 +590,25 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
}
- size = mUidRejectOnQuota.size();
+ size = mUidRejectOnMetered.size();
if (size > 0) {
- if (DBG) Slog.d(TAG, "Pushing " + size + " active UID rules");
- final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota;
- mUidRejectOnQuota = new SparseBooleanArray();
+ if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
+ final SparseBooleanArray uidRejectOnQuota = mUidRejectOnMetered;
+ mUidRejectOnMetered = new SparseBooleanArray();
for (int i = 0; i < uidRejectOnQuota.size(); i++) {
- setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i));
+ setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
+ uidRejectOnQuota.valueAt(i));
+ }
+ }
+
+ size = mUidAllowOnMetered.size();
+ if (size > 0) {
+ if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
+ final SparseBooleanArray uidAcceptOnQuota = mUidAllowOnMetered;
+ mUidAllowOnMetered = new SparseBooleanArray();
+ for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
+ setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
+ uidAcceptOnQuota.valueAt(i));
}
}
@@ -738,6 +759,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
@Override
public void onDaemonConnected() {
+ Slog.i(TAG, "onDaemonConnected()");
// event is dispatched from internal NDC thread, so we prepare the
// daemon back on main thread.
if (mConnectedSignal != null) {
@@ -1698,28 +1720,30 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
}
- @Override
- public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
+ private void setUidOnMeteredNetworkList(SparseBooleanArray quotaList, int uid,
+ boolean blacklist, boolean enable) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
// silently discard when control disabled
// TODO: eventually migrate to be always enabled
if (!mBandwidthControlEnabled) return;
+ final String chain = blacklist ? "naughtyapps" : "niceapps";
+ final String suffix = enable ? "add" : "remove";
+
synchronized (mQuotaLock) {
- final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
- if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
+ final boolean oldEnable = quotaList.get(uid, false);
+ if (oldEnable == enable) {
// TODO: eventually consider throwing
return;
}
try {
- mConnector.execute("bandwidth",
- rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid);
- if (rejectOnQuotaInterfaces) {
- mUidRejectOnQuota.put(uid, true);
+ mConnector.execute("bandwidth", suffix + chain, uid);
+ if (enable) {
+ quotaList.put(uid, true);
} else {
- mUidRejectOnQuota.delete(uid);
+ quotaList.delete(uid);
}
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
@@ -1728,6 +1752,39 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
@Override
+ public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
+ setUidOnMeteredNetworkList(mUidRejectOnMetered, uid, true, enable);
+ }
+
+ @Override
+ public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
+ setUidOnMeteredNetworkList(mUidAllowOnMetered, uid, false, enable);
+ }
+
+ @Override
+ public boolean setDataSaverModeEnabled(boolean enable) {
+ if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
+ synchronized (mQuotaLock) {
+ if (mDataSaverMode == enable) {
+ Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
+ return true;
+ }
+ try {
+ final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
+ if (changed) {
+ mDataSaverMode = enable;
+ } else {
+ Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
+ }
+ return changed;
+ } catch (RemoteException e) {
+ Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
+ return false;
+ }
+ }
+ }
+
+ @Override
public void setUidCleartextNetworkPolicy(int uid, int policy) {
if (Binder.getCallingUid() != uid) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
@@ -2221,29 +2278,22 @@ public class NetworkManagementService extends INetworkManagementService.Stub
synchronized (mQuotaLock) {
pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
- }
-
- synchronized (mUidRejectOnQuota) {
- pw.print("UID reject on quota ifaces: [");
- final int size = mUidRejectOnQuota.size();
- for (int i = 0; i < size; i++) {
- pw.print(mUidRejectOnQuota.keyAt(i));
- if (i < size - 1) pw.print(",");
- }
- pw.println("]");
+ pw.print("Data saver mode: "); pw.println(mDataSaverMode);
+ dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
+ dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
}
synchronized (mUidFirewallRules) {
dumpUidFirewallRule(pw, "", mUidFirewallRules);
}
- pw.println("UID firewall standby chain enabled: " +
+ pw.print("UID firewall standby chain enabled: "); pw.println(
mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
synchronized (mUidFirewallStandbyRules) {
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
}
- pw.println("UID firewall dozable chain enabled: " +
+ pw.print("UID firewall dozable chain enabled: "); pw.println(
mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
synchronized (mUidFirewallDozableRules) {
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
@@ -2267,6 +2317,29 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
+ pw.print("Netd service status: " );
+ if (mNetdService == null) {
+ pw.println("disconnected");
+ } else {
+ try {
+ final boolean alive = mNetdService.isAlive();
+ pw.println(alive ? "alive": "dead");
+ } catch (RemoteException e) {
+ pw.println("unreachable");
+ }
+ }
+ }
+
+ private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
+ pw.print("UID bandwith control ");
+ pw.print(name);
+ pw.print(" rule: [");
+ final int size = list.size();
+ for (int i = 0; i < size; i++) {
+ pw.print(list.keyAt(i));
+ if (i < size - 1) pw.print(",");
+ }
+ pw.println("]");
}
private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 49ae2936d6ff..9b92e4f0f04d 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2803,7 +2803,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
try {
- mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+ mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces);
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem setting uid rules", e);
} catch (RemoteException e) {
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 72a458bdb96c..622e46efdf2c 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -313,7 +313,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
public void testScreenChangesRules() throws Exception {
Future<Void> future;
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, true);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -322,7 +322,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
verifyAndReset();
// push strict policy for foreground uid, verify ALLOW rule
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, true);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -332,7 +332,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
// now turn screen off and verify REJECT rule
expect(mPowerManager.isInteractive()).andReturn(false).atLeastOnce();
- expectSetUidNetworkRules(UID_A, true);
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
@@ -342,7 +342,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
// and turn screen back on, verify ALLOW rule restored
expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, true);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -354,7 +354,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
public void testPolicyNone() throws Exception {
Future<Void> future;
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, true);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -363,7 +363,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
verifyAndReset();
// POLICY_NONE should RULE_ALLOW in foreground
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, true);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -372,7 +372,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
verifyAndReset();
// POLICY_NONE should RULE_ALLOW in background
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -385,7 +385,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
Future<Void> future;
// POLICY_REJECT should RULE_ALLOW in background
- expectSetUidNetworkRules(UID_A, true);
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
@@ -394,7 +394,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
verifyAndReset();
// POLICY_REJECT should RULE_ALLOW in foreground
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, true);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -403,7 +403,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
verifyAndReset();
// POLICY_REJECT should RULE_REJECT in background
- expectSetUidNetworkRules(UID_A, true);
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
@@ -416,7 +416,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
Future<Void> future;
// POLICY_NONE should have RULE_ALLOW in background
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -426,7 +426,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
verifyAndReset();
// adding POLICY_REJECT should cause RULE_REJECT
- expectSetUidNetworkRules(UID_A, true);
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
@@ -435,7 +435,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
verifyAndReset();
// removing POLICY_REJECT should return us to RULE_ALLOW
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -632,7 +632,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
Future<Void> future;
// POLICY_REJECT should RULE_REJECT in background
- expectSetUidNetworkRules(UID_A, true);
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
@@ -641,7 +641,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
verifyAndReset();
// uninstall should clear RULE_REJECT
- expectSetUidNetworkRules(UID_A, false);
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
expectSetUidForeground(UID_A, false);
future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
@@ -890,9 +890,9 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
expectLastCall().atLeastOnce();
}
- private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
+ private void expectSetUidMeteredNetworkBlacklist(int uid, boolean rejectOnQuotaInterfaces)
throws Exception {
- mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+ mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces);
expectLastCall().atLeastOnce();
}