diff options
author | Jeff Sharkey <jsharkey@android.com> | 2012-05-02 13:48:30 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-05-02 13:48:30 -0700 |
commit | 6f28f9ef315e3b5190259a943be91ecfafc69103 (patch) | |
tree | 6af38f850c1c2b24b1a9bf36c96b8e7cb886fa58 /services/java | |
parent | 0cd4f6718b3d9b9d147a28e32bbb3c0f9147d5a9 (diff) | |
parent | b24a78589b2bee4a86d5c864dd69169e134a339b (diff) | |
download | frameworks_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.java | 149 |
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) { |