am 3d1d57dc: Merge "Collect and persist tethering stats." into ics-factoryrom

* commit '3d1d57dcdb02ace6af5810bd4ec3f8fad5fc1799':
  Collect and persist tethering stats.
This commit is contained in:
Jeff Sharkey
2011-09-18 16:17:39 -07:00
committed by Android Git Automerger
7 changed files with 186 additions and 10 deletions

View File

@@ -83,6 +83,12 @@ interface IConnectivityManager
String[] getTetheredIfaces(); String[] getTetheredIfaces();
/**
* Return list of interface pairs that are actively tethered. Even indexes are
* remote interface, and odd indexes are corresponding local interfaces.
*/
String[] getTetheredIfacePairs();
String[] getTetheringErroredIfaces(); String[] getTetheringErroredIfaces();
String[] getTetherableUsbRegexs(); String[] getTetherableUsbRegexs();

View File

@@ -52,26 +52,34 @@ public class TrafficStats {
*/ */
public static final int UID_REMOVED = -4; public static final int UID_REMOVED = -4;
/**
* Special UID value used when collecting {@link NetworkStatsHistory} for
* tethering traffic.
*
* @hide
*/
public static final int UID_TETHERING = -5;
/** /**
* Default tag value for {@link DownloadManager} traffic. * Default tag value for {@link DownloadManager} traffic.
* *
* @hide * @hide
*/ */
public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFF0001; public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFFFF01;
/** /**
* Default tag value for {@link MediaPlayer} traffic. * Default tag value for {@link MediaPlayer} traffic.
* *
* @hide * @hide
*/ */
public static final int TAG_SYSTEM_MEDIA = 0xFFFF0002; public static final int TAG_SYSTEM_MEDIA = 0xFFFFFF02;
/** /**
* Default tag value for {@link BackupManager} traffic. * Default tag value for {@link BackupManager} traffic.
* *
* @hide * @hide
*/ */
public static final int TAG_SYSTEM_BACKUP = 0xFFFF0003; public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
/** /**
* Snapshot of {@link NetworkStats} when the currently active profiling * Snapshot of {@link NetworkStats} when the currently active profiling
@@ -90,6 +98,10 @@ public class TrafficStats {
* <p> * <p>
* Changes only take effect during subsequent calls to * Changes only take effect during subsequent calls to
* {@link #tagSocket(Socket)}. * {@link #tagSocket(Socket)}.
* <p>
* Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
* used internally by system services like {@link DownloadManager} when
* performing traffic on behalf of an application.
*/ */
public static void setThreadStatsTag(int tag) { public static void setThreadStatsTag(int tag) {
NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);

View File

@@ -230,6 +230,13 @@ interface INetworkManagementService
*/ */
NetworkStats getNetworkStatsUidDetail(int uid); NetworkStats getNetworkStatsUidDetail(int uid);
/**
* Return summary of network statistics for the requested pairs of
* tethering interfaces. Even indexes are remote interface, and odd
* indexes are corresponding local interfaces.
*/
NetworkStats getNetworkStatsTethering(in String[] ifacePairs);
/** /**
* Set quota for an interface. * Set quota for an interface.
*/ */

View File

@@ -2394,6 +2394,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return mTethering.getTetheredIfaces(); return mTethering.getTetheredIfaces();
} }
@Override
public String[] getTetheredIfacePairs() {
enforceTetherAccessPermission();
return mTethering.getTetheredIfacePairs();
}
public String[] getTetheringErroredIfaces() { public String[] getTetheringErroredIfaces() {
enforceTetherAccessPermission(); enforceTetherAccessPermission();
return mTethering.getErroredIfaces(); return mTethering.getErroredIfaces();

View File

@@ -123,6 +123,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
public static final int InterfaceTxCounterResult = 217; public static final int InterfaceTxCounterResult = 217;
public static final int InterfaceRxThrottleResult = 218; public static final int InterfaceRxThrottleResult = 218;
public static final int InterfaceTxThrottleResult = 219; public static final int InterfaceTxThrottleResult = 219;
public static final int QuotaCounterResult = 220;
public static final int TetheringStatsResult = 221;
public static final int InterfaceChange = 600; public static final int InterfaceChange = 600;
public static final int BandwidthControl = 601; public static final int BandwidthControl = 601;
@@ -1443,6 +1445,73 @@ public class NetworkManagementService extends INetworkManagementService.Stub
return stats; return stats;
} }
@Override
public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
if (ifacePairs.length % 2 != 0) {
throw new IllegalArgumentException(
"unexpected ifacePairs; length=" + ifacePairs.length);
}
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
for (int i = 0; i < ifacePairs.length; i += 2) {
final String ifaceIn = ifacePairs[i];
final String ifaceOut = ifacePairs[i + 1];
if (ifaceIn != null && ifaceOut != null) {
stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
}
}
return stats;
}
private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
final StringBuilder command = new StringBuilder();
command.append("bandwidth gettetherstats ").append(ifaceIn).append(" ").append(ifaceOut);
final String rsp;
try {
rsp = mConnector.doCommand(command.toString()).get(0);
} catch (NativeDaemonConnectorException e) {
throw new IllegalStateException("Error communicating to native daemon", e);
}
final String[] tok = rsp.split(" ");
/* Expecting: "code ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets" */
if (tok.length != 7) {
throw new IllegalStateException("Native daemon returned unexpected result: " + rsp);
}
final int code;
try {
code = Integer.parseInt(tok[0]);
} catch (NumberFormatException e) {
throw new IllegalStateException(
"Failed to parse native daemon return code for " + ifaceIn + " " + ifaceOut);
}
if (code != NetdResponseCode.TetheringStatsResult) {
throw new IllegalStateException(
"Unexpected return code from native daemon for " + ifaceIn + " " + ifaceOut);
}
try {
final NetworkStats.Entry entry = new NetworkStats.Entry();
entry.iface = ifaceIn;
entry.uid = UID_ALL;
entry.set = SET_DEFAULT;
entry.tag = TAG_NONE;
entry.rxBytes = Long.parseLong(tok[3]);
entry.rxPackets = Long.parseLong(tok[4]);
entry.txBytes = Long.parseLong(tok[5]);
entry.txPackets = Long.parseLong(tok[6]);
return entry;
} catch (NumberFormatException e) {
throw new IllegalStateException(
"problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
}
}
public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) { public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");

View File

@@ -19,7 +19,6 @@ package com.android.server.connectivity;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.bluetooth.BluetoothPan;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -28,15 +27,14 @@ import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.hardware.usb.UsbManager; import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.InterfaceConfiguration;
import android.net.IConnectivityManager; import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver; import android.net.INetworkManagementEventObserver;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkUtils; import android.net.NetworkUtils;
import android.os.Binder; import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.os.INetworkManagementService; import android.os.INetworkManagementService;
@@ -51,6 +49,7 @@ import com.android.internal.telephony.Phone;
import com.android.internal.util.IState; import com.android.internal.util.IState;
import com.android.internal.util.State; import com.android.internal.util.State;
import com.android.internal.util.StateMachine; import com.android.internal.util.StateMachine;
import com.google.android.collect.Lists;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -59,8 +58,8 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set; import java.util.Set;
/** /**
* @hide * @hide
* *
@@ -68,7 +67,6 @@ import java.util.Set;
* *
* TODO - look for parent classes and code sharing * TODO - look for parent classes and code sharing
*/ */
public class Tethering extends INetworkManagementEventObserver.Stub { public class Tethering extends INetworkManagementEventObserver.Stub {
private Context mContext; private Context mContext;
@@ -629,6 +627,19 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
return retVal; return retVal;
} }
public String[] getTetheredIfacePairs() {
final ArrayList<String> list = Lists.newArrayList();
synchronized (mIfaces) {
for (TetherInterfaceSM sm : mIfaces.values()) {
if (sm.isTethered()) {
list.add(sm.mMyUpstreamIfaceName);
list.add(sm.mIfaceName);
}
}
}
return list.toArray(new String[list.size()]);
}
public String[] getTetherableIfaces() { public String[] getTetherableIfaces() {
ArrayList<String> list = new ArrayList<String>(); ArrayList<String> list = new ArrayList<String>();
synchronized (mIfaces) { synchronized (mIfaces) {

View File

@@ -25,6 +25,7 @@ import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID; import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_DEFAULT;
@@ -34,6 +35,7 @@ import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi; import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.UID_REMOVED; import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
import static android.provider.Settings.Secure.NETSTATS_FORCE_COMPLETE_POLL; import static android.provider.Settings.Secure.NETSTATS_FORCE_COMPLETE_POLL;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION; import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY; import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
@@ -68,6 +70,7 @@ import android.net.NetworkState;
import android.net.NetworkStats; import android.net.NetworkStats;
import android.net.NetworkStatsHistory; import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate; import android.net.NetworkTemplate;
import android.net.TrafficStats;
import android.os.Binder; import android.os.Binder;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
@@ -89,6 +92,7 @@ import android.util.TrustedTime;
import com.android.internal.os.AtomicFile; import com.android.internal.os.AtomicFile;
import com.android.internal.util.Objects; import com.android.internal.util.Objects;
import com.android.server.EventLogTags; import com.android.server.EventLogTags;
import com.android.server.connectivity.Tethering;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
import com.google.android.collect.Maps; import com.google.android.collect.Maps;
import com.google.android.collect.Sets; import com.google.android.collect.Sets;
@@ -134,11 +138,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** Flags to control detail level of poll event. */ /** Flags to control detail level of poll event. */
private static final int FLAG_POLL_NETWORK = 0x1; private static final int FLAG_POLL_NETWORK = 0x1;
private static final int FLAG_POLL_UID = 0x2; private static final int FLAG_POLL_UID = 0x2;
private static final int FLAG_POLL_TETHER = 0x3;
private static final int FLAG_PERSIST_NETWORK = 0x10; private static final int FLAG_PERSIST_NETWORK = 0x10;
private static final int FLAG_PERSIST_UID = 0x20; private static final int FLAG_PERSIST_UID = 0x20;
private static final int FLAG_FORCE_PERSIST = 0x100; private static final int FLAG_FORCE_PERSIST = 0x100;
private static final int FLAG_POLL_ALL = FLAG_POLL_NETWORK | FLAG_POLL_UID; private static final int FLAG_POLL_ALL = FLAG_POLL_NETWORK | FLAG_POLL_UID | FLAG_POLL_TETHER;
private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
private final Context mContext; private final Context mContext;
@@ -195,6 +200,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private NetworkStats mLastPollNetworkSnapshot; private NetworkStats mLastPollNetworkSnapshot;
private NetworkStats mLastPollUidSnapshot; private NetworkStats mLastPollUidSnapshot;
private NetworkStats mLastPollOperationsSnapshot; private NetworkStats mLastPollOperationsSnapshot;
private NetworkStats mLastPollTetherSnapshot;
private NetworkStats mLastPersistNetworkSnapshot; private NetworkStats mLastPersistNetworkSnapshot;
private NetworkStats mLastPersistUidSnapshot; private NetworkStats mLastPersistUidSnapshot;
@@ -258,6 +264,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
// watch for tethering changes
final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler);
// listen for periodic polling events // listen for periodic polling events
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler); mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
@@ -543,6 +553,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
}; };
/**
* Receiver that watches for {@link Tethering} to claim interface pairs.
*/
private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
// permission above.
performPoll(FLAG_POLL_TETHER);
}
};
private BroadcastReceiver mPollReceiver = new BroadcastReceiver() { private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
@@ -686,12 +708,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0; boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0;
boolean pollUid = (flags & FLAG_POLL_UID) != 0; boolean pollUid = (flags & FLAG_POLL_UID) != 0;
boolean pollTether = (flags & FLAG_POLL_TETHER) != 0;
// when complete poll requested, any partial poll enables everything // when complete poll requested, any partial poll enables everything
final boolean forceCompletePoll = mSettings.getForceCompletePoll(); final boolean forceCompletePoll = mSettings.getForceCompletePoll();
if (forceCompletePoll && (pollNetwork || pollUid)) { if (forceCompletePoll && (pollNetwork || pollUid || pollTether)) {
pollNetwork = true; pollNetwork = true;
pollUid = true; pollUid = true;
pollTether = true;
} }
final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
@@ -723,6 +747,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
} }
if (pollTether) {
final String[] ifacePairs = mConnManager.getTetheredIfacePairs();
final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
ifacePairs);
performTetherPollLocked(tetherSnapshot, currentTime);
// persisted during normal UID cycle below
}
if (pollUid) { if (pollUid) {
final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
performUidPollLocked(uidSnapshot, currentTime); performUidPollLocked(uidSnapshot, currentTime);
@@ -848,6 +881,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mOperations = new NetworkStats(0L, 10); mOperations = new NetworkStats(0L, 10);
} }
/**
* Update {@link #mUidStats} historical usage for
* {@link TrafficStats#UID_TETHERING} based on tethering statistics.
*/
private void performTetherPollLocked(NetworkStats tetherSnapshot, long currentTime) {
ensureUidStatsLoadedLocked();
final NetworkStats delta = computeStatsDelta(
mLastPollTetherSnapshot, tetherSnapshot, false);
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
for (int i = 0; i < delta.size(); i++) {
entry = delta.getValues(i, entry);
final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
if (ident == null) {
if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
|| entry.txPackets > 0) {
Log.w(TAG, "dropping tether delta from unknown iface: " + entry);
}
continue;
}
final NetworkStatsHistory history = findOrCreateUidStatsLocked(
ident, UID_TETHERING, SET_DEFAULT, TAG_NONE);
history.recordData(timeStart, currentTime, entry);
}
// normal UID poll will trim any history beyond max
mLastPollTetherSnapshot = tetherSnapshot;
}
/** /**
* Sample recent statistics summary into {@link EventLog}. * Sample recent statistics summary into {@link EventLog}.
*/ */