本文最初是想查看bugreport源码,分析bugreport中的Wifi流量数据。对于bugreport源码查看,已经有比较详细,并且特别好的文档,见调试系列1:bugreport源码篇。从bugreport源码中可以查看到,bugreport实际执行的是android dumpstate命令,dumpstate命令的输出主要为显示/proc中的内容和dumpsys服务的内容等。其中我们关注的电量以及流量问题即是dumpsys batterystats获得。故需要查看batterystats服务的源码。
以下主要根据统计每个app消耗流量的思路进行展开,以Uid为u0a3994的应用进行描述。
涉及到的文件
- BatteryStats.java:BatteryStats类,提供访问电源相关数据的接口,主要包括wakelocks,processes,packages和serivces的信息。BatteryStats还有一个内部类Uid,主要提供与特定uid(在Android中,每个app都有一个唯一的uid,uid即是app id)相关的数据。
目录:android-6.0.0_r1/frameworks/base/core/java/android/os/BatteryStats.java - BatteryStatsImpl.java:BatteryStats和Uid均为抽象类,BatteryStatsImpl是其对应的实现类。
目录:android-6.0.0_r1/frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java - NetworkStatsFactory.java:NetworkStatsFactory类,获取流量数据的接口。获取流量也主要是通过读取/proc/net/xt_qtaguid目录中的文件来获得。
目录:android-6.0.0_r1/frameworks/base/core/java/com/android/internal/net/NetworkStatsFactory.java - NetworkStats.java:NetworkStats类,存储网络数据的类。
目录:android-6.0.0_r1/frameworks/base/core/java/android/net/NetworkStats.java - Android源码下载:Android 系统全套源代码分享 (更新到 7.1.1_r1)
在执行dumpsys batterystats命令时输出的部分内容如下:
Estimated power use (mAh):
Capacity: 3010, Computed drain: 28.5, actual drain: 0
Uid u0a3994: 8.22 ( cpu=0.0926 wifi=8.06 gps=0.0722 )
Wifi: 4.93 ( cpu=0.0479 wifi=4.88 )
Cell standby: 3.66 ( radio=3.66 )
Uid 1000: 3.48 ( cpu=3.42 wifi=0.00000030 sensor=0.0545 )
Idle: 3.41
Uid 0: 2.10 ( cpu=2.10 wifi=0.000211 )
Uid u0a81: 0.476 ( cpu=0.134 sensor=0.342 )
Screen: 0.390
Uid u0a32: 0.329 ( cpu=0.0302 wifi=0.299 )
Uid 1001: 0.218 ( cpu=0.218 )
Uid u0a19: 0.139 ( cpu=0.139 wifi=0.0000218 )
Uid 1021: 0.0902 ( cpu=0.0902 )
Uid u0a38: 0.0781 ( cpu=0.0781 wifi=0.00000440 )
......(次数省略部分内容)
u0a3994:
Wi-Fi network: 13.13KB received, 13.10KB sent (packets 85 received, 123 sent)
Wifi Running: 0ms (0.0%)
Full Wifi Lock: 0ms (0.0%)
Wifi Scan: 2m 11s 885ms (3.0%) 51x
Wake lock *alarm*: 8ms partial (4 times) realtime
Wake lock *job*/com.dianping.v1/com.dianping.base.push.pushservice.PushWakeUpJob: 258ms partial (38 times) realtime
TOTAL wake: 266ms partial realtime
Job com.dianping.v1/com.dianping.base.push.pushservice.PushWakeUpJob: 1s 409ms realtime (38 times)
Sensor GPS: 1s 528ms realtime (3 times)
Foreground for: 1h 13m 12s 523ms
Total cpu time: u=1s 200ms s=2s 300ms p=0mAh
Proc com.dianping.v1:dppushservice:
CPU: 1s 210ms usr + 2s 240ms krn ; 0ms fg
Apk com.dianping.v1:
Wakeup alarm *walarm*:com.dianping.push.START: 1 times
Wakeup alarm *walarm*:com.dianping.push.KEEP_ALIVE: 18 times
Service com.dianping.base.push.pushservice.PushWakeUpJob:
Created for: 0ms uptime
Starts: 0, launches: 38
从输出内容可得电池容量为3010mAh,u0a3994应用耗电8.22mAh,括号内为对应的组件耗电。注意省略号之后的内容,本文即从查找u0a3994应用的Wifi上下行流量数据来源进行展开。
BatteryStats.java
根据上文输出信息,可确定内容是调用BatteryStats.java中的public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart)函数进行输出的,故可以此函数为入口,深入查找流量数据来源。该文件中有两个dumpLocked函数,注意根据函数签名区分。
在dumpLocked()函数中找到以下代码段:
for (int iu=0; iu<NU; iu++) {
final int uid = uidStats.keyAt(iu);
if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
continue;
}
final Uid u = uidStats.valueAt(iu);
pw.print(prefix);
pw.print(" ");
UserHandle.formatUid(pw, uid);
pw.println(":"