├── python ├── scriptUtils │ ├── __init__.py │ ├── exception.py │ └── utils.py ├── AndroidAdb │ └── AndroidAdb.exe ├── installApp.py ├── get_package_name.py ├── get_current_activity.py ├── batch_uninstall.py ├── screenshot.py ├── getApp.py ├── backup_app.py ├── kill_5037.py ├── get_app_crash_log.py ├── batch_install.py ├── get_current_pkginfo.py ├── screenrecord.py ├── get_app_permission.py ├── get_cpu_mem_info.py ├── fps.py └── permission.json ├── image ├── tuiku.png ├── fps_cmd.png ├── logcat1.png ├── logcat2.png ├── device_id.png ├── fps_chart.png ├── cpu_mem_info.png └── device_name_list.png ├── shell ├── batch_uninstall.sh ├── getCurrentActivity.sh ├── screenshot.sh ├── getApp.sh └── getAppCrashLog.sh ├── README.md └── logcat └── logcat.py /python/scriptUtils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /image/tuiku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/image/tuiku.png -------------------------------------------------------------------------------- /image/fps_cmd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/image/fps_cmd.png -------------------------------------------------------------------------------- /image/logcat1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/image/logcat1.png -------------------------------------------------------------------------------- /image/logcat2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/image/logcat2.png -------------------------------------------------------------------------------- /image/device_id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/image/device_id.png -------------------------------------------------------------------------------- /image/fps_chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/image/fps_chart.png -------------------------------------------------------------------------------- /image/cpu_mem_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/image/cpu_mem_info.png -------------------------------------------------------------------------------- /image/device_name_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/image/device_name_list.png -------------------------------------------------------------------------------- /python/AndroidAdb/AndroidAdb.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gb112211/AndroidTestScripts/HEAD/python/AndroidAdb/AndroidAdb.exe -------------------------------------------------------------------------------- /shell/batch_uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | adb wait-for-device 4 | echo start remove... 5 | 6 | for package in `adb shell pm list package -3 | cut -d : -f 2 | tr -d "\r"` 7 | do 8 | echo remove $package 9 | adb uninstall $package 10 | done 11 | -------------------------------------------------------------------------------- /shell/getCurrentActivity.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #获取设备当前应用的Activity,打印在控制台 4 | adb shell dumpsys window w | grep \/ | grep name= | cut -d = -f 3 | cut -d \) -f 1 5 | 6 | #将结果写入currentActivity.txt文件中 7 | #adb shell dumpsys window w | grep \/ | grep name= | cut -d = -f 3 | cut -d \) -f 1 > currentActivity.txt 8 | -------------------------------------------------------------------------------- /python/scriptUtils/exception.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月23日 6 | 7 | @author: xuxu 8 | ''' 9 | class SriptException(Exception): 10 | def __init__(self, str): 11 | self.str = str 12 | 13 | def _str_(self): 14 | return self.str 15 | -------------------------------------------------------------------------------- /shell/screenshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #截取设备屏幕,将解图保存至当前目录下的screens文件夹 4 | 5 | time=`adb shell date +%F_%H:%M:%S | tr -d "\r"` 6 | adb shell screencap -p data/local/tmp/$time 7 | 8 | dir=screens 9 | 10 | if [ ! -d "$dir" ] 11 | then 12 | mkdir $dir 13 | fi 14 | 15 | adb pull data/local/tmp/$time $dir/${time}".png" 16 | -------------------------------------------------------------------------------- /python/installApp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #coding=utf-8 3 | 4 | ''' 5 | Created on 2019/5/30 10:24 6 | @author: rikixu 7 | ''' 8 | 9 | from scriptUtils import utils 10 | 11 | 12 | def install(apkPath): 13 | print (utils.adb("install -r %s" %apkPath).stdout.read()) 14 | 15 | 16 | if __name__ == "__main__": 17 | apkPath = raw_input("apk path:") 18 | install(apkPath) -------------------------------------------------------------------------------- /shell/getApp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #获取设备当前应用,存放于app目录下 4 | 5 | #获取设备当前应用的包名 6 | pkgname=`adb shell dumpsys window w | grep \/ | grep name= | cut -d = -f 3 | cut -d / -f 1` 7 | 8 | #获取应用的apk路径 9 | pkgpath=`adb shell pm list packages -f $pkgname | cut -d : -f 2 | cut -d = -f 1` 10 | 11 | #apk存放目录 12 | dir=app 13 | if [ ! -d "$dir" ] 14 | then 15 | mkdir $dir 16 | fi 17 | 18 | #pull apk 19 | echo start pull $pkgname 20 | `adb pull $pkgpath $dir` 21 | echo Completed 22 | 23 | -------------------------------------------------------------------------------- /python/get_package_name.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月26日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | import sys 12 | 13 | from scriptUtils import utils 14 | 15 | #获取设备上当前应用的包名,结果存放于当前目录下的PackageName.txt中 16 | 17 | PATH = lambda p: os.path.abspath(p) 18 | 19 | if __name__ == "__main__": 20 | f = open(PATH("%s/PackageName.txt" %os.getcwd()), "w") 21 | f.write("Package: \n%s\n" %utils.get_current_package_name()) 22 | f.close() 23 | print "Completed" 24 | sys.exit(0) 25 | -------------------------------------------------------------------------------- /python/get_current_activity.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月26日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | import sys 12 | 13 | from scriptUtils import utils 14 | 15 | #获取设备上当前应用的“包名/Activity”,结果存放于当前目录下的CurrentActivity.txt 16 | 17 | PATH = lambda p: os.path.abspath(p) 18 | 19 | if __name__ == "__main__": 20 | f = open(PATH("%s/CurrentActivity.txt" %os.getcwd()), "w") 21 | f.write("Activity: \n%s\n" %utils.get_focused_package_and_activity()) 22 | f.close() 23 | print "Completed" 24 | sys.exit(0) 25 | -------------------------------------------------------------------------------- /python/batch_uninstall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月26日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | 12 | #批量卸载设备上的应用 13 | 14 | def uninstall(): 15 | os.popen("adb wait-for-device") 16 | print "start uninstall..." 17 | for packages in os.popen("adb shell pm list packages -3").readlines(): 18 | packageName = packages.split(":")[-1].splitlines()[0] 19 | os.popen("adb uninstall %s" %packageName) 20 | print "remove %s successes." %packageName 21 | 22 | if __name__ == "__main__": 23 | uninstall() 24 | print " " 25 | print "All the third-party applications uninstall successes." -------------------------------------------------------------------------------- /python/screenshot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月26日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | 12 | from scriptUtils import utils 13 | 14 | #截取当前屏幕,截屏文件保存至当前目录下的screen文件夹中 15 | 16 | PATH = lambda p: os.path.abspath(p) 17 | 18 | def screenshot(): 19 | path = PATH("%s/screenshot" %os.getcwd()) 20 | utils.shell("screencap -p /data/local/tmp/tmp.png").wait() 21 | if not os.path.isdir(path): 22 | os.makedirs(path) 23 | 24 | utils.adb("pull /data/local/tmp/tmp.png %s" %PATH("%s/%s.png" %(path, utils.timestamp()))).wait() 25 | utils.shell("rm /data/local/tmp/tmp.png") 26 | 27 | if __name__ == "__main__": 28 | screenshot() 29 | print "success" 30 | -------------------------------------------------------------------------------- /shell/getAppCrashLog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 获取crash日志,存放至crash_log目录下 4 | 5 | timestamp=`adb shell date +%F_%H-%M-%S | tr -d "\r"` 6 | adb shell dumpsys dropbox | grep data_app_crash > temp.txt 7 | log_dir="./crash_log" 8 | 9 | if [ ! -d "$log_dir" ] 10 | then 11 | mkdir $log_dir 12 | fi 13 | 14 | get_crash_log() 15 | { 16 | time_list=[] 17 | index=0 18 | for result in `cat temp.txt | cut -d " " -f 2` 19 | do 20 | time_list[$index]=$result 21 | let "index+=1" 22 | 23 | done 24 | 25 | for time in ${time_list[@]} 26 | do 27 | adb shell dumpsys dropbox --print $time >> $log_dir/$timestamp.log 28 | done 29 | } 30 | 31 | get_crash_log 32 | rm -f temp.txt 33 | echo "Completed..." 34 | 35 | -------------------------------------------------------------------------------- /python/getApp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月26日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | 12 | from scriptUtils import utils 13 | 14 | #打开手机上的应用(包括系统应用),运行脚本,会将该应用对应的apk复制到本地的App文件夹下 15 | 16 | PATH = lambda p: os.path.abspath(p) 17 | 18 | def get_match_apk(package_name, path): 19 | list = [] 20 | for packages in utils.shell("pm list packages -f %s" %package_name).stdout.readlines(): 21 | if packages.split(":")[0] == "package": 22 | list.append(packages.split(":")[-1].split("=")[0]) 23 | 24 | utils.adb("pull %s %s" %(list[0], path)).wait() 25 | 26 | if __name__ == "__main__": 27 | path = PATH("%s/App" %os.getcwd()) 28 | if not os.path.isdir(path): 29 | os.makedirs(path) 30 | 31 | get_match_apk(utils.get_current_package_name(), path) 32 | print "Completed" 33 | 34 | -------------------------------------------------------------------------------- /python/backup_app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年2月12日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | 12 | from scriptUtils import utils 13 | 14 | #adb backup命令可以备份,该脚本只用于备份设备上安装的第三方应用,将apk保存在当前目录下的backup_app文件夹中 15 | 16 | PATH = lambda p : os.path.abspath(p) 17 | 18 | def get_apk_list(): 19 | apps = [] 20 | for apk in utils.shell("pm list packages -f -3").stdout.readlines(): 21 | apps.append(apk.split(":")[-1].split("=")[0]) 22 | 23 | return apps 24 | 25 | def backup_app(): 26 | apps = get_apk_list() 27 | for apk in apps: 28 | utils.adb("pull %s backup_app" %apk).wait() 29 | print "pull %s succeed." %apk 30 | 31 | if __name__ == "__main__": 32 | path = PATH("%s/backup_app" %os.getcwd()) 33 | if not os.path.isdir(path): 34 | os.mkdir(path) 35 | backup_app() 36 | print "Completed" 37 | -------------------------------------------------------------------------------- /python/kill_5037.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ''' 4 | Created on 2015年2月28日 5 | 6 | @author: xuxu 7 | ''' 8 | 9 | import os 10 | import platform 11 | 12 | #5037端口占用时,打开该进程路径,且杀掉占用该端口的进程(只支持Windows) 13 | 14 | def win(): 15 | pid = os.popen("netstat -ano | findstr 5037 | findstr LISTENING").read().split()[-1] 16 | 17 | #下面的命令执行结果,可能因电脑而异,若获取adb.exe时出错,可自行调试! 18 | #E:\>tasklist /FI "PID eq 10200" 19 | # 20 | #Image Name PID Session Name Session# Mem Usage 21 | #========================= ======== ================ =========== ============ 22 | #adb.exe 10200 Console 1 6,152 K 23 | 24 | process_name = os.popen('tasklist /FI "PID eq %s"' %pid).read().split()[-6] 25 | process_path = os.popen('wmic process where name="%s" get executablepath' %process_name).read().split("\r\n")[1] 26 | 27 | #分割路径,得到进程所在文件夹名 28 | name_list = process_path.split("\\") 29 | del name_list[-1] 30 | directory = "\\".join(name_list) 31 | 32 | #打开进程所在文件夹 33 | os.system("explorer.exe %s" %directory) 34 | #杀死该进程 35 | os.system("taskkill /F /PID %s" %pid) 36 | 37 | 38 | if __name__ == "__main__": 39 | win() 40 | -------------------------------------------------------------------------------- /python/get_app_crash_log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年6月2日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | 12 | from scriptUtils import utils 13 | 14 | # app发生crash,未及时在logcat中抓取到有效log时,可通过该脚本获取到log,日志存放至crash_log目录 15 | 16 | PATH = lambda p : os.path.abspath(p) 17 | 18 | path = PATH("%s/crash_log" %os.getcwd()) 19 | if not os.path.isdir(path): 20 | os.mkdir(path) 21 | 22 | # 获取app发生crash的时间列表 23 | def get_crash_time_list(): 24 | time_list = [] 25 | result_list = utils.shell("dumpsys dropbox | %s data_app_crash" %utils.find_util).stdout.readlines() 26 | for time in result_list: 27 | temp_list = time.split(" ") 28 | temp_time= [] 29 | temp_time.append(temp_list[0]) 30 | temp_time.append(temp_list[1]) 31 | time_list.append(" ".join(temp_time)) 32 | 33 | return time_list 34 | 35 | def get_crash_log(time_list): 36 | log_file = PATH("%s/crash_log/%s.txt" %(os.getcwd(), utils.timestamp())) 37 | f = open(log_file, "w") 38 | for time in time_list: 39 | cash_log = utils.shell("dumpsys dropbox --print %s" %time).stdout.read() 40 | f.write(cash_log) 41 | f.close() 42 | 43 | if __name__ == '__main__': 44 | time_list = get_crash_time_list() 45 | get_crash_log(time_list) 46 | print "Completed" 47 | 48 | -------------------------------------------------------------------------------- /python/batch_install.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ''' 4 | Created on 2015年1月26日 5 | 6 | @author: xuxu 7 | ''' 8 | 9 | import os 10 | import time 11 | import sys 12 | 13 | #需要在脚本所在目录AndroidAdb目录下有个AndroidAdb.exe程序,该adb可以支持安装以中文命名的apk 14 | #需要将apk文件放在脚本所在目录下的Apps目录下 15 | 16 | #检查AndroidAdb.exe 17 | def check_adb(): 18 | if os.path.isfile("%s\\AndroidAdb\\AndroidAdb.exe" %os.getcwd()): 19 | return True 20 | else: 21 | return False 22 | 23 | #检查Apps目录 24 | def check_dir(): 25 | if os.path.isdir("%s\\Apps" %os.getcwd()): 26 | return True 27 | else: 28 | return False 29 | 30 | #安装应用 31 | def install(): 32 | count = 0 33 | apps_dir = "%s\\Apps" %os.getcwd() 34 | for path, subdir, files in os.walk(apps_dir): 35 | for apk in files: 36 | os.popen("%s\\AndroidAdb\\AndroidAdb.exe install %s" %(os.getcwd(), os.path.join(path, apk))) 37 | count += 1 38 | 39 | print "\n%s apps install complete." %str(count) 40 | 41 | if __name__ == "__main__": 42 | if check_adb(): 43 | pass 44 | else: 45 | print "AndroidAdb.exe not exist." 46 | time.sleep(3) 47 | sys.exit(0) 48 | 49 | if check_dir(): 50 | pass 51 | else: 52 | print "Apps Directory not exist" 53 | time.sleep(3) 54 | sys.exit(0) 55 | 56 | install() 57 | -------------------------------------------------------------------------------- /python/get_current_pkginfo.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月26日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | import tempfile 12 | 13 | from scriptUtils import utils 14 | from scriptUtils.exception import SriptException 15 | 16 | #获取设备上当前应用的包信息,结果存放于当前目录下的PackageInfo.txt中 17 | 18 | PATH = lambda p: os.path.abspath(p) 19 | tempFile = tempfile.gettempdir() 20 | 21 | def get_aapt(): 22 | if "ANDROID_HOME" in os.environ: 23 | rootDir = os.path.join(os.environ["ANDROID_HOME"], "build-tools") 24 | for path, subdir, files in os.walk(rootDir): 25 | if "aapt.exe" in files: 26 | return os.path.join(path, "aapt.exe") 27 | elif "aapt" in files: 28 | return os.path.join(path, "aapt") 29 | else: 30 | raise SriptException("ANDROID_HOME not exist") 31 | 32 | def get_match_apk(package_name): 33 | list = [] 34 | for packages in utils.shell("pm list packages -f %s" %package_name).stdout.readlines(): 35 | list.append(packages.split(":")[-1].split("=")[0]) 36 | apk_name = list[0].split("/")[-1] 37 | 38 | utils.adb("pull %s %s" %(list[0], tempFile)).wait() 39 | 40 | return PATH("%s/%s" %(tempFile, apk_name)) 41 | 42 | if __name__ == "__main__": 43 | package_name = utils.get_current_package_name() 44 | os.popen("%s dump badging %s > PackageInfo.txt" %(get_aapt(), get_match_apk(package_name))) 45 | # os.popen("del %s\\*.apk" %tempFile) 46 | print "Completed" 47 | -------------------------------------------------------------------------------- /python/screenrecord.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月26日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | import os 11 | import string 12 | import sys 13 | import time 14 | 15 | from scriptUtils import utils 16 | 17 | #需要Android4.4及4.4以上版本,运行脚本后可录制设备上的操作,默认使用手机分辨率,手动设置录制时间。 18 | #录制结果存放于当前目录下的video目录下 19 | 20 | PATH = lambda p: os.path.abspath(p) 21 | 22 | def record(): 23 | utils.shell("rm -f /data/local/tmp/video.mp4") 24 | limit_time = raw_input("Please set the maximum recording time, in seconds. Maximum is 180.\n") 25 | if limit_time == "": 26 | utils.shell("screenrecord --time-limit 180 /data/local/tmp/video.mp4") 27 | try: 28 | _limit_time = int(limit_time) + 1 29 | except: 30 | record() 31 | if 0 < _limit_time <= 180: 32 | utils.shell("screenrecord --time-limit %s /data/local/tmp/video.mp4" %limit_time).wait() 33 | else: 34 | print "Please set again!" 35 | record() 36 | 37 | 38 | if __name__ == "__main__": 39 | sdk = string.atoi(utils.shell("getprop ro.build.version.sdk").stdout.read()) 40 | if sdk < 19: 41 | print "sdk version is %s, less than 19!" 42 | sys.exit(0) 43 | else: 44 | record() 45 | print "Get Video file..." 46 | time.sleep(3) 47 | 48 | path = PATH("%s/video" %os.getcwd()) 49 | if not os.path.isdir(path): 50 | os.makedirs(path) 51 | 52 | utils.adb("pull /data/local/tmp/video.mp4 %s" %PATH("%s/%s.mp4" %(path, utils.timestamp()))) 53 | print "Completed" 54 | -------------------------------------------------------------------------------- /python/get_app_permission.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | from scriptUtils import utils 5 | 6 | import json 7 | import os 8 | import sys 9 | 10 | reload(sys) 11 | sys.setdefaultencoding('utf8') 12 | 13 | PATH = lambda p: os.path.abspath(p) 14 | 15 | # 获取设备上当前应用的权限列表 16 | # Windows下会将结果写入permission.txt文件中,其他系统打印在控制台 17 | 18 | def get_permission_list(package_name): 19 | 20 | permission_list = [] 21 | result_list = utils.shell("dumpsys package %s | %s android.permission" %(package_name, utils.find_util)).stdout.readlines() 22 | 23 | for permission in result_list: 24 | permission_list.append(permission.strip()) 25 | 26 | return permission_list 27 | 28 | if __name__ == '__main__': 29 | package_name = utils.get_current_package_name() 30 | permission_list = get_permission_list(package_name) 31 | permission_json_file = file("permission.json") 32 | file_content = json.load(permission_json_file)["PermissList"] 33 | 34 | if utils.system is "Windows": 35 | f = open(PATH("%s/permission.txt" %os.getcwd()), "w") 36 | f.write("package: %s\n\n" %package_name) 37 | for permission in permission_list: 38 | for permission_dict in file_content: 39 | if permission == permission_dict["Key"]: 40 | f.write(permission_dict["Key"] + ":\n " + permission_dict["Memo"] + "\n") 41 | f.close 42 | else: 43 | print "package: %s\n" %package_name 44 | for permission in permission_list: 45 | for permission_dict in file_content: 46 | if permission == permission_dict["Key"]: 47 | print permission_dict["Key"] + ":" 48 | print " " + permission_dict["Memo"] 49 | -------------------------------------------------------------------------------- /python/get_cpu_mem_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | Created on 2015年1月28日 6 | 7 | @author: xuxu 8 | ''' 9 | 10 | #需要安装pychartdir模块,http://blog.csdn.net/gb112211/article/details/43272049 11 | 12 | import string 13 | 14 | from scriptUtils import utils 15 | from pychartdir import * 16 | 17 | PATH = lambda p: os.path.abspath(p) 18 | 19 | #打开待测应用,运行脚本,默认times为20次(可自己手动修改次数),获取该应用cpu、memory占用率的曲线图,图表保存至chart目录下 20 | 21 | #top次数 22 | times = 20 23 | 24 | #设备当前运行应用的包名 25 | pkg_name = utils.get_current_package_name() 26 | 27 | #获取cpu、mem占用 28 | def top(): 29 | cpu = [] 30 | mem = [] 31 | 32 | top_info = utils.shell("top -n %s | %s %s$" %(str(times), utils.find_util, pkg_name)).stdout.readlines() 33 | 34 | for info in top_info: 35 | #temp_list = del_space(info) 36 | temp_list = info.split() 37 | cpu.append(temp_list[2]) 38 | mem.append(temp_list[6]) 39 | 40 | return (cpu, mem) 41 | 42 | #去除top信息中的空格,便于获取cpu、mem的值 43 | #def del_space(str): 44 | # temp_list1 = str.split(" ") 45 | # temp_list2 = [] 46 | # 47 | # for str in temp_list1: 48 | # if str != "": 49 | # temp_list2.append(str) 50 | # 51 | # return temp_list2 52 | 53 | #绘制线性图表,具体接口的用法查看ChartDirecto的帮助文档 54 | def line_chart(): 55 | data = top() 56 | cpu_data = [] 57 | mem_data = [] 58 | 59 | #去掉cpu占用率中的百分号,并转换为int型 60 | for cpu in data[0]: 61 | cpu_data.append(string.atoi(cpu.split("%")[0])) 62 | 63 | #去掉内存占用中的单位K,并转换为int型,以M为单位 64 | for mem in data[1]: 65 | mem_data.append(string.atof(mem.split("K")[0])/1024) 66 | 67 | #横坐标 68 | labels = [] 69 | for i in range(1, times + 1): 70 | labels.append(str(i)) 71 | 72 | #自动设置图表区域宽度 73 | if times <= 50: 74 | xArea = times * 40 75 | elif 50 < times <= 90: 76 | xArea = times * 20 77 | else: 78 | xArea = 1800 79 | 80 | c = XYChart(xArea, 800, 0xCCEEFF, 0x000000, 1) 81 | c.setPlotArea(60, 100, xArea - 100, 650) 82 | c.addLegend(50, 30, 0, "arialbd.ttf", 15).setBackground(Transparent) 83 | 84 | c.addTitle("cpu and memery info(%s)" %pkg_name, "timesbi.ttf", 15).setBackground(0xCCEEFF, 0x000000, glassEffect()) 85 | c.yAxis().setTitle("The numerical", "arialbd.ttf", 12) 86 | c.xAxis().setTitle("Times", "arialbd.ttf", 12) 87 | 88 | c.xAxis().setLabels(labels) 89 | 90 | #自动设置X轴步长 91 | if times <= 50: 92 | step = 1 93 | else: 94 | step = times / 50 + 1 95 | 96 | c.xAxis().setLabelStep(step) 97 | 98 | layer = c.addLineLayer() 99 | layer.setLineWidth(2) 100 | layer.addDataSet(cpu_data, 0xff0000, "cpu(%)") 101 | layer.addDataSet(mem_data, 0x008800, "mem(M)") 102 | 103 | path = PATH("%s/chart" %os.getcwd()) 104 | if not os.path.isdir(path): 105 | os.makedirs(path) 106 | 107 | #图片保存至脚本当前目录的chart目录下 108 | c.makeChart(PATH("%s/%s.png" %(path, utils.timestamp()))) 109 | 110 | if __name__ == "__main__": 111 | print "Starting get top information..." 112 | line_chart() 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AndroidTestScripts 2 | ================== 3 | 4 | Android测试中常用到的脚本 5 | 6 | ### 主要脚本功能 7 | 8 | 批量安装应用(支持以中文命名的 apk)、批量卸载、截屏、录制视频、获取当前应用的 apk 文件、包名、Activity 名等。
9 | 10 | ### 2019.05.29 11 | 多设备的时候列表显示device ID,修改为显示设备model名 12 | 13 | ![device_id](image/device_name_list.png) 14 | 15 | ### 2018.05.01 16 | 修改 `screenrecord.py` ,原有脚本有时候会出现录制完的视频在 pull 到本地的时候卡死。修改后的脚本需要输入录制时间。 17 | 18 | 19 | ### 2016.07.19 20 | 增加部分python脚本对多设备的支持: 21 | 22 | ![device_id](image/device_id.png) 23 | ### 2016.04.22 24 | 增加 `fps.py`,获取测试界面的 `fps`、`jankniess`。 25 | 26 | 使用方法:按照提示输入参数,测试过程中操作界面,最终数据结果存放于 `fps_data` 目录下,csv 格式。 27 | 如有错误,请指出! 28 | 29 | #### demo: 30 | 31 | 测试界面: 32 | 33 | ![tuiku](image/tuiku.png) 34 | 35 | cmd 界面: 36 | 37 | ![fps_cmd](image/fps_cmd.png) 38 | 39 | 最终结果: 40 | 41 | ![fps_chart](image/fps_chart.png) 42 | 43 | 44 | ### 2016.01.21 45 | 增加 `logcat.py`,windows 中在 cmd 里面运行 logcat 命令,会给输出的日志内容根据优先级添加颜色。使用前提是已配置 adb 及 python 的环境变量,在 cmd 里面可以直接运行 adb 命令和python 脚本。 46 | 用法: 47 | 将`logcat.py` 配置到环境变量里面,使得可以在 cmd 中可以直接执行 logcat 命令。参数与 `adb logcat` 的一样。例如: 48 | ``` 49 | logcat -v time 50 | ``` 51 | 无颜色时截图: 52 | ![logcat1](image/logcat1.png) 53 | 54 | logcat 执行后: 55 | ![logcat2](image/logcat2.png) 56 | 57 | 当要使用重定向时,请使用 `adb logcat`. 58 | 59 | 60 | ### 2015.06.02 61 | 增加 `get_app_crash_log.py` 与 `getAppCrashLog.sh`, 应用发生 crash ,未及时从 logcat 获取到有效 log 时,可通过该脚本获取 log 62 | 63 | ### 2015.05.30 64 | 增加 `get_app_permission.py`,获取设备当前应用的权限详情,windows 下会将结果写入 `permission.txt` 文件中,其他系统打印在控制台: 65 | 66 | ``` 67 | [xuxu:...1/AndroidTestScripts/python]$ python get_app_permission.py (master✱) 68 | package: com.android.camera 69 | 70 | android.permission.READ_PHONE_STATE: 71 | 允许应用程序访问设备的手机功能。有此权限的应用程序可确定此手机的号码和序列号,是否正在通话,以及对方的号码等。 72 | android.permission.CAMERA: 73 | 允许应用程序使用相机拍照,这样应用程序可随时收集进入相机镜头的图像。 74 | android.permission.WRITE_EXTERNAL_STORAGE: 75 | 允许应用程序写入SD卡。 76 | android.permission.ACCESS_FINE_LOCATION: 77 | 访问精准的位置源,例如手机上的全球定位系统(如果有)。恶意应用程序可能会借此确定您所处的位置,并可能消耗额外的电池电量。 78 | android.permission.ACCESS_WIFI_STATE: 79 | 允许应用程序查看有关 WLAN 状态的信息。 80 | android.permission.ACCESS_NETWORK_STATE: 81 | 允许应用程序查看所有网络的状态。 82 | android.permission.WAKE_LOCK: 83 | 允许应用程序防止手机进入休眠状态。 84 | android.permission.RECORD_AUDIO: 85 | 允许应用程序访问录音路径。 86 | android.permission.MODIFY_AUDIO_SETTINGS: 87 | 允许应用程序修改整个系统的音频设置,如音量和路由。 88 | ``` 89 | 90 | ### 2015.02.12 91 | 因日常工作需要,增加备份设备中安装的第三方应用的脚本 `backup_app.py`。(区别于adb backup命令,只备份apk)
92 | 93 | ### 2015.01.31 94 | 修改 `screenrecord.py` 中的默认录制时间,默认最长录制时间为 180 秒
95 | 96 | ### 2015.01.29 97 | 新增脚本 `get_cpu_mem_info.py`,获取设备当前运行的应用的 cpu、memory 信息,默认 top times 取值为20次,可自己修改脚本中的该参数 98 | 99 | 脚本运行需要安装pychartdir模块,安装方法请参考 [http://blog.csdn.net/gb112211/article/details/43272049](http://blog.csdn.net/gb112211/article/details/43272049 "python pychartdir模块的安装及使用")
100 | 直接运行脚本,会生成线性图表存放于chart目录下,图表类似于:
101 | ![image](image/cpu_mem_info.png "chart" ) 102 | 103 | 104 | ### 2015.01.28 105 | 修改了设备状态判断的代码(脚本自己都曾使用OK,如有问题,可以QQ联系:274925460)
106 | 107 | ### 2015.01.26 108 | 109 | 1. 改写 python 分类中的脚本结构,将大部分方法分装进了 scriptUtils 包中的 utils 模块中
110 | 2. 新增 `screenrecord.py`(录制视频,Android4.4新增功能)
111 | 3. 使用时请直接在脚本目录下运行脚本(可以将脚本目录复制到桌面上,使用时很方便)
112 | 4. 需要配置 `ANDROID_HOME`,如果脚本执行失败,请在命令行模式下运行脚本,查看报错信息
113 | -------------------------------------------------------------------------------- /python/scriptUtils/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | ''' 4 | Created on 2015年1月23日 5 | 6 | @author: xuxu 7 | ''' 8 | 9 | import os 10 | import platform 11 | import re 12 | import subprocess 13 | import time 14 | import Tkinter as tk 15 | import ttk 16 | 17 | import exception 18 | 19 | serialno_num = "" 20 | 21 | # 判断系统类型,windows使用findstr,linux使用grep 22 | system = platform.system() 23 | if system is "Windows": 24 | find_util = "findstr" 25 | else: 26 | find_util = "grep" 27 | 28 | # 判断是否设置环境变量ANDROID_HOME 29 | if "ANDROID_HOME" in os.environ: 30 | if system == "Windows": 31 | command = os.path.join(os.environ["ANDROID_HOME"], "platform-tools", "adb.exe") 32 | else: 33 | command = os.path.join(os.environ["ANDROID_HOME"], "platform-tools", "adb") 34 | else: 35 | raise EnvironmentError( 36 | "Adb not found in $ANDROID_HOME path: %s." %os.environ["ANDROID_HOME"]) 37 | 38 | 39 | def get_screen_size(window): 40 | return window.winfo_screenwidth(),window.winfo_screenheight() 41 | 42 | 43 | def get_window_size(window): 44 | return window.winfo_reqwidth(),window.winfo_reqheight() 45 | 46 | 47 | def center_window(root, width, height): 48 | screenwidth = root.winfo_screenwidth() 49 | screenheight = root.winfo_screenheight() 50 | size = '%dx%d+%d+%d' % (width, height, (screenwidth - width)/2, (screenheight - height)/2) 51 | root.geometry(size) 52 | 53 | 54 | class Window(object): 55 | device_id = "" 56 | device_id_list = [] 57 | device_name_list = [] 58 | device_name_dict = {} 59 | root = None 60 | box = None 61 | 62 | def __init__(self, device_id_list, root): 63 | self.device_id_list = device_id_list 64 | self.device_name_dict = get_device_name_dict(self.device_id_list) 65 | self.get_device_name_list() 66 | self.device_id = device_id_list[0] 67 | self.root = root 68 | self.box = None 69 | 70 | def show_window(self): 71 | self.root.title(u'Serialno Number') 72 | center_window(self.root, 300, 240) 73 | self.root.maxsize(600, 400) 74 | self.root.minsize(300, 240) 75 | 76 | # options = self.device_id_list 77 | options = self.device_name_list 78 | self.box = ttk.Combobox(values=options) 79 | self.box.current(0) 80 | self.box.pack(expand = tk.YES) 81 | self.box.bind("<>", self.select) 82 | ttk.Button(text=u"确定", command=self.ok).pack(expand = tk.YES) 83 | 84 | self.root.mainloop() 85 | 86 | def select(self, event=None): 87 | for key, value in self.device_name_dict.iteritems(): 88 | if value == self.box.selection_get(): 89 | self.device_id = key 90 | # self.device_id = self.box.selection_get() 91 | 92 | def ok(self): 93 | global serialno_num 94 | serialno_num = self.device_id 95 | self.root.destroy() 96 | 97 | def get_device_name_list(self): 98 | for id in self.device_id_list: 99 | self.device_name_list.append(self.device_name_dict.get(id)) 100 | 101 | 102 | # adb命令 103 | def adb(args): 104 | global serialno_num 105 | if serialno_num == "": 106 | devices = get_device_list() 107 | if len(devices) == 1: 108 | # global serialno_num 109 | serialno_num = devices[0] 110 | else: 111 | root = tk.Tk() 112 | window = Window(devices, root) 113 | window.show_window() 114 | cmd = "%s -s %s %s" %(command, serialno_num, str(args)) 115 | return subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 116 | 117 | #adb shell命令 118 | def shell(args): 119 | global serialno_num 120 | if serialno_num == "": 121 | devices = get_device_list() 122 | if len(devices) == 1: 123 | serialno_num = devices[0] 124 | else: 125 | root = tk.Tk() 126 | window = Window(devices, root) 127 | window.show_window() 128 | cmd = "%s -s %s shell %s" %(command, serialno_num, str(args)) 129 | return subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 130 | 131 | #获取设备状态 132 | def get_state(): 133 | return os.popen("adb -s %s get-state" %serialno_num).read().strip() 134 | 135 | 136 | # 获取对应包名的pid 137 | def get_app_pid(pkg_name): 138 | if system is "Windows": 139 | string = shell("ps | findstr %s$" %pkg_name).stdout.read() 140 | 141 | string = shell("ps | grep -w %s" %pkg_name).stdout.read() 142 | 143 | if string == '': 144 | return "the process doesn't exist." 145 | 146 | pattern = re.compile(r"\d+") 147 | result = string.split(" ") 148 | result.remove(result[0]) 149 | 150 | return pattern.findall(" ".join(result))[0] 151 | 152 | 153 | # 杀掉对应包名的进程 154 | def kill_process(pkg_name): 155 | pid = get_app_pid(pkg_name) 156 | 157 | result = shell("kill %s" %str(pid)).stdout.read().split(": ")[-1] 158 | 159 | if result != "": 160 | raise exception.SriptException("Operation not permitted or No such process") 161 | 162 | 163 | # 获取设备上当前应用的包名与activity 164 | def get_focused_package_and_activity(): 165 | pattern = re.compile(r"[a-zA-Z0-9\.]+/.[a-zA-Z0-9\.]+") 166 | tmp = shell("dumpsys activity | %s mFocusedActivity" %find_util).stdout.read() 167 | name = "" 168 | try: 169 | name = pattern.findall(tmp)[0] 170 | except: 171 | tmp = shell("dumpsys window w | %s \/ | %s name=" %(find_util, find_util)).stdout.read() 172 | name = pattern.findall(tmp)[0] 173 | return name 174 | 175 | 176 | # 获取当前应用的包名 177 | def get_current_package_name(): 178 | return get_focused_package_and_activity().split("/")[0] 179 | 180 | 181 | # 获取当前设备的activity 182 | def get_current_activity(): 183 | return get_focused_package_and_activity().split("/")[-1] 184 | 185 | 186 | # 时间戳 187 | def timestamp(): 188 | return time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime(time.time())) 189 | 190 | 191 | def get_device_list(): 192 | devices = [] 193 | result = subprocess.Popen("adb devices", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.readlines() 194 | result.reverse() 195 | for line in result[1:]: 196 | if "attached" not in line.strip(): 197 | devices.append(line.split()[0]) 198 | else: 199 | break 200 | return devices 201 | 202 | def get_device_name_dict(devices): 203 | device_dict = {} 204 | if not devices: 205 | return 206 | 207 | for device in devices: 208 | cmd = "adb -s %s shell getprop ro.product.model" %device 209 | device_name = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.readline().strip() 210 | device_dict[device] = device_name 211 | return device_dict 212 | 213 | 214 | # 连接设备 215 | # adb("kill-server").wait() 216 | # adb("start-server").wait() 217 | adb("wait-for-device").wait() 218 | 219 | if get_state() != "device": 220 | adb("kill-server").wait() 221 | adb("start-server").wait() 222 | 223 | if get_state() != "device": 224 | raise exception.SriptException("Device not run") 225 | 226 | 227 | if __name__ == "__main__": 228 | print get_focused_package_and_activity() 229 | -------------------------------------------------------------------------------- /python/fps.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -* 3 | 4 | __author__ = 'xuxu' 5 | 6 | import time 7 | import os 8 | import sys 9 | 10 | from scriptUtils import utils 11 | 12 | PATH = lambda p: os.path.abspath(p) 13 | 14 | class SurfaceFlinger(object): 15 | 16 | CLEAR_BUFFER_CMD = "dumpsys SurfaceFlinger --latency-clear" 17 | FRAME_LATENCY_CMD = "dumpsys SurfaceFlinger --latency" 18 | PAUSE_LATENCY = 20 #两个frame之间的latency大于20,则不是一个jankniess 19 | PENDING_FENCE_TIME = (1 << 63) - 1 #Symbol of unfinished frame time 20 | 21 | refresh_period = -1 #刷新周期 22 | frame_buffer_data = [] 23 | frame_latency_data_size = 0 24 | max_Vsync = 0 25 | 26 | def __init__(self, activity_name, dump_time): 27 | """ 28 | :param activity_name: 当前界面的"package/activity" 29 | :param dump_time: 每次获取SurfaceFlinger数据的时间间隔 30 | """ 31 | self.activity_name = activity_name 32 | self.dump_time = dump_time 33 | 34 | #清除SurfaceFlinger缓存数据 35 | def __clear_buffer(self): 36 | results = utils.shell("{0} {1}".format(self.CLEAR_BUFFER_CMD, self.activity_name))\ 37 | .stdout.readlines() 38 | return not len(results) 39 | 40 | #开始获取SurfaceFlinger数据 41 | def start_dump_latency_data(self, ignore_pending_fence_time = False): 42 | results = [] 43 | if self.__clear_buffer(): 44 | time.sleep(self.dump_time) 45 | results = utils.shell("{0} {1}".format(self.FRAME_LATENCY_CMD, self.activity_name))\ 46 | .stdout.readlines() 47 | self.refresh_period = int(results[0].strip()) 48 | 49 | if self.refresh_period < 0: 50 | return False 51 | 52 | data_invalid_flag = False 53 | for line in results: 54 | if not line.strip(): 55 | break 56 | 57 | if len(line.split()) == 1 or line.split()[0] == "0": 58 | continue 59 | elif line.split()[1] == str(self.PENDING_FENCE_TIME): 60 | if ignore_pending_fence_time: 61 | data_invalid_flag = True 62 | else: 63 | return False 64 | 65 | self.frame_buffer_data.append(line.split()) 66 | if not data_invalid_flag: 67 | self.frame_latency_data_size += 1 68 | 69 | return True 70 | 71 | def get_frame_latency_data_size(self): 72 | return self.frame_latency_data_size 73 | 74 | def get_refresh_period(self): 75 | return self.refresh_period 76 | 77 | #获取Vsync增量数据 78 | def __get_delta_Vsync_data(self): 79 | delta_Vsync_data = [] 80 | if self.frame_buffer_data: 81 | first_Vsync_time = long(self.frame_buffer_data[0][1]) 82 | for i in xrange(0, self.frame_latency_data_size-1): 83 | cur_Vsync_time = long(self.frame_buffer_data[i+1][1]) 84 | delta_Vsync_data.append(cur_Vsync_time - first_Vsync_time) 85 | first_Vsync_time = cur_Vsync_time 86 | if self.max_Vsync < delta_Vsync_data[i]: 87 | self.max_Vsync = delta_Vsync_data[i] 88 | return delta_Vsync_data 89 | 90 | #在delta_Vsync_data基础上再获取增量数据 91 | def __get_delta2_Vsync_data(self): 92 | delta_Vsync_data = self.__get_delta_Vsync_data() 93 | delta2_Vsync_data = [] 94 | num_delta_Vsync = self.frame_latency_data_size - 1 95 | 96 | for i in xrange(0, num_delta_Vsync-1): 97 | delta2_Vsync_data.append(delta_Vsync_data[i+1] - delta_Vsync_data[i]) 98 | return delta2_Vsync_data 99 | 100 | def __get_normalized_delta2_Vsync(self): 101 | delta2_Vsync_data = self.__get_delta2_Vsync_data() 102 | normalized_delta2_Vsync = [] 103 | for i in xrange(0, self.frame_latency_data_size-2): 104 | normalized_delta2_Vsync.append(delta2_Vsync_data[i]/self.refresh_period) 105 | return normalized_delta2_Vsync 106 | 107 | def __get_round_normalized_delta2_Vsync(self): 108 | normalized_delta2_Vsync = self.__get_normalized_delta2_Vsync() 109 | round_normalized_delta2_Vsync = [] 110 | for i in xrange(0, self.frame_latency_data_size-2): 111 | value = round(max(normalized_delta2_Vsync[i], 0.0)) 112 | round_normalized_delta2_Vsync.append(value) 113 | 114 | return round_normalized_delta2_Vsync 115 | 116 | def get_Vsync_jankiness(self): 117 | if (self.refresh_period< 0): 118 | return -1 119 | round_normalized_delta2_Vsync = self.__get_round_normalized_delta2_Vsync() 120 | 121 | num_jankiness = 0 122 | for i in xrange(0, self.frame_latency_data_size-2): 123 | value = round_normalized_delta2_Vsync[i] 124 | if value > 0 and value < self.PAUSE_LATENCY: 125 | num_jankiness += 1 126 | 127 | return num_jankiness 128 | 129 | def get_max_delta_Vsync(self): 130 | return round(self.max_Vsync/self.refresh_period) 131 | 132 | def get_frame_rate(self): 133 | if self.refresh_period < 0: 134 | return -1 135 | if not self.frame_buffer_data: 136 | return -1 137 | start_time = long(self.frame_buffer_data[0][1]) 138 | end_time = long(self.frame_buffer_data[-1][1]) 139 | total_time = end_time - start_time 140 | return (self.frame_latency_data_size - 1) * 1e9 / total_time 141 | 142 | #停止数据采集 143 | def stop_dump_latency_data(self): 144 | self.refresh_period = -1 145 | self.frame_buffer_data = [] 146 | self.frame_latency_data_size = 0 147 | self.max_Vsync = 0 148 | 149 | def write_csv(*list): 150 | path = PATH("{}/fps_data".format(os.getcwd())) 151 | if not os.path.isdir(path): 152 | os.makedirs(path) 153 | f = open(PATH("%s/fps-%s.csv" %(path, utils.timestamp())), "w") 154 | times = list[0] 155 | fps = list[1] 156 | jankniess = list[2] 157 | 158 | for i in xrange(0, len(fps) - 1): 159 | f.write("{0},{1},{2},\n".format(str(times[i]), str(fps[i]), str(jankniess[i]))) 160 | 161 | f.close() 162 | 163 | if __name__ == "__main__": 164 | if not raw_input("Make sure the test Activity, in this process, you should keep in this Activity!\n" 165 | "Please press Enter continue..."): 166 | sleep_time = -1 167 | dump_time = -1 168 | while not 0 < sleep_time <= 10: 169 | try: 170 | sleep_time = float(raw_input("Please input sleep time(0-10s) :")) 171 | except: 172 | continue 173 | while dump_time < 0: 174 | try: 175 | dump_time = int(raw_input("Please input dump times: ")) 176 | except: 177 | continue 178 | 179 | activity_name = utils.get_focused_package_and_activity() 180 | print "Current Activity: " 181 | print activity_name 182 | sf = SurfaceFlinger(activity_name, sleep_time) 183 | times = ["time"] + [i for i in xrange(1, dump_time+1)] 184 | jankniess = ["Jankniess"] 185 | fps = ["fps"] 186 | for i in xrange(0, dump_time): 187 | sf.start_dump_latency_data() 188 | frame= sf.get_frame_rate(); 189 | if frame != -1: 190 | jankniess.append(sf.get_Vsync_jankiness()) 191 | fps.append(frame) 192 | sf.stop_dump_latency_data() 193 | print "jankniess:" 194 | print jankniess 195 | print "fps:" 196 | print fps 197 | 198 | write_csv(times, fps, jankniess) 199 | 200 | raw_input("Please press Enter quit...") 201 | sys.exit(0) 202 | -------------------------------------------------------------------------------- /logcat/logcat.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | ''' 4 | Created on 2016年1月21日 5 | 6 | @author: xuxu 7 | ''' 8 | 9 | #用法: logcat -v time 10 | 11 | import sys 12 | import os 13 | import ctypes 14 | import re 15 | 16 | #输出类别标志 17 | STD_INPUT_HANDLE = -10 18 | STD_OUTPUT_HANDLE= -11 19 | STD_ERROR_HANDLE = -12 20 | 21 | #颜色 22 | """ 23 | 24 | 0 = 黑色 8 = 灰色 25 | 1 = 蓝色 9 = 淡蓝色 26 | 2 = 绿色 A = 淡绿色 27 | 3 = 浅绿色 B = 淡浅绿色 28 | 4 = 红色 C = 淡红色 29 | 5 = 紫色 D = 淡紫色 30 | 6 = 黄色 E = 淡黄色 31 | 7 = 白色 F = 亮白色 32 | """ 33 | BLACK = 0X00 34 | RED = 0x0c 35 | DARKRED = 0x40 36 | BLUE = 0x09 37 | GREEN = 0x0a 38 | LIGHT_GREEN = 0x0b 39 | YELLOW = 0x0e 40 | WHITE = 0x0f 41 | PINK = 0x0d 42 | 43 | class Color(object): 44 | std_out_handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) 45 | 46 | def set_cmd_color(self, color, handle=std_out_handle): 47 | return ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color) 48 | 49 | def reset_color(self): 50 | self.set_cmd_color(RED | GREEN | BLUE) 51 | 52 | def show_verbose(self, msg): 53 | self.set_cmd_color(WHITE) 54 | sys.stdout.write(msg) 55 | self.reset_color() 56 | 57 | def show_debug(self, msg): 58 | self.set_cmd_color(LIGHT_GREEN) 59 | sys.stdout.write(msg) 60 | self.reset_color() 61 | 62 | def show_info(self, msg): 63 | self.set_cmd_color(GREEN) 64 | sys.stdout.write(msg) 65 | self.reset_color() 66 | 67 | def show_warn(self, msg): 68 | self.set_cmd_color(YELLOW) 69 | sys.stdout.write(msg) 70 | self.reset_color() 71 | 72 | def show_error(self, msg): 73 | self.set_cmd_color(RED) 74 | sys.stdout.write(msg) 75 | self.reset_color() 76 | 77 | def show_fatal(self, msg): 78 | self.set_cmd_color(DARKRED) 79 | sys.stdout.write(msg) 80 | self.reset_color() 81 | 82 | def main(argv): 83 | color = Color() 84 | command = "" 85 | if "-d" in argv: 86 | command = "adb logcat %s" %" ".join(argv[1:]) 87 | else: 88 | command = "adb logcat -d %s" %" ".join(argv[1:]) 89 | if "brief" in argv or "process" in argv or "time" in argv: 90 | while True: 91 | TAG = False 92 | lines = os.popen(command).readlines() 93 | os.popen("adb logcat -c") 94 | 95 | for line in lines: 96 | if re.search(r"beginning of", line): 97 | pass 98 | elif re.search(r"V\/.+(\d+\):)", line): 99 | color.show_verbose(line) 100 | elif re.search(r"D\/.+(\d+\):)", line): 101 | color.show_debug(line) 102 | elif re.search(r"I\/.+(\d+\):)", line): 103 | color.show_info(line) 104 | elif re.search(r"W\/.+(\d+\):)", line): 105 | color.show_warn(line) 106 | elif re.search(r"E\/.+(\d+\):)", line): 107 | color.show_error(line) 108 | elif re.search(r"F\/.+(\d+\):)", line): 109 | color.show_fatal(line) 110 | elif re.search(r"or defaults", line): 111 | color.show_info(line) 112 | TAG = True 113 | else: 114 | color.show_info(line) 115 | if TAG: 116 | break 117 | elif "thread" in argv: 118 | while True: 119 | TAG = False 120 | lines = os.popen(command).readlines() 121 | os.popen("adb logcat -c") 122 | 123 | if "invalid option" in lines[0]: 124 | for line in lines: 125 | color.show_info(line) 126 | break; 127 | 128 | for line in lines: 129 | if re.search(r"beginning of", line): 130 | pass 131 | elif re.search(r"V\(.+:.+\)", line): 132 | color.show_verbose(line) 133 | elif re.search(r"D\(.+:.+\)", line): 134 | color.show_debug(line) 135 | elif re.search(r"I\(.+:.+\)", line): 136 | color.show_info(line) 137 | elif re.search(r"W\(.+:.+\)", line): 138 | color.show_warn(line) 139 | elif re.search(r"E\(.+:.+\)", line): 140 | color.show_error(line) 141 | elif re.search(r"F\(.+:.+\)", line): 142 | color.show_fatal(line) 143 | elif re.search(r"or defaults", line): 144 | color.show_info(line) 145 | TAG = True 146 | else: 147 | color.show_info(line) 148 | if TAG: 149 | break 150 | elif "threadtime" in argv: 151 | while True: 152 | TAG = False 153 | lines = os.popen(command).readlines() 154 | os.popen("adb logcat -c") 155 | 156 | if "invalid option" in lines[0]: 157 | for line in lines: 158 | color.show_info(line) 159 | break; 160 | 161 | for line in lines: 162 | if re.search(r"beginning of", line): 163 | pass 164 | elif re.search(r"\s+V\s+", line): 165 | color.show_verbose(line) 166 | elif re.search(r"\s+D\s+", line): 167 | color.show_debug(line) 168 | elif re.search(r"\s+I\s+", line): 169 | color.show_info(line) 170 | elif re.search(r"\s+W\s+", line): 171 | color.show_warn(line) 172 | elif re.search(r"\s+E\s+", line): 173 | color.show_error(line) 174 | elif re.search(r"\s+F\s+", line): 175 | color.show_fatal(line) 176 | elif re.search(r"or defaults", line): 177 | color.show_info(line) 178 | TAG = True 179 | else: 180 | color.show_info(line) 181 | if TAG: 182 | break; 183 | elif "tag" in argv: 184 | while True: 185 | TAG = False 186 | lines = os.popen(command).readlines() 187 | os.popen("adb logcat -c") 188 | 189 | if "invalid option" in lines[0]: 190 | for line in lines: 191 | color.show_info(line) 192 | break; 193 | 194 | for line in lines: 195 | if re.search(r"beginning of", line): 196 | pass 197 | elif re.search(r"^V/\w+:", line): 198 | color.show_verbose(line) 199 | elif re.search(r"^D/\w+:", line): 200 | color.show_debug(line) 201 | elif re.search(r"^I/\w+:", line): 202 | color.show_info(line) 203 | elif re.search(r"^W/\w+:", line): 204 | color.show_warn(line) 205 | elif re.search(r"^E/\w+:", line): 206 | color.show_error(line) 207 | elif re.search(r"^F/\w+:", line): 208 | color.show_fatal(line) 209 | elif re.search(r"or defaults", line): 210 | color.show_info(line) 211 | TAG = True 212 | else: 213 | color.show_info(line) 214 | if TAG: 215 | break; 216 | else: 217 | while True: 218 | TAG = False 219 | lines = os.popen(command).readlines() 220 | os.popen("adb logcat -c") 221 | 222 | if "invalid option" in lines[0]: 223 | for line in lines: 224 | color.show_info(line) 225 | break; 226 | 227 | for line in lines: 228 | if re.search(r"beginning of", line): 229 | pass 230 | elif re.search(r"V\/.+(\d+\):)", line): 231 | color.show_verbose(line) 232 | elif re.search(r"D\/.+(\d+\):)", line): 233 | color.show_debug(line) 234 | elif re.search(r"I\/.+(\d+\):)", line): 235 | color.show_info(line) 236 | elif re.search(r"W\/.+(\d+\):)", line): 237 | color.show_warn(line) 238 | elif re.search(r"E\/.+(\d+\):)", line): 239 | color.show_error(line) 240 | elif re.search(r"F\/.+(\d+\):)", line): 241 | color.show_fatal(line) 242 | elif re.search(r"or defaults", line): 243 | color.show_info(line) 244 | TAG = True 245 | else: 246 | color.show_info(line) 247 | if TAG: 248 | break; 249 | 250 | if __name__ == "__main__": 251 | try: 252 | main(sys.argv) 253 | except: 254 | Color().reset_color() -------------------------------------------------------------------------------- /python/permission.json: -------------------------------------------------------------------------------- 1 | { 2 | "PermissList": [ 3 | { 4 | "Key": "android.permission.ACCESS_CHECKIN_PROPERTIES", 5 | "Title": "访问检入属性", 6 | "Memo": "允许对检入服务上传的属性进行读/写访问。普通应用程序不能使用此权限。", 7 | "Level": 0 8 | }, 9 | { 10 | "Key": "android.permission.ACCESS_COARSE_LOCATION", 11 | "Title": "大概位置", 12 | "Memo": "访问大概的位置源(例如蜂窝网络数据库)以确定手机的大概位置(如果可以)。恶意应用程序可借此确定您所处的大概位置。", 13 | "Level": 1 14 | }, 15 | { 16 | "Key": "android.permission.ACCESS_FINE_LOCATION", 17 | "Title": "精准的(GPS)位置", 18 | "Memo": "访问精准的位置源,例如手机上的全球定位系统(如果有)。恶意应用程序可能会借此确定您所处的位置,并可能消耗额外的电池电量。", 19 | "Level": 1 20 | }, 21 | { 22 | "Key": "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS", 23 | "Title": "访问额外的位置信息提供程序命令", 24 | "Memo": "访问额外的位置信息提供程序命令。恶意应用程序可借此干扰 GPS 或其他位置源的正常工作。", 25 | "Level": 1 26 | }, 27 | { 28 | "Key": "android.permission.ACCESS_MOCK_LOCATION", 29 | "Title": "使用模拟地点来源进行测试", 30 | "Memo": "创建模拟地点来源进行测试。恶意应用程序可能利用此选项覆盖由真实地点来源(如 GPS 或网络提供商)传回的地点和/或状态。", 31 | "Level": 1 32 | }, 33 | { 34 | "Key": "android.permission.ACCESS_NETWORK_STATE", 35 | "Title": "查看网络状态", 36 | "Memo": "允许应用程序查看所有网络的状态。", 37 | "Level": 0 38 | }, 39 | { 40 | "Key": "android.permission.ACCESS_SURFACE_FLINGER", 41 | "Title": "访问 SurfaceFlinger", 42 | "Memo": "允许应用程序使用 SurfaceFlinger 低级别功能。", 43 | "Level": 0 44 | }, 45 | { 46 | "Key": "android.permission.ACCESS_WIFI_STATE", 47 | "Title": "查看 WLAN 状态", 48 | "Memo": "允许应用程序查看有关 WLAN 状态的信息。", 49 | "Level": 0 50 | }, 51 | { 52 | "Key": "android.permission.ADD_SYSTEM_SERVICE", 53 | "Title": "系统级服务", 54 | "Memo": "允许程序发布系统级服务", 55 | "Level": 0 56 | }, 57 | { 58 | "Key": "android.permission.BATTERY_STATS", 59 | "Title": "修改电池统计信息", 60 | "Memo": "允许修改收集的电池使用情况统计信息。普通应用程序不能使用此权限。", 61 | "Level": 0 62 | }, 63 | { 64 | "Key": "android.permission.BLUETOOTH", 65 | "Title": "创建蓝牙连接", 66 | "Memo": "允许应用程序查看本地蓝牙手机的配置,以及建立或接受与配对设备的连接。", 67 | "Level": 1 68 | }, 69 | { 70 | "Key": "android.permission.BLUETOOTH_ADMIN", 71 | "Title": "蓝牙管理", 72 | "Memo": "允许应用程序配置本地蓝牙手机,以及发现远程设备并与其配对。", 73 | "Level": 0 74 | }, 75 | { 76 | "Key": "android.permission.BRICK", 77 | "Title": "永久停用手机", 78 | "Memo": "允许应用程序永久停用整个手机,这非常危险。", 79 | "Level": 2 80 | }, 81 | { 82 | "Key": "android.permission.BROADCAST_PACKAGE_REMOVED", 83 | "Title": "发送包删除的广播", 84 | "Memo": "允许应用程序广播已删除某应用程序包的通知。恶意应用程序可借此终止任何正在运行的其他应用程序。", 85 | "Level": 1 86 | }, 87 | { 88 | "Key": "android.permission.BROADCAST_STICKY", 89 | "Title": "发送置顶广播", 90 | "Memo": "允许应用程序发送顽固广播,这些广播在结束后仍会保留。恶意应用程序可能会借此使手机耗用太多内存,从而降低其速度或稳定性。", 91 | "Level": 1 92 | }, 93 | { 94 | "Key": "android.permission.CALL_PHONE", 95 | "Title": "直接拨打电话号码", 96 | "Memo": "允许应用程序在您不介入的情况下拨打电话。恶意应用程序可借此在您的话费单上产生意外通话费。请注意,此权限不允许应用程序拨打紧急呼救电话。", 97 | "Level": 2 98 | }, 99 | { 100 | "Key": "android.permission.CALL_PRIVILEGED", 101 | "Title": "直接呼叫任何电话号码", 102 | "Memo": "允许应用程序在您不介入的情况下拨打任何电话(包括紧急呼救)。恶意应用程序可借此向应急服务机构拨打骚扰电话甚至非法电话。", 103 | "Level": 2 104 | }, 105 | { 106 | "Key": "android.permission.CAMERA", 107 | "Title": "拍照", 108 | "Memo": "允许应用程序使用相机拍照,这样应用程序可随时收集进入相机镜头的图像。", 109 | "Level": 0 110 | }, 111 | { 112 | "Key": "android.permission.CHANGE_COMPONENT_ENABLED_STATE", 113 | "Title": "启用或停用应用程序组件", 114 | "Memo": "允许应用程序更改是否启用其他应用程序的组件。恶意应用程序可借此停用重要的手机功能。使用此权限时务必谨慎,因为这可能导致应用程序组件进入不可用、不一致或不稳定的状态。", 115 | "Level": 1 116 | }, 117 | { 118 | "Key": "android.permission.CHANGE_CONFIGURATION", 119 | "Title": "更改用户界面设置", 120 | "Memo": "允许应用程序更改当前配置,例如语言设置或整体的字体大小。", 121 | "Level": 0 122 | }, 123 | { 124 | "Key": "android.permission.CHANGE_NETWORK_STATE", 125 | "Title": "更改网络连接性", 126 | "Memo": "允许应用程序更改网络连接的状态。", 127 | "Level": 0 128 | }, 129 | { 130 | "Key": "android.permission.CHANGE_WIFI_STATE", 131 | "Title": "更改 WLAN 状态", 132 | "Memo": "允许应用程序连接到 WLAN 接入点以及与 WLAN 接入点断开连接,并对配置的 WLAN 网络进行更改。", 133 | "Level": 0 134 | }, 135 | { 136 | "Key": "android.permission.CLEAR_APP_CACHE", 137 | "Title": "删除所有应用程序缓存数据", 138 | "Memo": "允许应用程序通过删除应用程序缓存目录中的文件释放手机存储空间。通常此权限只适用于系统进程。", 139 | "Level": 0 140 | }, 141 | { 142 | "Key": "android.permission.CLEAR_APP_USER_DATA", 143 | "Title": "删除其他应用程序的数据", 144 | "Memo": "允许应用程序清除用户数据。", 145 | "Level": 1 146 | }, 147 | { 148 | "Key": "android.permission.CONTROL_LOCATION_UPDATES", 149 | "Title": "控制位置更新通知", 150 | "Memo": "允许启用/停用来自收音机的位置更新通知。普通应用程序不能使用此权限。", 151 | "Level": 0 152 | }, 153 | { 154 | "Key": "android.permission.DELETE_CACHE_FILES", 155 | "Title": "删除其他应用程序的缓存", 156 | "Memo": "允许应用程序删除缓存文件。", 157 | "Level": 0 158 | }, 159 | { 160 | "Key": "android.permission.DELETE_PACKAGES", 161 | "Title": "删除应用程序", 162 | "Memo": "允许应用程序删除 Android 包。恶意应用程序可借此删除重要的应用程序。", 163 | "Level": 0 164 | }, 165 | { 166 | "Key": "android.permission.DEVICE_POWER", 167 | "Title": "开机或关机", 168 | "Memo": "允许应用程序打开或关闭手机。", 169 | "Level": 0 170 | }, 171 | { 172 | "Key": "android.permission.DIAGNOSTIC", 173 | "Title": "读取/写入诊断所拥有的资源", 174 | "Memo": "允许应用程序读取/写入诊断组所拥有的任何资源(例如,/dev 中的文件)。这可能会影响系统稳定性和安全性。此权限仅供制造商或运营商诊断硬件问题。", 175 | "Level": 2 176 | }, 177 | { 178 | "Key": "android.permission.DISABLE_KEYGUARD", 179 | "Title": "停用键锁", 180 | "Memo": "允许应用程序停用键锁和任何关联的密码安全设置。例如,在手机上接听电话时停用键锁,在通话结束后重新启用键锁。", 181 | "Level": 0 182 | }, 183 | { 184 | "Key": "android.permission.DUMP", 185 | "Title": "检索系统内部状态", 186 | "Memo": "允许应用程序检索系统的内部状态。恶意应用程序可借此检索它们本不需要的各种保密信息和安全信息。", 187 | "Level": 0 188 | }, 189 | { 190 | "Key": "android.permission.EXPAND_STATUS_BAR", 191 | "Title": "展开/收拢状态栏", 192 | "Memo": "允许应用程序展开或收拢状态栏。", 193 | "Level": 0 194 | }, 195 | { 196 | "Key": "android.permission.FACTORY_TEST", 197 | "Title": "在出厂测试模式下运行", 198 | "Memo": "作为一项低级制造商测试来运行,从而允许对手机硬件进行完全访问。此权限仅当手机在制造商测试模式下运行时才可用。", 199 | "Level": 0 200 | }, 201 | { 202 | "Key": "android.permission.FLASHLIGHT", 203 | "Title": "控制闪光灯", 204 | "Memo": "允许应用程序控制闪光灯。", 205 | "Level": 0 206 | }, 207 | { 208 | "Key": "android.permission.FORCE_BACK", 209 | "Title": "强制应用程序关闭", 210 | "Memo": "允许应用程序强制前端的任何活动关闭并重新开始。普通应用程序从不需要使用此权限。", 211 | "Level": 0 212 | }, 213 | { 214 | "Key": "android.permission.FOTA_UPDATE", 215 | "Title": "系统升级", 216 | "Memo": "运行应用程序使用空中升级系统", 217 | "Level": 0 218 | }, 219 | { 220 | "Key": "android.permission.GET_ACCOUNTS", 221 | "Title": "发现已知帐户", 222 | "Memo": "允许应用程序获取手机已知的帐户列表。", 223 | "Level": 0 224 | }, 225 | { 226 | "Key": "android.permission.GET_PACKAGE_SIZE", 227 | "Title": "计算应用程序存储空间", 228 | "Memo": "允许应用程序检索其代码、数据和缓存大小", 229 | "Level": 0 230 | }, 231 | { 232 | "Key": "android.permission.GET_TASKS", 233 | "Title": "检索当前运行的应用程序", 234 | "Memo": "允许应用程序检索有关当前和最近运行的任务的信息。恶意应用程序可借此发现有关其他应用程序的保密信息。", 235 | "Level": 1 236 | }, 237 | { 238 | "Key": "android.permission.HARDWARE_TEST", 239 | "Title": "测试硬件", 240 | "Memo": "允许应用程序控制各外围设备以进行硬件测试。", 241 | "Level": 0 242 | }, 243 | { 244 | "Key": "android.permission.INJECT_EVENTS", 245 | "Title": "按键和控制按钮", 246 | "Memo": "允许应用程序将其自己的输入活动(按键等)提供给其他应用程序。恶意应用程序可借此掌控手机。", 247 | "Level": 2 248 | }, 249 | { 250 | "Key": "android.permission.INSTALL_PACKAGES", 251 | "Title": "直接安装应用程序", 252 | "Memo": "允许应用程序安装全新的或更新的 Android 包。恶意应用程序可能会借此添加其具有任意权限的新应用程序。", 253 | "Level": 1 254 | }, 255 | { 256 | "Key": "android.permission.INTERNAL_SYSTEM_WINDOW", 257 | "Title": "显示未授权的窗口", 258 | "Memo": "允许创建专用于内部系统用户界面的窗口。普通应用程序不能使用此权限。", 259 | "Level": 0 260 | }, 261 | { 262 | "Key": "android.permission.INTERNET", 263 | "Title": "访问网络", 264 | "Memo": "允许程序访问网络.", 265 | "Level": 0 266 | }, 267 | { 268 | "Key": "android.permission.MANAGE_APP_TOKENS", 269 | "Title": "管理应用程序令牌", 270 | "Memo": "允许应用程序创建和管理自己的令牌,从而绕开其常规的 Z 方向。普通应用程序从不需要使用此权限。", 271 | "Level": 0 272 | }, 273 | { 274 | "Key": "android.permission.MASTER_CLEAR", 275 | "Title": "恢复出厂设置", 276 | "Memo": "允许应用程序将系统恢复为出厂设置,即清除所有数据、配置以及所安装的应用程序。", 277 | "Level": 2 278 | }, 279 | { 280 | "Key": "android.permission.MODIFY_AUDIO_SETTINGS", 281 | "Title": "更改您的音频设置", 282 | "Memo": "允许应用程序修改整个系统的音频设置,如音量和路由。", 283 | "Level": 0 284 | }, 285 | { 286 | "Key": "android.permission.MODIFY_PHONE_STATE", 287 | "Title": "修改手机状态", 288 | "Memo": "允许应用程序控制设备的电话功能。拥有此权限的应用程序可自行切换网络、打开和关闭无线通信等,而不会通知您。", 289 | "Level": 1 290 | }, 291 | { 292 | "Key": "android.permission.MOUNT_UNMOUNT_FILESYSTEMS", 293 | "Title": "装载和卸载文件系统", 294 | "Memo": "允许应用程序装载和卸载可移动存储器的文件系统。", 295 | "Level": 0 296 | }, 297 | { 298 | "Key": "android.permission.PERSISTENT_ACTIVITY", 299 | "Title": "让应用程序始终运行", 300 | "Memo": "允许应用程序部分持续运行,这样系统便不能将其用于其他应用程序。", 301 | "Level": 0 302 | }, 303 | { 304 | "Key": "android.permission.PROCESS_OUTGOING_CALLS", 305 | "Title": "拦截外拨电话", 306 | "Memo": "允许应用程序处理外拨电话或更改要拨打的号码。恶意应用程序可能会借此监视、另行转接甚至阻止外拨电话。", 307 | "Level": 2 308 | }, 309 | { 310 | "Key": "android.permission.READ_CALENDAR", 311 | "Title": "读取日历活动", 312 | "Memo": "允许应用程序读取您手机上存储的所有日历活动。恶意应用程序可借此将您的日历活动发送给其他人。", 313 | "Level": 1 314 | }, 315 | { 316 | "Key": "android.permission.READ_CONTACTS", 317 | "Title": "读取联系人数据", 318 | "Memo": "允许应用程序读取您手机上存储的所有联系人(地址)数据。恶意应用程序可借此将您的数据发送给其他人。", 319 | "Level": 1 320 | }, 321 | { 322 | "Key": "android.permission.READ_FRAME_BUFFER", 323 | "Title": "读取帧缓冲区", 324 | "Memo": "允许应用程序读取帧缓冲区中的内容,比如抓屏程序.", 325 | "Level": 0 326 | }, 327 | { 328 | "Key": "android.permission.READ_INPUT_STATE", 329 | "Title": "记录您键入的内容和执行的操作", 330 | "Memo": "允许应用程序查看您按的键,即使在与其他应用程序交互(例如输入密码)时也不例外。普通应用程序从不需要使用此权限。", 331 | "Level": 2 332 | }, 333 | { 334 | "Key": "android.permission.READ_LOGS", 335 | "Title": "读取系统日志文件", 336 | "Memo": "允许应用程序从系统的各日志文件中读取信息。这样应用程序可以发现您的手机使用情况,但这些信息不应包含任何个人信息或保密信息。", 337 | "Level": 0 338 | }, 339 | { 340 | "Key": "android.permission.READ_OWNER_DATA", 341 | "Title": "读取所有者数据", 342 | "Memo": "允许应用程序读取您手机上存储的手机所有者数据。恶意应用程序可借此读取手机所有者数据。", 343 | "Level": 1 344 | }, 345 | { 346 | "Key": "android.permission.READ_SMS", 347 | "Title": "读取短信或彩信", 348 | "Memo": "允许应用程序读取您的手机或 SIM 卡中存储的短信。恶意应用程序可借此读取您的机密信息。", 349 | "Level": 2 350 | }, 351 | { 352 | "Key": "android.permission.READ_SYNC_SETTINGS", 353 | "Title": "读取同步设置", 354 | "Memo": "允许应用程序读取同步设置,例如是否为(联系人)启用同步。", 355 | "Level": 0 356 | }, 357 | { 358 | "Key": "android.permission.READ_SYNC_STATS", 359 | "Title": "读取同步统计信息", 360 | "Memo": "允许应用程序读取同步统计信息;例如已发生的同步历史记录。", 361 | "Level": 0 362 | }, 363 | { 364 | "Key": "android.permission.REBOOT", 365 | "Title": "强行重新启动手机", 366 | "Memo": "允许应用程序强行重新启动手机。", 367 | "Level": 1 368 | }, 369 | { 370 | "Key": "android.permission.RECEIVE_BOOT_COMPLETED", 371 | "Title": "开机时自动启动", 372 | "Memo": "允许应用程序在系统完成启动后即自行启动。这样会延长手机的启动时间,而且如果应用程序一直运行,会降低手机的整体速度。", 373 | "Level": 1 374 | }, 375 | { 376 | "Key": "android.permission.RECEIVE_MMS", 377 | "Title": "接收彩信", 378 | "Memo": "允许应用程序接收和处理彩信。恶意应用程序可借此监视您的信息,或者将信息删除而不向您显示。", 379 | "Level": 1 380 | }, 381 | { 382 | "Key": "android.permission.RECEIVE_SMS", 383 | "Title": "接收短信", 384 | "Memo": "允许应用程序接收和处理短信。恶意应用程序可借此监视您的信息,或者将信息删除而不向您显示。", 385 | "Level": 1 386 | }, 387 | { 388 | "Key": "android.permission.RECEIVE_WAP_PUSH", 389 | "Title": "接收 WAP", 390 | "Memo": "允许应用程序接收和处理 WAP 信息。恶意应用程序可借此监视您的信息,或者将信息删除而不向您显示。", 391 | "Level": 1 392 | }, 393 | { 394 | "Key": "android.permission.RECORD_AUDIO", 395 | "Title": "录音", 396 | "Memo": "允许应用程序访问录音路径。", 397 | "Level": 1 398 | }, 399 | { 400 | "Key": "android.permission.REORDER_TASKS", 401 | "Title": "对正在运行的应用程序重新排序", 402 | "Memo": "允许应用程序将任务移至前端和后台。恶意应用程序可借此强行进入前端,而不受您的控制。", 403 | "Level": 1 404 | }, 405 | { 406 | "Key": "android.permission.RESTART_PACKAGES", 407 | "Title": "重启程序", 408 | "Memo": "允许程序自己重启或重启其他程序", 409 | "Level": 0 410 | }, 411 | { 412 | "Key": "android.permission.SEND_SMS", 413 | "Title": "发送短信", 414 | "Memo": "允许应用程序发送短信。恶意应用程序可能会不经您的确认就发送信息,给您带来费用。", 415 | "Level": 2 416 | }, 417 | { 418 | "Key": "android.permission.SET_ACTIVITY_WATCHER", 419 | "Title": "监控所有应用程序的启动", 420 | "Memo": "允许应用程序监控系统启动活动的方式。恶意应用程序可借此彻底损坏系统。此权限仅在开发时才需要,普通的手机应用不需要。", 421 | "Level": 1 422 | }, 423 | { 424 | "Key": "android.permission.SET_ALWAYS_FINISH", 425 | "Title": "关闭所有后台应用程序", 426 | "Memo": "允许应用程序控制活动是否始终是一转至后台就完成。普通应用程序从不需要使用此权限。", 427 | "Level": 0 428 | }, 429 | { 430 | "Key": "android.permission.SET_ANIMATION_SCALE", 431 | "Title": "修改全局动画速度", 432 | "Memo": "允许应用程序随时更改全局动画速度(加快或放慢动画)。", 433 | "Level": 0 434 | }, 435 | { 436 | "Key": "android.permission.SET_DEBUG_APP", 437 | "Title": "启用应用程序调试", 438 | "Memo": "允许应用程序启动对其他应用程序的调试。恶意应用程序可借此终止其他应用程序。", 439 | "Level": 1 440 | }, 441 | { 442 | "Key": "android.permission.SET_ORIENTATION", 443 | "Title": "更改屏幕显示方向", 444 | "Memo": "允许应用程序随时更改屏幕的旋转方向。普通应用程序从不需要使用此权限。", 445 | "Level": 0 446 | }, 447 | { 448 | "Key": "android.permission.SET_PREFERRED_APPLICATIONS", 449 | "Title": "设置首选应用程序", 450 | "Memo": "允许应用程序修改首选的应用程序。这样恶意应用程序可能会暗中更改运行的应用程序,从而骗过您的现有应用程序来收集您的保密数据。", 451 | "Level": 1 452 | }, 453 | { 454 | "Key": "android.permission.SET_PROCESS_FOREGROUND", 455 | "Title": "强制前台运行", 456 | "Memo": "允许程序强制前台运行", 457 | "Level": 0 458 | }, 459 | { 460 | "Key": "android.permission.SET_PROCESS_LIMIT", 461 | "Title": "限制运行的进程个数", 462 | "Memo": "允许应用程序控制将运行的进程数上限。普通应用程序从不需要使用此权限。", 463 | "Level": 0 464 | }, 465 | { 466 | "Key": "android.permission.SET_TIME_ZONE", 467 | "Title": "设置时区", 468 | "Memo": "允许应用程序更改手机的时区。", 469 | "Level": 0 470 | }, 471 | { 472 | "Key": "android.permission.SET_WALLPAPER", 473 | "Title": "设置壁纸", 474 | "Memo": "允许应用程序设置系统壁纸。", 475 | "Level": 0 476 | }, 477 | { 478 | "Key": "android.permission.SET_WALLPAPER_HINTS", 479 | "Title": "设置壁纸大小提示", 480 | "Memo": "允许应用程序设置有关壁纸大小的提示。", 481 | "Level": 0 482 | }, 483 | { 484 | "Key": "android.permission.SIGNAL_PERSISTENT_PROCESSES", 485 | "Title": "向应用程序发送 Linux 信号", 486 | "Memo": "允许应用程序请求将所提供的信号发送给所有持久进程。", 487 | "Level": 0 488 | }, 489 | { 490 | "Key": "android.permission.STATUS_BAR", 491 | "Title": "停用或修改状态栏", 492 | "Memo": "允许应用程序停用状态栏或者增删系统图标。", 493 | "Level": 0 494 | }, 495 | { 496 | "Key": "android.permission.SUBSCRIBED_FEEDS_READ", 497 | "Title": "读取订阅的供稿", 498 | "Memo": "允许应用程序获取有关当前同步的供稿的详细信息。", 499 | "Level": 0 500 | }, 501 | { 502 | "Key": "android.permission.SUBSCRIBED_FEEDS_WRITE", 503 | "Title": "写入订阅的供稿", 504 | "Memo": "允许应用程序修改您当前同步的供稿。恶意应用程序可借此更改您同步的供稿。", 505 | "Level": 1 506 | }, 507 | { 508 | "Key": "android.permission.SYSTEM_ALERT_WINDOW", 509 | "Title": "显示系统级警报", 510 | "Memo": "允许应用程序显示系统警报窗口。恶意应用程序可借此掌控整个手机屏幕。", 511 | "Level": 1 512 | }, 513 | { 514 | "Key": "android.permission.VIBRATE", 515 | "Title": "控制振动器", 516 | "Memo": "允许应用程序控制振动器。", 517 | "Level": 0 518 | }, 519 | { 520 | "Key": "android.permission.WAKE_LOCK", 521 | "Title": "防止手机休眠", 522 | "Memo": "允许应用程序防止手机进入休眠状态。", 523 | "Level": 0 524 | }, 525 | { 526 | "Key": "android.permission.WRITE_APN_SETTINGS", 527 | "Title": "写入(接入点名称)设置", 528 | "Memo": "允许应用程序修改 APN 设置,例如任何 APN 的代理和端口。", 529 | "Level": 0 530 | }, 531 | { 532 | "Key": "android.permission.WRITE_CALENDAR", 533 | "Title": "添加或修改日历活动以及向邀请对象发送电子邮件", 534 | "Memo": "允许应用程序添加或更改日历中的活动,这可能会向邀请对象发送电子邮件。恶意应用程序可能会借此清除或修改您的日历活动,或者向邀请对象发送电子邮件。", 535 | "Level": 1 536 | }, 537 | { 538 | "Key": "android.permission.WRITE_CONTACTS", 539 | "Title": "写入联系数据", 540 | "Memo": "允许应用程序修改您手机上存储的联系人(地址)数据。恶意应用程序可借此清除或修改您的联系人数据。", 541 | "Level": 1 542 | }, 543 | { 544 | "Key": "android.permission.WRITE_GSERVICES", 545 | "Title": "修改 Google 地图", 546 | "Memo": "允许应用程序修改 Google 服务地图。普通应用程序不能使用此权限。", 547 | "Level": 0 548 | }, 549 | { 550 | "Key": "android.permission.WRITE_OWNER_DATA", 551 | "Title": "写入所有者数据", 552 | "Memo": "允许应用程序修改您手机上存储的手机所有者数据。恶意应用程序可借此清除或修改所有者数据。", 553 | "Level": 1 554 | }, 555 | { 556 | "Key": "android.permission.WRITE_SETTINGS", 557 | "Title": "修改全局系统设置", 558 | "Memo": "允许应用程序修改系统设置方面的数据。恶意应用程序可借此破坏您的系统配置。", 559 | "Level": 1 560 | }, 561 | { 562 | "Key": "android.permission.WRITE_SMS", 563 | "Title": "编辑短信或彩信", 564 | "Memo": "允许应用程序写入手机或 SIM 卡中存储的短信。恶意应用程序可借此删除您的信息。", 565 | "Level": 1 566 | }, 567 | { 568 | "Key": "android.permission.WRITE_SYNC_SETTINGS", 569 | "Title": "写入同步设置", 570 | "Memo": "允许应用程序修改同步设置,例如是否为(联系人)启用同步。", 571 | "Level": 1 572 | }, 573 | { 574 | "Key": "android.permission.ACCESS_CACHE_FILESYSTEM", 575 | "Title": "访问缓存文件系统", 576 | "Memo": "允许应用程序读取和写入缓存文件系统。", 577 | "Level": 0 578 | }, 579 | { 580 | "Key": "android.permission.ACCOUNT_MANAGER", 581 | "Title": "作为帐户身份验证程序", 582 | "Memo": "允许应用程序使用 AccountManager 的帐户身份验证程序功能,包括创建帐户以及获取和设置其密码。", 583 | "Level": 0 584 | }, 585 | { 586 | "Key": "android.permission.ASEC_ACCESS", 587 | "Title": "获取有关安全存储的信息", 588 | "Memo": "允许应用程序获取有关安全存储的信息。", 589 | "Level": 0 590 | }, 591 | { 592 | "Key": "android.permission.ASEC_CREATE", 593 | "Title": "创建安全存储", 594 | "Memo": "允许应用程序创建安全存储。", 595 | "Level": 0 596 | }, 597 | { 598 | "Key": "android.permission.ASEC_DESTROY", 599 | "Title": "清除安全存储", 600 | "Memo": "允许应用程序清除安全存储。", 601 | "Level": 0 602 | }, 603 | { 604 | "Key": "android.permission.ASEC_MOUNT_UNMOUNT", 605 | "Title": "安装/卸载安全存储", 606 | "Memo": "允许应用程序安装/卸载安全存储。", 607 | "Level": 0 608 | }, 609 | { 610 | "Key": "android.permission.ASEC_RENAME", 611 | "Title": "重命名安全存储", 612 | "Memo": "允许应用程序重命名安全存储。", 613 | "Level": 0 614 | }, 615 | { 616 | "Key": "android.permission.AUTHENTICATE_ACCOUNTS", 617 | "Title": "作为帐户身份验证程序", 618 | "Memo": "允许应用程序使用 AccountManager 的帐户身份验证程序功能,包括创建帐户以及获取和设置其密码。", 619 | "Level": 0 620 | }, 621 | { 622 | "Key": "android.permission.BACKUP", 623 | "Title": "控制系统备份和还原", 624 | "Memo": "允许应用程序控制系统的备份和还原机制。普通应用程序不能使用此权限。", 625 | "Level": 0 626 | }, 627 | { 628 | "Key": "android.permission.BIND_APPWIDGET", 629 | "Title": "选择窗口小部件", 630 | "Memo": "允许应用程序告诉系统哪个应用程序可以使用哪些窗口小部件。具有该权限的应用程序可以允许其他应用程序访问个人数据。普通应用程序不能使用此权限。", 631 | "Level": 0 632 | }, 633 | { 634 | "Key": "android.permission.BIND_DEVICE_ADMIN", 635 | "Title": "与设备管理器交互", 636 | "Memo": "允许持有对象将意向发送到设备管理器。普通的应用程序一律无需此权限。", 637 | "Level": 0 638 | }, 639 | { 640 | "Key": "android.permission.BIND_INPUT_METHOD", 641 | "Title": "绑定至输入法", 642 | "Memo": "允许手机用户绑定至输入法的顶级界面。普通应用程序从不需要使用此权限。", 643 | "Level": 0 644 | }, 645 | { 646 | "Key": "android.permission.BIND_WALLPAPER", 647 | "Title": "绑定到壁纸", 648 | "Memo": "允许手机用户绑定到壁纸的顶级界面。应该从不需要将此权限授予普通应用程序。", 649 | "Level": 0 650 | }, 651 | { 652 | "Key": "android.permission.BROADCAST_SMS", 653 | "Title": "发送短信收到的广播", 654 | "Memo": "允许应用程序广播已收到短信的通知。恶意应用程序可借此伪造收到的短信。", 655 | "Level": 1 656 | }, 657 | { 658 | "Key": "android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE", 659 | "Title": "C2DM权限(云端)", 660 | "Memo": "C2DM允许第三方开发者开发相关的应用来推送少量数据消息到用户的手机上。", 661 | "Level": 1 662 | }, 663 | { 664 | "Key": "android.permission.CHANGE_BACKGROUND_DATA_SETTING", 665 | "Title": "更改背景数据使用设置", 666 | "Memo": "允许应用程序更改背景数据使用设置。", 667 | "Level": 0 668 | }, 669 | { 670 | "Key": "android.permission.CHANGE_WIFI_MULTICAST_STATE", 671 | "Title": "允许接收WLAN多播", 672 | "Memo": "允许应用程序接收并非直接向您的设备发送的数据包。这样在查找附近提供的服务时很有用。这种操作所耗电量大于非多播模式。", 673 | "Level": 1 674 | }, 675 | { 676 | "Key": "android.permission.COPY_PROTECTED_DATA", 677 | "Title": "复制保护数据", 678 | "Memo": "允许调用默认的容器服务复制内容。不适用于普通应用程序使用。", 679 | "Level": 1 680 | }, 681 | { 682 | "Key": "android.permission.FORCE_STOP_PACKAGES", 683 | "Title": "强行停止其他应用程序", 684 | "Memo": "允许应用程序强行停止其他应用程序。", 685 | "Level": 0 686 | }, 687 | { 688 | "Key": "android.permission.GLOBAL_SEARCH", 689 | "Title": "全局搜索", 690 | "Memo": "允许应用程序使用全局搜索。", 691 | "Level": 0 692 | }, 693 | { 694 | "Key": "android.permission.GLOBAL_SEARCH_CONTROL", 695 | "Title": "全局搜索控制", 696 | "Memo": "允许应用程序控制全局搜索。", 697 | "Level": 0 698 | }, 699 | { 700 | "Key": "android.permission.INSTALL_LOCATION_PROVIDER", 701 | "Title": "允许安装位置信息提供程序", 702 | "Memo": "创建模拟地点来源进行测试。恶意应用程序可能利用此选项覆盖由真实地点来源(如 GPS 或网络提供商)所传回的地点和/或状态,或者监视您的位置并将其提供给外部来源。", 703 | "Level": 1 704 | }, 705 | { 706 | "Key": "android.permission.KILL_BACKGROUND_PROCESSES", 707 | "Title": "结束后台进程", 708 | "Memo": "无论内存资源是否紧张,都允许应用程序结束其他应用程序的后台进程。", 709 | "Level": 0 710 | }, 711 | { 712 | "Key": "android.permission.LEDS", 713 | "Title": "控制键盘灯", 714 | "Memo": "允许应用程序控制键盘灯。", 715 | "Level": 0 716 | }, 717 | { 718 | "Key": "android.permission.MANAGE_ACCOUNTS", 719 | "Title": "管理帐户列表", 720 | "Memo": "允许应用程序执行添加、删除帐户及删除其密码之类的操作。", 721 | "Level": 0 722 | }, 723 | { 724 | "Key": "android.permission.MEIZU_SYS_PHONE_FUNC", 725 | "Title": "魅族手机系统程序", 726 | "Memo": "魅族手机系统程序。不做解释.", 727 | "Level": 0 728 | }, 729 | { 730 | "Key": "android.permission.MOUNT_FORMAT_FILESYSTEMS", 731 | "Title": "格式化外部存储设备", 732 | "Memo": "允许应用程序格式化可移除的存储设备。", 733 | "Level": 2 734 | }, 735 | { 736 | "Key": "android.permission.MOVE_PACKAGE", 737 | "Title": "移动应用程序资源", 738 | "Memo": "允许应用程序在内部介质和外部介质之间移动应用程序资源。", 739 | "Level": 0 740 | }, 741 | { 742 | "Key": "android.permission.PACKAGE_USAGE_STATS", 743 | "Title": "更新组件使用统计", 744 | "Memo": "允许使用统计资料的收集组件修改。普通应用程序不适合使用。", 745 | "Level": 0 746 | }, 747 | { 748 | "Key": "android.permission.PERFORM_CDMA_PROVISIONING", 749 | "Title": "直接启动CDMA电话设置", 750 | "Memo": "允许应用程序启动 CDMA 服务。恶意应用程序可能会无端启动 CDMA 服务", 751 | "Level": 1 752 | }, 753 | { 754 | "Key": "android.permission.READ_CONTACTS_SUPER", 755 | "Title": "读取联系人", 756 | "Memo": "允许应用程序读取联系人数据(超级权限).", 757 | "Level": 2 758 | }, 759 | { 760 | "Key": "android.permission.READ_HISTORY_BOOKMARKS", 761 | "Title": "读取历史记录", 762 | "Memo": "允许应用程序读取浏览器历史记录.", 763 | "Level": 1 764 | }, 765 | { 766 | "Key": "android.permission.READ_PHONE_STATE", 767 | "Title": "读取手机状态和身份", 768 | "Memo": "允许应用程序访问设备的手机功能。有此权限的应用程序可确定此手机的号码和序列号,是否正在通话,以及对方的号码等。", 769 | "Level": 1 770 | }, 771 | { 772 | "Key": "android.permission.READ_USER_DICTIONARY", 773 | "Title": "读取用户定义的词典", 774 | "Memo": "允许应用程序读取用户在用户词典中存储的任意私有字词、名称和短语。", 775 | "Level": 0 776 | }, 777 | { 778 | "Key": "android.permission.SET_TIME", 779 | "Title": "设置时间", 780 | "Memo": "允许应用程序更改手机的时间。", 781 | "Level": 0 782 | }, 783 | { 784 | "Key": "android.permission.SET_WALLPAPER_COMPONENT", 785 | "Title": "设置壁纸组件", 786 | "Memo": "允许应用程序设置壁纸组件。", 787 | "Level": 0 788 | }, 789 | { 790 | "Key": "android.permission.SHUTDOWN", 791 | "Title": "部分关机", 792 | "Memo": "使活动管理器进入关闭状态。不执行彻底关机。", 793 | "Level": 0 794 | }, 795 | { 796 | "Key": "android.permission.STOP_APP_SWITCHES", 797 | "Title": "禁止切换应用程序", 798 | "Memo": "禁止用户切换到另一应用程序。", 799 | "Level": 0 800 | }, 801 | { 802 | "Key": "android.permission.UPDATE_DEVICE_STATS", 803 | "Title": "更新设备状态", 804 | "Memo": "允许应用程序更新设备状态。", 805 | "Level": 0 806 | }, 807 | { 808 | "Key": "android.permission.USE_CREDENTIALS", 809 | "Title": "使用帐户的身份验证凭据", 810 | "Memo": "允许应用程序请求身份验证标记。", 811 | "Level": 0 812 | }, 813 | { 814 | "Key": "android.permission.WRITE_CONTACTS_SUPER", 815 | "Title": "写入联系人数据", 816 | "Memo": "允许应用程序写入联系人数据(超级权限)。", 817 | "Level": 0 818 | }, 819 | { 820 | "Key": "android.permission.WRITE_EXTERNAL_STORAGE", 821 | "Title": "修改/删除SD卡中的内容", 822 | "Memo": "允许应用程序写入SD卡。", 823 | "Level": 0 824 | }, 825 | { 826 | "Key": "com.android.browser.permission.WRITE_HISTORY_BOOKMARKS", 827 | "Title": "写入浏览器历史和书签记录", 828 | "Memo": "允许应用程序写入浏览器历史和书签记录。", 829 | "Level": 0 830 | }, 831 | { 832 | "Key": "android.permission.WRITE_SECURE_SETTINGS", 833 | "Title": "修改安全系统设置", 834 | "Memo": "允许应用程序修改系统的安全设置数据。普通应用程序不能使用此权限。", 835 | "Level": 1 836 | }, 837 | { 838 | "Key": "android.permission.WRITE_USER_DICTIONARY", 839 | "Title": "写入用户定义的词典", 840 | "Memo": "允许应用程序向用户词典中写入新词。", 841 | "Level": 1 842 | } 843 | ] 844 | } --------------------------------------------------------------------------------