summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2012-05-02 13:48:30 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-05-02 13:48:30 -0700
commit6f28f9ef315e3b5190259a943be91ecfafc69103 (patch)
tree6af38f850c1c2b24b1a9bf36c96b8e7cb886fa58 /services/java
parent0cd4f6718b3d9b9d147a28e32bbb3c0f9147d5a9 (diff)
parentb24a78589b2bee4a86d5c864dd69169e134a339b (diff)
downloadframeworks_base-6f28f9ef315e3b5190259a943be91ecfafc69103.zip
frameworks_base-6f28f9ef315e3b5190259a943be91ecfafc69103.tar.gz
frameworks_base-6f28f9ef315e3b5190259a943be91ecfafc69103.tar.bz2
Merge "Push existing rules when netd reconnects." into jb-dev
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/NetworkManagementService.java149
1 files changed, 98 insertions, 51 deletions
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 09d0698..817d04d 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -23,7 +23,6 @@ import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_TETHERING;
-import static android.provider.Settings.Secure.NETSTATS_ENABLED;
import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceRxThrottleResult;
@@ -45,19 +44,19 @@ import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import com.android.internal.net.NetworkStatsFactory;
import com.android.server.NativeDaemonConnector.Command;
-import com.google.android.collect.Sets;
+import com.google.android.collect.Maps;
import java.io.BufferedReader;
import java.io.DataInputStream;
@@ -74,7 +73,8 @@ import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.concurrent.CountDownLatch;
@@ -133,8 +133,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub
*/
private NativeDaemonConnector mConnector;
+ private final Handler mMainHandler = new Handler();
+
private Thread mThread;
- private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
+ private CountDownLatch mConnectedSignal = new CountDownLatch(1);
private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
new RemoteCallbackList<INetworkManagementEventObserver>();
@@ -143,9 +145,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub
private Object mQuotaLock = new Object();
/** Set of interfaces with active quotas. */
- private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet();
+ private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
/** Set of interfaces with active alerts. */
- private HashSet<String> mActiveAlertIfaces = Sets.newHashSet();
+ private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
/** Set of UIDs with active reject rules. */
private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
@@ -172,35 +174,19 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
public static NetworkManagementService create(Context context) throws InterruptedException {
- NetworkManagementService service = new NetworkManagementService(context);
+ final NetworkManagementService service = new NetworkManagementService(context);
+ final CountDownLatch connectedSignal = service.mConnectedSignal;
if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
service.mThread.start();
if (DBG) Slog.d(TAG, "Awaiting socket connection");
- service.mConnectedSignal.await();
+ connectedSignal.await();
if (DBG) Slog.d(TAG, "Connected");
return service;
}
public void systemReady() {
- // only enable bandwidth control when support exists, and requested by
- // system setting.
- final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
- final boolean shouldEnable =
- Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 1) != 0;
-
- if (hasKernelSupport && shouldEnable) {
- Slog.d(TAG, "enabling bandwidth control");
- try {
- mConnector.execute("bandwidth", "enable");
- mBandwidthControlEnabled = true;
- } catch (NativeDaemonConnectorException e) {
- Log.wtf(TAG, "problem enabling bandwidth controls", e);
- }
- } else {
- Slog.d(TAG, "not enabling bandwidth control");
- }
-
- SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
+ prepareNativeDaemon();
+ if (DBG) Slog.d(TAG, "Prepared");
}
@Override
@@ -264,8 +250,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
private void notifyInterfaceRemoved(String iface) {
// netd already clears out quota and alerts for removed ifaces; update
// our sanity-checking state.
- mActiveAlertIfaces.remove(iface);
- mActiveQuotaIfaces.remove(iface);
+ mActiveAlerts.remove(iface);
+ mActiveQuotas.remove(iface);
final int length = mObservers.beginBroadcast();
for (int i = 0; i < length; i++) {
@@ -292,24 +278,85 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
/**
- * Let us know the daemon is connected
+ * Prepare native daemon once connected, enabling modules and pushing any
+ * existing in-memory rules.
*/
- protected void onDaemonConnected() {
- mConnectedSignal.countDown();
- }
+ private void prepareNativeDaemon() {
+ mBandwidthControlEnabled = false;
+
+ // only enable bandwidth control when support exists
+ final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
+ if (hasKernelSupport) {
+ Slog.d(TAG, "enabling bandwidth control");
+ try {
+ mConnector.execute("bandwidth", "enable");
+ mBandwidthControlEnabled = true;
+ } catch (NativeDaemonConnectorException e) {
+ Log.wtf(TAG, "problem enabling bandwidth controls", e);
+ }
+ } else {
+ Slog.d(TAG, "not enabling bandwidth control");
+ }
+
+ SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
+ // push any existing quota or UID rules
+ synchronized (mQuotaLock) {
+ int size = mActiveQuotas.size();
+ if (size > 0) {
+ Slog.d(TAG, "pushing " + size + " active quota rules");
+ final HashMap<String, Long> activeQuotas = mActiveQuotas;
+ mActiveQuotas = Maps.newHashMap();
+ for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
+ setInterfaceQuota(entry.getKey(), entry.getValue());
+ }
+ }
+
+ size = mActiveAlerts.size();
+ if (size > 0) {
+ Slog.d(TAG, "pushing " + size + " active alert rules");
+ final HashMap<String, Long> activeAlerts = mActiveAlerts;
+ mActiveAlerts = Maps.newHashMap();
+ for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
+ setInterfaceAlert(entry.getKey(), entry.getValue());
+ }
+ }
+
+ size = mUidRejectOnQuota.size();
+ if (size > 0) {
+ Slog.d(TAG, "pushing " + size + " active uid rules");
+ final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota;
+ mUidRejectOnQuota = new SparseBooleanArray();
+ for (int i = 0; i < uidRejectOnQuota.size(); i++) {
+ setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i));
+ }
+ }
+ }
+ }
//
// Netd Callback handling
//
- class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
- /** {@inheritDoc} */
+ private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
+ @Override
public void onDaemonConnected() {
- NetworkManagementService.this.onDaemonConnected();
+ // event is dispatched from internal NDC thread, so we prepare the
+ // daemon back on main thread.
+ if (mConnectedSignal != null) {
+ mConnectedSignal.countDown();
+ mConnectedSignal = null;
+ } else {
+ mMainHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ prepareNativeDaemon();
+ }
+ });
+ }
}
- /** {@inheritDoc} */
+ @Override
public boolean onEvent(int code, String raw, String[] cooked) {
switch (code) {
case NetdResponseCode.InterfaceChange:
@@ -962,14 +1009,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub
if (!mBandwidthControlEnabled) return;
synchronized (mQuotaLock) {
- if (mActiveQuotaIfaces.contains(iface)) {
+ if (mActiveQuotas.containsKey(iface)) {
throw new IllegalStateException("iface " + iface + " already has quota");
}
try {
// TODO: support quota shared across interfaces
mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
- mActiveQuotaIfaces.add(iface);
+ mActiveQuotas.put(iface, quotaBytes);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
@@ -985,13 +1032,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub
if (!mBandwidthControlEnabled) return;
synchronized (mQuotaLock) {
- if (!mActiveQuotaIfaces.contains(iface)) {
+ if (!mActiveQuotas.containsKey(iface)) {
// TODO: eventually consider throwing
return;
}
- mActiveQuotaIfaces.remove(iface);
- mActiveAlertIfaces.remove(iface);
+ mActiveQuotas.remove(iface);
+ mActiveAlerts.remove(iface);
try {
// TODO: support quota shared across interfaces
@@ -1011,19 +1058,19 @@ public class NetworkManagementService extends INetworkManagementService.Stub
if (!mBandwidthControlEnabled) return;
// quick sanity check
- if (!mActiveQuotaIfaces.contains(iface)) {
+ if (!mActiveQuotas.containsKey(iface)) {
throw new IllegalStateException("setting alert requires existing quota on iface");
}
synchronized (mQuotaLock) {
- if (mActiveAlertIfaces.contains(iface)) {
+ if (mActiveAlerts.containsKey(iface)) {
throw new IllegalStateException("iface " + iface + " already has alert");
}
try {
// TODO: support alert shared across interfaces
mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
- mActiveAlertIfaces.add(iface);
+ mActiveAlerts.put(iface, alertBytes);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
@@ -1039,7 +1086,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
if (!mBandwidthControlEnabled) return;
synchronized (mQuotaLock) {
- if (!mActiveAlertIfaces.contains(iface)) {
+ if (!mActiveAlerts.containsKey(iface)) {
// TODO: eventually consider throwing
return;
}
@@ -1047,7 +1094,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
try {
// TODO: support alert shared across interfaces
mConnector.execute("bandwidth", "removeinterfacealert", iface);
- mActiveAlertIfaces.remove(iface);
+ mActiveAlerts.remove(iface);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
@@ -1077,7 +1124,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
// TODO: eventually migrate to be always enabled
if (!mBandwidthControlEnabled) return;
- synchronized (mUidRejectOnQuota) {
+ synchronized (mQuotaLock) {
final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
// TODO: eventually consider throwing
@@ -1272,8 +1319,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
synchronized (mQuotaLock) {
- pw.print("Active quota ifaces: "); pw.println(mActiveQuotaIfaces.toString());
- pw.print("Active alert ifaces: "); pw.println(mActiveAlertIfaces.toString());
+ pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
+ pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
}
synchronized (mUidRejectOnQuota) {