功耗和温升通常是Android系统的硬伤,尤其是结构空间有限的Android系统设备,比如用Android系统开发的手表设备。结构有限意味着能放的电池容量不会很大,导致待机时间变得特别短。
而且通常这种手表设备的在原始Android系统上,功耗比较正常,但内置一些功能应用后,功耗变得很大,待机时间特别短。下面是功耗分析的一般步骤:
遇到待机功耗偏高问题,分析步骤如下:
1.确定飞行模式下低电流是否正常?
正常情况飞行模式下待机电流在3-5mA;
不正常:给硬件和驱动分析解决;
2.若飞行模式正常,开始确认原生Launcher3的软件版本是否正常?(去掉一切客户预置的apk)
正常情况下Launcher3软件版本
4G模式待机电流10-13mA
2G/3G模式待机电流7-9mA
需要注意的是信号不好时会影响这个范围值;
若不正常:抓取mtklog分析;
3.若Launcher3软件正常,加上客户预置的WatchLauncher等apk后电流不正常?
抓取mtklog分析;
4.功耗异常mtklog分析方法:
一般应用层的功耗问题有以下种情况
一是某个应用持有唤醒锁未释放;
二是后台有网络访问行为发生;
三是定位调用GPS;
四是蓝牙WIFI搜索或扫描
五其他Sensor在后台持续工作如心率传感器。
4.1 首先确认是否正常待机
要确认CPU是否正常睡眠进入待机,需要查看PowerManagerService是否释放了所有持有的唤醒锁,如下:
查看sys_log
Line 3115: 01-01 00:05:14.731848 973 1003 D PowerManagerService: acquireWakeLockInternal: lock=256728484, flags=0x3000001a, tag="key_u_wake_lock", ws=null, uid=1000, pid=4287
Line 3137: 01-01 00:05:14.753272 973 1003 D PowerManagerNotifier: onWakeLockAcquired: flags=805306394, tag="key_u_wake_lock", packageName=android.fise.com.fiseassitant, ownerUid=1000, ownerPid=4287, workSource=null
Line 4344: 01-01 00:05:24.765232 973 2238 D PowerManagerService: releaseWakeLockInternal: lock=256728484 [key_u_wake_lock], flags=0x0, total_time=10033ms
Line 4345: 01-01 00:05:24.765673 973 2238 D PowerManagerNotifier: onWakeLockReleased: flags=805306394, tag="key_u_wake_lock", packageName=android.fise.com.fiseassitant, ownerUid=1000, ownerPid=4287, workSource=null
Line 6433: 01-01 00:05:43.614531 973 2910 D PowerManagerService: acquireWakeLockInternal: lock=23202550, flags=0x3000001a, tag="key_u_wake_lock", ws=null, uid=1000, pid=4287
Line 6452: 01-01 00:05:43.621134 973 2910 D PowerManagerNotifier: onWakeLockAcquired: flags=805306394, tag="key_u_wake_lock", packageName=android.fise.com.fiseassitant, ownerUid=1000, ownerPid=4287, workSource=null
如上如果灭屏后一段时间走了PowerManagerService: releaseWakeLockInternal方法且没有在走PowerManagerService: acquireWakeLockInternal
其中tag是持有或释放锁的名字,packageName是持有或释放该锁的进程。
这其中需要注意的是,测试功耗时先将时间同步到正常网络时间,并且灭屏1分钟后开始记下测试时间,精确到秒。再来对比log。
另外需要编译userdebug/eng版本才有PowerManagerServicelog输出,测试时只保留mobilelog开启,其他log都关闭。
4.2若CPU正常进入休眠,那说明有其他行为
网络访问行为需要查看mainlog,搜索关键字libc-netbsd 找到res_queryN后面的网址,如下,设备访问的每一个网址都会走这个方法:网址就是name = mepodownload.mediatek.com;
找到应用所访问的网址,再系统里整个搜索该网址名字,搜不到则是三方应用访问。如果搜出是系统所访问,则再仔细追踪为何会走到访问网络代码。
Line 1738: 01-01 00:00:09.832529 261 2119 D libc-netbsd: res_queryN name = mepodownload.mediatek.com., class = 1, type = 1
Line 1944: 12-04 18:21:59.875462 261 3053 D libc-netbsd: res_queryN name = xcap.ims.mnc000.mcc460.pub.3gppnetwork.org, class = 1, type = 1
Line 1962: 12-04 18:21:59.910583 261 3060 D libc-netbsd: res_queryN name = device.jiajialife.com, class = 1, type = 1
Line 1983: 12-04 18:22:00.029618 261 3075 D libc-netbsd: res_queryN name = device.jiajialife.com, class = 1, type = 1
Line 1993: 12-04 18:22:00.086842 261 3084 D libc-netbsd: res_queryN name = asia.pool.ntp.org, class = 1, type = 1
Line 2007: 12-04 18:22:00.151345 261 3089 D libc-netbsd: res_queryN name = s.jpush.cn, class = 1, type = 1
Line 2031: 12-04 18:22:00.633921 261 3147 D libc-netbsd: res_queryN name = push5.adups.com, class = 1, type = 1
Line 2036: 12-04 18:22:00.697235 261 3053 D libc-netbsd: res_queryN name = xcap.ims.mnc000.mcc460.pub.3gppnetwork.org succeed
Line 2037: 12-04 18:22:00.697236 261 3060 D libc-netbsd: res_queryN name = device.jiajialife.com succeed
Line 2038: 12-04 18:22:00.697236 261 3075 D libc-netbsd: res_queryN name = device.jiajialife.com succeed
Line 2052: 12-04 18:22:01.004627 261 3172 D libc-netbsd: res_queryN name = hshh.org, class = 1, type = 1
Line 2064: 12-04 18:22:01.031378 261 3174 D libc-netbsd: res_queryN name = app-measurement.com, class = 1, type = 1
Line 2068: 12-04 18:22:01.075390 261 3084 D libc-netbsd: res_queryN name = asia.pool.ntp.org succeed
Line 2070: 12-04 18:22:01.538021 261 3089 D libc-netbsd: res_queryN name = s.jpush.cn succeed
Line 2071: 12-04 18:22:01.540837 261 3172 D libc-netbsd: res_queryN name = hshh.org succeed
Line 2072: 12-04 18:22:01.541703 261 3147 D libc-netbsd: res_queryN name = push5.adups.com succeed
Line 2078: 12-04 18:22:01.578749 261 3174 D libc-netbsd: res_queryN name = app-measurement.com succeed
Line 2090: 12-04 18:22:03.000968 261 3177 D libc-netbsd: res_queryN name = bsf.mnc000.mcc460.pub.3gppnetwork.org, class = 1, type = 1
Line 2099: 12-04 18:22:03.978395 261 3177 D libc-netbsd: res_queryN name = bsf.mnc000.mcc460.pub.3gppnetwork.org succeed
Line 2116: 12-04 18:22:09.304616 261 3209 D libc-netbsd: res_queryN name = stats.jpush.cn, class = 1, type = 1
Line 2120: 12-04 18:22:09.738866 261 3209 D libc-netbsd: res_queryN name = stats.jpush.cn succeed
Line 2135: 12-04 18:22:10.544604 261 3211 D libc-netbsd: res_queryN name = t1.hshh.org, class = 1, type = 1
Line 2141: 12-04 18:22:11.455542 261 3211 D libc-netbsd: res_queryN name = t1.hshh.org succeed
Line 2153: 12-04 18:22:13.353241 261 3215 D libc-netbsd: res_queryN name = hshh.org, class = 1, type = 1
Line 2154: 12-04 18:22:13.353320 261 3215 D libc-netbsd: res_queryN name = hshh.org succeed
Line 2166: 12-04 18:22:14.875000 261 3219 D libc-netbsd: res_queryN name = stats.jpush.cn, class = 1, type = 1
Line 2167: 12-04 18:22:14.875085 261 3219 D libc-netbsd: res_queryN name = stats.jpush.cn succeed
Line 2208: 12-04 18:22:17.129304 261 3234 D libc-netbsd: res_queryN name = supl.google.com, class = 1, type = 1
Line 2212: 12-04 18:22:18.877794 261 3234 D libc-netbsd: res_queryN name = supl.google.com succeed
Line 2236: 12-04 18:22:22.354728 261 3238 D libc-netbsd: res_queryN name = t1.hshh.org, class = 1, type = 1
Line 2237: 12-04 18:22:22.354806 261 3238 D libc-netbsd: res_queryN name = t1.hshh.org succeed
Line 2266: 12-04 18:22:25.201207 261 3317 D libc-netbsd: res_queryN name = push5.adups.com, class = 1, type = 1
Line 2267: 12-04 18:22:25.201321 261 3317 D libc-netbsd: res_queryN name = push5.adups.com succeed
Line 2308: 12-04 18:22:28.354897 261 3387 D libc-netbsd: res_queryN name = imtt.dd.qq.com, class = 1, type = 1
Line 2323: 12-04 18:22:28.372317 261 3389 D libc-netbsd: res_queryN name = stats.jpush.cn, class = 1, type = 1
Line 2324: 12-04 18:22:28.372513 261 3389 D libc-netbsd: res_queryN name = stats.jpush.cn succeed
如果看到自己的log res_queryN name = 后面没有名字输出,那说明你的代码是Android O以后的,可以去bionic/libc/dns/net/getaddrinfo.c
里面修改打印方法:
res_queryN(){
.....
if (LOAD_IS_USER)
debug_log("res_queryN succeed");
else
debug_log("res_queryN name = %s succeed", name);
return ancount;
改为:
if (LOAD_IS_USER)
debug_log("res_queryN name = %s succeed", name);
else
debug_log("res_queryN name = %s succeed", name);
return ancount;
这样再编译,访问的所有网址域名都能打印出来了。
4.3CPU正常,网络也没访问,则查看GPS定位是否有持续
定位直接搜索Location关键字,可以搜出
开始定位log:可以得到是gps定位还是network定位,是哪个应用调用了定位等信息。
083004 05-12 09:50:00.510 827 1468 D LocationManagerService: request 1434db9 gps Request[ACCURACY_FINE gps requested=+10s0ms fastest=+10s0ms] from com.tct.weather(10052)//是哪个应用定位。
结束定位log:
108716 05-12 09:50:31.004 827 1468 I LocationManagerService: remove 1434db9
这句log打印在LocationManagerService.java的requestLocationUpdatesLocked方法中,user版本不会输出,可以将log级别调到e级。
4.4如果CPU正常待机,没有使用网络,没有定位,功耗还是挺不正常,那可以想想是否有使用蓝牙功能,若有
搜索startLeScan字样,这里是确定使用的是蓝牙4.0或以上。
2324: 12-04 18:22:28.372513 261 3389 D BluetoothAdapter: startLeScan(): 00000000-0000-1000-8000-00805F9B34FB
然后看多久扫描一次,是不是频繁在扫描。
4.5如果蓝牙也正常,则看看是否有一些后台测试类的Sensor,如心率,血压等。计步的GSensor可以忽略,这个比较成熟消耗功耗比较少。
这个只能自己看自己的监听代码,是否睡眠后还在监听着Sensor。
找到功耗的引起的原因,有时候也不一定能优化好,比如找到是定位,但是定位必须要那么短间隔定位一次,那也没法进行优化。
不过知道每一部分功耗消耗在哪里,我们作为软件工程师也能够向客户交代,每一部分功耗消耗在哪里。
常规功耗优化手段:
1.访问数据网络间隔尽量加长,减少访问量:比如如果和服务器后台有连接,可以减少发送数据包,心跳包等。
2.尽量加长定位间隔:比如5分钟一次改为10分钟一次等。
3.用户不操作时可以将网络切换到2G或3G去待机,晚上半夜期间甚至可以判断用户未使用时然后开启分析模式。-------这个效果比较好。
基本上所有软件层功耗问题,通过以上步骤都可以得到解决。若有遗漏,请大家补充。