Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 忽略所有子目录下的 __pycache__ 目录
**/__pycache__/
logs/
19 changes: 13 additions & 6 deletions config.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
mailbox=187215129@qq.com
96 changes: 96 additions & 0 deletions mobileperf/android/admonitor.py
Original file line number Diff line number Diff line change
@@ -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: [email protected]
'''

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")

14 changes: 8 additions & 6 deletions mobileperf/android/cpu_top.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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")
Expand All @@ -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:
Expand Down Expand Up @@ -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...")
Expand Down
2 changes: 1 addition & 1 deletion mobileperf/android/devicemonitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion mobileperf/android/fd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 6 additions & 4 deletions mobileperf/android/fps.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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!')
Expand Down
2 changes: 1 addition & 1 deletion mobileperf/android/globaldata.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 6 additions & 5 deletions mobileperf/android/logcat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand All @@ -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):
Expand All @@ -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",
Expand Down Expand Up @@ -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,
Expand Down
24 changes: 13 additions & 11 deletions mobileperf/android/meminfos.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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占用变高,降低采集频率
Expand Down Expand Up @@ -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)):
Expand Down Expand Up @@ -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)
Expand Down
Loading