# -*- coding: UTF-8 -*-
"""/*
V1.0 check
V1.1 增加一个写入txt文件可以查看log
V1.2 屏蔽cat /proc/ufs_debug | grep gear',#MTK cat /d/mmc0/err_state',#emmc 返回0 正常这个两个节点,会导致报错。
v1.3 项目-verify记录适配QCOM MTK UFS EMMC
V1.4 增加MV获取健壮性get_storage中查找。
v1.5 确认增加emmc cmd
V1.6 更改MIUI cmd aidl CLD上层不支持sm指令,只有service
V1.7 更改MIUI cmd service CLD "ps"命令改小写,大写不生效,out file 中factorybuild 添加MIUI字段
V1.8 添加展锐平台配置命令
*/"""
import os, re
import time
import threading
import subprocess
import string
import traceback
from dataclasses import dataclass
from typing import Optional
dir=os.path.dirname(os.path.abspath(__file__))
@dataclass
class Materiel:
vendor: Optional[str] = None # char* → Python 字符串(可为空)
size: Optional[str] = None
# 定义嵌套结构体 memory
@dataclass
class Memory:
DDR: Materiel = Materiel() # 嵌套 Materiel 结构体
Storage: Materiel = Materiel()
match_memory = {
#DDR厂商
'0x01' : 'SAMSUNG',
'0x06' : 'SKHYNIX',
'0xff' : 'MICRON',
'0x13' : 'CXMT',
# UFS厂商
'0x012c': 'MICRON',
'0x01ce': 'SAMSUNG',
'0x01ad': 'SKHYNIX',
'0x0a9b': 'YMTC',
'0x0a6b': 'HOSIN',
'0x0cd6': 'HOSIN',
'0x0f86': 'YMTC',
# EMMC厂商
'0x0002': 'SANDISK',
'0x0045': 'SANDISK',
'0x0011': 'TOSHIBA',
'0x0013': 'MICRON',
'0x0015': 'SAMSUNG',
'0x0070': 'KINGSTON',
'0x0090': 'HYNIX',
'0x009b': 'YMTC',
'0x0086': 'YMTC_XB',
'0x00d6': 'HOSIN'
}
def get_storage(ret_mv):
for i in range(ret_mv.count(" ")):
if "D:" in ret_mv.split()[i]:
DDR_VX = ret_mv.split()[i+1]
DDR_S = ret_mv.split()[i+2]
if "U:" in ret_mv.split()[i]:
Sto_VX = ret_mv.split()[i+1]
Sto_S = ret_mv.split()[i+2]
break
elif "E:" in ret_mv.split()[i]:
Sto_VX = ret_mv.split()[i+1]
Sto_S = ret_mv.split()[i+2]
break
i += 1
DDR_NAME = match_memory[DDR_VX]
Sto_NAME = match_memory[Sto_VX]
ddr_chip = Materiel(vendor=DDR_NAME,size=DDR_S)
storage_chip = Materiel(vendor=Sto_NAME,size=Sto_S)
sys_memory = Memory(
DDR = ddr_chip,
Storage = storage_chip
)
return sys_memory
class mythread(threading.Thread):
global General
global fac_cmd
global UFS_cmd
global EMMC_cmd
global QCOM_cmd
global MTK_cmd
global SPRD_cmd
global miui_cmd
global py_v
global test_cmd
py_v = "V1.7"
def _safe_adb_command(self, command: str) -> str:
"""安全执行 ADB 命令并返回结果"""
try:
print(command)
result = subprocess.run(
["adb", "-s", self.threadid, "shell", command],
# check=True,
capture_output=True,
text=True
)
return result.stdout.strip() + result.stderr.strip()
except subprocess.CalledProcessError as e:
raise RuntimeError(f"ADB 命令失败: {command}\n错误: {e.stderr}") from e
General = [
' cat proc/mv',
' ls -al /dev/block/by-name/mem',# mem分区的大小是4M
' ls -al /dev/block/by-name/ffu',# ffu分区的大小是8M
' ls -al /dev/block/by-name/gsort',# gsort分区的大小是16M
' find /sys/devices/ -name clkgate_enable', #MTK QCOM 返回1 pass
' find /sys/devices/platform/ -name wb_enable',
' find /sys/devices/platform/ -name enable_wb',
' find /sys/devices/platform/ -name enable_tw',
' find /sys/devices/platform/ -name tw_enable',#wb 功能检查 返回路径再cat cat返回1或ture 则pass
' find /sys/devices/ -name wb_avail_buf',
' find /sys/devices/ -name wb_cur_buf',
' find /sys/devices/ -name wb_flush_status',
' find /sys/devices/ -name wb_life_time_est',
# ' dmesg | grep ffu',
]
UFS_cmd = [
' ls -lZ /sys/class/mi_memory/mi_memory_device/ufshcd0',
' cat /sys/class/mi_memory/mi_memory_device/ufshcd0/dump_device_desc', #ufshcd0 中有7个节点 1
' cat /sys/class/mi_memory/mi_memory_device/ufshcd0/dump_health_desc', #ufshcd0 中有7个节点 2
' cat /sys/class/mi_memory/mi_memory_device/ufshcd0/dump_string_desc_serial', #ufshcd0 中有7个节点 3
' cat /sys/class/mi_memory/mi_memory_device/ufshcd0/hr', #ufshcd0 中有7个节点 4
' cat /sys/class/mi_memory/mi_memory_device/ufshcd0/show_hba',# 返回的值中检查pa_err_cnt_total、dl_err_cnt_total和dme_err_cnt都为0 ufshcd0 中有7个节点 5
' cat /sys/class/mi_memory/mi_memory_device/ufshcd0/err_state',#ufs 返回0 正常 ufshcd0 中有7个节点 6
' cat /sys/class/mi_memory/mi_memory_device/ufshcd0/err_reason',#ufs 返回0 正常 ufshcd0 中有7个节点 7
' find /sys/devices/ -name ufscld',# 返回正常的路径就支持cld功能 尝试cat frag_level和trigger 再echo 1 > trigger触发 之后查看dmesg
' cat /sys/class/mi_memory/mi_memory_device/ddr/ddr_id',#ddr 中有4个节点 1
' cat /sys/class/mi_memory/mi_memory_device/ddr/ddr_size',#ddr 中有4个节点 2
' cat /sys/class/mi_memory/mi_memory_device/ddr/ddr_type',#ddr 中有4个节点 3
' cat /sys/class/mi_memory/mi_memory_device/ddr/ddr_vendor',#ddr 中有4个节点 4
]
EMMC_cmd = [
' cat proc/mv',
' ls -al /dev/block/by-name/mem',# mem分区的大小是4M
' ls -al /dev/block/by-name/ffu',# ffu分区的大小是8M
' ls -al /dev/block/by-name/gsort',# gsort分区的大小是16M
' find /sys/class -name hr', #emmc 没有ufshcd0 只有hr节点
' cat /d/mmc0/err_state',#emmc 返回0 正常
' find /sys/class -name life_time',
' find /sys/class -name serial',
]
QCOM_cmd = [
' find /sys/devices/ -name spm_lvl',#返回值为3则pass
' find /sys/devices/ -name rpm_lvl',#返回值为3则pass
' find /sys/devices/ -name clkscale_enable', #QCOM 返回1 pass
' find /sys/devices/ -name power_mode', #高通
' cat /proc/zoneinfo | grep Movable -A 10',#pasr 判断movable 为0底层禁用
]
MTK_cmd = [
# ' cat /proc/ufs_debug | grep gear', #MTK
]
SPRD_cmd = [
' cat /proc/ufs/cmd_history | grep gear'
]
fac_cmd = [ #此只验证工具是否合入 ,不验证工具是否正确支持。需要根据返回值以及串口自行查看
' ls -lZ vendor/bin/ddr_clock_switch', #检查vendor bin下memory tool 1
' ls -lZ vendor/bin/ddr_tool', #检查vendor bin下memory tool 2
' ls -lZ vendor/bin/fatal_error', #检查vendor bin下memory tool 3
' ls -lZ vendor/bin/ghr', #检查vendor bin下memory tool 4
' ls -lZ vendor/bin/gpi', #检查vendor bin下memory tool 5
' ls -lZ vendor/bin/gsort', #检查vendor bin下memory tool 6
' ls -lZ vendor/bin/grr', #检查vendor bin下memory tool 7
' ls -lZ vendor/bin/mec', #检查vendor bin下memory tool 8
' ls -lZ vendor/bin/mem_parser', #检查vendor bin下memory tool 9
' ls -lZ vendor/bin/memtest', #检查vendor bin下memory tool 10
' ls -lZ vendor/bin/QMESA_64', #检查vendor bin下memory tool 11
' ls -lZ vendor/bin/ss_map', #检查vendor bin下memory tool 12
' ls -lZ vendor/bin/start_gsort.sh', #检查vendor bin下memory tool 13
' ls -lZ vendor/bin/qmesa_parser', #检查vendor bin下memory tool 应该有14个
' ls /vendor/bin/factory_info.xml',
' ghr',
# ' mec',
' mem_parser --nandheader',
' mem_parser --ghr',
' mem_parser --ddrheader',
' mem_parser --gsortqb',
' mem_parser --ufs',
' mem_parser --ddr',
' mem_parser -y',
# ' ls /data/local/tmp/ddr',# mem_parser -y check
# ' cat /data/local/tmp/ddr/eye_result___.txt',
# ' find sys/devices/ -name dvfsrc_opp_table',
' ddr_clock_switch -l',
' ddr_clock_switch -c',
' ddr_clock_switch -m',
' ddr_clock_switch -b',
' ddr_tool -r -t 1',
# ' ./start_gsort.sh',
' gsort -e -n 10 -r',#ddr retraining
# ' fatal_error -s test', #fatal_error
]
miui_cmd = [
''
' ps -A | grep cld'
# ' sm get-frag-level',
# ' sm trigger-cld',
]
test_cmd = [
# ' gsort -e -n 10 -r',
# ' find /sys/devices/ -name ufscld',# 返回正常的路径就支持cld功能 尝试cat frag_level和trigger 再echo 1 > trigger触发 之后查看dmesg
' ddr_tool -r -t 1',
'fatal_error -s test',
]
def __init__(self, deviceid):
threading.Thread.__init__(self)
self.threadid = deviceid
def run(self):
print ("Starting " + self.threadid)
self.start_ddr()
print ("Exiting " + self.threadid)
os.system("pause")
def pick_cmd(self, str_cmd: str) -> str:
last_path_segment = str_cmd.rsplit("/", 1)[-1]
last_word = last_path_segment.split()[-1]
# print (last_word)
return last_word
def pick_cmd_fac(self, str_cmd: str) -> str:
if "gsort -e" in str_cmd:
return "Retraining"
elif "ddr_tool -r" in str_cmd:
return "ddr_tool"
elif "start_gsort.sh" in str_cmd:
return "gsort_test"
elif "fatal_error" in str_cmd:
return "fatal_error"
return str_cmd
def pick_cmd_ufs(self, cmd_ret: str) -> str:
if "ufscld" in cmd_ret:
return "ufscld"
else:
return cmd_ret
def pick_fac_or_pre(self, str_cmd: str) -> str:
if "1" in str_cmd:
return "Factory"
else:
return "MIUI"
def pick_strorage(self,ret_mv):
if "U:" in ret_mv:
return "UFS"
elif "E:" in ret_mv:
return "EMMC"
else:
return "ERROR"
def check(self,cmd,ret)-> str:
def get_fun_mem(ret: str) -> str:
if "" != ret:
# print(cmd+ret)
ret1 = self._safe_adb_command(f" cat /proc/partitions | grep {self.pick_cmd(ret)}")
ret_2 = ret1.split("%s"%(self.pick_cmd(ret)))[int(ret1.count(self.pick_cmd("%s"%(self.pick_cmd(ret)))) - 1)]
ret_size = ret_2.split(" ")[int(ret_2.count(" ") - 1)]
# print(type(ret_size))
return str(ret_size)
else:
return "fail"
def get_fun_spm_lvl(ret: str) -> str:
if "" != ret:
spm_lvl = self._safe_adb_command(f"cat {ret}")
return spm_lvl
else:
return "fail"
def get_fun_wb(ret: str) -> str:
if "" != ret:
wb = self._safe_adb_command(f" cat {ret}")
return wb
def get_fun_cld(ret: str) -> str:
if "" != ret:
ret_cld1 = self._safe_adb_command(f" cat {ret}/frag_level")
ret_cld2 = self._safe_adb_command(f" cat {ret}/trigger")
self._safe_adb_command(f" echo 1 > {ret}/trigger")
ret_cld3 = self._safe_adb_command(f" dmesg | grep ufscld")
return "cat frag_level %s\n cat trigger %s\necho 1 > trigger\ndmesg | grep ufscld\n%s" % (ret_cld1, ret_cld2,ret_cld3)
else:
return "fail"
def get_fun_wb_buf(ret: str) -> str:
if "" != ret:
wb_buf = self._safe_adb_command(f"cat {ret}")
return wb_buf
def get_fun_emmc_hr(ret: str) -> str:
if "" != ret:
hr = self._safe_adb_command(f" cat {ret}")
return hr
def get_fun_power_mode(ret: str) -> str:
if "" != ret:
power_mode = self._safe_adb_command(f" cat {ret}")
return power_mode
else:
return "fail"
def get_fun_fac_info(ret: str) -> str:
if "" != ret:
fac_info = self._safe_adb_command(f" cat {ret}")
return fac_info
else:
return "fail"
def get_fun_dvfsrc(ret: str) -> str:
if "" != ret:
dvfsrc = self._safe_adb_command(f" cat {ret}")
return dvfsrc
def get_fun_ddr_tool(ret: str) -> str:
if "" != ret:
ret_1 = ""
print("开始ddrtool测试")
ret_1 = subprocess.run(["adb", "-s", self.threadid, "shell", "ddr_tool -c"],capture_output=True,text=True)
self._safe_adb_command(f"ddr_tool --run --time=1")
ret_2 = subprocess.run(["adb", "-s", self.threadid, "shell", "ddr_tool -c"],capture_output=True,text=True)
self._safe_adb_command(f"ddr_tool --run --time=1")
ret_3 = subprocess.run(["adb", "-s", self.threadid, "shell", "ddr_tool -c"],capture_output=True,text=True)
return f"ddrtool testing\n {ret_1.stdout}\n{ret_2.stdout}\n{ret_3.stdout}\n"
def get_fun_Retraining(ret: str) -> str:
print("开始Retraining测试")
ret_1 = self._safe_adb_command(f" gsort -e -c")
print(ret_1)
self._safe_adb_command(f"reboot")
subprocess.check_output(f'adb -s {self.threadid} wait-for-device', shell=True).decode().strip()
time.sleep(5)
subprocess.check_output(f'adb -s {self.threadid} wait-for-device', shell=True).decode().strip()
ret_2 = self._safe_adb_command(f" gsort -e -c")
print(ret_2)
return f"Retraining testing\n adb shell gsort -e -c{ret_1}\nadb shell reboot\nadb shell gsort -e -c {ret_2}"
def get_fun_gsort_test(ret: str) -> str:
print("开始gsort测试")
self._safe_adb_command(f"reboot")
subprocess.check_output(f'adb -s {self.threadid} wait-for-device', shell=True).decode().strip()
gsort_ret = self._safe_adb_command(f" gsort --check")
return f"gsort testing\n {ret} + {gsort_ret}"
def get_fun_fatal_error(ret: str) -> str:
ret_1 = self._safe_adb_command(f" fatal_error -g")
self._safe_adb_command(f" fatal_error -c")
ret_2 = self._safe_adb_command(f" fatal_error -g")
return f"fatal_error testing\n {ret_1}\n fatal_error -c\n{ret_2}"
def get_default(ret: str) -> str:
return ret if ret else "no_output"
switcher = {
"mem":get_fun_mem,
"ffu":get_fun_mem,
"gsort":get_fun_mem,
"spm_lvl":get_fun_spm_lvl,
"rpm_lvl":get_fun_spm_lvl,
"clkgate_enable":get_fun_spm_lvl,
"wb_enable":get_fun_wb,
"enable_wb":get_fun_wb,
"enable_tw":get_fun_wb,
"tw_enable":get_fun_wb,
"ufscld":get_fun_cld,
"wb_avail_buf":get_fun_wb_buf,
"wb_cur_buf":get_fun_wb_buf,
"wb_flush_buf":get_fun_wb_buf,
"wb_life_time_est":get_fun_wb_buf,
"hr" : get_fun_emmc_hr,
"power_mode":get_fun_power_mode,
"factory_info.xml":get_fun_fac_info,
"dvfsrc_opp_table":get_fun_dvfsrc,
"ddr_tool":get_fun_ddr_tool,
"gsort_test":get_fun_gsort_test,
"Retraining":get_fun_Retraining,
"fatal_error":get_fun_fatal_error,
"life_time":get_fun_emmc_hr,
"serial":get_fun_emmc_hr,
}
return switcher.get(cmd,lambda x: get_default(x))(ret)
def start_ddr(self):
os.system("adb -s " + self.threadid + " wait-for-device")
os.system("adb -s " + self.threadid + " root")
platform = self._safe_adb_command(f" getprop ro.boot.hardware") #获取项目平台 版本 信息
FAC_Version = self._safe_adb_command(f" getprop ro.boot.factorybuild")
hwname = self._safe_adb_command(f" getprop ro.boot.hwname")
storage_type = self.pick_strorage(self._safe_adb_command(f" cat proc/mv"))
sys_memory = get_storage(self._safe_adb_command(f" cat proc/mv"))
PRE_FAC = self.pick_fac_or_pre(FAC_Version)
with open("%s项目-verify记录-%s(%s)+%s(%s)-%s-%s.txt"%(hwname,sys_memory.DDR.size,sys_memory.DDR.vendor,sys_memory.Storage.size,sys_memory.Storage.vendor,PRE_FAC,py_v), "w") as file:
file.writelines("[hwname]: %s\n[factorybuild]: %s\n"%(hwname,PRE_FAC))
if "UFS" == storage_type:
for i in range(len(General)):
ret = self._safe_adb_command(f"{General[i]}")
fun_ret = self.check(self.pick_cmd(General[i]),ret)
if "not found" in ret or "No such file or directory" in ret:
file.writelines("\nadb shell %s\n%s\n"%(General[i],"fail"))
else:
file.writelines("\nadb shell %s\n%s\n"%(General[i],fun_ret))
i += 1
if "UFS" == storage_type:
i = 0
for i in range(len(UFS_cmd)):
ret = self._safe_adb_command(f"{UFS_cmd[i]}")
fun_ret = self.check(self.pick_cmd_ufs(ret),ret)
if "not found" in ret or "No such file or directory" in ret:
file.writelines("\nadb shell %s\n%s\n"%(UFS_cmd[i],"NONE"))
else:
file.writelines("\nadb shell %s\n%s\n"%(UFS_cmd[i],fun_ret))
i += 1
else:
i=0
for i in range(len(EMMC_cmd)):
ret = self._safe_adb_command(f"{EMMC_cmd[i]}")
fun_ret = self.check(self.pick_cmd(EMMC_cmd[i]),ret)
if "not found" in ret or "No such file or directory" in ret:
file.writelines("\nadb shell %s\n%s\n"%(EMMC_cmd[i],"NONE"))
else:
file.writelines("\nadb shell %s\n%s\n"%(EMMC_cmd[i],fun_ret))
i += 1
if "qcom" == platform:
i=0
for i in range(len(QCOM_cmd)):
ret = self._safe_adb_command(f"{QCOM_cmd[i]}")
fun_ret = self.check(self.pick_cmd(QCOM_cmd[i]),ret)
if "not found" in ret or "No such file or directory" in ret:
file.writelines("\nadb shell %s\n%s\n"%(QCOM_cmd[i],"NONE"))
else:
file.writelines("\nadb shell %s\n%s\n"%(QCOM_cmd[i],fun_ret))
i += 1
elif("SPRD" == self._safe_adb_command(f" ro.vendor.keybox.id.value")):
i=0
for i in range(len(SPRD_cmd)):
ret = self._safe_adb_command(f"{SPRD_cmd[i]}")
if "not found" in ret or "No such file or directory" in ret:
file.writelines("\nadb shell %s\n%s\n"%(SPRD_cmd[i],"NONE"))
else:
file.writelines("\nadb shell %s\n%s\n"%(SPRD_cmd[i],ret))
i += 1
else:
i=0
for i in range(len(MTK_cmd)):
ret = self._safe_adb_command(f"{MTK_cmd[i]}")
if "not found" in ret or "No such file or directory" in ret:
file.writelines("\nadb shell %s\n%s\n"%(MTK_cmd[i],"NONE"))
else:
file.writelines("\nadb shell %s\n%s\n"%(MTK_cmd[i],ret))
i += 1
if "1" == FAC_Version:
i=0
for i in range(len(fac_cmd)):
ret = self._safe_adb_command(f"{fac_cmd[i]}")
fun_ret = self.check(self.pick_cmd_fac(fac_cmd[i]),ret)
if "not found" in ret or "No such file or directory" in ret:
file.writelines("\nadb shell %s\n%s\n"%(fac_cmd[i],"NONE"))
else:
file.writelines("\nadb shell %s\n%s\n"%(fac_cmd[i],fun_ret))
i += 1
else:
i=0
for i in range(len(miui_cmd)):
ret = self._safe_adb_command(f"{miui_cmd[i]}")
if "not found" in ret or "No such file or directory" in ret:
file.writelines("\nadb shell %s\n%s\n"%(miui_cmd[i],"NONE"))
else:
file.writelines("\nadb shell %s\n%s\n"%(miui_cmd[i],ret))
i += 1
def get_device():
global deviceList
global platform
global FAC_Version
global hwname
global storage_type
deviceList = []
for i in range(1):
try:
pout1 = subprocess.Popen('adb devices', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
getDevice = pout1.stdout.readlines()
a = int(len(getDevice))
for j in range(1, a - 1):
deviceId = getDevice[j].split()
device = deviceId[0]
deviceList.append(device)
print (deviceList)
except IndexError:
print ("no devices")
def start_run():
for k in range(int(len(deviceList))):
deviceid = bytes.decode(deviceList[k])
thread = mythread(deviceid)
thread.start()
if __name__ == '__main__':
get_device()
start_run()
time.sleep(5)
帮我优化一下这个脚本
最新发布