Merge "Refactored NetworkManagerService to support Data Saver." into nyc-dev

This commit is contained in:
Felipe Leme
2016-03-25 20:39:57 +00:00
committed by Android (Google) Code Review
4 changed files with 122 additions and 47 deletions

View File

@@ -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);

View File

@@ -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 {
@@ -583,6 +589,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");
@@ -603,13 +612,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));
}
}
@@ -723,6 +744,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) {
@@ -1683,28 +1705,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();
@@ -1712,6 +1736,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) {
@@ -2206,29 +2263,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);
@@ -2252,6 +2302,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) {

View File

@@ -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) {

View File

@@ -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();
}