本篇文章介绍在没有功耗仪的情况下如何测试手机的功耗,原理是读取手机系统中实时更新的电流记录/sys/class/power_supply/battery/current_now,高通平台为此目录,其他平台手机目录有部分变动,可以在系统目下自行查找
battery_custom.py
import os
import io
import sys
from threading import Timer
import logging
import time
import re
import datetime
import matplotlib.pyplot as plt
packageName = 'com.tcl.camera'
class Performance(object):
def __init__(self,deviceId ='',resultpath=None,log=None,logCount = 10):
self.devicedId =deviceId
self.isFirst = True
self.stop_flag = False
self.result_path = resultpath
if os.path.exists(resultpath):
os.remove(resultpath)
self.__ua_list = []
if resultpath is None:
self.result_path=Path.DATA_PATH+self.__class__.__name__+".csv"
self.log = log
if log is None:
self.log=get_logger(self.__class__.__name__)
if logCount <0:
logCount = 1
self.logCount = logCount
pass
def start(self):
self.timer = Timer(0.1,self.__fun__get__ua)
self.stop_timer = Timer(self.logCount,self.stop)
self.timer.start()
pass
def __get_uA(self):
output = os.popen('adb -s '+ self.devicedId+ ' shell cat /sys/class/power_supply/battery/current_now').read()
if not output:
return -1
try:
ua = int(output.strip())
except Exception:
ua = -1
return ua
pass
def __fun__get__ua(self):
if self.stop_flag:
self.log.info('Finish')
self.toChart()
return
self.timer = Timer(0.1,self.__fun__get__ua)
self.timer.start()
current_timestamp = time.time()
ua=self.__get_uA()
if self.isFirst:
self.isFirst = False
self.__ua_list.append(ua)
self.stop_timer.start()
elif ua>0:
string = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(current_timestamp))+",ua:"+str(ua)
self.log.info(string)
self.__ua_list.append(ua)
pass
def stop(self):
# self.timer.cancel()
self.stop_flag = True
pass
def toChart(self):
chartPath = self.result_path.replace(".csv",".png")
allma = 0.0
utimes = []
xdatas = []
time = 0.0
for ua in self.__ua_list:
utimes.append(ua/1000.0)
time = time +0.1
xdatas.append(time)
allma = allma+ua
allmah = allma*0.1/3600
averma = allma/1000.0/len(utimes)
self.log.info("consumed Energy:"+str(allmah)+" average:"+str(averma))
plt.figure(num='utime')
uc = plt.plot(xdatas, utimes, color='#FF0000',linewidth=1,label='power')
plt.legend(loc = 'best')
plt.xlabel('s')
plt.ylabel('mA')
title = "power info"
plt.title(title)
plt.savefig(chartPath, dpi=500)
pass
if __name__ == '__main__':
ps = os.popen("adb devices")
result = ps.readline()
deviceId = ''
for i in range(1):
result = ps.readline().split()
if len(result) < 1:
print(" device not found")
exit()
deviceId = result[0]
ps.close()
cnt = 10
if len(sys.argv) >= 2:
cnt = int(sys.argv[1])
# if len(sys.argv) >= 3:
# packageName = sys.argv[2]
# ps = os.popen('adb -s '+deviceId +' shell ps| grep '+packageName)
# result =ps.readline().split()
# pid = -1
# if len(result) >1:
# pid = result[1]
# else:
# print(packageName+" process name not found")
# exit()
# print(deviceId+' '+packageName+' '+str(pid))
# ps.close()
logging.basicConfig(level=logging.INFO, format='%(name)s - %(levelname)s: %(message)s')
logger = logging.getLogger("POWER")
o = Performance(deviceId,'battery_result.csv',logger,cnt)
o.start()
测试一:
-
连接手机:adb kill-server
-
手机连网,需要连接与电脑相同的网络或者同一wlan热点,记录手机ip 如:10.155.155.155
-
命令行输入:adb tcpip 5555 ,断开手机数据线连接,命令行输入: adb connect 10.155.155.155 , 如果成功回显“connected to 10.155.2.135:5555” 则连接成功
(2,3 步骤为了断开手机充电,因此转为wifi连接调试,但会产生一定功耗)
-
打开待测试app测试,本次试验app为手机camera应用
-
运行脚本:python battery_custom.py 60 ,参数60为记录秒数,脚本运行期间会打印读取的电流,单位uA,每秒读取10次, 每次功耗记为:(uA*0.1/3600) uAh
-
查看结果:脚本运行结束后会打印 consumed Energy:6366 average:392.48 ,consumed Energy为总功耗单位为uAh,average为平均电流单位为mA, 同时会在运行目录下生成battery_result.png文件记录实时电流图
ps:由于需要wifi连接并且adb shell 获取电量会产生功耗,所以测试需要空跑一次(重复5,6即可),记录一个相对值 测试手机为高通平台的手机,其他类型的手机测试前需要查看命令是否生效
其他试验:
使用battery historain 工具结合dumpsys batterystats命令测试
battery historain 的使用方法可以Google,可参考: github.com/google/batt…
免安装版本可使用:bathist.ef.lc/ 注意测试时需要断开usb
battery historain 用于分析电量消耗的占比,所测实时电流并不准确,相对而言读取系统的实时电流更为准确