Linux eBPF 技术
Linux中的eBPF(Extended Berkeley Packet Filter)是一种革命性的内核技术,它就像一个安全且高效的“小程序”引擎,允许开发者在不直接修改内核代码的情况下,在内核空间运行自己编写的程序。这些小程序可以在很多关键路径上运行,比如网络数据包处理、系统调用跟踪、性能分析,甚至是文件系统和安全策略执行等场景
调试命令
adb shell dumpsys netd trafficcontroller
lxg@lixiaogang:~$ adb shell dumpsys netd trafficcontroller
TrafficController
BPF module status: BPF_LEVEL_BASIC
mCookieTagMap status: OK
mUidCounterSetMap status: OK
mAppUidStatsMap status: OK
mStatsMapA status: OK
mStatsMapB status: OK
mIfaceIndexNameMap status: OK
mIfaceStatsMap status: OK
mConfigurationMap status: OK
mUidOwnerMap status: OK
Cgroup ingress program status: OK
Cgroup egress program status: OK
xt_bpf ingress program status: OK
xt_bpf egress program status: OK
xt_bpf bandwidth whitelist program status: OK
xt_bpf bandwidth blacklist program status: OK
BPF map content:
mCookieTagMap:
cookie=760 tag=0xfffffe03 uid=1000
cookie=347 tag=0xfffffe02 uid=1000
cookie=555 tag=0xfffffe02 uid=1000
cookie=759 tag=0xfffffe02 uid=1000
mUidCounterSetMap:
1001 1
10046 1
10029 1
10036 1
mAppUidStatsMap::
uid rxBytes rxPackets txBytes txPackets
10046 54619 360 39385 401
1051 1215 12 827 12
0 0 0 14940 170
10018 10383 14 1785 16
1020 97099 351 57571 205
1052 17859 139 17973 144
1000 46792 199 28380 241
mStatsMapA:
ifaceIndex ifaceName tag_hex uid_int cnt_set rxBytes rxPackets txBytes txPackets
10 usb0 0x0 10046 1 8493 47 7894 62
10 usb0 0x0 10046 0 1993 25 2097 29
14 wlan0 0x0 1052 0 4672 68 12775 68
14 wlan0 0x0 1020 0 16820 64 6950 20
14 wlan0 0xfffffe03 1000 0 656 2 676 2
14 wlan0 0x0 0 0 0 0 368 3
14 wlan0 0xfffffe02 1000 0 160 3 0 0
10 usb0 0x0 1052 0 13187 71 5198 76
10 usb0 0x0 1000 0 444 8 991 12
10 usb0 0x0 1020 0 13872 40 6936 20
10 usb0 0x0 1051 0 180 2 148 2
10 usb0 0x0 0 0 0 0 1508 8
14 wlan0 0x0 1000 0 816 5 676 2
mStatsMapB:
ifaceIndex ifaceName tag_hex uid_int cnt_set rxBytes rxPackets txBytes txPackets
mIfaceIndexNameMap:
ifaceIndex=8 ifaceName=sit0
ifaceIndex=9 ifaceName=ip6tnl0
ifaceIndex=6 ifaceName=ip_vti0
ifaceIndex=7 ifaceName=ip6_vti0
ifaceIndex=4 ifaceName=gre0
ifaceIndex=2 ifaceName=eth0
ifaceIndex=13 ifaceName=wlan0
ifaceIndex=3 ifaceName=tunl0
ifaceIndex=10 ifaceName=usb0
ifaceIndex=5 ifaceName=gretap0
ifaceIndex=14 ifaceName=wlan0
ifaceIndex=1 ifaceName=lo
ifaceIndex=12 ifaceName=wlan0
mIfaceStatsMap::
ifaceIndex ifaceName rxBytes rxPackets txBytes txPackets
2 eth0 1345 7 3498 24
13 wlan0 4432 14 10504 44
10 usb0 476366 1759 495960 2198
5 gretap0 0 0 384 4
14 wlan0 358823 1204 343910 1104
1 lo 4076 33 4076 33
12 wlan0 8022 35 18872 106
current ownerMatch configuration: 0
current statsMap configuration: 0
mUidOwnerMap:
10006 HAPPY_BOX_MATCH
mUidPermissionMap:
10005 PERMISSION_NONE
10035 PERMISSION_NONE
1001 BPF_PERMISSION_INTERNET BPF_PERMISSION_UPDATE_DEVICE_STATS
10003 PERMISSION_NONE
10022 PERMISSION_NONE
1073 PERMISSION_NONE
10002 PERMISSION_NONE
10034 PERMISSION_NONE
10006 BPF_PERMISSION_INTERNET BPF_PERMISSION_UPDATE_DEVICE_STATS
1002 BPF_PERMISSION_INTERNET BPF_PERMISSION_UPDATE_DEVICE_STATS
10039 PERMISSION_NONE
1003 PERMISSION_NONE
10007 PERMISSION_NONE
10045 PERMISSION_NONE
10025 PERMISSION_NONE
10014 PERMISSION_NONE
10032 PERMISSION_NONE
10020 PERMISSION_NONE
10012 PERMISSION_NONE
10024 PERMISSION_NONE
10041 PERMISSION_NONE
1041 BPF_PERMISSION_UPDATE_DEVICE_STATS
10017 PERMISSION_NONE
10033 PERMISSION_NONE
1013 BPF_PERMISSION_INTERNET BPF_PERMISSION_UPDATE_DEVICE_STATS
10010 PERMISSION_NONE
10027 PERMISSION_NONE
10011 PERMISSION_NONE
10004 PERMISSION_NONE
10037 PERMISSION_NONE
10000 PERMISSION_NONE
1047 BPF_PERMISSION_UPDATE_DEVICE_STATS
1067 PERMISSION_NONE
10038 PERMISSION_NONE
10043 PERMISSION_NONE
1066 PERMISSION_NONE
10013 PERMISSION_NONE
10036 PERMISSION_NONE
1063 PERMISSION_NONE
10019 PERMISSION_NONE
10023 PERMISSION_NONE
10001 PERMISSION_NONE
mPrivilegedUser:
1001 ALLOW_UPDATE_DEVICE_STATS
1002 ALLOW_UPDATE_DEVICE_STATS
1013 ALLOW_UPDATE_DEVICE_STATS
1041 ALLOW_UPDATE_DEVICE_STATS
1047 ALLOW_UPDATE_DEVICE_STATS
10006 ALLOW_UPDATE_DEVICE_STATS
adb shell dumpsys netstats –full –uid
adb shell dumpsys netstats --full --uid
Active interfaces:
iface=usb0 ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}]
Active UID interfaces:
iface=usb0 ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}]
Top openSession callers (uid=count):
Dev stats:
Pending bytes: 238053
Complete history:
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=false}] uid=-1 set=ALL tag=0x0
NetworkStatsHistory: bucketDuration=3600
st=1711681200 rb=0 rp=0 tb=212 tp=3 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=-1 set=ALL tag=0x0
NetworkStatsHistory: bucketDuration=3600
st=1711681200 rb=59748425 rp=43312 tb=786425 tp=17976 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=-1 set=ALL tag=0x0
NetworkStatsHistory: bucketDuration=3600
st=1712026800 rb=125126 rp=587 tb=112927 tp=845 op=0
Xt stats:
Pending bytes: 238053
Complete history:
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=false}] uid=-1 set=ALL tag=0x0
NetworkStatsHistory: bucketDuration=3600
st=1711681200 rb=0 rp=0 tb=328 tp=5 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=-1 set=ALL tag=0x0
NetworkStatsHistory: bucketDuration=3600
st=1711681200 rb=59748425 rp=43312 tb=786425 tp=17976 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=-1 set=ALL tag=0x0
NetworkStatsHistory: bucketDuration=3600
st=1712026800 rb=125126 rp=587 tb=112927 tp=845 op=0
UID stats:
Pending bytes: 221756
Complete history:
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=false}] uid=0 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=0 rp=0 tb=376 tp=5 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=0 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=0 rp=0 tb=2453 tp=39 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=1000 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=59334215 rp=42639 tb=713280 tp=17139 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=1020 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=11798 rp=33 tb=7792 tp=22 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=1051 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=1692 rp=17 tb=1084 tp=17 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=10021 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=14889 rp=42 tb=12920 tp=156 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=10021 set=FOREGROUND tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=163011 rp=132 tb=6382 tp=135 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=10046 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=36438 rp=269 tb=22295 tp=279 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460082..., metered=true, defaultNetwork=true}] uid=10046 set=FOREGROUND tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1711677600 rb=189046 rp=168 tb=12387 tp=166 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=0 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=0 rp=0 tb=5660 tp=76 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=1000 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=45532 rp=186 tb=26713 tp=227 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=1020 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=33160 rp=110 tb=23282 tp=78 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=1051 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=1035 rp=10 tb=679 tp=10 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=10018 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=3043 rp=4 tb=272 tp=5 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=10018 set=FOREGROUND tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=7340 rp=10 tb=1513 tp=11 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=10046 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=7437 rp=26 tb=3073 tp=27 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=10046 set=FOREGROUND tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=36696 rp=262 tb=26321 tp=283 op=0
单次开机流量数据
adb shell dumpsys netstats –uid
adb shell dumpsys netstats --uid
Active interfaces:
iface=usb0 ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}]
Active UID interfaces:
iface=usb0 ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}]
Top openSession callers (uid=count):
Dev stats:
Pending bytes: 1250069
History since boot:
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=-1 set=ALL tag=0x0
NetworkStatsHistory: bucketDuration=3600
st=1712026800 rb=617403 rp=2788 tb=632666 tp=3407 op=0
Xt stats:
Pending bytes: 1250069
History since boot:
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=-1 set=ALL tag=0x0
NetworkStatsHistory: bucketDuration=3600
st=1712026800 rb=617403 rp=2788 tb=632666 tp=3407 op=0
UID stats:
Pending bytes: 1231831
History since boot:
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=-5 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=382993 rp=1247 tb=408558 tp=1408 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=0 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=0 rp=0 tb=8149 tp=95 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=1000 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=50694 rp=279 tb=39314 tp=365 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=1020 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=48712 rp=154 tb=31058 tp=100 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=1051 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=1307 rp=13 tb=903 tp=13 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=1052 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=15602 rp=86 tb=6357 tp=93 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=10018 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=3043 rp=4 tb=272 tp=5 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=10018 set=FOREGROUND tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=7340 rp=10 tb=1513 tp=11 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=10046 set=DEFAULT tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=9430 rp=51 tb=5170 tp=56 op=0
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086..., metered=true, defaultNetwork=true}] uid=10046 set=FOREGROUND tag=0x0
NetworkStatsHistory: bucketDuration=7200
st=1712023200 rb=113062 rp=968 tb=98354 tp=1112 op=0
解释
ident=[{type=MOBILE, subType=COMBINED, subscriberId=460086…, metered=true, defaultNetwork=true}]: 描述的是网络接口身份信息,其中:
- type=MOBILE: 表明这是一个移动网络类型,如2G、3G、4G、5G等。
- subType=COMBINED: 可能是指综合型的移动网络,即不分具体的子类型。
- subscriberId=460086…: 移动网络运营商提供的SIM卡的唯一标识(IMSI的一部分)。
- metered=true: 表示该网络是计费的,即使用此网络产生的流量可能会计入用户的套餐限额。
- defaultNetwork=true: 表示这是设备默认连接的网络。
- uid=10046: 指的是执行此次流量操作的用户ID(UID)。在Android系统中,每个应用程序都有一个对应的UID,用于区分不同的应用并进行权限控制。
set=DEFAULT: 这里的“set”通常指的是网络统计集合,DEFAULT可能是默认的统计集合,涵盖了所有的网络活动。
tag=0x0: “tag”在这里通常用于标记特定的网络流量源,0x0表示没有特定的tag标签,可能是所有未特别标记的网络流量。
NetworkStatsHistory: bucketDuration=7200: 描述的是网络流量历史统计信息,这里的bucketDuration表示每个统计桶的时间长度,单位是秒,这里为7200秒,即2小时。
后面的 st=1712023200 rb=9430 rp=51 tb=5170 tp=56 op=0:
- st=开始时间戳,这里的1712023200是一个Unix时间戳,转换成日期需要进一步处理。
- rb=收到(Received)的总字节数。
- rp=收到(Received)的包数。
- tb=发送(Transmitted)的总字节数。
- tp=发送(Transmitted)的包数。
- op=未知字段,可能根据上下文有不同的含义,这里没有足够的信息来准确说明。在某些网络统计中,op可能代表丢包数量或其他操作计数。
源码
frameworks/base/services/core/java/com/android/server/net/NetworkStatsService.java
// 是否启用网络流量统计增强功能,这可能涉及到补充和完善网络使用数据
import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
// 设备级别的网络流量统计bucket(时间间隔)持续时间
import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
// 设备级别的网络流量统计数据的删除保留期限
import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
// 设备级别网络流量统计持久化的最大字节数
import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
// 设备级别网络流量统计数据的旋转保留期限
import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
// 触发全局流量警报的字节数阈值
import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
// 网络流量统计信息的轮询间隔
import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
// 是否启用网络流量统计采样功能
import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
// 基于用户ID的网络流量统计bucket持续时间
import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
public class NetworkStatsService extends INetworkStatsService.Stub {
static final String TAG = "NetworkStats";
/**
* Default external settings that read from
* {@link android.provider.Settings.Global}.
*/
private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
private final ContentResolver mResolver;
public DefaultNetworkStatsSettings(Context context) {
mResolver = checkNotNull(context.getContentResolver());
// TODO: adjust these timings for production builds
}
private long getGlobalLong(String name, long def) {
return Settings.Global.getLong(mResolver, name, def);
}
private boolean getGlobalBoolean(String name, boolean def) {
final int defInt = def ? 1 : 0;
return Settings.Global.getInt(mResolver, name, defInt) != 0;
}
@Override
public long getPollInterval() {
return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
}
@Override
public long getGlobalAlertBytes(long def) {
return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
}
@Override
public boolean getSampleEnabled() {
return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
}
@Override
public boolean getAugmentEnabled() {
return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true);
}
@Override
public Config getDevConfig() {
// 修改此处的流量统计间隔时间
return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
}
@Override
public Config getXtConfig() {
return getDevConfig();
}
@Override
public Config getUidConfig() {
// 修改此处的流量统计间隔时间
return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
}
@Override
public Config getUidTagConfig() {
// 修改此处的流量统计间隔时间
return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
}
@Override
public long getDevPersistBytes(long def) {
return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
}
@Override
public long getXtPersistBytes(long def) {
return getDevPersistBytes(def);
}
@Override
public long getUidPersistBytes(long def) {
return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
}
@Override
public long getUidTagPersistBytes(long def) {
return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
}
}
@Override
protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
long duration = DateUtils.DAY_IN_MILLIS;
final HashSet<String> argSet = new HashSet<String>();
for (String arg : args) {
argSet.add(arg);
if (arg.startsWith("--duration=")) {
try {
duration = Long.parseLong(arg.substring(11));
} catch (NumberFormatException ignored) {
}
}
}
// usage: dumpsys netstats --full --uid --tag --poll --checkin
final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
final boolean checkin = argSet.contains("--checkin");
final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " ");
synchronized (mStatsLock) {
if (args.length > 0 && "--proto".equals(args[0])) {
// In this case ignore all other arguments.
dumpProtoLocked(fd);
return;
}
if (poll) {
performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
pw.println("Forced poll");
return;
}
if (checkin) {
final long end = System.currentTimeMillis();
final long start = end - duration;
pw.print("v1,");
pw.print(start / SECOND_IN_MILLIS); pw.print(',');
pw.print(end / SECOND_IN_MILLIS); pw.println();
pw.println("xt");
mXtRecorder.dumpCheckin(rawWriter, start, end);
if (includeUid) {
pw.println("uid");
mUidRecorder.dumpCheckin(rawWriter, start, end);
}
if (includeTag) {
pw.println("tag");
mUidTagRecorder.dumpCheckin(rawWriter, start, end);
}
return;
}
pw.println("Active interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveIfaces.size(); i++) {
pw.printPair("iface", mActiveIfaces.keyAt(i));
pw.printPair("ident", mActiveIfaces.valueAt(i));
pw.println();
}
pw.decreaseIndent();
pw.println("Active UID interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveUidIfaces.size(); i++) {
pw.printPair("iface", mActiveUidIfaces.keyAt(i));
pw.printPair("ident", mActiveUidIfaces.valueAt(i));
pw.println();
}
pw.decreaseIndent();
// Get the top openSession callers
final SparseIntArray calls;
synchronized (mOpenSessionCallsPerUid) {
calls = mOpenSessionCallsPerUid.clone();
}
final int N = calls.size();
final long[] values = new long[N];
for (int j = 0; j < N; j++) {
values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j);
}
Arrays.sort(values);
pw.println("Top openSession callers (uid=count):");
pw.increaseIndent();
final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT);
for (int j = N - 1; j >= end; j--) {
final int uid = (int) (values[j] & 0xffffffff);
final int count = (int) (values[j] >> 32);
pw.print(uid); pw.print("="); pw.println(count);
}
pw.decreaseIndent();
pw.println();
pw.println("Dev stats:");
pw.increaseIndent();
mDevRecorder.dumpLocked(pw, fullHistory);
pw.decreaseIndent();
pw.println("Xt stats:");
pw.increaseIndent();
mXtRecorder.dumpLocked(pw, fullHistory);
pw.decreaseIndent();
if (includeUid) {
pw.println("UID stats:");
pw.increaseIndent();
mUidRecorder.dumpLocked(pw, fullHistory);
pw.decreaseIndent();
}
if (includeTag) {
pw.println("UID tag stats:");
pw.increaseIndent();
mUidTagRecorder.dumpLocked(pw, fullHistory);
pw.decreaseIndent();
}
}
}
}
frameworks/base/services/core/java/com/android/server/net/NetworkStatsRecorder.java
public class NetworkStatsRecorder {
private static final String TAG = "NetworkStatsRecorder";
public void dumpLocked(IndentingPrintWriter pw, boolean fullHistory) {
if (mPending != null) {
pw.print("Pending bytes: "); pw.println(mPending.getTotalBytes());
}
if (fullHistory) {
pw.println("Complete history:");
getOrLoadCompleteLocked().dump(pw);
} else {
pw.println("History since boot:");
mSinceBoot.dump(pw);
}
}
}
frameworks/base/services/core/java/com/android/server/net/NetworkStatsCollection.java
public class NetworkStatsCollection implements FileRotator.Reader {
public void dump(IndentingPrintWriter pw) {
for (Key key : getSortedKeys()) {
pw.print("ident="); pw.print(key.ident.toString());
pw.print(" uid="); pw.print(key.uid);
pw.print(" set="); pw.print(NetworkStats.setToString(key.set));
pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag));
final NetworkStatsHistory history = mStats.get(key);
pw.increaseIndent();
history.dump(pw, true);
pw.decreaseIndent();
}
}
}
frameworks/base/core/java/android/net/NetworkStatsHistory.java
public class NetworkStatsHistory implements Parcelable {
public void dump(IndentingPrintWriter pw, boolean fullHistory) {
pw.print("NetworkStatsHistory: bucketDuration=");
pw.println(bucketDuration / SECOND_IN_MILLIS);
pw.increaseIndent();
final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32);
if (start > 0) {
pw.print("(omitting "); pw.print(start); pw.println(" buckets)");
}
for (int i = start; i < bucketCount; i++) {
pw.print("st="); pw.print(bucketStart[i] / SECOND_IN_MILLIS);
if (rxBytes != null) { pw.print(" rb="); pw.print(rxBytes[i]); }
if (rxPackets != null) { pw.print(" rp="); pw.print(rxPackets[i]); }
if (txBytes != null) { pw.print(" tb="); pw.print(txBytes[i]); }
if (txPackets != null) { pw.print(" tp="); pw.print(txPackets[i]); }
if (operations != null) { pw.print(" op="); pw.print(operations[i]); }
pw.println();
}
pw.decreaseIndent();
}
}
UID 类型
frameworks/base/core/java/android/app/usage/NetworkStats.java
public final class NetworkStats implements AutoCloseable {
private final static String TAG = "NetworkStats";
/**
* Special UID value for aggregate/unspecified.
*/
public static final int UID_ALL = android.net.NetworkStats.UID_ALL;
/**
* Special UID value for removed apps.
*/
public static final int UID_REMOVED = TrafficStats.UID_REMOVED;
/**
* Special UID value for data usage by tethering.
*/
public static final int UID_TETHERING = TrafficStats.UID_TETHERING;
}
frameworks/base/core/java/android/net/TrafficStats.java
public class TrafficStats {
/**
* The return value to indicate that the device does not support the statistic.
*/
public final static int UNSUPPORTED = -1;
/** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long KB_IN_BYTES = 1024;
/** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
/** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
/** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
/** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
@Deprecated
public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
/**
* Special UID value used when collecting {@link NetworkStatsHistory} for
* removed applications.
*
* @hide
*/
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;
}
App 根据UID获取流量
@RequiresApi(api = Build.VERSION_CODES.M)
@SuppressLint("HardwareIds")
public static long getNetworkStatsByUid() {
long summaryTotal = 0;
try {
NetworkStats.Bucket summaryBucket = null;
summaryBucket = new NetworkStats.Bucket();
long startTime = System.currentTimeMillis() - SystemClock.elapsedRealtime();
Log.d(TAG, "startTime: " + startTime);
NetworkStats NetworkStats = sNSM.queryDetailsForUid(ConnectivityManager.TYPE_MOBILE, sTM.getSubscriberId(), startTime, System.currentTimeMillis(), -5);
do {
NetworkStats.getNextBucket(summaryBucket);
long summaryRx = summaryBucket.getRxBytes();
long summaryTx = summaryBucket.getTxBytes();
summaryTotal += summaryRx + summaryTx;
} while (NetworkStats.hasNextBucket());
} catch (Exception e) {
e.printStackTrace();
}
Log.d(TAG, "summaryTotal: " + summaryTotal);
return summaryTotal;
}