From 892f0c0bfea99b93bd52cf8a6e2a051891a68e82 Mon Sep 17 00:00:00 2001 From: wangjiaqiang Date: Tue, 17 Jun 2025 14:21:54 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E5=90=8C=E6=97=B6=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.conf | 19 +- mobileperf/android/cpu_top.py | 14 +- mobileperf/android/devicemonitor.py | 2 +- mobileperf/android/fd.py | 2 +- mobileperf/android/fps.py | 10 +- mobileperf/android/globaldata.py | 2 +- mobileperf/android/logcat.py | 6 +- mobileperf/android/meminfos.py | 24 +-- mobileperf/android/monkey.py | 8 +- mobileperf/android/powerconsumption.py | 10 +- mobileperf/android/report.py | 8 + mobileperf/android/startup.py | 200 +++++++++++++++++++--- mobileperf/android/thread_num.py | 2 +- mobileperf/android/tools/androiddevice.py | 2 +- mobileperf/android/trafficstats.py | 12 +- readme.md | 4 + 16 files changed, 251 insertions(+), 74 deletions(-) diff --git a/config.conf b/config.conf index 1d25a25..7e9ad6d 100755 --- a/config.conf +++ b/config.conf @@ -2,23 +2,30 @@ #test process,example: package=com.alibaba.ailabs.genie.contacts #support multi process,separate use; if contains child process,first must be main process #com.tencent.mm com.sina.weibo com.taobao.taobao -package=com.taobao.taobao +package=ai.socialapps.speakmaster +# package=com.weaver.app.prod #collect frequency, int type,unit: second -frequency=5 +frequency=2 #collect timeout ,int type ,unit:minute, for example:72 hours 4320 timeout=4320 #dumpheap frequency, int type,unit: minute dumpheap_freq=60 #adb serialnum,adb devices result example WSKFSKBQLFA695D6 -serialnum=9e15838 +#Pixel 6 +serialnum=24251FDF6001BM +serialnums=24251FDF6001BM,ZY322SQQRG,ZY22DXTT48 +# Moto G 6 +# serialnum=ZY322SQQRG +# Moto G Pure +# serialnum=ZY22DXTT48 #except log tag,tools will check in logcat,save exception log in exception.log,multi tags separate use ; exceptionlog=fatal exception;has died #monkey test,true will enable,other disable -monkey= +monkey=true #test results save path,forbidden space, default None,will save in mobileperf/results #example save_path=/Users/look/Desktop/project/mobileperf_output -save_path= +save_path=/Users/wangjiaqiang/Documents/mobileperf_output #device pull path,test end,tool pull path to PC,multi path separate use; phone_log_path=/data/anr #mailbox Reserved, no use -mailbox=390125133@qq.com \ No newline at end of file +mailbox=187215129@qq.com \ No newline at end of file diff --git a/mobileperf/android/cpu_top.py b/mobileperf/android/cpu_top.py index 168ec4c..5457f78 100644 --- a/mobileperf/android/cpu_top.py +++ b/mobileperf/android/cpu_top.py @@ -304,7 +304,7 @@ def _top_cpuinfo(self): return out = str(out,"utf-8") out.replace('\r','') - top_file = os.path.join(RuntimeData.package_save_path, 'top.txt') + top_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'top.txt') with open(top_file, "a+",encoding="utf-8") as writer: writer.write(TimeUtils.getCurrentTime() + " top info:\n") writer.write(out + "\n\n") @@ -316,7 +316,7 @@ def _top_cpuinfo(self): def get_max_freq(self): out = self.device.adb.run_shell_cmd("cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq") out.replace('\r', '') - max_freq_file = os.path.join(RuntimeData.package_save_path, 'scaling_max_freq.txt') + max_freq_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'scaling_max_freq.txt') with open(max_freq_file, "a+",encoding="utf-8") as writer: writer.write(TimeUtils.getCurrentTime() + " scaling_max_freq:\n") writer.write(out + "\n\n") @@ -328,7 +328,7 @@ def _collect_package_cpu_thread(self,start_time): ''' end_time = time.time() + self._timeout cpu_title = ["datetime", "device_cpu_rate%", "user%", "system%","idle%"] - cpu_file = os.path.join(RuntimeData.package_save_path, 'cpuinfo.csv') + cpu_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'cpuinfo.csv') for i in range(0, len(self.packages)): cpu_title.extend(["package", "pid", "pid_cpu%"]) if len(self.packages) > 1: @@ -393,9 +393,11 @@ def start(self,start_time): :return: ''' if not RuntimeData.package_save_path: - RuntimeData.package_save_path = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results', self.packages[0], start_time) - if not os.path.exists(RuntimeData.package_save_path): - os.makedirs(RuntimeData.package_save_path) + RuntimeData.package_save_path = {} + if not RuntimeData.package_save_path[self.device.adb.DEVICEID]: + RuntimeData.package_save_path[self.device.adb.DEVICEID] = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results', self.packages[0], start_time) + if not os.path.exists(RuntimeData.package_save_path[self.device.adb.DEVICEID]): + os.makedirs(RuntimeData.package_save_path[self.device.adb.DEVICEID]) self.start_time = start_time self.cpu_collector.start(start_time) logger.debug("INFO: CpuMonitor has started...") diff --git a/mobileperf/android/devicemonitor.py b/mobileperf/android/devicemonitor.py index 6dbdc6d..ddd8336 100644 --- a/mobileperf/android/devicemonitor.py +++ b/mobileperf/android/devicemonitor.py @@ -65,7 +65,7 @@ def stop(self): def _activity_monitor_thread(self): activity_title = ("datetime", "current_activity") - self.activity_file = os.path.join(RuntimeData.package_save_path, 'current_activity.csv') + self.activity_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'current_activity.csv') try: with open(self.activity_file, 'a+') as af: csv.writer(af, lineterminator='\n').writerow(activity_title) diff --git a/mobileperf/android/fd.py b/mobileperf/android/fd.py index 888ca09..564f2c6 100644 --- a/mobileperf/android/fd.py +++ b/mobileperf/android/fd.py @@ -67,7 +67,7 @@ def get_process_fd(self, process): def _collect_fd_thread(self, start_time): end_time = time.time() + self._timeout fd_list_titile = ("datatime", "packagename", "pid", "fd_num") - fd_file = os.path.join(RuntimeData.package_save_path, 'fd_num.csv') + fd_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'fd_num.csv') try: with open(fd_file, 'a+') as df: csv.writer(df, lineterminator='\n').writerow(fd_list_titile) diff --git a/mobileperf/android/fps.py b/mobileperf/android/fps.py index 54522e7..9f75e15 100755 --- a/mobileperf/android/fps.py +++ b/mobileperf/android/fps.py @@ -195,7 +195,7 @@ def _calculate_janky(self,timestamps): def _calculator_thread(self,start_time): '''处理surfaceflinger数据 ''' - fps_file = os.path.join(RuntimeData.package_save_path, 'fps.csv') + fps_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'fps.csv') if self.use_legacy_method: fps_title = ['datetime', 'fps'] else: @@ -504,9 +504,11 @@ def start(self,start_time): '''启动FPSMonitor日志监控器 ''' if not RuntimeData.package_save_path: - RuntimeData.package_save_path = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results', self.package, start_time) - if not os.path.exists(RuntimeData.package_save_path): - os.makedirs(RuntimeData.package_save_path) + RuntimeData.package_save_path = {} + if not RuntimeData.package_save_path[self.device.adb.DEVICEID]: + RuntimeData.package_save_path[self.device.adb.DEVICEID] = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results', self.package, start_time) + if not os.path.exists(RuntimeData.package_save_path[self.device.adb.DEVICEID]): + os.makedirs(RuntimeData.package_save_path[self.device.adb.DEVICEID]) self.start_time = start_time self.fpscollector.start(start_time) logger.debug('FPS monitor has start!') diff --git a/mobileperf/android/globaldata.py b/mobileperf/android/globaldata.py index a524df7..58d6c18 100755 --- a/mobileperf/android/globaldata.py +++ b/mobileperf/android/globaldata.py @@ -15,7 +15,7 @@ class RuntimeData(): # 记录pid变更前的pid old_pid = None packages = None - package_save_path = None + package_save_path = {} start_time = None exit_event = threading.Event() top_dir = None diff --git a/mobileperf/android/logcat.py b/mobileperf/android/logcat.py index 889e96c..a05a78b 100644 --- a/mobileperf/android/logcat.py +++ b/mobileperf/android/logcat.py @@ -58,7 +58,7 @@ def start(self,start_time): # https://developer.android.com/studio/command-line/logcat #alternativeBuffers # 默认缓冲区 main system crash,输出全部缓冲区 if not self.running: - self.device.adb.start_logcat(RuntimeData.package_save_path, [], ' -b all') + self.device.adb.start_logcat(RuntimeData.package_save_path[self.device.adb.DEVICEID], [], ' -b all') time.sleep(1) self.running = True @@ -100,11 +100,11 @@ def handle_exception(self, log_line): for tag in self.exception_log_list: if tag in log_line: logger.debug("exception Info: " + log_line) - tmp_file = os.path.join(RuntimeData.package_save_path, 'exception.log') + tmp_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'exception.log') with open(tmp_file, 'a+',encoding="utf-8") as f: f.write(log_line + '\n') # 这个路径 空格会有影响 - process_stack_log_file = os.path.join(RuntimeData.package_save_path, 'process_stack_%s_%s.log' % ( + process_stack_log_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'process_stack_%s_%s.log' % ( self.package, TimeUtils.getCurrentTimeUnderline())) # 如果进程挂了,pid会变 ,抓变后进程pid的堆栈没有意义 # self.logmonitor.device.adb.get_process_stack(self.package,process_stack_log_file) diff --git a/mobileperf/android/meminfos.py b/mobileperf/android/meminfos.py index 0fda1b2..95ba577 100644 --- a/mobileperf/android/meminfos.py +++ b/mobileperf/android/meminfos.py @@ -181,7 +181,7 @@ def _dumpsys_meminfo(self): ''' time_old = time.time() out = self.device.adb.run_shell_cmd('dumpsys meminfo') - meminfo_file = os.path.join(RuntimeData.package_save_path, 'dumpsys_meminfo.txt') + meminfo_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'dumpsys_meminfo.txt') with open(meminfo_file, "a+",encoding="utf-8") as writer: writer.write(TimeUtils.getCurrentTime()+" dumpsys meminfo info:\n") writer.write(out+"\n\n") @@ -204,7 +204,7 @@ def _dumpsys_process_meminfo(self,process): # if self.num % 10 == 0: #避免:在windows 无法创建文件名,不能有冒号: process_rename = process.replace(":","_") - meminfo_file = os.path.join(RuntimeData.package_save_path, 'dumpsys_meminfo_%s.txt'%process_rename) + meminfo_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'dumpsys_meminfo_%s.txt'%process_rename) with open(meminfo_file, "a+",encoding="utf-8") as writer: writer.write(TimeUtils.getCurrentTime()+" dumpsys meminfo package info:\n") if out: @@ -227,10 +227,10 @@ def _collect_memory_thread(self, start_time): pid_list_titile.extend(["package", "pid"]) if len(self.packages)>1: mem_list_titile.append("total_pss(MB)") - mem_file = os.path.join(RuntimeData.package_save_path, 'meminfo.csv') - pid_file = os.path.join(RuntimeData.package_save_path, 'pid_change.csv') + mem_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'meminfo.csv') + pid_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'pid_change.csv') for package in self.packages: - pss_detail_file = os.path.join(RuntimeData.package_save_path, 'pss_%s.csv'%package.split(".")[-1].replace(":","_")) + pss_detail_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'pss_%s.csv'%package.split(".")[-1].replace(":","_")) with open(pss_detail_file, 'a+',encoding="utf-8") as df: csv.writer(df, lineterminator='\n').writerow(pss_detail_titile) try: @@ -265,7 +265,7 @@ def _collect_memory_thread(self, start_time): if 0 == mem_pck_snapshot.totalPSS: logger.error("package total pss is 0:%s"%package) continue - pss_detail_file = os.path.join(RuntimeData.package_save_path,'pss_%s.csv' % package.split(".")[-1].replace(":","_")) + pss_detail_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID],'pss_%s.csv' % package.split(".")[-1].replace(":","_")) pss_detail_list= [TimeUtils.formatTimeStamp(collection_time),package,mem_pck_snapshot.pid,mem_pck_snapshot.totalPSS, mem_pck_snapshot.javaHeap,mem_pck_snapshot.nativeHeap,mem_pck_snapshot.system] with open(pss_detail_file, 'a+',encoding="utf-8") as pss_writer: @@ -284,7 +284,7 @@ def _collect_memory_thread(self, start_time): self.device.adb.delete_file(hprof_path+"/" + file) # if (before - starttime_stamp) % 60 < self._interval and "D" in self.device.adb.get_system_version(): for package in self.packages: - self.device.adb.dumpheap(package,RuntimeData.package_save_path) + self.device.adb.dumpheap(package,RuntimeData.package_save_path[self.device.adb.DEVICEID]) starttime_stamp = before # self.device.adb.run_shell_cmd("kill -10 %s"%str(mem_pck_snapshot.pid)) # dumpsys meminfo 耗时长,可能会导致system server cpu占用变高,降低采集频率 @@ -322,7 +322,7 @@ def _collect_memory_thread(self, start_time): if package and package in RuntimeData.config_dic["pid_change_focus_package"]: # 确保有tombstones文件才提单 self.device.adb.pull_file("/data/vendor/tombstones", - RuntimeData.package_save_path) + RuntimeData.package_save_path[self.device.adb.DEVICEID]) if pid_change: old_package_pid_pss_list = mem_device_snapshot.package_pid_pss_list for i in range(0, len(self.packages)): @@ -378,9 +378,11 @@ def __init__(self, device_id, packages, interval = 1.0, timeout=24 * 60 * 60, me def start(self,start_time): if not RuntimeData.package_save_path: - RuntimeData.package_save_path = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results', self.packages[0], start_time) - if not os.path.exists(RuntimeData.package_save_path): - os.makedirs(RuntimeData.package_save_path) + RuntimeData.package_save_path = {} + if not RuntimeData.package_save_path[self.device.adb.DEVICEID]: + RuntimeData.package_save_path[self.device.adb.DEVICEID] = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results', self.packages[0], start_time) + if not os.path.exists(RuntimeData.package_save_path[self.device.adb.DEVICEID]): + os.makedirs(RuntimeData.package_save_path[self.device.adb.DEVICEID]) self.start_time = start_time # self.meminfo_collector.start(start_time) self.meminfo_package_collector.start(start_time) diff --git a/mobileperf/android/monkey.py b/mobileperf/android/monkey.py index cdef747..ae89dba 100644 --- a/mobileperf/android/monkey.py +++ b/mobileperf/android/monkey.py @@ -57,6 +57,8 @@ def stop(self): '''结束monkey ''' self.stop_monkey() + if self.device.adb.is_process_running("com.android.commands.monkey"): + self.device.adb.kill_process("com.android.commands.monkey") def start_monkey(self, package,timeout): '''运行monkey进程 @@ -70,7 +72,7 @@ def start_monkey(self, package,timeout): '--pct-motion 10 --pct-trackball 0 --pct-anyevent 10 --pct-flip 0 --pct-pinchzoom 0 ' \ '--throttle 1000 %s' % (package, str(timeout)) self._log_pipe = self.device.adb.run_shell_cmd(self.monkey_cmd, sync=False) - self._monkey_thread = threading.Thread(target=self._monkey_thread_func, args=[RuntimeData.package_save_path]) + self._monkey_thread = threading.Thread(target=self._monkey_thread_func, args=[RuntimeData.package_save_path[self.device.adb.DEVICEID]]) # self._monkey_thread.setDaemon(True) self._monkey_thread.start() @@ -160,7 +162,9 @@ def save(self, save_file_path, loglist): start_time = TimeUtils.getCurrentTimeUnderline() logger.debug(start_time) RuntimeData.top_dir = FileUtils.get_top_dir() - RuntimeData.package_save_path = os.path.join(RuntimeData.top_dir, 'results', "com.alibaba.ailabs.genie.contacts", start_time) + if not RuntimeData.package_save_path: + RuntimeData.package_save_path = {} + RuntimeData.package_save_path[self.device.adb.DEVICEID] = os.path.join(RuntimeData.top_dir, 'results', "com.alibaba.ailabs.genie.contacts", start_time) main_activity = ["com.alibaba.ailabs.genie.contacts.MainActivity"] activity_list = ["com.alibaba.ailabs.genie.contacts.MainActivity", "com.alibaba.ailabs.genie.contacts.cmd.CmdDispatchActivity", diff --git a/mobileperf/android/powerconsumption.py b/mobileperf/android/powerconsumption.py index e9d9bc1..fc8bf0a 100644 --- a/mobileperf/android/powerconsumption.py +++ b/mobileperf/android/powerconsumption.py @@ -157,7 +157,7 @@ def _collect_power_thread(self,start_time): ''' end_time = time.time() + self._timeout power_list_titile = ("datetime","level","voltage(V)","tempreture(C)","current(mA)") - power_device_file = os.path.join(RuntimeData.package_save_path, 'powerinfo.csv') + power_device_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'powerinfo.csv') try: with open(power_device_file, 'a+') as df: csv.writer(df, lineterminator='\n').writerow(power_list_titile) @@ -231,9 +231,11 @@ def __init__(self, device_id, interval = 1.0, timeout = 24 * 60 * 60,power_queue def start(self,start_time): if not RuntimeData.package_save_path: - RuntimeData.package_save_path = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results',self.device.adb._device_id,start_time) - if not os.path.exists(RuntimeData.package_save_path): - os.makedirs(RuntimeData.package_save_path) + RuntimeData.package_save_path = {} + if not RuntimeData.package_save_path[self.device.adb.DEVICEID]: + RuntimeData.package_save_path[self.device.adb.DEVICEID] = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results',self.device.adb._device_id,start_time) + if not os.path.exists(RuntimeData.package_save_path[self.device.adb.DEVICEID]): + os.makedirs(RuntimeData.package_save_path[self.device.adb.DEVICEID]) self.start_time = start_time self.power_collector.start(start_time) logger.debug("INFO: PowerMonitor has started...") diff --git a/mobileperf/android/report.py b/mobileperf/android/report.py index 7e41e6f..5eb8da3 100644 --- a/mobileperf/android/report.py +++ b/mobileperf/android/report.py @@ -31,6 +31,14 @@ def __init__(self, csv_dir, packages=[]): "x_axis": "datatime", "y_axis": "pid_num", "values": ["pid"]}, + "thread_num.csv": {"table_name": "thread_num", + "x_axis": "datatime", + "y_axis": "thread_num", + "values": ["thread_num"]}, + "fps.csv": {"table_name": "fps", + "x_axis": "datatime", + "y_axis": "fps-jank", + "values": ["fps","jank"]}, } self.packages = packages if len(self.packages)>0: diff --git a/mobileperf/android/startup.py b/mobileperf/android/startup.py index 6cbe99d..ae4b416 100644 --- a/mobileperf/android/startup.py +++ b/mobileperf/android/startup.py @@ -49,11 +49,16 @@ def __init__(self, device_id=None, package=None,interval=None): self.config_dic = self.parse_data_from_config() RuntimeData.config_dic = self.config_dic self.serialnum = device_id if device_id != None else self.config_dic['serialnum']#代码中重新传入device_id 则会覆盖原来配置文件config.conf的值,主要为了debug方便 + self.serialnums = device_id if device_id != None else self.config_dic['serialnums']#代码中重新传入device_id 则会覆盖原来配置文件config.conf的值,主要为了debug方便 self.packages = package if package != None else self.config_dic['package']#代码中重新传入package 则会覆盖原来配置文件config.conf的值,为了debug方便 self.frequency = interval if interval != None else self.config_dic['frequency']#代码中重新传入interval 则会覆盖原来配置文件config.conf的值,为了debug方便 self.timeout = self.config_dic['timeout'] self.exceptionlog_list = self.config_dic["exceptionlog"] self.device = AndroidDevice(self.serialnum) + self.devices = {} + if self.serialnums: + for serialnum in self.serialnums.split(","): + self.devices[serialnum] = AndroidDevice(serialnum) # 如果config文件中 packagename为空,就获取前台进程,匹配图兰朵,测的app太多,支持配置文件不传package if not self.packages: # 进程名不会有#,转化为list @@ -125,6 +130,7 @@ def parse_data_from_config(self): config_dic = self.check_config_option(config_dic, paser, "Common", "dumpheap_freq") config_dic = self.check_config_option(config_dic, paser, "Common", "timeout") config_dic = self.check_config_option(config_dic, paser, "Common", "serialnum") + config_dic = self.check_config_option(config_dic, paser, "Common", "serialnums") config_dic = self.check_config_option(config_dic, paser, "Common", "mailbox") config_dic = self.check_config_option(config_dic, paser, "Common", "exceptionlog") config_dic = self.check_config_option(config_dic, paser, "Common", "save_path") @@ -156,13 +162,13 @@ def check_config_option(self, config_dic, parse, section, option): else: config_dic[option] = parse.get(section, option).split(";") except:#配置项中数值发生错误 - if option != 'serialnum': + if option != 'serialnum' and option != 'serialnums': logger.debug("config option error:"+option) self._config_error() else: config_dic[option] = '' else:#配置项没有配置 - if option not in ['serialnum',"main_activity","activity_list","pid_change_focus_package","shell_file"]: + if option not in ['serialnum',"serialnums","main_activity","activity_list","pid_change_focus_package","shell_file"]: logger.debug("config option error:" + option) self._config_error() else: @@ -175,6 +181,10 @@ def _config_error(self): # @profile def run(self, time_out=None): + if self.serialnums: + self.runMultiSerial(time_out) + return + self.clear_heapdump() # objgraph.show_growth() # 对设备连接情况的检查 @@ -220,11 +230,11 @@ def run(self, time_out=None): start_time = TimeUtils.getCurrentTimeUnderline() RuntimeData.start_time = start_time if self.config_dic["save_path"]: - RuntimeData.package_save_path = os.path.join(self.config_dic["save_path"], self.packages[0], start_time) + RuntimeData.package_save_path[self.serialnum] = os.path.join(self.config_dic["save_path"], self.packages[0], start_time) else: - RuntimeData.package_save_path = os.path.join(RuntimeData.top_dir, 'results', self.packages[0], start_time) - FileUtils.makedir(RuntimeData.package_save_path) - self.save_device_info() + RuntimeData.package_save_path[self.serialnum] = os.path.join(RuntimeData.top_dir, 'results', self.packages[0], start_time) + FileUtils.makedir(RuntimeData.package_save_path[self.serialnum]) + self.save_device_info(self.serialnum) for monitor in self.monitors: #启动所有的monitors try: @@ -274,13 +284,124 @@ def run(self, time_out=None): logger.error("Exception in run") logger.error(e) + def runMultiSerial(self, time_out=None): + # objgraph.show_growth() +# 对设备连接情况的检查 + logger.debug("check device connection") + try: + for serialnum in self.serialnums.split(","): + self.clear_heapdump(serialnum) + is_device_connect = False + for i in range(0,5): + if self.devices[serialnum].adb.is_connected(serialnum): + is_device_connect = True + break + else: + logger.error("device not found:"+serialnum) + time.sleep(2) + if not is_device_connect: + logger.error("after 5 times check,device not found:" + serialnum) + continue + # 对是否安装被测app的检查 只在最开始检查一次 + if not self.devices[serialnum].adb.is_app_installed(self.packages[0]): + logger.error("test app not installed:" + self.packages[0]) + return + try: + #初始化数据处理的类,将没有消息队列传递过去,以便获取数据,并处理 + # datahandle = DataWorker(self.get_queue_dic()) + # 将queue传进去,与datahandle那个线程交互 + self.add_monitor(CpuMonitor(serialnum, self.packages, self.frequency, self.timeout)) + self.add_monitor(MemMonitor(serialnum, self.packages, self.frequency, self.timeout)) + self.add_monitor(TrafficMonitor(serialnum, self.packages, self.frequency, self.timeout)) + # 软件方式 获取电量不准,已用硬件方案测试功耗 + # self.add_monitor(PowerMonitor(self.serialnum, self.frequency,self.timeout)) + self.add_monitor(FPSMonitor(serialnum,self.packages[0],self.frequency,self.timeout)) + # 6.0以下能采集到fd数据,7.0以上没权限 + if self.devices[serialnum].adb.get_sdk_version() <= 23: + self.add_monitor(FdMonitor(serialnum, self.packages[0], self.frequency,self.timeout)) + self.add_monitor(ThreadNumMonitor(serialnum,self.packages[0],self.frequency,self.timeout)) + if self.config_dic["monkey"] == "true": + self.add_monitor(Monkey(serialnum, self.packages[0])) + if self.config_dic["main_activity"] and self.config_dic["activity_list"]: + self.add_monitor(DeviceMonitor(serialnum, self.packages[0], self.frequency,self.config_dic["main_activity"], + self.config_dic["activity_list"],RuntimeData.exit_event)) + + if len(self.monitors): + start_time = TimeUtils.getCurrentTimeUnderline() + RuntimeData.start_time = start_time + if self.config_dic["save_path"]: + RuntimeData.package_save_path[serialnum] = os.path.join(self.config_dic["save_path"], serialnum, self.packages[0], start_time) + else: + RuntimeData.package_save_path[serialnum] = os.path.join(RuntimeData.top_dir, 'results', serialnum, self.packages[0], start_time) + FileUtils.makedir(RuntimeData.package_save_path[serialnum]) + self.save_device_info(serialnum) + for monitor in self.monitors: + #启动所有的monitors + try: + monitor.start(start_time) + except Exception as e: + logger.error(e) + # logcat的代码可能会引起死锁,拎出来单独处理logcat + try: + self.logcat_monitor = LogcatMonitor(serialnum, self.packages[0]) + # 如果有异常日志标志,才启动这个模块 + if self.exceptionlog_list: + self.logcat_monitor.set_exception_list(self.exceptionlog_list) + self.logcat_monitor.add_log_handle(self.logcat_monitor.handle_exception) + time.sleep(1) + self.logcat_monitor.start(start_time) + except Exception as e: + logger.error(e) + # try: + # datahandle.stop() + # time.sleep(self.frequency*2) + # # 延迟一点时间结束上报,已让数据上报完 + # # report.stop() + # except: + # logger.debug("report or datahandle stop exception") + # finally: + # logger.info("time is up, end") + # os._exit(0) + except Exception as e: + logger.error("Exception in run") + logger.error(e) + e.with_traceback() + + if len(self.monitors) > 0: + timeout = time_out if time_out != None else self.config_dic['timeout'] + endtime = time.time() + timeout + while (time.time() < endtime):#吊着主线程防止线程中断 + # 时间到或测试过程中检测到异常 + if self.check_exit_signal_quit(): + logger.error("app " + str(self.packages[0]) + " exit signal, quit!") + break + time.sleep(self.frequency) + logger.debug("time is up,finish!!!") + self.stop() + except KeyboardInterrupt:#捕获键盘异常的事件,例如ctrl c + logger.debug(" catch keyboardInterrupt, goodbye!!!") + # 收尾工作 + self.stop() + os._exit(0) + except Exception as e: + logger.error("Exception in run") + logger.error(e) + e.with_traceback() + # 测试前清空 tmp 目录下dump文件 清理超过一周的文件,避免同时测试会有冲突 - def clear_heapdump(self): - filelist = self.device.adb.list_dir("/data/local/tmp") - if filelist: - for file in filelist: - if self.packages[0] in file and self.device.adb.is_overtime_days("/data/local/tmp/"+file,3): - self.device.adb.delete_file("/data/local/tmp/%s" % file) + def clear_heapdump(self, serialnum=None): + if serialnum and serialnum in self.devices.keys(): + filelist = self.devices[serialnum].adb.list_dir("/data/local/tmp") + if filelist: + for file in filelist: + if self.packages[0] in file and self.devices[serialnum].adb.is_overtime_days("/data/local/tmp/"+file,3): + self.devices[serialnum].adb.delete_file("/data/local/tmp/%s" % file) + else: + filelist = self.device.adb.list_dir("/data/local/tmp") + if filelist: + for file in filelist: + if self.packages[0] in file and self.device.adb.is_overtime_days("/data/local/tmp/"+file,3): + self.device.adb.delete_file("/data/local/tmp/%s" % file) def stop(self): for monitor in self.monitors: @@ -295,15 +416,29 @@ def stop(self): except Exception as e: logger.error("stop exception for logcat monitor") logger.error(e) - if self.config_dic["monkey"] =="true": - self.device.adb.kill_process("com.android.commands.monkey") + # if self.config_dic["monkey"] =="true": + # if self.serialnums: + # for serialnum in self.serialnums: + # self.devices[serialnum].adb.kill_process("com.android.commands.monkey") + # else: + # self.device.adb.kill_process("com.android.commands.monkey") # 统计测试时长 cost_time =round((float) (time.time() - TimeUtils.getTimeStamp(RuntimeData.start_time,TimeUtils.UnderLineFormatter))/3600,2) - self.add_device_info("test cost time:",str(cost_time)+"h") + # 根据csv生成excel汇总文件 - Report(RuntimeData.package_save_path,self.packages) - self.pull_heapdump() - self.pull_log_files() + if self.serialnums: + for serialnum in RuntimeData.package_save_path.keys(): + logger.debug("serialnum: " + serialnum + ", serialnum in self.devices: " + str(serialnum in RuntimeData.package_save_path.keys())) + if serialnum in RuntimeData.package_save_path.keys(): + self.add_device_info(serialnum, "test cost time:",str(cost_time)+"h") + Report(RuntimeData.package_save_path[serialnum] + "/",self.packages) + self.pull_heapdump(serialnum) + self.pull_log_files(serialnum) + else: + self.add_device_info(self.serialnum, "test cost time:",str(cost_time)+"h") + Report(RuntimeData.package_save_path[self.serialnum] + "/",self.packages) + self.pull_heapdump() + self.pull_log_files() # self.memory_analyse() # self.device.adb.bugreport(RuntimeData.package_save_path) os._exit(0) @@ -324,34 +459,43 @@ def memory_analyse(self): - def pull_heapdump(self): + def pull_heapdump(self, serialnum=None): # 把dumpheap文件拷贝出来 - filelist = self.device.adb.list_dir("/data/local/tmp") + if serialnum and serialnum in RuntimeData.package_save_path.keys(): + filelist = self.devices[serialnum].adb.list_dir("/data/local/tmp") + else: + filelist = self.device.adb.list_dir("/data/local/tmp") if filelist: for file in filelist: if self.packages[0] in file: - self.device.adb.pull_file("/data/local/tmp/%s" % file, RuntimeData.package_save_path) + if serialnum and serialnum in RuntimeData.package_save_path.keys(): + self.devices[serialnum].adb.pull_file("/data/local/tmp/%s" % file, RuntimeData.package_save_path[serialnum]) + else: + self.device.adb.pull_file("/data/local/tmp/%s" % file, RuntimeData.package_save_path[self.serialnum]) - def pull_log_files(self): + def pull_log_files(self, serialnum=None): if self.config_dic["phone_log_path"]: for src_path in self.config_dic["phone_log_path"]: - self.device.adb.pull_file(src_path, RuntimeData.package_save_path) + if serialnum and serialnum in RuntimeData.package_save_path.keys(): + self.devices[serialnum].adb.pull_file(src_path, RuntimeData.package_save_path[serialnum]) + else: + self.device.adb.pull_file(src_path, RuntimeData.package_save_path[self.serialnum]) # self.device.adb.pull_file_between_time(src_path,RuntimeData.package_save_path, # TimeUtils.getTimeStamp(RuntimeData.start_time,TimeUtils.UnderLineFormatter),time.time()) # release系统pull /sdcard/mtklog/可以 没有权限/sdcard/mtklog/mobilelog - def save_device_info(self): - device_file = os.path.join(RuntimeData.package_save_path,"device_test_info.txt") + def save_device_info(self, device_id): + device_file = os.path.join(RuntimeData.package_save_path[device_id],"device_test_info.txt") with open(device_file,"w+",encoding="utf-8") as writer: - writer.write("device serialnum:"+self.serialnum+"\n") + writer.write("device serialnum:"+device_id+"\n") writer.write("device model:"+self.device.adb.get_phone_brand()+" "+self.device.adb.get_phone_model()+"\n") writer.write("test package:" + self.packages[0] + "\n") writer.write("system version:"+self.device.adb.get_system_version()+"\n") writer.write("test package ver:" + self.device.adb.get_package_ver(self.packages[0]) + "\n") - def add_device_info(self,key,value): - device_file = os.path.join(RuntimeData.package_save_path,"device_test_info.txt") + def add_device_info(self,device_id, key, value): + device_file = os.path.join(RuntimeData.package_save_path[device_id],"device_test_info.txt") with open(device_file,"a+",encoding="utf-8") as writer: writer.write(key+":"+value+"\n") diff --git a/mobileperf/android/thread_num.py b/mobileperf/android/thread_num.py index 95f92ee..b105d03 100644 --- a/mobileperf/android/thread_num.py +++ b/mobileperf/android/thread_num.py @@ -66,7 +66,7 @@ def _collect_thread_num_thread(self, start_time): end_time = time.time() + self._timeout thread_list_titile = ( "datatime", "packagename", "pid", "thread_num") - thread_num_file = os.path.join(RuntimeData.package_save_path, 'thread_num.csv') + thread_num_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'thread_num.csv') try: with open(thread_num_file, 'a+') as df: csv.writer(df, lineterminator='\n').writerow(thread_list_titile) diff --git a/mobileperf/android/tools/androiddevice.py b/mobileperf/android/tools/androiddevice.py index 66a42d3..583cae2 100644 --- a/mobileperf/android/tools/androiddevice.py +++ b/mobileperf/android/tools/androiddevice.py @@ -315,7 +315,7 @@ def run_shell_cmd(self, cmd, **kwds): ''' # 如果失去连接后,adb又正常连接了 if not self.before_connect and self.after_connect: - cpu_uptime_file = os.path.join(RuntimeData.package_save_path, "uptime.txt") + cpu_uptime_file = os.path.join(RuntimeData.package_save_path[self.DEVICEID], "uptime.txt") with open(cpu_uptime_file, "a+",encoding = "utf-8") as writer: writer.write(TimeUtils.getCurrentTimeUnderline() + " /proc/uptime:" + self.run_adb_cmd("shell cat /proc/uptime") + "\n") self.before_connect = True diff --git a/mobileperf/android/trafficstats.py b/mobileperf/android/trafficstats.py index 9b2f22e..e7d5c1b 100644 --- a/mobileperf/android/trafficstats.py +++ b/mobileperf/android/trafficstats.py @@ -250,7 +250,7 @@ def get_traffic_with_stats(self): traffic_list_title = ( "datetime", "packagename", "uid", "uid_total(KB)", "uid_total_packets", "rx(KB)", "rx_packets", "tx(KB)", "tx_packets", "fg(KB)", "bg(KB)", "lo(KB)") - traffic_file = os.path.join(RuntimeData.package_save_path, 'traffics_uid.csv') + traffic_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'traffics_uid.csv') try: with open(traffic_file, 'a+') as df: csv.writer(df, lineterminator='\n').writerow(traffic_list_title) @@ -323,7 +323,7 @@ def get_traffic_with_stats(self): def get_traffic_with_dev(self): end_time = time.time() + self._timeout traffic_title = ["datetime", "device_total(KB)", "device_receive(KB)", "device_transport(KB)"] - traffic_file = os.path.join(RuntimeData.package_save_path, 'traffic.csv') + traffic_file = os.path.join(RuntimeData.package_save_path[self.device.adb.DEVICEID], 'traffic.csv') for i in range(0, len(self.packages)): traffic_title.extend(["package", "pid", "pid_rx(KB)","pid_tx(KB)","pid_total(KB)"]) if len(self.packages) > 1: @@ -458,9 +458,11 @@ def __init__(self, device_id, packages, interval = 1.0, timeout=10 * 60, traffic def start(self,start_time): if not RuntimeData.package_save_path: - RuntimeData.package_save_path = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results', self.packages[0], start_time) - if not os.path.exists(RuntimeData.package_save_path): - os.makedirs(RuntimeData.package_save_path) + RuntimeData.package_save_path = {} + if not RuntimeData.package_save_path[self.device.adb.DEVICEID]: + RuntimeData.package_save_path[self.device.adb.DEVICEID] = os.path.join(os.path.abspath(os.path.join(os.getcwd(), "../..")),'results', self.packages[0], start_time) + if not os.path.exists(RuntimeData.package_save_path[self.device.adb.DEVICEID]): + os.makedirs(RuntimeData.package_save_path[self.device.adb.DEVICEID]) self.start_time = start_time self.traffic_colloctor.start(start_time) logger.debug("INFO: TrafficMonitor has started...") diff --git a/readme.md b/readme.md index 96ccb91..7ab43b7 100644 --- a/readme.md +++ b/readme.md @@ -31,10 +31,14 @@ mobileperf is python PC 工具,可以收集Android性能数据: cpu 内存 流 - 稳定性好,能连续运行72小时以上 - 少量占用PC资源,消耗PC内存约12M左右 +- 支持多设备同时测试(wjq123521) + ## 使用方法 - 安装python3.7 [python下载链接](https://www.python.org/downloads/),加入到环境变量中,执行python --version,确保是python3 - 安装adb,确保adb devices能找到设备 - 修改配置文件,示例参考根目录下config.conf +- 多设备测试,配置文件中serialnums,用分号分割: serialnums=24251FDF6001BM,ZY322SQQRG,ZY22DXTT48 + - 运行,mac、linux 在mobileperf工具根目录下执行sh run.sh,windows 双击run.bat,结束测试,等待设置测试时长到或按Ctrl+C From ba6416eabd7ae209373bdfd021d70cc6c40da985 Mon Sep 17 00:00:00 2001 From: wangjiaqiang Date: Tue, 17 Jun 2025 15:24:11 +0800 Subject: [PATCH 2/3] =?UTF-8?q?Fix=20=E5=A4=9A=E8=AE=BE=E5=A4=87=E4=B8=8B?= =?UTF-8?q?=20monitor=20=E9=87=8D=E5=A4=8Dstart=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mobileperf/android/startup.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/mobileperf/android/startup.py b/mobileperf/android/startup.py index ae4b416..b079032 100644 --- a/mobileperf/android/startup.py +++ b/mobileperf/android/startup.py @@ -243,13 +243,15 @@ def run(self, time_out=None): logger.error(e) # logcat的代码可能会引起死锁,拎出来单独处理logcat try: - self.logcat_monitor = LogcatMonitor(self.serialnum, self.packages[0]) + if not self.logcat_monitor: + self.logcat_monitor = {} + self.logcat_monitor[self.serialnum] = LogcatMonitor(self.serialnum, self.packages[0]) # 如果有异常日志标志,才启动这个模块 if self.exceptionlog_list: - self.logcat_monitor.set_exception_list(self.exceptionlog_list) - self.logcat_monitor.add_log_handle(self.logcat_monitor.handle_exception) + self.logcat_monitor[self.serialnum].set_exception_list(self.exceptionlog_list) + self.logcat_monitor[self.serialnum].add_log_handle(self.logcat_monitor[self.serialnum].handle_exception) time.sleep(1) - self.logcat_monitor.start(start_time) + self.logcat_monitor[self.serialnum].start(start_time) except Exception as e: logger.error(e) @@ -338,18 +340,21 @@ def runMultiSerial(self, time_out=None): for monitor in self.monitors: #启动所有的monitors try: - monitor.start(start_time) + if monitor.device.adb.DEVICEID == serialnum: + monitor.start(start_time) except Exception as e: logger.error(e) # logcat的代码可能会引起死锁,拎出来单独处理logcat try: - self.logcat_monitor = LogcatMonitor(serialnum, self.packages[0]) + if not self.logcat_monitor: + self.logcat_monitor = {} + self.logcat_monitor[serialnum] = LogcatMonitor(serialnum, self.packages[0]) # 如果有异常日志标志,才启动这个模块 if self.exceptionlog_list: - self.logcat_monitor.set_exception_list(self.exceptionlog_list) - self.logcat_monitor.add_log_handle(self.logcat_monitor.handle_exception) + self.logcat_monitor[serialnum].set_exception_list(self.exceptionlog_list) + self.logcat_monitor[serialnum].add_log_handle(self.logcat_monitor[serialnum].handle_exception) time.sleep(1) - self.logcat_monitor.start(start_time) + self.logcat_monitor[serialnum].start(start_time) except Exception as e: logger.error(e) # try: @@ -411,8 +416,9 @@ def stop(self): logger.error(e) try: - if self.logcat_monitor: - self.logcat_monitor.stop() + for serialnum in self.logcat_monitor.keys(): + if self.logcat_monitor[serialnum]: + self.logcat_monitor[serialnum].stop() except Exception as e: logger.error("stop exception for logcat monitor") logger.error(e) From 52bc7981d783b7e9227d2aced9099e8ac1be8046 Mon Sep 17 00:00:00 2001 From: wangjiaqiang Date: Fri, 20 Jun 2025 18:37:38 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E5=B9=BF=E5=91=8A=E5=B9=B6=E5=85=B3=E9=97=AD=E5=B9=BF=E5=91=8A?= =?UTF-8?q?=E7=9A=84monitor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++ mobileperf/android/admonitor.py | 96 +++++++++++++++++++++++++++++++++ mobileperf/android/logcat.py | 5 +- mobileperf/android/startup.py | 9 ++++ 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 mobileperf/android/admonitor.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30cfe3d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# 忽略所有子目录下的 __pycache__ 目录 +**/__pycache__/ +logs/ \ No newline at end of file diff --git a/mobileperf/android/admonitor.py b/mobileperf/android/admonitor.py new file mode 100644 index 0000000..99db58d --- /dev/null +++ b/mobileperf/android/admonitor.py @@ -0,0 +1,96 @@ +#encoding:utf-8 +''' +@description: 广告监控器 + +@author: wangjiaqiang + +@Copyright (c) 2014-2025 Zuoyebang, All rights reserved + +@license: Apache Software License 2.0 + +@contact: 187215129@qq.com +''' + +import os +import sys +import threading +import time + +BaseDir=os.path.dirname(__file__) +sys.path.append(os.path.join(BaseDir,'../..')) +from mobileperf.common.log import logger +from mobileperf.android.tools.androiddevice import AndroidDevice + + +class AdMonitor(object): + def __init__(self, device_id, package, interval=1.0, timeout=24*60*60, ad_queue=None): + self.device = AndroidDevice(device_id) + self.package = package + self._interval = interval + self._timeout = timeout + self._stop_event = threading.Event() + self.ad_queue = ad_queue + self._start_time = None + self.collect_ad_thread = None + + def start(self, start_time): + logger.debug("INFO: AdMonitor has started...") + self._start_time = start_time + self.enable_app_test_mode() + self.collect_ad_thread = threading.Thread(target=self._collect_ad_thread, args=(start_time,)) + self.collect_ad_thread.start() + + def stop(self): + logger.debug("INFO: AdMonitor has stopped...") + if self.collect_ad_thread: + self._stop_event.set() + self.disable_app_test_mode() + self.collect_ad_thread.join(timeout=1) + self.collect_ad_thread = None + #结束的时候,发送一个任务完成的信号,以结束队列 + if self.ad_queue: + self.ad_queue.task_done() + + def _collect_ad_thread(self, start_time): + """每10秒执行一次关闭广告的操作 + + Args: + start_time: 开始时间 + """ + logger.debug("INFO: Ad closing thread started...") + end_time = time.time() + self._timeout + # 计算运行时间,不超过timeout + while not self._stop_event.is_set() and time.time() < end_time: + try: + # 执行关闭广告的adb命令 + cmd = 'am broadcast -a "com.zuoyebang.TestManagerReceiver.HIDE_AD" -n ai.socialapps.speakmaster/com.zuoyebang.appfactory.test.TestManagerReceiver' + result = self.device.adb.run_shell_cmd(cmd) + logger.debug(f"INFO: Executed ad closing command, result: {result}") + + # 等待10秒,如果在此期间收到停止信号则退出 + if self._stop_event.wait(10): + break + except Exception as e: + logger.error(f"ERROR: Failed to execute ad closing command: {str(e)}") + # 发生异常时也等待10秒再继续 + if self._stop_event.wait(10): + break + + logger.debug("INFO: Ad closing thread finished") + + def enable_app_test_mode(self): + """ + 启用app测试模式 + """ + logger.debug("INFO: Enabling app test mode...") + self.device.adb.run_shell_cmd('am broadcast -a "com.zuoyebang.TestManagerReceiver.SET_ENABLE" -n ai.socialapps.speakmaster/com.zuoyebang.appfactory.test.TestManagerReceiver --ez "enable" "true"') + logger.debug("INFO: App test mode enabled") + + def disable_app_test_mode(self): + """ + 禁用app测试模式 + """ + logger.debug("INFO: Disabling app test mode...") + self.device.adb.run_shell_cmd('am broadcast -a "com.zuoyebang.TestManagerReceiver.SET_ENABLE" -n ai.socialapps.speakmaster/com.zuoyebang.appfactory.test.TestManagerReceiver --ez "enable" "false"') + logger.debug("INFO: App test mode disabled") + \ No newline at end of file diff --git a/mobileperf/android/logcat.py b/mobileperf/android/logcat.py index a05a78b..4930185 100644 --- a/mobileperf/android/logcat.py +++ b/mobileperf/android/logcat.py @@ -117,6 +117,7 @@ class LaunchTime(object): def __init__(self,deviceid, packagename = ""): # 列表的容积应该不用担心,与系统有一定关系,一般存几十万条数据没问题的 self.launch_list = [("datetime","packagenme/activity","this_time(s)","total_time(s)","launchtype")] + self.serialnum = deviceid self.packagename = packagename def handle_launchtime(self, log_line): @@ -127,7 +128,7 @@ def handle_launchtime(self, log_line): #如果监控到到fully drawn这样的log,则优先统计这种log,它表示了到起始界面自定义界面的启动时间 :return:void ''' - # logger.debug(log_line) + # logger.debug("------handle_launchtime: " + log_line) # 08-28 10:57:30.229 18882 19137 D IC5: CLogProducer == > code = 0, uuid = 4FE71E350379C64611CCD905938C10CA, eventType = performance, eventName = am_activity_launch_timeme, \ # log_time = 2019-08-28 10:57:30.229, contextInfo = {"tag": "am_activity_launch_time", "start_time": "2019-08-28 10:57:16", # "activity_name_original": "com.android.settings\/.FallbackHome", @@ -169,7 +170,7 @@ def trim_value(self, content): def update_launch_list(self, content,timestamp): # if self.packagename in content[1]: self.launch_list.append(content) - tmp_file = os.path.join(RuntimeData.package_save_path, 'launch_logcat.csv') + tmp_file = os.path.join(RuntimeData.package_save_path[self.serialnum], 'launch_logcat.csv') perf_data = {"task_id":"",'launch_time':[],'cpu':[],"mem":[], 'traffic':[], "fluency":[],'power':[],} dic = {"time": timestamp, diff --git a/mobileperf/android/startup.py b/mobileperf/android/startup.py index b079032..f296ffd 100644 --- a/mobileperf/android/startup.py +++ b/mobileperf/android/startup.py @@ -38,6 +38,7 @@ from mobileperf.android.monkey import Monkey from mobileperf.android.globaldata import RuntimeData from mobileperf.android.report import Report +from mobileperf.android.admonitor import AdMonitor class StartUp(object): @@ -56,6 +57,7 @@ def __init__(self, device_id=None, package=None,interval=None): self.exceptionlog_list = self.config_dic["exceptionlog"] self.device = AndroidDevice(self.serialnum) self.devices = {} + # self.get_connected_devices() if self.serialnums: for serialnum in self.serialnums.split(","): self.devices[serialnum] = AndroidDevice(serialnum) @@ -101,6 +103,11 @@ def add_monitor(self, monitor): def remove_monitor(self, monitor): self.monitors.remove(monitor) + def get_connected_devices(self): + result = AndroidDevice.list_local_devices() + logger.debug("get_connected_devices result:%s" % result) + return result + def parse_data_from_config(self): ''' 从配置文件中解析出需要的信息,包名,时间间隔,设备的序列号等 @@ -222,6 +229,7 @@ def run(self, time_out=None): self.add_monitor(ThreadNumMonitor(self.serialnum,self.packages[0],self.frequency,self.timeout)) if self.config_dic["monkey"] == "true": self.add_monitor(Monkey(self.serialnum, self.packages[0])) + self.add_monitor(AdMonitor(self.serialnum, self.packages[0], self.frequency, self.timeout)) if self.config_dic["main_activity"] and self.config_dic["activity_list"]: self.add_monitor(DeviceMonitor(self.serialnum, self.packages[0], self.frequency,self.config_dic["main_activity"], self.config_dic["activity_list"],RuntimeData.exit_event)) @@ -322,6 +330,7 @@ def runMultiSerial(self, time_out=None): if self.devices[serialnum].adb.get_sdk_version() <= 23: self.add_monitor(FdMonitor(serialnum, self.packages[0], self.frequency,self.timeout)) self.add_monitor(ThreadNumMonitor(serialnum,self.packages[0],self.frequency,self.timeout)) + self.add_monitor(AdMonitor(self.serialnum, self.packages[0], self.frequency, self.timeout)) if self.config_dic["monkey"] == "true": self.add_monitor(Monkey(serialnum, self.packages[0])) if self.config_dic["main_activity"] and self.config_dic["activity_list"]: