taotoolkit 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- taotoolkit/__init__.py +81 -0
- taotoolkit/asrVrf.py +322 -0
- taotoolkit/tao_camDvt.py +1186 -0
- taotoolkit/tao_cmdTool.py +626 -0
- taotoolkit/tao_common.py +435 -0
- taotoolkit/tao_device.py +1011 -0
- taotoolkit/tao_flash.py +823 -0
- taotoolkit/tao_tuning.py +1344 -0
- taotoolkit/tao_vrfTool.py +690 -0
- taotoolkit-1.0.0.dist-info/METADATA +50 -0
- taotoolkit-1.0.0.dist-info/RECORD +13 -0
- taotoolkit-1.0.0.dist-info/WHEEL +5 -0
- taotoolkit-1.0.0.dist-info/top_level.txt +1 -0
taotoolkit/tao_device.py
ADDED
|
@@ -0,0 +1,1011 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- encoding: utf-8 -*-
|
|
3
|
+
"""设备操作层, adb/设备 设备描述json、打开相机, 拍照, 截屏, 录屏。"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
import subprocess
|
|
9
|
+
import sys
|
|
10
|
+
import threading
|
|
11
|
+
import time
|
|
12
|
+
import json
|
|
13
|
+
import argparse
|
|
14
|
+
from time import sleep
|
|
15
|
+
from colorama import Fore
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import uiautomator2 as u2
|
|
19
|
+
except Exception: # pragma: no cover
|
|
20
|
+
u2 = None
|
|
21
|
+
|
|
22
|
+
from func_timeout import FunctionTimedOut, func_timeout
|
|
23
|
+
|
|
24
|
+
from .tao_common import (
|
|
25
|
+
debugCtrl,
|
|
26
|
+
checkMsg,
|
|
27
|
+
eExit,
|
|
28
|
+
exit,
|
|
29
|
+
iExit,
|
|
30
|
+
findFilesBySuffixKeyword,
|
|
31
|
+
inputSerial,
|
|
32
|
+
logd,
|
|
33
|
+
loge,
|
|
34
|
+
logh,
|
|
35
|
+
logi,
|
|
36
|
+
logw,
|
|
37
|
+
oCmd,
|
|
38
|
+
sysVersion,
|
|
39
|
+
pCmd,
|
|
40
|
+
parseArgs,
|
|
41
|
+
parseDeviceInfo,
|
|
42
|
+
rCmd,
|
|
43
|
+
normalize_args,
|
|
44
|
+
register_command,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
CACHE_FILE = os.path.join(os.path.dirname(__file__), ".dev_cache.json")
|
|
48
|
+
CACHE_TTL = 3600
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _load_cache():
|
|
52
|
+
try:
|
|
53
|
+
if not os.path.exists(CACHE_FILE):
|
|
54
|
+
return None
|
|
55
|
+
with open(CACHE_FILE) as f:
|
|
56
|
+
c = json.load(f)
|
|
57
|
+
if time.time() - c.get("ts", 0) > CACHE_TTL:
|
|
58
|
+
return None
|
|
59
|
+
return c
|
|
60
|
+
except Exception:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _save_cache(serial, screen_w, screen_h, android_ver):
|
|
65
|
+
try:
|
|
66
|
+
with open(CACHE_FILE, "w") as f:
|
|
67
|
+
json.dump(
|
|
68
|
+
{
|
|
69
|
+
"ts": time.time(),
|
|
70
|
+
"serial": serial,
|
|
71
|
+
"screen_w": screen_w,
|
|
72
|
+
"screen_h": screen_h,
|
|
73
|
+
"android_ver": android_ver,
|
|
74
|
+
},
|
|
75
|
+
f,
|
|
76
|
+
)
|
|
77
|
+
except Exception:
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class DevOp:
|
|
82
|
+
"""android device operate"""
|
|
83
|
+
|
|
84
|
+
def __init__(self, serial="", needRoot=False):
|
|
85
|
+
logd(f"serial = {serial} needroot ={needRoot}")
|
|
86
|
+
|
|
87
|
+
cache = _load_cache()
|
|
88
|
+
out, _ = pCmd("adb devices -l", 1, False, waitDone=True, timeOut=5, logLevel="debug")
|
|
89
|
+
|
|
90
|
+
if cache != None and cache["serial"] in out:
|
|
91
|
+
cache_hit = True
|
|
92
|
+
else:
|
|
93
|
+
cache_hit = False
|
|
94
|
+
|
|
95
|
+
if cache_hit:
|
|
96
|
+
if cache == None:
|
|
97
|
+
eExit("cache file error")
|
|
98
|
+
else:
|
|
99
|
+
logd(f"[cache] 命中缓存,跳过设备扫描: {cache['serial']}")
|
|
100
|
+
self.serial = cache["serial"]
|
|
101
|
+
self.curScreenW = cache["screen_w"]
|
|
102
|
+
self.curScreenH = cache["screen_h"]
|
|
103
|
+
self.androidVersion = cache["android_ver"]
|
|
104
|
+
self.devices = [{"serial": self.serial}]
|
|
105
|
+
else:
|
|
106
|
+
logd("[cache] 未命中,完整初始化")
|
|
107
|
+
self.devices = self.getConnectedDevices()
|
|
108
|
+
if serial == "":
|
|
109
|
+
self.serial = self.getSerial()
|
|
110
|
+
else:
|
|
111
|
+
self.serial = serial
|
|
112
|
+
self.checkSerial(serial)
|
|
113
|
+
self.curScreenW, self.curScreenH = self.getScreenSize()
|
|
114
|
+
self.androidVersion = self.getAndroidVersion()
|
|
115
|
+
_save_cache(self.serial, self.curScreenW, self.curScreenH, self.androidVersion)
|
|
116
|
+
|
|
117
|
+
self.curPath = os.getcwd()
|
|
118
|
+
self.refScreenW = 720
|
|
119
|
+
self.refScreenH = 1600
|
|
120
|
+
self.xRatio = self.curScreenW / self.refScreenW
|
|
121
|
+
self.yRatio = self.curScreenH / self.refScreenH
|
|
122
|
+
self.soc = None
|
|
123
|
+
|
|
124
|
+
if needRoot:
|
|
125
|
+
self.adbRoot()
|
|
126
|
+
info, err = self.adbRemount()
|
|
127
|
+
if "reboot" in err or "reboot" in info:
|
|
128
|
+
self.adbReboot()
|
|
129
|
+
logh("Now reboot your device for settings to take effect")
|
|
130
|
+
exit()
|
|
131
|
+
|
|
132
|
+
def checkSerial(self, serial):
|
|
133
|
+
serialList = []
|
|
134
|
+
if self.devices == None:
|
|
135
|
+
eExit(f"no devices detected")
|
|
136
|
+
else:
|
|
137
|
+
for i in self.devices:
|
|
138
|
+
serialList.append(i["serial"])
|
|
139
|
+
if serial == i["serial"]:
|
|
140
|
+
return True
|
|
141
|
+
eExit(f"[{serial}] no such a device, detected {' , '.join(serialList)}")
|
|
142
|
+
|
|
143
|
+
def getConnectedDevices(self):
|
|
144
|
+
try:
|
|
145
|
+
out, error = pCmd("adb devices -l", 1, True, waitDone=True, timeOut=6, logLevel="debug")
|
|
146
|
+
if "offline" in out or "unauthorized" in out:
|
|
147
|
+
tmp = out.split("\n")[1].split(" ")[0]
|
|
148
|
+
eExit(f"{tmp} devices offline or unauthorized")
|
|
149
|
+
if len(out.split("\n")) == 3:
|
|
150
|
+
eExit("no device detected")
|
|
151
|
+
logd(out)
|
|
152
|
+
lines = out.strip().split("\n")
|
|
153
|
+
devices = []
|
|
154
|
+
for line in lines[1:]:
|
|
155
|
+
device_info = line.split("\t")[0]
|
|
156
|
+
devices.append(parseDeviceInfo(device_info))
|
|
157
|
+
if len(devices) == 0:
|
|
158
|
+
eExit("no devices detect")
|
|
159
|
+
return devices
|
|
160
|
+
except subprocess.CalledProcessError as e:
|
|
161
|
+
loge(str(e))
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
def getSerial(self):
|
|
165
|
+
if self.devices is None:
|
|
166
|
+
eExit("no devices detected")
|
|
167
|
+
devices = self.devices or []
|
|
168
|
+
serial_index = 0
|
|
169
|
+
if len(devices) == 1:
|
|
170
|
+
serial_index = 0
|
|
171
|
+
elif len(devices) > 1:
|
|
172
|
+
logi(f"more than one devices connect, {len(devices)}")
|
|
173
|
+
for index, value in enumerate(devices):
|
|
174
|
+
logi(f"{index} {value['serial']} {value['model']}")
|
|
175
|
+
serial_index = inputSerial(0, len(devices) - 1)
|
|
176
|
+
|
|
177
|
+
return devices[serial_index]["serial"]
|
|
178
|
+
|
|
179
|
+
def getAndroidVersion(self):
|
|
180
|
+
cmd = f"adb -s {self.serial} shell getprop |grep ro.build.version.release"
|
|
181
|
+
out = rCmd(cmd)[0]
|
|
182
|
+
logd(out)
|
|
183
|
+
if out == "":
|
|
184
|
+
logw("get android version failed, set it to 16 by default")
|
|
185
|
+
return "16"
|
|
186
|
+
return out.split("[")[2].split("]")[0]
|
|
187
|
+
|
|
188
|
+
def getProductBoard(self):
|
|
189
|
+
cmd = f"adb -s {self.serial} shell getprop |grep ro.product.board"
|
|
190
|
+
out = rCmd(cmd)[0]
|
|
191
|
+
return out.split("[")[2].split("]")[0]
|
|
192
|
+
|
|
193
|
+
def getScreenSize(self):
|
|
194
|
+
cmd = f"adb -s {self.serial} shell wm size"
|
|
195
|
+
out, _error = rCmd(cmd, checkErr=True)
|
|
196
|
+
if "Physical size:" in out:
|
|
197
|
+
size_str = out.split(":")[1].strip()
|
|
198
|
+
width, height = map(int, size_str.split("x"))
|
|
199
|
+
return width, height
|
|
200
|
+
logw(f"get {self.serial} lcd size failed, set it to 720x1600 by default")
|
|
201
|
+
return 720, 1600
|
|
202
|
+
|
|
203
|
+
def slectBoard(self):
|
|
204
|
+
boardList = ["dove", "larkl", "lark", "larkpro"]
|
|
205
|
+
while True:
|
|
206
|
+
try:
|
|
207
|
+
user_input = input(f"{Fore.GREEN}请输入SOC型号 {boardList}: {Fore.RESET}")
|
|
208
|
+
if user_input in boardList:
|
|
209
|
+
return user_input
|
|
210
|
+
loge("无效的SOC型号,请重新输入")
|
|
211
|
+
except ValueError:
|
|
212
|
+
loge("输入无效,请输入SOC型号.")
|
|
213
|
+
|
|
214
|
+
def getASRDevice(self):
|
|
215
|
+
if self.devices:
|
|
216
|
+
for device in self.devices:
|
|
217
|
+
prop = ["ro.boot.hardware.soc", "ro.product.model", "ro.soc.model"]
|
|
218
|
+
for i in prop:
|
|
219
|
+
cmd = f"adb -s {device['serial']} shell getprop |grep -iE {i} "
|
|
220
|
+
out = rCmd(cmd)[0]
|
|
221
|
+
logd(out)
|
|
222
|
+
if "asr" in out.lower():
|
|
223
|
+
if "8601" in out.lower():
|
|
224
|
+
self.soc = "dove"
|
|
225
|
+
elif "8602" in out.lower():
|
|
226
|
+
self.soc = "dovelite"
|
|
227
|
+
elif "8661" in out.lower():
|
|
228
|
+
self.soc = "lark"
|
|
229
|
+
elif "8662" in out.lower():
|
|
230
|
+
self.soc = "larkl"
|
|
231
|
+
elif "8861" in out.lower():
|
|
232
|
+
self.soc = "larkpro"
|
|
233
|
+
else:
|
|
234
|
+
self.soc = None
|
|
235
|
+
if self.soc is not None:
|
|
236
|
+
return self.soc
|
|
237
|
+
logw("get SOC from prop failed, manual set it")
|
|
238
|
+
self.soc = self.slectBoard()
|
|
239
|
+
return self.soc
|
|
240
|
+
eExit("No device connected.")
|
|
241
|
+
|
|
242
|
+
def getSoc(self):
|
|
243
|
+
if self.devices:
|
|
244
|
+
prop = ["ro.boot.hardware.soc", "ro.product.model", "ro.soc.model"]
|
|
245
|
+
for i in prop:
|
|
246
|
+
cmd = f"adb -s {self.serial} shell getprop |grep -iE {i} "
|
|
247
|
+
out = rCmd(cmd)[0]
|
|
248
|
+
logd(out)
|
|
249
|
+
if "asr" in out.lower():
|
|
250
|
+
if "8601" in out.lower():
|
|
251
|
+
self.soc = "dove"
|
|
252
|
+
elif "8602" in out.lower():
|
|
253
|
+
self.soc = "dovelite"
|
|
254
|
+
elif "8661" in out.lower():
|
|
255
|
+
self.soc = "lark"
|
|
256
|
+
elif "8662" in out.lower():
|
|
257
|
+
self.soc = "larkl"
|
|
258
|
+
elif "8861" in out.lower():
|
|
259
|
+
self.soc = "larkpro"
|
|
260
|
+
else:
|
|
261
|
+
self.soc = None
|
|
262
|
+
if self.soc is not None:
|
|
263
|
+
return self.soc
|
|
264
|
+
logw("get SOC from prop failed, manual set it")
|
|
265
|
+
self.soc = self.slectBoard()
|
|
266
|
+
return self.soc
|
|
267
|
+
eExit("ASR SOC not found")
|
|
268
|
+
|
|
269
|
+
def checkCameraOpened(self):
|
|
270
|
+
cmd = f"adb -s {self.serial} shell dumpsys window | grep mFocus"
|
|
271
|
+
out, error = rCmd(cmd)
|
|
272
|
+
if "camera" in out.lower():
|
|
273
|
+
return True
|
|
274
|
+
loge("camera not open, start camera ...")
|
|
275
|
+
rCmd("adb shell am start -a android.media.action.STILL_IMAGE_CAMERA", 1)
|
|
276
|
+
sleep(2)
|
|
277
|
+
|
|
278
|
+
def adbRoot(self):
|
|
279
|
+
cmd = f"adb -s {self.serial} root"
|
|
280
|
+
return rCmd(cmd, 0.5, showCmd=True, timeOut=10, showRet=True, logLevel="info")
|
|
281
|
+
|
|
282
|
+
def adbRemount(self):
|
|
283
|
+
cmd = f"adb -s {self.serial} remount"
|
|
284
|
+
info, err = rCmd(cmd, 0.5, timeOut=10)
|
|
285
|
+
self.setLcdTimeout()
|
|
286
|
+
if err != "":
|
|
287
|
+
logi(err.split("\n")[0])
|
|
288
|
+
logi(err.split("\n")[-2])
|
|
289
|
+
elif info != "":
|
|
290
|
+
logi(info.split("\n")[0])
|
|
291
|
+
return info, err
|
|
292
|
+
|
|
293
|
+
def setLcdTimeout(self, time_s=3600):
|
|
294
|
+
cmd = f"adb -s {self.serial} shell settings put system screen_off_timeout {time_s * 1000}"
|
|
295
|
+
_ = rCmd(cmd, 0.5, showCmd=True, timeOut=3, logLevel="debug", showRet=True)
|
|
296
|
+
|
|
297
|
+
def adbReboot(self):
|
|
298
|
+
cmd = f"adb -s {self.serial} reboot"
|
|
299
|
+
return rCmd(cmd, 0.5, timeOut=10)
|
|
300
|
+
|
|
301
|
+
def adbScreenBrightness(self, brightness=255):
|
|
302
|
+
cmd = f'adb -s {self.serial} shell "settings put system screen_brightness {brightness}"'
|
|
303
|
+
oCmd(cmd, showCmd=True, logLevel="info")
|
|
304
|
+
|
|
305
|
+
def adbSocket(self):
|
|
306
|
+
cmd = f"adb -s {self.serial} forward tcp:12218 localabstract:camera_tuning_server"
|
|
307
|
+
rCmd(cmd, 0.5, checkErr=True)
|
|
308
|
+
|
|
309
|
+
def adbTap(self, cordinateABS, slp=1):
|
|
310
|
+
cordinate = [cordinateABS[0] * self.xRatio, cordinateABS[1] * self.yRatio]
|
|
311
|
+
cordinate = list(map(int, cordinate))
|
|
312
|
+
cmd = f"adb -s {self.serial} shell input tap {cordinate[0]} {cordinate[1]}"
|
|
313
|
+
rCmd(cmd, slp, True, logLevel="info")
|
|
314
|
+
|
|
315
|
+
def adbSwipe(self, cordinateABS, slp=2, time_ms=600):
|
|
316
|
+
cordinate = [
|
|
317
|
+
cordinateABS[0] * self.xRatio,
|
|
318
|
+
cordinateABS[1] * self.yRatio,
|
|
319
|
+
cordinateABS[2] * self.xRatio,
|
|
320
|
+
cordinateABS[3] * self.yRatio,
|
|
321
|
+
]
|
|
322
|
+
cordinate = list(map(int, cordinate))
|
|
323
|
+
cmd = f"adb -s {self.serial} shell input swipe {cordinate[0]} {cordinate[1]} {cordinate[2]} {cordinate[3]} {time_ms}"
|
|
324
|
+
rCmd(cmd, slp, True, logLevel="info")
|
|
325
|
+
|
|
326
|
+
def take_screenshot(self, outPath):
|
|
327
|
+
success = self._try_screencap(args=["-p"], outPath=outPath)
|
|
328
|
+
if success:
|
|
329
|
+
return True
|
|
330
|
+
return self._try_screencap(args=["--preserve-display-colors", "-p"], outPath=outPath)
|
|
331
|
+
|
|
332
|
+
def _try_screencap(self, args, outPath):
|
|
333
|
+
try:
|
|
334
|
+
cmd = ["adb", "-s", self.serial, "exec-out", "screencap"] + args
|
|
335
|
+
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=15)
|
|
336
|
+
if result.returncode != 0:
|
|
337
|
+
logi(f"failed: {result.stderr.decode()}")
|
|
338
|
+
return False
|
|
339
|
+
data = result.stdout
|
|
340
|
+
if len(data) < 8 or data[:4] != b"\x89PNG":
|
|
341
|
+
logw(f"invalid PNG, size={len(data)}, args={args}")
|
|
342
|
+
return False
|
|
343
|
+
os.makedirs(os.path.dirname(outPath), exist_ok=True)
|
|
344
|
+
with open(outPath, "wb") as f:
|
|
345
|
+
f.write(data)
|
|
346
|
+
logi(f"success: {outPath}, size={len(data)}")
|
|
347
|
+
return True
|
|
348
|
+
except subprocess.TimeoutExpired:
|
|
349
|
+
loge(f"timeout, args={args}")
|
|
350
|
+
return False
|
|
351
|
+
except Exception as e:
|
|
352
|
+
loge(f"exception: {e}")
|
|
353
|
+
return False
|
|
354
|
+
|
|
355
|
+
def adbScreenCap(self, fileName):
|
|
356
|
+
outPath = os.path.join(self.curPath, fileName + ".png")
|
|
357
|
+
self.take_screenshot(outPath)
|
|
358
|
+
|
|
359
|
+
def adbScreenRec(
|
|
360
|
+
self,
|
|
361
|
+
fileName,
|
|
362
|
+
limitTime_s="30",
|
|
363
|
+
bitRate_Mbps="2",
|
|
364
|
+
inputWidth=None,
|
|
365
|
+
inputHeight=None,
|
|
366
|
+
debug=True,
|
|
367
|
+
isThread=False,
|
|
368
|
+
):
|
|
369
|
+
limitTime_s = int(limitTime_s)
|
|
370
|
+
bitRate_Mbps = int(float(bitRate_Mbps) * 1000000)
|
|
371
|
+
inputWidth = int(inputWidth) if inputWidth is not None else None
|
|
372
|
+
inputHeight = int(inputHeight) if inputHeight is not None else None
|
|
373
|
+
mp4Name = fileName + ".mp4"
|
|
374
|
+
cmd1 = f"adb -s {self.serial} shell screenrecord --time-limit {limitTime_s}"
|
|
375
|
+
cmd2 = f"--bugreport --bit-rate {bitRate_Mbps}" if debug else f"--bit-rate {int(bitRate_Mbps)}"
|
|
376
|
+
if inputWidth is None or inputHeight is None:
|
|
377
|
+
recordWidth, recordHeight = self.curScreenW, self.curScreenH
|
|
378
|
+
elif inputWidth > self.curScreenW or inputHeight > self.curScreenH:
|
|
379
|
+
logw(
|
|
380
|
+
f"inputWidth {inputWidth} or inputHeight {inputHeight} > lcdWidth {self.curScreenW} or lcdHeight {self.curScreenH}, use lcd size"
|
|
381
|
+
)
|
|
382
|
+
recordWidth, recordHeight = self.curScreenW, self.curScreenH
|
|
383
|
+
else:
|
|
384
|
+
recordWidth, recordHeight = inputWidth, inputHeight
|
|
385
|
+
|
|
386
|
+
cmd3 = f"--size {recordWidth}x{recordHeight} /sdcard/{mp4Name}"
|
|
387
|
+
cmd = f"{cmd1} {cmd2} {cmd3}"
|
|
388
|
+
if sysVersion == "Linux":
|
|
389
|
+
pCmd(cmd, showCmd=True, splitCmd=False, shell=True, logLevel="info", waitDone=False)
|
|
390
|
+
else:
|
|
391
|
+
pCmd(cmd, showCmd=True, splitCmd=False, shell=False, logLevel="info", waitDone=False)
|
|
392
|
+
try:
|
|
393
|
+
if isThread:
|
|
394
|
+
logi(
|
|
395
|
+
f"等待{limitTime_s}s 自动结束录制 {mp4Name} {bitRate_Mbps / 1000000}Mbps {recordWidth}x{recordHeight}"
|
|
396
|
+
)
|
|
397
|
+
sleep(float(limitTime_s))
|
|
398
|
+
else:
|
|
399
|
+
logi(
|
|
400
|
+
f"回车或等待{limitTime_s}s 结束录制 {mp4Name} {bitRate_Mbps / 1000000}Mbps {recordWidth}x{recordHeight}"
|
|
401
|
+
)
|
|
402
|
+
char = func_timeout(float(limitTime_s), lambda: input())
|
|
403
|
+
if char or char == "":
|
|
404
|
+
pass
|
|
405
|
+
except FunctionTimedOut:
|
|
406
|
+
pass
|
|
407
|
+
finally:
|
|
408
|
+
stopCmd = f"adb -s {self.serial} shell pkill -2 -f screenrecord"
|
|
409
|
+
pCmd(stopCmd, 0.5, showCmd=True, splitCmd=False, shell=True, logLevel="info")
|
|
410
|
+
outfile = os.path.join(self.curPath, mp4Name)
|
|
411
|
+
cmd = f"adb -s {self.serial} pull sdcard/{mp4Name} {outfile}"
|
|
412
|
+
pCmd(cmd, 1, showCmd=True, splitCmd=False, shell=True, timeOut=10, logLevel="info")
|
|
413
|
+
|
|
414
|
+
def keyHome(self, slp=0.5):
|
|
415
|
+
cmd = f"adb -s {self.serial} shell input keyevent KEYCODE_HOME"
|
|
416
|
+
rCmd(cmd, slp)
|
|
417
|
+
|
|
418
|
+
def keyBack(self, slp=0.5):
|
|
419
|
+
cmd = f"adb -s {self.serial} shell input keyevent BACK"
|
|
420
|
+
rCmd(cmd, slp)
|
|
421
|
+
|
|
422
|
+
def keyMenu(self, slp=0.5):
|
|
423
|
+
cmd = f"adb -s {self.serial} shell input keyevent KEYCODE_MENU"
|
|
424
|
+
rCmd(cmd, slp)
|
|
425
|
+
|
|
426
|
+
def keyPower(self, slp=0.5):
|
|
427
|
+
cmd = f"adb -s {self.serial} shell input keyevent KEYCODE_POWER"
|
|
428
|
+
rCmd(cmd, slp)
|
|
429
|
+
|
|
430
|
+
def keyWakeup(self, slp=0.5):
|
|
431
|
+
cmd = f"adb -s {self.serial} shell input keyevent KEYCODE_WAKEUP"
|
|
432
|
+
rCmd(cmd, slp)
|
|
433
|
+
|
|
434
|
+
def adbCmd(self, cmdStr, withShell=True, slp=0.5):
|
|
435
|
+
if withShell:
|
|
436
|
+
cmd = f"adb -s {self.serial} shell {cmdStr}"
|
|
437
|
+
else:
|
|
438
|
+
cmd = f"adb -s {self.serial} {cmdStr}"
|
|
439
|
+
rCmd(cmd, slp, showCmd=True, logLevel="info")
|
|
440
|
+
|
|
441
|
+
def keyCapture(self, slp=0.5):
|
|
442
|
+
cmd = f"adb -s {self.serial} shell input keyevent 27"
|
|
443
|
+
rCmd(cmd, slp)
|
|
444
|
+
|
|
445
|
+
def pushFile(self, local, target):
|
|
446
|
+
cmd = f"adb -s {self.serial} push {local} {target}"
|
|
447
|
+
out, err = rCmd(cmd, 0.5, showCmd=True, logLevel="info")
|
|
448
|
+
logi(out)
|
|
449
|
+
checkMsg(err, "failed", "device may need remount")
|
|
450
|
+
if "Read-only" in out:
|
|
451
|
+
eExit("device is Read-only, may need remount")
|
|
452
|
+
|
|
453
|
+
def isLcdOn(self):
|
|
454
|
+
cmd = f"adb -s {self.serial} shell dumpsys window policy"
|
|
455
|
+
out, _ = rCmd(cmd, 0.5)
|
|
456
|
+
return not re.search("screenState=SCREEN_STATE_OFF", out)
|
|
457
|
+
|
|
458
|
+
def isScreenLock(self):
|
|
459
|
+
try:
|
|
460
|
+
cmd = f"adb -s {self.serial} shell dumpsys window policy"
|
|
461
|
+
out, _ = rCmd(cmd, 0.5)
|
|
462
|
+
return bool(re.search("showing=true", out))
|
|
463
|
+
except Exception as e:
|
|
464
|
+
loge(f"获取手机lock状态异常{e}")
|
|
465
|
+
return False
|
|
466
|
+
|
|
467
|
+
def lcdOnAndUnlock(self, on=1):
|
|
468
|
+
if on == 0:
|
|
469
|
+
if self.isLcdOn():
|
|
470
|
+
self.keyPower(1)
|
|
471
|
+
if self.isLcdOn():
|
|
472
|
+
self.keyPower(1)
|
|
473
|
+
else:
|
|
474
|
+
if self.isLcdOn():
|
|
475
|
+
if self.isScreenLock():
|
|
476
|
+
self.keyMenu(1)
|
|
477
|
+
if self.isScreenLock():
|
|
478
|
+
self.keyPower(1)
|
|
479
|
+
else:
|
|
480
|
+
self.keyWakeup(1)
|
|
481
|
+
self.keyMenu(1)
|
|
482
|
+
if self.isScreenLock():
|
|
483
|
+
self.keyPower(1)
|
|
484
|
+
|
|
485
|
+
def openCam(self, id=0):
|
|
486
|
+
if id == 0:
|
|
487
|
+
rCmd("adb shell am start -a android.media.action.STILL_IMAGE_CAMERA", 1)
|
|
488
|
+
else:
|
|
489
|
+
rCmd("adb shell am start -a android.media.action.STILL_IMAGE_CAMERA", 2)
|
|
490
|
+
sleep(1)
|
|
491
|
+
self.adbTap((600, 1400))
|
|
492
|
+
sleep(2)
|
|
493
|
+
|
|
494
|
+
def getSuffixList(self, path: str, *suffix: str):
|
|
495
|
+
fileList = []
|
|
496
|
+
cmd = f"adb -s {self.serial} shell ls -t {path}"
|
|
497
|
+
allFileList = rCmd(cmd)[0].split("\n")[0:-1]
|
|
498
|
+
logd(str(allFileList))
|
|
499
|
+
for file in allFileList:
|
|
500
|
+
for i in suffix:
|
|
501
|
+
if file.lower().endswith(i) and "thumb" not in file:
|
|
502
|
+
fileList.append(file)
|
|
503
|
+
return fileList
|
|
504
|
+
|
|
505
|
+
def capJPG(self, name="null", wait=3):
|
|
506
|
+
outPath = self.curPath
|
|
507
|
+
logi(f"capture {os.path.join(outPath, name)}.jpg")
|
|
508
|
+
jpgPath = r"/sdcard/DCIM/Camera/"
|
|
509
|
+
oldFileList = self.getSuffixList(jpgPath, "jpg", "jpeg")
|
|
510
|
+
cmd = f"adb -s {self.serial} shell input keyevent 27"
|
|
511
|
+
rCmd(cmd, 0.5, True, logLevel="info")
|
|
512
|
+
sleep(wait)
|
|
513
|
+
|
|
514
|
+
founded = False
|
|
515
|
+
for i in range(5):
|
|
516
|
+
fileList = self.getSuffixList(jpgPath, "jpg", "jpeg")
|
|
517
|
+
for f in fileList:
|
|
518
|
+
if "~" in f:
|
|
519
|
+
fileList.remove(f)
|
|
520
|
+
jpgNameList = list(set(fileList) - set(oldFileList))
|
|
521
|
+
if jpgNameList != []:
|
|
522
|
+
jpgName = jpgNameList[0]
|
|
523
|
+
founded = True
|
|
524
|
+
if name == "null":
|
|
525
|
+
cmd = f"adb -s {self.serial} pull {jpgPath}{jpgName}"
|
|
526
|
+
else:
|
|
527
|
+
cmd = f"adb -s {self.serial} pull {jpgPath}{jpgName} {name}.jpg"
|
|
528
|
+
rCmd(cmd, 0.5, True, logLevel="info")
|
|
529
|
+
break
|
|
530
|
+
else:
|
|
531
|
+
sleep(1.0)
|
|
532
|
+
if not founded:
|
|
533
|
+
loge(f"capture {os.path.join(outPath, name)}.jpg failed")
|
|
534
|
+
return False
|
|
535
|
+
return True
|
|
536
|
+
|
|
537
|
+
def killCamera(self):
|
|
538
|
+
cmd = f"adb -s {self.serial} shell input keyevent KEYCODE_HOME"
|
|
539
|
+
rCmd(cmd, 0.5)
|
|
540
|
+
rCmd("adb shell pm clear com.asrmicro.camera", 0.5, showCmd=True, logLevel="info")
|
|
541
|
+
keyStr = "camera"
|
|
542
|
+
cmd = f"adb -s {self.serial} shell ps -e |grep {keyStr}"
|
|
543
|
+
out, _err = rCmd(cmd, showCmd=True, logLevel="info")
|
|
544
|
+
for i in out.splitlines():
|
|
545
|
+
PID = i.split()[1]
|
|
546
|
+
if r"android.hardware.camera.provider@2" in i.split()[8]:
|
|
547
|
+
cmd = f"adb -s {self.serial} shell kill -9 {PID}"
|
|
548
|
+
out, err = rCmd(cmd, 0.5, showCmd=True, logLevel="info")
|
|
549
|
+
if "Operation not permitted" in err:
|
|
550
|
+
eExit("Operation not permitted,device need need remount")
|
|
551
|
+
sleep(2)
|
|
552
|
+
|
|
553
|
+
def backUpSo(self, so):
|
|
554
|
+
backUpName = so + ".ori"
|
|
555
|
+
cmd = f"adb -s {self.serial} shell ls vendor/lib64/ | grep {backUpName}"
|
|
556
|
+
out, _ = pCmd(cmd, showCmd=True, showRet=False, logLevel="debug")
|
|
557
|
+
if out == "":
|
|
558
|
+
logi(f"{backUpName} not exist, backup {so}")
|
|
559
|
+
cmd = f"adb -s {self.serial} shell cp vendor/lib64/{so} vendor/lib64/{backUpName}"
|
|
560
|
+
_, _ = pCmd(cmd, showCmd=True, showRet=True, logLevel="debug")
|
|
561
|
+
else:
|
|
562
|
+
logi(f"{backUpName} already exist, skip backup")
|
|
563
|
+
|
|
564
|
+
def pushso(self, so):
|
|
565
|
+
for i in so:
|
|
566
|
+
soWithOutPath = os.path.basename(i)
|
|
567
|
+
self.backUpSo(soWithOutPath)
|
|
568
|
+
cmd = f"adb -s {self.serial} push {i} vendor/lib64/{soWithOutPath}"
|
|
569
|
+
out, err = pCmd(cmd, showCmd=True, showRet=True, logLevel="info")
|
|
570
|
+
if "Read-only" in out:
|
|
571
|
+
eExit("device is Read-only, may need remount")
|
|
572
|
+
self.killCamera()
|
|
573
|
+
|
|
574
|
+
def pushI2cTransfer(self):
|
|
575
|
+
cmd = f"adb -s {self.serial} shell ls /system/bin/ |grep i2c_transfer"
|
|
576
|
+
out = rCmd(cmd)[0]
|
|
577
|
+
if "i2c_transfer" not in out:
|
|
578
|
+
i2cttPath = os.path.join(sys.path[0], "i2c_transfer")
|
|
579
|
+
if not os.path.exists(i2cttPath):
|
|
580
|
+
loge(f"{i2cttPath} not exist!")
|
|
581
|
+
return
|
|
582
|
+
cmd = f"adb -s {self.serial} push {i2cttPath} system/bin"
|
|
583
|
+
out, err = rCmd(cmd, showCmd=True, logLevel="debug")
|
|
584
|
+
checkMsg(err, "failed", "device may need remount")
|
|
585
|
+
cmd = f"adb -s {self.serial} shell chmod a+x /system/bin/i2c_transfer"
|
|
586
|
+
out, err = rCmd(cmd, showCmd=True, logLevel="debug")
|
|
587
|
+
|
|
588
|
+
def i2cTest(self, dev, addr):
|
|
589
|
+
self.pushI2cTransfer()
|
|
590
|
+
cmd = f"adb shell /system/bin/i2c_transfer {dev} w2@{addr} 0x0 0x0 r1"
|
|
591
|
+
info, _ = rCmd(cmd, showCmd=True, logLevel="debug")
|
|
592
|
+
return info != ""
|
|
593
|
+
|
|
594
|
+
def i2cDet(self, devID=None):
|
|
595
|
+
self.pushI2cTransfer()
|
|
596
|
+
if devID is not None:
|
|
597
|
+
for j in range(0x10, 0x77):
|
|
598
|
+
print("\r" + f"detecting dev[{devID}] addr[{hex(j)}]", end=" ")
|
|
599
|
+
if self.i2cTest(devID, hex(j)):
|
|
600
|
+
print(f"| dev-{devID} detected {hex(j)}")
|
|
601
|
+
print("")
|
|
602
|
+
else:
|
|
603
|
+
for i in range(0, 2):
|
|
604
|
+
for j in range(0x10, 0x77):
|
|
605
|
+
print("\r" + f"detecting dev[{i}] addr[{hex(j)}]", end=" ")
|
|
606
|
+
if self.i2cTest(i, hex(j)):
|
|
607
|
+
print(f"| dev-{i} detected {hex(j)}")
|
|
608
|
+
print("")
|
|
609
|
+
|
|
610
|
+
def i2cDump(self, busID, devAddr):
|
|
611
|
+
cmd = f"adb -s {self.serial} shell /system/bin/i2cdump -f -y {busID} {devAddr}"
|
|
612
|
+
rCmd(cmd, showCmd=True, showRet=True, logLevel="info")
|
|
613
|
+
|
|
614
|
+
def i2c(self, devID, devAddr, regAddr, regValue=None, readNum=1):
|
|
615
|
+
self.pushI2cTransfer()
|
|
616
|
+
addr_len = 2 if len(regAddr) > 4 else 1
|
|
617
|
+
preCmdStr = f"adb -s {self.serial} shell /system/bin/i2c_transfer {devID}"
|
|
618
|
+
if regValue == None:
|
|
619
|
+
if readNum == 1:
|
|
620
|
+
if addr_len == 2:
|
|
621
|
+
regAddrH = hex(int(regAddr, 16) >> 8)
|
|
622
|
+
regAddrL = hex(int(regAddr, 16) & 0xFF)
|
|
623
|
+
cmd = f"{preCmdStr} w2@{devAddr} {regAddrH} {regAddrL} r1"
|
|
624
|
+
else:
|
|
625
|
+
cmd = f"{preCmdStr} w1@{devAddr} {regAddr} r1"
|
|
626
|
+
info, err = rCmd(cmd, showCmd=True)
|
|
627
|
+
checkMsg(err, "inaccessible", "device may need remount")
|
|
628
|
+
info = info.strip().split("\n")[0].strip("'")
|
|
629
|
+
logi(f"read bus[{devID}] dev[{devAddr}] {regAddr} = {info}")
|
|
630
|
+
else:
|
|
631
|
+
regAddr = int(regAddr, 16)
|
|
632
|
+
for i in range(readNum):
|
|
633
|
+
if addr_len == 2:
|
|
634
|
+
regAddrH = hex(regAddr >> 8)
|
|
635
|
+
regAddrL = hex(regAddr & 0xFF)
|
|
636
|
+
cmd = f"{preCmdStr} w{addr_len}@{devAddr} {regAddrH} {regAddrL} r1"
|
|
637
|
+
else:
|
|
638
|
+
cmd = f"{preCmdStr} w{addr_len}@{devAddr} {regAddr} r1"
|
|
639
|
+
info, err = rCmd(cmd, showCmd=True)
|
|
640
|
+
checkMsg(err, "inaccessible", "device may need remount")
|
|
641
|
+
info = info.strip().split("\n")[0].strip("'")
|
|
642
|
+
logi(f"read bus[{devID}] dev[{devAddr}] {hex(regAddr)} = {info}")
|
|
643
|
+
regAddr = regAddr + 1
|
|
644
|
+
else:
|
|
645
|
+
cmd = ""
|
|
646
|
+
value_len = 2 if len(regValue) > 4 else 1
|
|
647
|
+
if addr_len == 2:
|
|
648
|
+
regAddrH = hex(int(regAddr, 16) >> 8)
|
|
649
|
+
regAddrL = hex(int(regAddr, 16) & 0xFF)
|
|
650
|
+
if value_len == 1:
|
|
651
|
+
cmd = f"{preCmdStr} w3@{devAddr} {regAddrH} {regAddrL} {regValue}"
|
|
652
|
+
elif value_len == 2:
|
|
653
|
+
regValueH = hex(int(regValue, 16) >> 8)
|
|
654
|
+
regValueL = hex(int(regValue, 16) & 0xFF)
|
|
655
|
+
cmd = f"{preCmdStr} w4@{devAddr} {regAddrH} {regAddrL} {regValueH} {regValueL}"
|
|
656
|
+
else:
|
|
657
|
+
cmd = f"{preCmdStr} w2@{devAddr} {regAddr} {regValue}"
|
|
658
|
+
info, err = rCmd(cmd, showCmd=True)
|
|
659
|
+
checkMsg(err, "inaccessible", "device may need remount")
|
|
660
|
+
info = info.strip().split("\n")[0].strip("'")
|
|
661
|
+
logi(f"write bus[{devID}] dev[{devAddr}] {regAddr} = {regValue}")
|
|
662
|
+
|
|
663
|
+
def i2c_write_addr16_value8(self, devID, devAddr, regAddr, value):
|
|
664
|
+
regValue = str(hex(value))
|
|
665
|
+
regAddrH = hex(int(regAddr, 16) >> 8)
|
|
666
|
+
regAddrL = hex(int(regAddr, 16) & 0xFF)
|
|
667
|
+
preCmdStr = f"adb -s {self.serial} shell /system/bin/i2c_transfer {devID}"
|
|
668
|
+
cmd = f"{preCmdStr} w3@{devAddr} {regAddrH} {regAddrL} {regValue}"
|
|
669
|
+
info, err = rCmd(cmd, showCmd=True)
|
|
670
|
+
checkMsg(err, "inaccessible", "device may need remount")
|
|
671
|
+
info = info.strip().split("\n")[0].strip("'")
|
|
672
|
+
logi(f"write bus[{devID}] dev[{devAddr}] {regAddr} = {regValue}")
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
def CLI_pushSo(argsList):
|
|
676
|
+
parser = argparse.ArgumentParser(prog="pushso", description="android设备push so文件")
|
|
677
|
+
parser.add_argument("-p", "--path", required=True, nargs="+", help="so文件名或路径,支持多so文件 push")
|
|
678
|
+
parser.add_argument("-s", "--serial", type=str, default="", help="设备SN号(多设备需指定)")
|
|
679
|
+
args = parser.parse_args(argsList)
|
|
680
|
+
|
|
681
|
+
dev = DevOp(args.serial)
|
|
682
|
+
so = []
|
|
683
|
+
if len(args.path) == 1:
|
|
684
|
+
if os.path.isdir(args.path[0]):
|
|
685
|
+
so = findFilesBySuffixKeyword(args.path[0], ".so", "")
|
|
686
|
+
dev.pushso(so)
|
|
687
|
+
else:
|
|
688
|
+
dev.pushso(args.path)
|
|
689
|
+
else:
|
|
690
|
+
dev.pushso(args.path)
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def CLI_scrcpy(argsList):
|
|
694
|
+
parser = argparse.ArgumentParser(prog="scrcpy", description="android设备投屏")
|
|
695
|
+
parser.add_argument("-s", "--serial", type=str, default="", help="设备SN号(多设备需指定)")
|
|
696
|
+
parser.add_argument("--top", action="store_true", dest="top", help="投屏置顶")
|
|
697
|
+
parser.set_defaults(top=False)
|
|
698
|
+
parser.add_argument("--lcdoff", action="store_true", dest="lcdoff", help="关闭lcd")
|
|
699
|
+
parser.set_defaults(lcdoff=False)
|
|
700
|
+
args = parser.parse_args(argsList)
|
|
701
|
+
|
|
702
|
+
dev = DevOp(args.serial)
|
|
703
|
+
args_top = "scrcpy --always-on-top" if args.top else "scrcpy"
|
|
704
|
+
lcd_off = "-SKw -s" if args.lcdoff else "-Kw -s"
|
|
705
|
+
cmd = f"{args_top} {lcd_off} {dev.serial} --shortcut-mod=lctrl"
|
|
706
|
+
info, err = pCmd(cmd, showCmd=True, waitDone=False, logLevel="info")
|
|
707
|
+
# print(err)
|
|
708
|
+
checkMsg(err, "Device disconnected", err)
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
def CLI_power(argsList):
|
|
712
|
+
parser = argparse.ArgumentParser(prog="power", description="android power on/off")
|
|
713
|
+
parser.add_argument("-s", "--serial", type=str, default="", help="设备SN号(多设备需指定)")
|
|
714
|
+
parser.add_argument("--off", action="store_false", dest="power", help="关闭屏幕")
|
|
715
|
+
parser.set_defaults(power=True)
|
|
716
|
+
args = parser.parse_args(argsList)
|
|
717
|
+
|
|
718
|
+
dev = DevOp(args.serial)
|
|
719
|
+
logi("power on" if args.power else "power off")
|
|
720
|
+
dev.lcdOnAndUnlock(args.power)
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
def CLI_cam(args):
|
|
724
|
+
dev = DevOp()
|
|
725
|
+
if len(args) == 0:
|
|
726
|
+
dev.openCam()
|
|
727
|
+
else:
|
|
728
|
+
# TODO 支持切换前摄
|
|
729
|
+
dev.openCam(int(args[0]))
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
def CLI_screenCap(argsList):
|
|
733
|
+
parser = argparse.ArgumentParser(prog="screenCap", description="android设备截屏")
|
|
734
|
+
parser.add_argument(
|
|
735
|
+
"-f", "--file", required=False, default="tmp", help="截屏文件名,自动添加后缀.png (默认tmp,可选)"
|
|
736
|
+
)
|
|
737
|
+
parser.add_argument("-s", "--serial", type=str, default="", help="设备SN号(多设备需指定)")
|
|
738
|
+
args = parser.parse_args(argsList)
|
|
739
|
+
|
|
740
|
+
dev = DevOp(args.serial)
|
|
741
|
+
if not dev.isLcdOn():
|
|
742
|
+
eExit("lcd off")
|
|
743
|
+
dev.adbScreenCap(args.file)
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
def CLI_screenRec(argsList):
|
|
747
|
+
parser = argparse.ArgumentParser(prog="screenRec", description="对android设备录屏")
|
|
748
|
+
parser.add_argument(
|
|
749
|
+
"-f", "--file", required=False, default="tmp", help="录制文件名,自动添加后缀.mp4 (默认tmp,可选)"
|
|
750
|
+
)
|
|
751
|
+
parser.add_argument("-t", "--time", required=False, default="30", help="录制时间,单位秒 (默认30秒,可选)")
|
|
752
|
+
parser.add_argument("-b", "--bitrate", required=False, default="2", help="录制比特率,单位Mbps (默认2,可选)")
|
|
753
|
+
parser.add_argument("-s", "--serial", type=str, default="", help="设备SN号(多设备需指定)")
|
|
754
|
+
parser.add_argument("--width", required=False, default=None, help="录制宽度 (默认lcd size,可选)")
|
|
755
|
+
parser.add_argument("--height", required=False, default=None, help="录制高度 (默认lcd size,可选)")
|
|
756
|
+
parser.add_argument(
|
|
757
|
+
"--no-debug", action="store_false", dest="debug", help="禁用调试模式,开启可在视频上添加时间戳等额外信息"
|
|
758
|
+
)
|
|
759
|
+
parser.set_defaults(debug=True) # 设置默认值为 True
|
|
760
|
+
args = parser.parse_args(argsList)
|
|
761
|
+
|
|
762
|
+
dev = DevOp(args.serial)
|
|
763
|
+
if not dev.isLcdOn():
|
|
764
|
+
eExit("lcd off")
|
|
765
|
+
dev.adbScreenRec(
|
|
766
|
+
fileName=args.file,
|
|
767
|
+
limitTime_s=args.time,
|
|
768
|
+
bitRate_Mbps=args.bitrate,
|
|
769
|
+
inputWidth=args.width if args.width else None,
|
|
770
|
+
inputHeight=args.height if args.height else None,
|
|
771
|
+
debug=args.debug,
|
|
772
|
+
)
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
def i2cParseArguments(argsList):
|
|
776
|
+
parser = argparse.ArgumentParser(prog="iic", description="对android设备进行iic操作")
|
|
777
|
+
|
|
778
|
+
# 创建子解析器
|
|
779
|
+
subparsers = parser.add_subparsers(dest="operation", required=True, help="操作类型")
|
|
780
|
+
|
|
781
|
+
# 1. rw 操作
|
|
782
|
+
parser_rw = subparsers.add_parser("rw", help="读写操作")
|
|
783
|
+
parser_rw.add_argument("-b", "--busid", required=True, choices=["0", "1", "2"], help="设备ID (必须)")
|
|
784
|
+
parser_rw.add_argument("-d", "--devaddr", required=True, help="设备地址 (必须)")
|
|
785
|
+
parser_rw.add_argument("-a", "--addr", required=True, help="设备寄存器地址 (必须)")
|
|
786
|
+
parser_rw.add_argument("-v", "--value", required=False, default=None, help="设备寄存器值 (读取不用设)")
|
|
787
|
+
parser_rw.add_argument("-r", "--readnum", type=str, default="1", help="读取寄存器数量 (可选)")
|
|
788
|
+
|
|
789
|
+
# 2. det 操作
|
|
790
|
+
parser_det = subparsers.add_parser("det", help="检测操作")
|
|
791
|
+
parser_det.add_argument("-b", "--busid", choices=["0", "1", "2"], help="设备ID (可选)")
|
|
792
|
+
|
|
793
|
+
# 3. dump 操作
|
|
794
|
+
parser_dump = subparsers.add_parser("dump", help="总线检查操作")
|
|
795
|
+
parser_dump.add_argument("-b", "--busid", required=True, choices=["0", "1", "2"], help="设备ID (必须)")
|
|
796
|
+
parser_dump.add_argument("-d", "--devaddr", required=True, help="设备地址 (必须)")
|
|
797
|
+
|
|
798
|
+
args = parser.parse_args(argsList)
|
|
799
|
+
return args
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
def CLI_i2c(argsList):
|
|
803
|
+
args = i2cParseArguments(argsList)
|
|
804
|
+
dev = DevOp(needRoot=False)
|
|
805
|
+
|
|
806
|
+
if args.operation == "det":
|
|
807
|
+
# det 操作:busid 可选
|
|
808
|
+
if args.busid is not None:
|
|
809
|
+
dev.i2cDet(int(args.busid))
|
|
810
|
+
else:
|
|
811
|
+
dev.i2cDet()
|
|
812
|
+
|
|
813
|
+
elif args.operation == "dump":
|
|
814
|
+
# dump 操作:busid 和 devaddr 必须
|
|
815
|
+
dev.i2cDump(args.busid, args.devaddr)
|
|
816
|
+
|
|
817
|
+
elif args.operation == "rw":
|
|
818
|
+
# rw 操作:
|
|
819
|
+
dev.i2c(args.busid, args.devaddr, args.addr, args.value, int(args.readnum))
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
def CLI_kcam(args):
|
|
823
|
+
dev = DevOp()
|
|
824
|
+
dev.killCamera()
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
def CLI_capjpg(argsList):
|
|
828
|
+
parser = argparse.ArgumentParser(prog="capjpg", description="拍摄jpg并导出到PC指定文件名")
|
|
829
|
+
parser.add_argument("-f", "--file", type=str, default="null", help="jpg名称")
|
|
830
|
+
parser.add_argument("-s", "--serial", type=str, default="", help="设备SN号")
|
|
831
|
+
parser.add_argument("-w", "--wait", type=int, default=3, help="拍照之后等待时间,单位秒,deault 3s")
|
|
832
|
+
parser.add_argument("-d", "--devname", type=str, default=None, help="jpg名称后缀标签")
|
|
833
|
+
parser.add_argument("--reset", action="store_true", help="清除缓存,重新扫描设备")
|
|
834
|
+
args = parser.parse_args(argsList)
|
|
835
|
+
if args.reset and os.path.exists(CACHE_FILE):
|
|
836
|
+
os.remove(CACHE_FILE)
|
|
837
|
+
logi("[cache] 缓存已清除")
|
|
838
|
+
dev = DevOp(args.serial)
|
|
839
|
+
dev.checkCameraOpened()
|
|
840
|
+
name = args.file + args.devname if args.devname else args.file
|
|
841
|
+
dev.capJPG(name, wait=args.wait)
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
def CLI_capjpgThread(argsList):
|
|
845
|
+
parser = argparse.ArgumentParser(prog="capjpg2", description="同时拍摄两台机器jpg并导出到PC指定文件名")
|
|
846
|
+
parser.add_argument("-f", "--file", type=str, default="null", help="jpg名称")
|
|
847
|
+
parser.add_argument("-s1", "--serial1", type=str, required=True, help="设备1 SN号")
|
|
848
|
+
parser.add_argument("-s2", "--serial2", type=str, required=True, help="设备2 SN号")
|
|
849
|
+
parser.add_argument("-w", "--wait", type=int, default=3, help="拍照之后等待时间,单位秒")
|
|
850
|
+
parser.add_argument("-d1", "--devname1", type=str, required=True, help="设备1 jpg名称后缀标签")
|
|
851
|
+
parser.add_argument("-d2", "--devname2", type=str, required=True, help="设备2 jpg名称后缀标签")
|
|
852
|
+
args = parser.parse_args(argsList)
|
|
853
|
+
d1 = f"-f {args.file} -s {args.serial1} -w {args.wait} -d {args.devname1}".split()
|
|
854
|
+
d2 = f"-f {args.file} -s {args.serial2} -w {args.wait} -d {args.devname2}".split()
|
|
855
|
+
thread1 = threading.Thread(target=CLI_capjpg, args=(d1,))
|
|
856
|
+
thread2 = threading.Thread(target=CLI_capjpg, args=(d2,))
|
|
857
|
+
thread1.start()
|
|
858
|
+
thread2.start()
|
|
859
|
+
thread1.join()
|
|
860
|
+
thread2.join()
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
def CLI_wirelessHelp(args=None):
|
|
864
|
+
print(" linux: 10.1.164.212")
|
|
865
|
+
print(" windows: 10.1.176.39")
|
|
866
|
+
print(" 手机开启热点,PC连接热点")
|
|
867
|
+
print(' adb shell ifconfig |grep "inet addr" #查看ip')
|
|
868
|
+
print(" adb shell ip route #查看ip")
|
|
869
|
+
print(" adb tcpip 5 ")
|
|
870
|
+
print(" adb connect 192.168.191.2:5 ")
|
|
871
|
+
print(" adb disconnect 192.168.191.2:5 #断开连接")
|
|
872
|
+
print(" adb usb #切换回usb")
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
def CLI_rootRemount(argsList):
|
|
876
|
+
parser = argparse.ArgumentParser(prog="rootRemount", description="android设备root,remount")
|
|
877
|
+
parser.add_argument("-s", "--serial", type=str, default="", help="设备SN号(多设备需指定)")
|
|
878
|
+
args = parser.parse_args(argsList)
|
|
879
|
+
|
|
880
|
+
dev = DevOp(args.serial, needRoot=True)
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
def _dsrPrepare(dev_1: DevOp, dev_2: DevOp):
|
|
884
|
+
dev_1.adbTap((500, 1500), 0)
|
|
885
|
+
dev_1.adbTap((500, 1500), 0)
|
|
886
|
+
dev_1.adbTap((580, 128), 0)
|
|
887
|
+
dev_1.adbTap((580, 128), 0)
|
|
888
|
+
dev_2.adbTap((580, 128), 0)
|
|
889
|
+
dev_2.adbTap((580, 128), 0)
|
|
890
|
+
sleep(1)
|
|
891
|
+
dev_1.adbTap((580, 128), 0)
|
|
892
|
+
dev_2.adbTap((580, 128), 0)
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
def CLI_threadScreenRec(argsList):
|
|
896
|
+
parser = argparse.ArgumentParser(prog="screenRec", description="对android设备录屏")
|
|
897
|
+
parser.add_argument(
|
|
898
|
+
"-f", "--file", required=False, default="tmp", help="录制文件名,自动添加后缀.mp4 (默认tmp,可选)"
|
|
899
|
+
)
|
|
900
|
+
parser.add_argument("-t", "--time", required=False, default="30", help="录制时间,单位秒 (默认30秒,可选)")
|
|
901
|
+
parser.add_argument("-b", "--bitrate", required=False, default="2", help="录制比特率,单位Mbps (默认2,可选)")
|
|
902
|
+
parser.add_argument("--width", required=False, default=None, help="录制宽度 (默认lcd size,可选)")
|
|
903
|
+
parser.add_argument("--height", required=False, default=None, help="录制高度 (默认lcd size,可选)")
|
|
904
|
+
parser.add_argument(
|
|
905
|
+
"--no-debug", action="store_false", dest="debug", help="禁用调试模式,开启可在视频上添加时间戳等额外信息"
|
|
906
|
+
)
|
|
907
|
+
parser.set_defaults(debug=True) # 设置默认值为 True
|
|
908
|
+
|
|
909
|
+
parser.add_argument("--serial1", required=True, help="设备1 SN号")
|
|
910
|
+
parser.add_argument("--serial2", required=True, help="设备2 SN号")
|
|
911
|
+
args = parser.parse_args(argsList)
|
|
912
|
+
s1 = args.serial1
|
|
913
|
+
s2 = args.serial2
|
|
914
|
+
dev_1 = DevOp(s1)
|
|
915
|
+
dev_2 = DevOp(s2)
|
|
916
|
+
_dsrPrepare(dev_1, dev_2)
|
|
917
|
+
|
|
918
|
+
thread1 = threading.Thread(
|
|
919
|
+
target=dev_1.adbScreenRec,
|
|
920
|
+
kwargs={
|
|
921
|
+
"fileName": f"{args.file}_{s1}",
|
|
922
|
+
"limitTime_s": args.time,
|
|
923
|
+
"bitRate_Mbps": args.bitrate,
|
|
924
|
+
"inputWidth": args.width,
|
|
925
|
+
"inputHeight": args.height,
|
|
926
|
+
"debug": args.debug,
|
|
927
|
+
"isThread": True,
|
|
928
|
+
},
|
|
929
|
+
)
|
|
930
|
+
|
|
931
|
+
thread2 = threading.Thread(
|
|
932
|
+
target=dev_2.adbScreenRec,
|
|
933
|
+
kwargs={
|
|
934
|
+
"fileName": f"{args.file}_{s2}",
|
|
935
|
+
"limitTime_s": args.time,
|
|
936
|
+
"bitRate_Mbps": args.bitrate,
|
|
937
|
+
"inputWidth": args.width,
|
|
938
|
+
"inputHeight": args.height,
|
|
939
|
+
"debug": args.debug,
|
|
940
|
+
"isThread": True,
|
|
941
|
+
},
|
|
942
|
+
)
|
|
943
|
+
|
|
944
|
+
thread1.start()
|
|
945
|
+
thread2.start()
|
|
946
|
+
thread1.join()
|
|
947
|
+
thread2.join()
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
def CLI_clenDevCache(argsList):
|
|
951
|
+
if os.path.exists(CACHE_FILE):
|
|
952
|
+
os.remove(CACHE_FILE)
|
|
953
|
+
logi("[cache] 缓存已清除")
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
_COMMAND_REGISTRY = {}
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
def printHelp():
|
|
960
|
+
print("[device]")
|
|
961
|
+
print("pushso -h :push so to vendor/lib64")
|
|
962
|
+
print("scr -h :android 投屏")
|
|
963
|
+
print("po -h :android power {--off}")
|
|
964
|
+
print("cam :open camera")
|
|
965
|
+
print("sc -h :android 截屏- {name}:without suffix")
|
|
966
|
+
print("sr -h :android 录屏- {name}:without suffix")
|
|
967
|
+
print("dsr -h :android 双设备同时录屏")
|
|
968
|
+
print("iic {rw/det/dump} -h :android i2c 操作")
|
|
969
|
+
print("kcam :kill android cameraserver and clean camera app")
|
|
970
|
+
print("capjpg -h :capture jpg")
|
|
971
|
+
print("capjpg2 -h :capture jpg in a threaded way")
|
|
972
|
+
print("wi :show wireless help")
|
|
973
|
+
print("rt -h :root and remount")
|
|
974
|
+
print("cl :clear device cache")
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
CLI_pushSo = register_command("pushso", registry=_COMMAND_REGISTRY)(CLI_pushSo)
|
|
978
|
+
CLI_scrcpy = register_command("scr", registry=_COMMAND_REGISTRY)(CLI_scrcpy)
|
|
979
|
+
CLI_power = register_command("po", registry=_COMMAND_REGISTRY)(CLI_power)
|
|
980
|
+
CLI_cam = register_command("cam", registry=_COMMAND_REGISTRY)(CLI_cam)
|
|
981
|
+
CLI_screenCap = register_command("sc", registry=_COMMAND_REGISTRY)(CLI_screenCap)
|
|
982
|
+
CLI_screenRec = register_command("sr", registry=_COMMAND_REGISTRY)(CLI_screenRec)
|
|
983
|
+
CLI_threadScreenRec = register_command("dsr", registry=_COMMAND_REGISTRY)(CLI_threadScreenRec)
|
|
984
|
+
CLI_i2c = register_command("iic", registry=_COMMAND_REGISTRY)(CLI_i2c)
|
|
985
|
+
CLI_kcam = register_command("kcam", registry=_COMMAND_REGISTRY)(CLI_kcam)
|
|
986
|
+
CLI_capjpg = register_command("capjpg", registry=_COMMAND_REGISTRY)(CLI_capjpg)
|
|
987
|
+
CLI_capjpgThread = register_command("capjpg2", registry=_COMMAND_REGISTRY)(CLI_capjpgThread)
|
|
988
|
+
CLI_wirelessHelp = register_command("wi", registry=_COMMAND_REGISTRY)(CLI_wirelessHelp)
|
|
989
|
+
CLI_rootRemount = register_command("rt", registry=_COMMAND_REGISTRY)(CLI_rootRemount)
|
|
990
|
+
CLI_clenDevCache = register_command("cl", registry=_COMMAND_REGISTRY)(CLI_clenDevCache)
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
def deviceMain(args):
|
|
994
|
+
debugCtrl(1) if "debug" in args else debugCtrl(0)
|
|
995
|
+
args.remove("debug") if "debug" in args else args
|
|
996
|
+
args = normalize_args(args)
|
|
997
|
+
if len(args) < 1 or args[0] in {"help", "-h", "--help"}:
|
|
998
|
+
printHelp()
|
|
999
|
+
return
|
|
1000
|
+
cmd = args[0]
|
|
1001
|
+
handler = _COMMAND_REGISTRY.get(cmd)
|
|
1002
|
+
if handler is None:
|
|
1003
|
+
loge(f"unsupport command {cmd}")
|
|
1004
|
+
return
|
|
1005
|
+
handler(args[1:])
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
if __name__ == "__main__":
|
|
1009
|
+
debugCtrl(1) if "debug" in sys.argv else debugCtrl(0)
|
|
1010
|
+
sys.argv.remove("debug") if "debug" in sys.argv else sys.argv
|
|
1011
|
+
deviceMain(sys.argv)
|