Loading api/current.txt +2 −1 Original line number Diff line number Diff line Loading @@ -11240,7 +11240,8 @@ package android.net { method public static long getUidUdpRxPackets(int); method public static long getUidUdpTxBytes(int); method public static long getUidUdpTxPackets(int); method public static void setThreadStatsTag(java.lang.String); method public static void setThreadStatsTag(int); method public static deprecated void setThreadStatsTag(java.lang.String); method public static void tagSocket(java.net.Socket) throws java.net.SocketException; method public static void untagSocket(java.net.Socket) throws java.net.SocketException; field public static final int UNSUPPORTED = -1; // 0xffffffff core/java/android/net/NetworkPolicyManager.java +36 −2 Original line number Diff line number Diff line Loading @@ -16,14 +16,21 @@ package android.net; import static android.content.pm.PackageManager.GET_SIGNATURES; import static android.text.format.Time.MONTH_DAY; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.os.RemoteException; import android.text.format.Time; import com.google.android.collect.Sets; import java.io.PrintWriter; import java.util.HashSet; /** * Manager for creating and modifying network policy rules. Loading Loading @@ -210,8 +217,35 @@ public class NetworkPolicyManager { * usually to protect critical system services. */ public static boolean isUidValidForPolicy(Context context, int uid) { return (uid >= android.os.Process.FIRST_APPLICATION_UID && uid <= android.os.Process.LAST_APPLICATION_UID); // first, quick-reject non-applications if (uid < android.os.Process.FIRST_APPLICATION_UID || uid > android.os.Process.LAST_APPLICATION_UID) { return false; } final PackageManager pm = context.getPackageManager(); final HashSet<Signature> systemSignature; try { systemSignature = Sets.newHashSet( pm.getPackageInfo("android", GET_SIGNATURES).signatures); } catch (NameNotFoundException e) { throw new RuntimeException("problem finding system signature", e); } try { // reject apps signed with system cert for (String packageName : pm.getPackagesForUid(uid)) { final HashSet<Signature> packageSignature = Sets.newHashSet( pm.getPackageInfo(packageName, GET_SIGNATURES).signatures); if (packageSignature.containsAll(systemSignature)) { return false; } } } catch (NameNotFoundException e) { } // nothing found above; we can apply policy to UID return true; } /** {@hide} */ Loading core/java/android/net/TrafficStats.java +35 −3 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package android.net; import android.app.DownloadManager; import android.app.backup.BackupManager; import android.content.Context; import android.media.MediaPlayer; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.RemoteException; Loading Loading @@ -49,6 +52,27 @@ public class TrafficStats { */ public static final int UID_REMOVED = -4; /** * Default tag value for {@link DownloadManager} traffic. * * @hide */ public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFF0001; /** * Default tag value for {@link MediaPlayer} traffic. * * @hide */ public static final int TAG_SYSTEM_MEDIA = 0xFFFF0002; /** * Default tag value for {@link BackupManager} traffic. * * @hide */ public static final int TAG_SYSTEM_BACKUP = 0xFFFF0003; /** * Snapshot of {@link NetworkStats} when the currently active profiling * session started, or {@code null} if no session active. Loading @@ -67,12 +91,20 @@ public class TrafficStats { * Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. */ public static void setThreadStatsTag(String tag) { public static void setThreadStatsTag(int tag) { BlockGuard.setThreadSocketStatsTag(tag); } /** * @deprecated unsupported, will eventually be removed */ @Deprecated public static void setThreadStatsTag(String tag) { setThreadStatsTag(tag.hashCode()); } public static void clearThreadStatsTag() { BlockGuard.setThreadSocketStatsTag(null); BlockGuard.setThreadSocketStatsTag(-1); } /** Loading Loading @@ -103,7 +135,7 @@ public class TrafficStats { * parameters. When finished, call {@link #untagSocket(Socket)} to remove * statistics parameters. * * @see #setThreadStatsTag(String) * @see #setThreadStatsTag(int) * @see #setThreadStatsUid(int) */ public static void tagSocket(Socket socket) throws SocketException { Loading services/java/com/android/server/NetworkManagementService.java +75 −24 Original line number Diff line number Diff line Loading @@ -38,6 +38,11 @@ import android.os.SystemProperties; import android.util.Log; import android.util.Slog; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import dalvik.system.BlockGuard; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; Loading @@ -48,6 +53,7 @@ import java.io.InputStreamReader; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.util.concurrent.CountDownLatch; Loading @@ -65,9 +71,18 @@ class NetworkManagementService extends INetworkManagementService.Stub { private static final int ADD = 1; private static final int REMOVE = 2; /** Path to {@code /proc/uid_stat}. */ @Deprecated private static final File STATS_UIDSTAT = new File("/proc/uid_stat"); private static final File STATS_NETFILTER = new File("/proc/net/xt_qtaguid/stats"); private final File mProcStatsUidstat; /** Path to {@code /proc/net/xt_qtaguid/stats}. */ private final File mProcStatsNetfilter; /** {@link #mProcStatsNetfilter} headers. */ private static final String KEY_IFACE = "iface"; private static final String KEY_TAG_HEX = "acct_tag_hex"; private static final String KEY_UID = "uid_tag_int"; private static final String KEY_RX = "rx_bytes"; private static final String KEY_TX = "tx_bytes"; class NetdResponseCode { public static final int InterfaceListResult = 110; Loading Loading @@ -107,10 +122,13 @@ class NetworkManagementService extends INetworkManagementService.Stub { * * @param context Binder context for this service */ private NetworkManagementService(Context context) { private NetworkManagementService(Context context, File procRoot) { mContext = context; mObservers = new ArrayList<INetworkManagementEventObserver>(); mProcStatsUidstat = new File(procRoot, "uid_stat"); mProcStatsNetfilter = new File(procRoot, "net/xt_qtaguid/stats"); if ("simulator".equals(SystemProperties.get("ro.product.device"))) { return; } Loading @@ -121,7 +139,8 @@ class NetworkManagementService extends INetworkManagementService.Stub { } public static NetworkManagementService create(Context context) throws InterruptedException { NetworkManagementService service = new NetworkManagementService(context); NetworkManagementService service = new NetworkManagementService( context, new File("/proc/")); if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); service.mThread.start(); if (DBG) Slog.d(TAG, "Awaiting socket connection"); Loading @@ -130,6 +149,12 @@ class NetworkManagementService extends INetworkManagementService.Stub { return service; } // @VisibleForTesting public static NetworkManagementService createForTest(Context context, File procRoot) { // TODO: eventually connect with mock netd return new NetworkManagementService(context, procRoot); } public void registerObserver(INetworkManagementEventObserver obs) { Slog.d(TAG, "Registering observer"); mObservers.add(obs); Loading Loading @@ -888,7 +913,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); if (STATS_NETFILTER.exists()) { if (mProcStatsNetfilter.exists()) { return getNetworkStatsDetailNetfilter(UID_ALL); } else { return getNetworkStatsDetailUidstat(UID_ALL); Loading @@ -902,7 +927,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); } if (STATS_NETFILTER.exists()) { if (mProcStatsNetfilter.exists()) { return getNetworkStatsDetailNetfilter(uid); } else { return getNetworkStatsDetailUidstat(uid); Loading @@ -914,35 +939,35 @@ class NetworkManagementService extends INetworkManagementService.Stub { */ private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24); final ArrayList<String> keys = Lists.newArrayList(); final ArrayList<String> values = Lists.newArrayList(); final HashMap<String, String> parsed = Maps.newHashMap(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(STATS_NETFILTER)); reader = new BufferedReader(new FileReader(mProcStatsNetfilter)); // assumes format from kernel: // idx iface acct_tag_hex uid_tag_int rx_bytes tx_bytes // skip first line, which is legend // parse first line as header String line = reader.readLine(); while ((line = reader.readLine()) != null) { final StringTokenizer t = new StringTokenizer(line); splitLine(line, keys); final String idx = t.nextToken(); final String iface = t.nextToken(); // parse remaining lines while ((line = reader.readLine()) != null) { splitLine(line, values); parseLine(keys, values, parsed); try { // TODO: kernel currently emits tag in upper half of long; // eventually switch to directly using int. final int tag = (int) (Long.parseLong(t.nextToken().substring(2), 16) >> 32); final int uid = Integer.parseInt(t.nextToken()); final long rx = Long.parseLong(t.nextToken()); final long tx = Long.parseLong(t.nextToken()); final String iface = parsed.get(KEY_IFACE); final int tag = BlockGuard.kernelToTag(parsed.get(KEY_TAG_HEX)); final int uid = Integer.parseInt(parsed.get(KEY_UID)); final long rx = Long.parseLong(parsed.get(KEY_RX)); final long tx = Long.parseLong(parsed.get(KEY_TX)); if (limitUid == UID_ALL || limitUid == uid) { stats.addEntry(iface, uid, tag, rx, tx); } } catch (NumberFormatException e) { Slog.w(TAG, "problem parsing stats for idx " + idx + ": " + e); Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); } } } catch (IOException e) { Loading @@ -964,7 +989,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { private NetworkStats getNetworkStatsDetailUidstat(int limitUid) { final String[] knownUids; if (limitUid == UID_ALL) { knownUids = STATS_UIDSTAT.list(); knownUids = mProcStatsUidstat.list(); } else { knownUids = new String[] { String.valueOf(limitUid) }; } Loading @@ -973,7 +998,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { SystemClock.elapsedRealtime(), knownUids.length); for (String uid : knownUids) { final int uidInt = Integer.parseInt(uid); final File uidPath = new File(STATS_UIDSTAT, uid); final File uidPath = new File(mProcStatsUidstat, uid); final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv")); final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd")); stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx); Loading Loading @@ -1047,6 +1072,32 @@ class NetworkManagementService extends INetworkManagementService.Stub { mConnector.doCommand(String.format("bandwidth %s", (enabled ? "enable" : "disable"))); } /** * Split given line into {@link ArrayList}. */ private static void splitLine(String line, ArrayList<String> outSplit) { outSplit.clear(); final StringTokenizer t = new StringTokenizer(line); while (t.hasMoreTokens()) { outSplit.add(t.nextToken()); } } /** * Zip the two given {@link ArrayList} as key and value pairs into * {@link HashMap}. */ private static void parseLine( ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) { outParsed.clear(); final int size = Math.min(keys.size(), values.size()); for (int i = 0; i < size; i++) { outParsed.put(keys.get(i), values.get(i)); } } /** * Utility method to read a single plain-text {@link Long} from the given * {@link File}, usually from a {@code /proc/} filesystem. Loading services/java/com/android/server/net/NetworkPolicyManagerService.java +48 −58 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.IPowerManager; import android.os.Message; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.telephony.TelephonyManager; Loading Loading @@ -148,6 +149,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS; private static final int MSG_RULES_CHANGED = 0x1; private static final int MSG_METERED_IFACES_CHANGED = 0x2; private final Context mContext; private final IActivityManager mActivityManager; private final IPowerManager mPowerManager; Loading Loading @@ -210,7 +214,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mHandlerThread = new HandlerThread(TAG); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); } Loading Loading @@ -269,9 +273,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // only someone like AMS should only be calling us mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); // skip when UID couldn't have any policy if (!isUidValidForPolicy(mContext, uid)) return; synchronized (mRulesLock) { // because a uid can have multiple pids running inside, we need to // remember all pid states and summarize foreground at uid level. Loading @@ -292,9 +293,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // only someone like AMS should only be calling us mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); // skip when UID couldn't have any policy if (!isUidValidForPolicy(mContext, uid)) return; synchronized (mRulesLock) { // clear records and recompute, when they exist final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); Loading Loading @@ -599,20 +597,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } // dispatch changed rule to existing listeners // TODO: dispatch outside of holding lock final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); if (listener != null) { try { listener.onMeteredIfacesChanged(meteredIfaces); } catch (RemoteException e) { } } } mListeners.finishBroadcast(); mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); } /** Loading Loading @@ -804,32 +790,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mListeners.register(listener); synchronized (mRulesLock) { // dispatch any existing rules to new listeners // TODO: dispatch outside of holding lock final int size = mUidRules.size(); for (int i = 0; i < size; i++) { final int uid = mUidRules.keyAt(i); final int uidRules = mUidRules.valueAt(i); if (uidRules != RULE_ALLOW_ALL) { try { listener.onUidRulesChanged(uid, uidRules); } catch (RemoteException e) { } } } // dispatch any metered ifaces to new listeners // TODO: dispatch outside of holding lock if (mMeteredIfaces.size() > 0) { final String[] meteredIfaces = mMeteredIfaces.toArray( new String[mMeteredIfaces.size()]); try { listener.onMeteredIfacesChanged(meteredIfaces); } catch (RemoteException e) { } } } // TODO: consider dispatching existing rules to new listeners } @Override Loading Loading @@ -978,8 +939,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } private void updateRulesForUidLocked(int uid) { if (!isUidValidForPolicy(mContext, uid)) return; final int uidPolicy = getUidPolicy(uid); final boolean uidForeground = isUidForeground(uid); Loading @@ -999,7 +958,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { //kernelSetUidRejectPaid(uid, rejectPaid); // dispatch changed rule to existing listeners // TODO: dispatch outside of holding lock mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); } private Handler.Callback mHandlerCallback = new Handler.Callback() { /** {@inheritDoc} */ public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_RULES_CHANGED: { final int uid = msg.arg1; final int uidRules = msg.arg2; final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); Loading @@ -1011,7 +979,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } mListeners.finishBroadcast(); return true; } case MSG_METERED_IFACES_CHANGED: { final String[] meteredIfaces = (String[]) msg.obj; final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); if (listener != null) { try { listener.onMeteredIfacesChanged(meteredIfaces); } catch (RemoteException e) { } } } mListeners.finishBroadcast(); return true; } default: { return false; } } } }; private String getActiveSubscriberId() { final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( Loading Loading
api/current.txt +2 −1 Original line number Diff line number Diff line Loading @@ -11240,7 +11240,8 @@ package android.net { method public static long getUidUdpRxPackets(int); method public static long getUidUdpTxBytes(int); method public static long getUidUdpTxPackets(int); method public static void setThreadStatsTag(java.lang.String); method public static void setThreadStatsTag(int); method public static deprecated void setThreadStatsTag(java.lang.String); method public static void tagSocket(java.net.Socket) throws java.net.SocketException; method public static void untagSocket(java.net.Socket) throws java.net.SocketException; field public static final int UNSUPPORTED = -1; // 0xffffffff
core/java/android/net/NetworkPolicyManager.java +36 −2 Original line number Diff line number Diff line Loading @@ -16,14 +16,21 @@ package android.net; import static android.content.pm.PackageManager.GET_SIGNATURES; import static android.text.format.Time.MONTH_DAY; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.os.RemoteException; import android.text.format.Time; import com.google.android.collect.Sets; import java.io.PrintWriter; import java.util.HashSet; /** * Manager for creating and modifying network policy rules. Loading Loading @@ -210,8 +217,35 @@ public class NetworkPolicyManager { * usually to protect critical system services. */ public static boolean isUidValidForPolicy(Context context, int uid) { return (uid >= android.os.Process.FIRST_APPLICATION_UID && uid <= android.os.Process.LAST_APPLICATION_UID); // first, quick-reject non-applications if (uid < android.os.Process.FIRST_APPLICATION_UID || uid > android.os.Process.LAST_APPLICATION_UID) { return false; } final PackageManager pm = context.getPackageManager(); final HashSet<Signature> systemSignature; try { systemSignature = Sets.newHashSet( pm.getPackageInfo("android", GET_SIGNATURES).signatures); } catch (NameNotFoundException e) { throw new RuntimeException("problem finding system signature", e); } try { // reject apps signed with system cert for (String packageName : pm.getPackagesForUid(uid)) { final HashSet<Signature> packageSignature = Sets.newHashSet( pm.getPackageInfo(packageName, GET_SIGNATURES).signatures); if (packageSignature.containsAll(systemSignature)) { return false; } } } catch (NameNotFoundException e) { } // nothing found above; we can apply policy to UID return true; } /** {@hide} */ Loading
core/java/android/net/TrafficStats.java +35 −3 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package android.net; import android.app.DownloadManager; import android.app.backup.BackupManager; import android.content.Context; import android.media.MediaPlayer; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.RemoteException; Loading Loading @@ -49,6 +52,27 @@ public class TrafficStats { */ public static final int UID_REMOVED = -4; /** * Default tag value for {@link DownloadManager} traffic. * * @hide */ public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFF0001; /** * Default tag value for {@link MediaPlayer} traffic. * * @hide */ public static final int TAG_SYSTEM_MEDIA = 0xFFFF0002; /** * Default tag value for {@link BackupManager} traffic. * * @hide */ public static final int TAG_SYSTEM_BACKUP = 0xFFFF0003; /** * Snapshot of {@link NetworkStats} when the currently active profiling * session started, or {@code null} if no session active. Loading @@ -67,12 +91,20 @@ public class TrafficStats { * Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. */ public static void setThreadStatsTag(String tag) { public static void setThreadStatsTag(int tag) { BlockGuard.setThreadSocketStatsTag(tag); } /** * @deprecated unsupported, will eventually be removed */ @Deprecated public static void setThreadStatsTag(String tag) { setThreadStatsTag(tag.hashCode()); } public static void clearThreadStatsTag() { BlockGuard.setThreadSocketStatsTag(null); BlockGuard.setThreadSocketStatsTag(-1); } /** Loading Loading @@ -103,7 +135,7 @@ public class TrafficStats { * parameters. When finished, call {@link #untagSocket(Socket)} to remove * statistics parameters. * * @see #setThreadStatsTag(String) * @see #setThreadStatsTag(int) * @see #setThreadStatsUid(int) */ public static void tagSocket(Socket socket) throws SocketException { Loading
services/java/com/android/server/NetworkManagementService.java +75 −24 Original line number Diff line number Diff line Loading @@ -38,6 +38,11 @@ import android.os.SystemProperties; import android.util.Log; import android.util.Slog; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import dalvik.system.BlockGuard; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; Loading @@ -48,6 +53,7 @@ import java.io.InputStreamReader; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.util.concurrent.CountDownLatch; Loading @@ -65,9 +71,18 @@ class NetworkManagementService extends INetworkManagementService.Stub { private static final int ADD = 1; private static final int REMOVE = 2; /** Path to {@code /proc/uid_stat}. */ @Deprecated private static final File STATS_UIDSTAT = new File("/proc/uid_stat"); private static final File STATS_NETFILTER = new File("/proc/net/xt_qtaguid/stats"); private final File mProcStatsUidstat; /** Path to {@code /proc/net/xt_qtaguid/stats}. */ private final File mProcStatsNetfilter; /** {@link #mProcStatsNetfilter} headers. */ private static final String KEY_IFACE = "iface"; private static final String KEY_TAG_HEX = "acct_tag_hex"; private static final String KEY_UID = "uid_tag_int"; private static final String KEY_RX = "rx_bytes"; private static final String KEY_TX = "tx_bytes"; class NetdResponseCode { public static final int InterfaceListResult = 110; Loading Loading @@ -107,10 +122,13 @@ class NetworkManagementService extends INetworkManagementService.Stub { * * @param context Binder context for this service */ private NetworkManagementService(Context context) { private NetworkManagementService(Context context, File procRoot) { mContext = context; mObservers = new ArrayList<INetworkManagementEventObserver>(); mProcStatsUidstat = new File(procRoot, "uid_stat"); mProcStatsNetfilter = new File(procRoot, "net/xt_qtaguid/stats"); if ("simulator".equals(SystemProperties.get("ro.product.device"))) { return; } Loading @@ -121,7 +139,8 @@ class NetworkManagementService extends INetworkManagementService.Stub { } public static NetworkManagementService create(Context context) throws InterruptedException { NetworkManagementService service = new NetworkManagementService(context); NetworkManagementService service = new NetworkManagementService( context, new File("/proc/")); if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); service.mThread.start(); if (DBG) Slog.d(TAG, "Awaiting socket connection"); Loading @@ -130,6 +149,12 @@ class NetworkManagementService extends INetworkManagementService.Stub { return service; } // @VisibleForTesting public static NetworkManagementService createForTest(Context context, File procRoot) { // TODO: eventually connect with mock netd return new NetworkManagementService(context, procRoot); } public void registerObserver(INetworkManagementEventObserver obs) { Slog.d(TAG, "Registering observer"); mObservers.add(obs); Loading Loading @@ -888,7 +913,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); if (STATS_NETFILTER.exists()) { if (mProcStatsNetfilter.exists()) { return getNetworkStatsDetailNetfilter(UID_ALL); } else { return getNetworkStatsDetailUidstat(UID_ALL); Loading @@ -902,7 +927,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); } if (STATS_NETFILTER.exists()) { if (mProcStatsNetfilter.exists()) { return getNetworkStatsDetailNetfilter(uid); } else { return getNetworkStatsDetailUidstat(uid); Loading @@ -914,35 +939,35 @@ class NetworkManagementService extends INetworkManagementService.Stub { */ private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24); final ArrayList<String> keys = Lists.newArrayList(); final ArrayList<String> values = Lists.newArrayList(); final HashMap<String, String> parsed = Maps.newHashMap(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(STATS_NETFILTER)); reader = new BufferedReader(new FileReader(mProcStatsNetfilter)); // assumes format from kernel: // idx iface acct_tag_hex uid_tag_int rx_bytes tx_bytes // skip first line, which is legend // parse first line as header String line = reader.readLine(); while ((line = reader.readLine()) != null) { final StringTokenizer t = new StringTokenizer(line); splitLine(line, keys); final String idx = t.nextToken(); final String iface = t.nextToken(); // parse remaining lines while ((line = reader.readLine()) != null) { splitLine(line, values); parseLine(keys, values, parsed); try { // TODO: kernel currently emits tag in upper half of long; // eventually switch to directly using int. final int tag = (int) (Long.parseLong(t.nextToken().substring(2), 16) >> 32); final int uid = Integer.parseInt(t.nextToken()); final long rx = Long.parseLong(t.nextToken()); final long tx = Long.parseLong(t.nextToken()); final String iface = parsed.get(KEY_IFACE); final int tag = BlockGuard.kernelToTag(parsed.get(KEY_TAG_HEX)); final int uid = Integer.parseInt(parsed.get(KEY_UID)); final long rx = Long.parseLong(parsed.get(KEY_RX)); final long tx = Long.parseLong(parsed.get(KEY_TX)); if (limitUid == UID_ALL || limitUid == uid) { stats.addEntry(iface, uid, tag, rx, tx); } } catch (NumberFormatException e) { Slog.w(TAG, "problem parsing stats for idx " + idx + ": " + e); Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); } } } catch (IOException e) { Loading @@ -964,7 +989,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { private NetworkStats getNetworkStatsDetailUidstat(int limitUid) { final String[] knownUids; if (limitUid == UID_ALL) { knownUids = STATS_UIDSTAT.list(); knownUids = mProcStatsUidstat.list(); } else { knownUids = new String[] { String.valueOf(limitUid) }; } Loading @@ -973,7 +998,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { SystemClock.elapsedRealtime(), knownUids.length); for (String uid : knownUids) { final int uidInt = Integer.parseInt(uid); final File uidPath = new File(STATS_UIDSTAT, uid); final File uidPath = new File(mProcStatsUidstat, uid); final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv")); final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd")); stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx); Loading Loading @@ -1047,6 +1072,32 @@ class NetworkManagementService extends INetworkManagementService.Stub { mConnector.doCommand(String.format("bandwidth %s", (enabled ? "enable" : "disable"))); } /** * Split given line into {@link ArrayList}. */ private static void splitLine(String line, ArrayList<String> outSplit) { outSplit.clear(); final StringTokenizer t = new StringTokenizer(line); while (t.hasMoreTokens()) { outSplit.add(t.nextToken()); } } /** * Zip the two given {@link ArrayList} as key and value pairs into * {@link HashMap}. */ private static void parseLine( ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) { outParsed.clear(); final int size = Math.min(keys.size(), values.size()); for (int i = 0; i < size; i++) { outParsed.put(keys.get(i), values.get(i)); } } /** * Utility method to read a single plain-text {@link Long} from the given * {@link File}, usually from a {@code /proc/} filesystem. Loading
services/java/com/android/server/net/NetworkPolicyManagerService.java +48 −58 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.IPowerManager; import android.os.Message; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.telephony.TelephonyManager; Loading Loading @@ -148,6 +149,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS; private static final int MSG_RULES_CHANGED = 0x1; private static final int MSG_METERED_IFACES_CHANGED = 0x2; private final Context mContext; private final IActivityManager mActivityManager; private final IPowerManager mPowerManager; Loading Loading @@ -210,7 +214,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mHandlerThread = new HandlerThread(TAG); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); } Loading Loading @@ -269,9 +273,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // only someone like AMS should only be calling us mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); // skip when UID couldn't have any policy if (!isUidValidForPolicy(mContext, uid)) return; synchronized (mRulesLock) { // because a uid can have multiple pids running inside, we need to // remember all pid states and summarize foreground at uid level. Loading @@ -292,9 +293,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // only someone like AMS should only be calling us mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG); // skip when UID couldn't have any policy if (!isUidValidForPolicy(mContext, uid)) return; synchronized (mRulesLock) { // clear records and recompute, when they exist final SparseBooleanArray pidForeground = mUidPidForeground.get(uid); Loading Loading @@ -599,20 +597,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } // dispatch changed rule to existing listeners // TODO: dispatch outside of holding lock final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); if (listener != null) { try { listener.onMeteredIfacesChanged(meteredIfaces); } catch (RemoteException e) { } } } mListeners.finishBroadcast(); mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); } /** Loading Loading @@ -804,32 +790,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mListeners.register(listener); synchronized (mRulesLock) { // dispatch any existing rules to new listeners // TODO: dispatch outside of holding lock final int size = mUidRules.size(); for (int i = 0; i < size; i++) { final int uid = mUidRules.keyAt(i); final int uidRules = mUidRules.valueAt(i); if (uidRules != RULE_ALLOW_ALL) { try { listener.onUidRulesChanged(uid, uidRules); } catch (RemoteException e) { } } } // dispatch any metered ifaces to new listeners // TODO: dispatch outside of holding lock if (mMeteredIfaces.size() > 0) { final String[] meteredIfaces = mMeteredIfaces.toArray( new String[mMeteredIfaces.size()]); try { listener.onMeteredIfacesChanged(meteredIfaces); } catch (RemoteException e) { } } } // TODO: consider dispatching existing rules to new listeners } @Override Loading Loading @@ -978,8 +939,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } private void updateRulesForUidLocked(int uid) { if (!isUidValidForPolicy(mContext, uid)) return; final int uidPolicy = getUidPolicy(uid); final boolean uidForeground = isUidForeground(uid); Loading @@ -999,7 +958,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { //kernelSetUidRejectPaid(uid, rejectPaid); // dispatch changed rule to existing listeners // TODO: dispatch outside of holding lock mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); } private Handler.Callback mHandlerCallback = new Handler.Callback() { /** {@inheritDoc} */ public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_RULES_CHANGED: { final int uid = msg.arg1; final int uidRules = msg.arg2; final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); Loading @@ -1011,7 +979,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } mListeners.finishBroadcast(); return true; } case MSG_METERED_IFACES_CHANGED: { final String[] meteredIfaces = (String[]) msg.obj; final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); if (listener != null) { try { listener.onMeteredIfacesChanged(meteredIfaces); } catch (RemoteException e) { } } } mListeners.finishBroadcast(); return true; } default: { return false; } } } }; private String getActiveSubscriberId() { final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( Loading