def packageuid(cls): try: package = \ os.popen('adb -s %s shell ps |grep %s' % (Config.devices(), Config.packagename())).read().split(" ")[0] # 字符串截取坑:截取时不包含冒号后的数 3:7 的意思也就是:3,4,5,6 packageuid = package[0:2] + package[3:7] return packageuid.strip() except IndexError as e: cls.log.error("读取错误:未读取到 packageuid 数据")
def get_processmem(): result = subprocess.getoutput('adb shell "dumpsys meminfo ' + Config.packagename() + ' | grep TOTAL"') meminfo = result.split("\n")[0].split(" ") for i in range(len(meminfo) - 1, -1, -1): if meminfo[i] == "": meminfo.pop(i) return [meminfo[1], meminfo[2], meminfo[3]]
def meminfo(cls): try: memadb = "adb -s {} shell cat /proc/meminfo |grep MemTotal".format( Config.devices()) meminfo = int(os.popen(memadb).read().split()[1]) / 1024 / 1024 meminfo = '{:.2f}'.format(meminfo) + 'G' return meminfo except Exception as e: cls.log.error("读取系统内存信息失败") cls.log.error(e)
def packagepid(cls): try: packagepid = os.popen('adb shell ps |grep %s' % Config.packagename()) for index in packagepid.readlines(): if 'io.liuliu.music:' not in index: packagepid = index.strip().split()[1] return packagepid except IndexError: cls.log.info("读取错误:未读取到 packagepid 数据")
def dataread(cls): # 根据包名 获取到包对应的 UID packageuid = int( os.popen('adb -s %s shell ps |grep %s' % (Config.devices(), Config.packagename())).read().split( " ")[0].split('a', 1)[1]) + 10000 cls.log.debug("packageuid = %d" % packageuid) # 根据包对应UID 找到对应的网络数据;并且读取出来用字符串分割方法按行分割; packagenetdata = os.popen( 'adb -s %s shell cat /proc/net/xt_qtaguid/stats |grep %d' % (Config.devices(), packageuid)).read().splitlines() tx_packagenetdata = 0 rx_packagenetdata = 0 for dataread in packagenetdata: packnetdata = dataread.split(" ") if (int(packnetdata[3]) == packageuid) and (packnetdata[1] == 'wlan0'): cls.log.debug(packnetdata) tx_packagenetdata += int(packnetdata[7]) rx_packagenetdata += int(packnetdata[5]) return [tx_packagenetdata, rx_packagenetdata]
def cpuinfo(cls): try: cpunamecmd = "adb -s {} shell cat /proc/cpuinfo".format( Config.devices()) cpukercmd = "adb -s {} shell cat /proc/cpuinfo |grep ^processor |wc -l".format( Config.devices()) cpuname = subprocess.Popen(cpunamecmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) cpuname = str(cpuname.stdout.read()).split('Hardware', 1)[1].split(':', 1)[1] cpuname = cpuname[0:len(cpuname) - 3].strip() cpuker = subprocess.Popen(cpukercmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) cpuker = str(cpuker.stdout.read()).split()[1] cpuker = int(cpuker[0:len(cpuker) - 3].strip()) cpuratelist = [] for index in range(cpuker): cpuratecmd = "adb shell cat /sys/devices/system/cpu/cpu{}/cpufreq/cpuinfo_max_freq".format( index) cpurate = int(os.popen(cpuratecmd).read()) cpuratelist.append(cpurate) cpuratemax = '{:.1f}'.format((max(cpuratelist) / 1000000)) + 'GHz' return { 'cpuname': cpuname, 'cpucure': cpuker, 'cpuratemax': cpuratemax } except Exception as e: cls.log.error(e) cls.log.error("未获取到cpu信息")
def cpu_processtime(cls): cmd = "adb -s " + Config.devices( ) + " shell cat /proc/" + SystemInfo.packagepid() + "/stat" p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) (output, err) = p.communicate() res = output.split() utime = res[13].decode() stime = res[14].decode() cutime = res[15].decode() cstime = res[16].decode() result = int(utime) + int(stime) + int(cutime) + int(cstime) return result
def batterydata(cls): level = '' temperature = '' usbpowered = '' # 根据UID获取对应的电量消耗 battery = os.popen('adb -s %s shell dumpsys battery' % (Config.devices())).readlines() # 按行读取电量数据;如果该行存在对应关键字则开始读取 level和temperature 数据 for output in battery: if 'USB powered' in output: usbpowered = output.split(":", 1) cls.log.debug("设备是否充电 : %s" % usbpowered[1].split("\n", 1)[0].split(" ", 1)[1]) if 'level' in output: level = output.split(":", 1) cls.log.debug("设备当前电量 : %d" % int(level[1])) if 'temperature' in output: temperature = output.split(":", 1) cls.log.debug("设备当前温度 : %d" % int(temperature[1])) return int(level[1]), int(temperature[1]), usbpowered[1].split( "\n", 1)[0].split(" ", 1)[1]
class BatteryAlgorithm(object): os.popen('adb -s %s shell dumpsys batterystats --reset' % (Config.devices())) print('电量测试:电量数据已重置') # 每隔一段时间统计一次电量;需要传入一个row 值;电量算法存在问题 同理CPU算法同样存在问题 写法中不可以再加等待时间 不然会造成数据抓取不准确 @classmethod def battery_writedata(cls, row, waittime=10): battery_detaildata = BatteryStats.batterystatsdata() current_power = battery_detaildata['totalbattery'] time.sleep(waittime) battery_sysdata = BatteryStats.batterydata() temperature = int(battery_sysdata[1]) // 10 currenttime = SystemInfo.systime() currentactivity = SystemInfo.currentactivity() batterycapacity = battery_detaildata['batterycapacity'] new_power = battery_detaildata['totalbattery'] power_persecond = new_power - current_power batterydata = [ currenttime, batterycapacity, currentactivity, temperature, new_power, power_persecond ] ExcleDataSave.write_batterydata(row=row, batterydata=batterydata)
def cpu_totaltime(cls): cmd = "adb -s " + Config.devices() + " shell cat /proc/stat" p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) (output, err) = p.communicate() res = output.split() # 无需读取总数 cpu 即为总数 result = 0 for info in res: if info.decode() == "cpu": user = res[1].decode() nice = res[2].decode() system = res[3].decode() idle = res[4].decode() iowait = res[5].decode() irq = res[6].decode() softirq = res[7].decode() result = int(user) + int(nice) + int(system) + int(idle) + int( iowait) + int(irq) + int(softirq) return result
def getgfxdata(cls): gfxdataclean = os.popen( 'adb -s %s shell dumpsys gfxinfo %s' % (Config.devices(), Config.packagename())).readlines() cls.log.debug(gfxdataclean) # 清洗列表中数据;把 \n 都清洗掉;清洗好后的数据放入 gfxdata gfxdata = [] for index in range(len(gfxdataclean)): if gfxdataclean[index] != '\n': gfxdata.append(gfxdataclean[index].strip()) totalframesrendered = '' jankyframes = '' framesactivity = '' dictkeycount = 1 dictframes = {} for index in range(len(gfxdata)): # totalframesrendered:总计渲染了多少帧 if 'Total frames rendered' in gfxdata[index]: totalframesrendered = gfxdata[index].split(':')[1] cls.log.debug('总计渲染页面totalframesrendered = %s' % totalframesrendered) # Janky frames 掉帧率;渲染时间在 16.67 ms以上的帧 if 'Janky frames' in gfxdata[index]: jankyframes = gfxdata[index].split(':')[1] cls.log.debug('掉帧率 jankyframes = %s' % jankyframes) # 读取帧率详细时间数据; if ('io.liuliu.music/' in gfxdata[index]) and ('Draw' in gfxdata[index + 1]): # 找到 io.liuliu.music 后根据展示规则 判断文档下一行是否存在 Draw 如果存在则进入d分析逻辑 # 根据读取的数据判断 Draw、Process、Execute 分别的 index 保证数据准确性 framesactivity = gfxdata[index].split('/')[1].strip() cls.log.info('帧率测试:开始计算 index = %d' % index) gfxdetailed = gfxdata[index + 1].split('\t', 4) drawindex = gfxdetailed.index('Draw') processindex = gfxdetailed.index('Process') executeindex = gfxdetailed.index('Execute') # 判断是否有详细的帧率时间数据;需要在 Draw 下判断才符合规则 # 读取共有多少行帧率时间数据; startpersecgfxtime = index + 2 isbaddata = 'false' persecgfxcollect = [] while isbaddata == 'false': if ('io.liuliu.music' not in gfxdata[startpersecgfxtime]) \ and ('View hierarchy' not in gfxdata[startpersecgfxtime]): persecgfx = gfxdata[startpersecgfxtime].split('\t', 4) drawtime = float(persecgfx[drawindex]) processtime = float(persecgfx[processindex]) executetime = float(persecgfx[executeindex]) persecgfxcollect.append( [drawtime, processtime, executetime]) startpersecgfxtime += 1 else: isbaddata = 'true' cls.log.info('帧率测试:数据读取完成或无帧率详细数据 index = %d' % startpersecgfxtime) # 判断 persecgfxcollect 是否为空;如果 persecgfxcollect 无数据则不向字典写数据 if len(persecgfxcollect) != 0: dictframes[dictkeycount] = persecgfxcollect dictkeycount += 1 return totalframesrendered, jankyframes, dictframes, framesactivity
def firstinstalltime(cls): installtime = os.popen( 'adb shell dumpsys package %s |grep firstInstallTime' % Config.packagename()).read().split("=", 1) installtime = installtime[1].lstrip().rstrip() return installtime
def packageversioncode(cls): versioncode = os.popen( 'adb shell dumpsys package %s |grep versionCode' % Config.packagename()).read().split() versioncode = versioncode[0].split("=", 1)[1] return versioncode
def packageversion(cls): version = os.popen('adb shell dumpsys package %s |grep versionName' % Config.packagename()).read().split('=')[1].rstrip() return version
def batterystatsdata(cls): # 数据 return 顺序:totalbattery, batterycapacity, cpubattery, wifibattery, sensorbattery, camerabattery # 防止 battery 文件不能被实时更新;每次写数据前先判断文件是否存在;存在则删除之前文件,不存在则不做操作 if os.path.exists('./Datafile/log/battery.txt'): os.popen('rm -rf ./Datafile/log/battery.txt') time.sleep(0.3) cls.log.debug("文件 battery.txt 已被成功清除") else: cls.log.error("文件:battery.txt 不存在") # 保存 battery.txt 至脚本本地目录; try: os.popen( 'adb -s %s shell dumpsys batterystats >./Datafile/log/battery.txt' % (Config.devices())) time.sleep(0.5) if os.path.exists('./Datafile/log/battery.txt'): cls.log.debug("文件 battery.txt 已成功写入本地") except (IOError, Exception): cls.log.error("读取电量状态数据错误;battery.txt 存储失败") # 获取电池总电量:Capacity try: time.sleep(0.5) cmd = "cat ./Datafile/log/battery.txt |grep -E 'Capacity|capacity'" batterycapacity = int( os.popen(cmd).read().split(',', 1)[0].split(" ")[5]) cls.log.info("电池容量为 %d mAh" % batterycapacity) except (IndexError, IOError): batterycapacity = 1 # 电量的详细消耗数据写入 batterystatsdata后按照空格分割;分别读取 batterystatsdata = os.popen( 'cat ./Datafile/log/battery.txt |grep Uid|grep %s' % SystemInfo.packageuid()).read().split(" ") totalbattery = 0.0 # 判断UID是否存在;存在的话根据UID读取总体电量消耗 totalbattery if SystemInfo.packageuid() + ':' in batterystatsdata: totalbatteryindex = batterystatsdata.index( SystemInfo.packageuid() + ':') + 1 totalbattery = float(batterystatsdata[totalbatteryindex]) cls.log.info("当前应用消耗电量 %f" % totalbattery) cls.log.info("当前应用消耗电量百分比:%s" % '{:.2%}'.format(totalbattery / batterycapacity)) else: cls.log.error("电量数据不存在 totalbattery=%s" % totalbattery) # 判断CPU、WiFi、sensor、camera 是否存在;存在的话则写入,不存在的话则报错 cpubattery = 0.0 wifibattery = 0.0 sensorbattery = 0.0 camerabattery = 0.0 for output in batterystatsdata: if 'cpu' in output: cpubattery = float(output.split('=', 2)[1]) cls.log.info("当前CPU电量消耗 %f" % cpubattery) if 'wifi' in output: wifibattery = float(output.split('=', 2)[1]) cls.log.info("当前WIFI电量消耗 %f" % wifibattery) if 'sensor' in output: sensorbattery = float(output.split('=', 2)[1]) cls.log.info("当前硬件电量消耗 %f" % sensorbattery) if 'camera' in output: camerabattery = float(output.split('=', 2)[1]) cls.log.info("当前相机电量消耗 %f" % camerabattery) # batterycapacity 数据如果取不到时可能会造成问题;目前给默认值1 得到 totalbattery 本身 batterydict = { 'batterycapacity': batterycapacity, 'totalbattery': totalbattery, 'percent': '{:.2%}'.format(totalbattery / batterycapacity), 'cpubattery': cpubattery, 'wifibattery': wifibattery, 'sensorbattery': sensorbattery, 'camerabattery': camerabattery } return batterydict