Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/ts/misc/run_android.py
16344 views
1
#!/usr/bin/env python
2
import os
3
import re
4
import getpass
5
from run_utils import Err, log, execute, isColorEnabled, hostos
6
from run_suite import TestSuite
7
8
9
def exe(program):
10
return program + ".exe" if hostos == 'nt' else program
11
12
13
class ApkInfo:
14
def __init__(self):
15
self.pkg_name = None
16
self.pkg_target = None
17
self.pkg_runner = None
18
19
def forcePackage(self, package):
20
if package:
21
if package.startswith("."):
22
self.pkg_target += package
23
else:
24
self.pkg_target = package
25
26
27
class Tool:
28
def __init__(self):
29
self.cmd = []
30
31
def run(self, args=[], silent=False):
32
cmd = self.cmd[:]
33
cmd.extend(args)
34
return execute(self.cmd + args, silent)
35
36
37
class Adb(Tool):
38
def __init__(self, sdk_dir):
39
Tool.__init__(self)
40
exe_path = os.path.join(sdk_dir, exe("platform-tools/adb"))
41
if not os.path.isfile(exe_path) or not os.access(exe_path, os.X_OK):
42
exe_path = None
43
# fix adb tool location
44
if not exe_path:
45
exe_path = "adb"
46
self.cmd = [exe_path]
47
48
def init(self, serial):
49
# remember current device serial. Needed if another device is connected while this script runs
50
if not serial:
51
serial = self.detectSerial()
52
if serial:
53
self.cmd.extend(["-s", serial])
54
55
def detectSerial(self):
56
adb_res = self.run(["devices"], silent=True)
57
# assume here that device name may consists of any characters except newline
58
connected_devices = re.findall(r"^[^\n]+[ \t]+device\r?$", adb_res, re.MULTILINE)
59
if not connected_devices:
60
raise Err("Can not find Android device")
61
elif len(connected_devices) != 1:
62
raise Err("Too many (%s) devices are connected. Please specify single device using --serial option:\n\n%s", len(connected_devices), adb_res)
63
else:
64
return connected_devices[0].split("\t")[0]
65
66
def getOSIdentifier(self):
67
return "Android" + self.run(["shell", "getprop ro.build.version.release"], silent=True).strip()
68
69
70
class Aapt(Tool):
71
def __init__(self, sdk_dir):
72
Tool.__init__(self)
73
aapt_fn = exe("aapt")
74
aapt = None
75
for r, ds, fs in os.walk(os.path.join(sdk_dir, 'build-tools')):
76
if aapt_fn in fs:
77
aapt = os.path.join(r, aapt_fn)
78
break
79
if not aapt:
80
raise Err("Can not find aapt tool: %s", aapt_fn)
81
self.cmd = [aapt]
82
83
def dump(self, exe):
84
res = ApkInfo()
85
output = self.run(["dump", "xmltree", exe, "AndroidManifest.xml"], silent=True)
86
if not output:
87
raise Err("Can not dump manifest from %s", exe)
88
tags = re.split(r"[ ]+E: ", output)
89
# get package name
90
manifest_tag = [t for t in tags if t.startswith("manifest ")]
91
if not manifest_tag:
92
raise Err("Can not read package name from: %s", exe)
93
res.pkg_name = re.search(r"^[ ]+A: package=\"(?P<pkg>.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", manifest_tag[0], flags=re.MULTILINE).group("pkg")
94
# get test instrumentation info
95
instrumentation_tag = [t for t in tags if t.startswith("instrumentation ")]
96
if not instrumentation_tag:
97
raise Err("Can not find instrumentation detials in: %s", exe)
98
res.pkg_runner = re.search(r"^[ ]+A: android:name\(0x[0-9a-f]{8}\)=\"(?P<runner>.*?)\" \(Raw: \"(?P=runner)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("runner")
99
res.pkg_target = re.search(r"^[ ]+A: android:targetPackage\(0x[0-9a-f]{8}\)=\"(?P<pkg>.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("pkg")
100
if not res.pkg_name or not res.pkg_runner or not res.pkg_target:
101
raise Err("Can not find instrumentation detials in: %s", exe)
102
return res
103
104
105
class AndroidTestSuite(TestSuite):
106
def __init__(self, options, cache, id, android_env={}):
107
TestSuite.__init__(self, options, cache, id)
108
sdk_dir = options.android_sdk or os.environ.get("ANDROID_SDK", False) or os.path.dirname(os.path.dirname(self.cache.android_executable))
109
log.debug("Detecting Android tools in directory: %s", sdk_dir)
110
self.adb = Adb(sdk_dir)
111
self.aapt = Aapt(sdk_dir)
112
self.env = android_env
113
114
def isTest(self, fullpath):
115
if os.path.isfile(fullpath):
116
if fullpath.endswith(".apk") or os.access(fullpath, os.X_OK):
117
return True
118
return False
119
120
def getOS(self):
121
return self.adb.getOSIdentifier()
122
123
def checkPrerequisites(self):
124
self.adb.init(self.options.serial)
125
126
def runTest(self, module, path, logfile, workingDir, args=[]):
127
args = args[:]
128
exe = os.path.abspath(path)
129
130
if exe.endswith(".apk"):
131
info = self.aapt.dump(exe)
132
if not info:
133
raise Err("Can not read info from test package: %s", exe)
134
info.forcePackage(self.options.package)
135
self.adb.run(["uninstall", info.pkg_name])
136
137
output = self.adb.run(["install", exe], silent=True)
138
if not (output and "Success" in output):
139
raise Err("Can not install package: %s", exe)
140
141
params = ["-e package %s" % info.pkg_target]
142
ret = self.adb.run(["shell", "am instrument -w %s %s/%s" % (" ".join(params), info.pkg_name, info.pkg_runner)])
143
return None, ret
144
else:
145
device_dir = getpass.getuser().replace(" ", "") + "_" + self.options.mode + "/"
146
if isColorEnabled(args):
147
args.append("--gtest_color=yes")
148
tempdir = "/data/local/tmp/"
149
android_dir = tempdir + device_dir
150
exename = os.path.basename(exe)
151
android_exe = android_dir + exename
152
self.adb.run(["push", exe, android_exe])
153
self.adb.run(["shell", "chmod 777 " + android_exe])
154
env_pieces = ["export %s=%s" % (a, b) for a, b in self.env.items()]
155
pieces = ["cd %s" % android_dir, "./%s %s" % (exename, " ".join(args))]
156
log.warning("Run: %s" % " && ".join(pieces))
157
ret = self.adb.run(["shell", " && ".join(env_pieces + pieces)])
158
# try get log
159
hostlogpath = os.path.join(workingDir, logfile)
160
self.adb.run(["pull", android_dir + logfile, hostlogpath])
161
# cleanup
162
self.adb.run(["shell", "rm " + android_dir + logfile])
163
self.adb.run(["shell", "rm " + tempdir + "__opencv_temp.*"], silent=True)
164
if os.path.isfile(hostlogpath):
165
return hostlogpath, ret
166
return None, ret
167
168
169
if __name__ == "__main__":
170
log.error("This is utility file, please execute run.py script")
171
172