手机功耗测试实践

1,653 阅读2分钟

本篇文章介绍在没有功耗仪的情况下如何测试手机的功耗,原理是读取手机系统中实时更新的电流记录/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()

测试一:

  1. 连接手机:adb kill-server

  2. 手机连网,需要连接与电脑相同的网络或者同一wlan热点,记录手机ip 如:10.155.155.155

  3. 命令行输入:adb tcpip 5555 ,断开手机数据线连接,命令行输入: adb connect 10.155.155.155 , 如果成功回显“connected to 10.155.2.135:5555” 则连接成功

(2,3 步骤为了断开手机充电,因此转为wifi连接调试,但会产生一定功耗)

  1. 打开待测试app测试,本次试验app为手机camera应用

  2. 运行脚本:python battery_custom.py 60 ,参数60为记录秒数,脚本运行期间会打印读取的电流,单位uA,每秒读取10次, 每次功耗记为:(uA*0.1/3600) uAh

  3. 查看结果:脚本运行结束后会打印 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 用于分析电量消耗的占比,所测实时电流并不准确,相对而言读取系统的实时电流更为准确