python-audio-autotest-3.10 1.5.12rc1__py3-none-any.whl → 1.6__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.
- pyaatlibs/__init__.py +3 -2
- pyaatlibs/aatapp.py +92 -26
- pyaatlibs/activitystatemachine.py +4 -1
- pyaatlibs/adbutils.py +63 -35
- pyaatlibs/apk/audioworker.apk +0 -0
- pyaatlibs/appinterface.py +57 -22
- pyaatlibs/argutils.py +2 -0
- pyaatlibs/audiofunction.py +59 -27
- pyaatlibs/audiosignalframelogger.py +10 -9
- pyaatlibs/audiothread.py +32 -25
- pyaatlibs/audioworker.py +211 -90
- pyaatlibs/logcatlistener.py +19 -8
- pyaatlibs/logger.py +21 -8
- pyaatlibs/signalanalyzer.py +3 -1
- pyaatlibs/signalmatcher.py +14 -9
- pyaatlibs/tests/audioworker_test.py +168 -162
- pyaatlibs/timeutils.py +14 -5
- pyaatlibs/trials.py +9 -3
- {python_audio_autotest_3_10-1.5.12rc1.dist-info → python_audio_autotest_3_10-1.6.dist-info}/METADATA +1 -1
- python_audio_autotest_3_10-1.6.dist-info/RECORD +25 -0
- python_audio_autotest_3_10-1.5.12rc1.dist-info/RECORD +0 -25
- {python_audio_autotest_3_10-1.5.12rc1.dist-info → python_audio_autotest_3_10-1.6.dist-info}/WHEEL +0 -0
- {python_audio_autotest_3_10-1.5.12rc1.dist-info → python_audio_autotest_3_10-1.6.dist-info}/licenses/LICENSE +0 -0
- {python_audio_autotest_3_10-1.5.12rc1.dist-info → python_audio_autotest_3_10-1.6.dist-info}/top_level.txt +0 -0
pyaatlibs/__init__.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
import platform
|
3
3
|
|
4
|
-
__version__ = "1.
|
4
|
+
__version__ = "1.6"
|
5
5
|
__author__ = "Hao-Wei Lee"
|
6
6
|
if platform.system() == "Windows":
|
7
7
|
SEP = "\\"
|
@@ -12,5 +12,6 @@ else:
|
|
12
12
|
|
13
13
|
ROOT_DIR = SEP.join(os.path.dirname(os.path.realpath(__file__)).split(SEP)[:-1])
|
14
14
|
|
15
|
+
|
15
16
|
def get_path(*names):
|
16
|
-
|
17
|
+
return "{}{}{}".format(ROOT_DIR, SEP, SEP.join(names))
|
pyaatlibs/aatapp.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import os
|
2
2
|
|
3
|
+
|
3
4
|
class AATApp(object):
|
4
5
|
INTENT_PREFIX = "am broadcast -a"
|
5
6
|
HTC_INTENT_PREFIX = "audio.htc.com.intent."
|
@@ -19,12 +20,24 @@ class AATApp(object):
|
|
19
20
|
|
20
21
|
@staticmethod
|
21
22
|
def playback_nonoffload(device, filename="440Hz.wav"):
|
22
|
-
cmd = " ".join([
|
23
|
+
cmd = " ".join([
|
24
|
+
AATApp.INTENT_PREFIX,
|
25
|
+
AATApp.HTC_INTENT_PREFIX + "playback.nonoffload",
|
26
|
+
"--es",
|
27
|
+
"file",
|
28
|
+
filename,
|
29
|
+
])
|
23
30
|
device.shell(cmd)
|
24
31
|
|
25
32
|
@staticmethod
|
26
33
|
def playback_offload(device, filename="440Hz.mp3"):
|
27
|
-
cmd = " ".join([
|
34
|
+
cmd = " ".join([
|
35
|
+
AATApp.INTENT_PREFIX,
|
36
|
+
AATApp.HTC_INTENT_PREFIX + "playback.offload",
|
37
|
+
"--es",
|
38
|
+
"file",
|
39
|
+
filename,
|
40
|
+
])
|
28
41
|
device.shell(cmd)
|
29
42
|
|
30
43
|
@staticmethod
|
@@ -34,7 +47,13 @@ class AATApp(object):
|
|
34
47
|
|
35
48
|
@staticmethod
|
36
49
|
def record_start(device):
|
37
|
-
cmd = " ".join([
|
50
|
+
cmd = " ".join([
|
51
|
+
AATApp.INTENT_PREFIX,
|
52
|
+
AATApp.HTC_INTENT_PREFIX + "record.start",
|
53
|
+
"--ei",
|
54
|
+
"spt_xmax",
|
55
|
+
"1000",
|
56
|
+
])
|
38
57
|
device.shell(cmd)
|
39
58
|
|
40
59
|
@staticmethod
|
@@ -44,12 +63,20 @@ class AATApp(object):
|
|
44
63
|
|
45
64
|
@staticmethod
|
46
65
|
def record_dump(device, path):
|
47
|
-
cmd = " ".join(
|
66
|
+
cmd = " ".join(
|
67
|
+
[AATApp.INTENT_PREFIX, AATApp.HTC_INTENT_PREFIX + "record.dump", "--es", "path", path]
|
68
|
+
)
|
48
69
|
device.shell(cmd)
|
49
70
|
|
50
71
|
@staticmethod
|
51
72
|
def voip_start(device):
|
52
|
-
cmd = " ".join([
|
73
|
+
cmd = " ".join([
|
74
|
+
AATApp.INTENT_PREFIX,
|
75
|
+
AATApp.HTC_INTENT_PREFIX + "voip.start",
|
76
|
+
"--ei",
|
77
|
+
"spt_xmax",
|
78
|
+
"1000",
|
79
|
+
])
|
53
80
|
device.shell(cmd)
|
54
81
|
|
55
82
|
@staticmethod
|
@@ -59,7 +86,13 @@ class AATApp(object):
|
|
59
86
|
|
60
87
|
@staticmethod
|
61
88
|
def voip_use_speaker(device, use=True):
|
62
|
-
cmd = " ".join([
|
89
|
+
cmd = " ".join([
|
90
|
+
AATApp.INTENT_PREFIX,
|
91
|
+
AATApp.HTC_INTENT_PREFIX + "voip.switch.speaker",
|
92
|
+
"--ez",
|
93
|
+
"use",
|
94
|
+
str(1 if use else 0),
|
95
|
+
])
|
63
96
|
device.shell(cmd)
|
64
97
|
|
65
98
|
@staticmethod
|
@@ -75,17 +108,31 @@ class AATApp(object):
|
|
75
108
|
def print_log(device, severity="i", tag="AATAppAPIs", log=None):
|
76
109
|
if not log:
|
77
110
|
return
|
78
|
-
cmd = " ".join([
|
79
|
-
|
111
|
+
cmd = " ".join([
|
112
|
+
AATApp.INTENT_PREFIX,
|
113
|
+
AATApp.HTC_INTENT_PREFIX + "log.print",
|
114
|
+
"--es",
|
115
|
+
"sv",
|
116
|
+
str(severity),
|
117
|
+
"--es",
|
118
|
+
"tag",
|
119
|
+
str(tag),
|
120
|
+
"--es",
|
121
|
+
"log",
|
122
|
+
'"{}"'.format(log),
|
123
|
+
])
|
80
124
|
device.shell(cmd)
|
81
125
|
|
126
|
+
|
82
127
|
import threading
|
83
128
|
import time
|
84
129
|
from pyaatlibs.audiofunction import ToneDetectorThread, ToneDetector
|
85
130
|
from pyaatlibs.logger import Logger
|
86
131
|
from pyaatlibs.adbutils import Adb
|
87
132
|
|
133
|
+
|
88
134
|
class AATAppToneDetectorThread(ToneDetectorThread):
|
135
|
+
|
89
136
|
def __init__(self, serialno, target_freq, callback):
|
90
137
|
super(AATAppToneDetectorThread, self).__init__(target_freq=target_freq, callback=callback)
|
91
138
|
self.serialno = serialno
|
@@ -114,7 +161,7 @@ class AATAppToneDetectorThread(ToneDetectorThread):
|
|
114
161
|
Logger.log(self.get_tag(), "dump called")
|
115
162
|
Logger.log(self.get_tag(), "----------------------------------------------")
|
116
163
|
for msg in self.extra["dump"]:
|
117
|
-
Logger.log("{}::dump".format(self.get_tag()), "
|
164
|
+
Logger.log("{}::dump".format(self.get_tag()), '"{}"'.format(msg))
|
118
165
|
del self.extra["dump"][:]
|
119
166
|
Logger.log(self.get_tag(), "----------------------------------------------")
|
120
167
|
self.extra["dump-lock"].release()
|
@@ -123,11 +170,7 @@ class AATAppToneDetectorThread(ToneDetectorThread):
|
|
123
170
|
super(AATAppToneDetectorThread, self).join(timeout=timeout)
|
124
171
|
|
125
172
|
def run(self):
|
126
|
-
shared_vars = {
|
127
|
-
"start_time": None,
|
128
|
-
"last_event": None,
|
129
|
-
"last_freq": -1
|
130
|
-
}
|
173
|
+
shared_vars = {"start_time": None, "last_event": None, "last_freq": -1}
|
131
174
|
|
132
175
|
self.extra = {}
|
133
176
|
self.extra["adb-read-prop-max-elapsed"] = -1
|
@@ -144,8 +187,11 @@ class AATAppToneDetectorThread(ToneDetectorThread):
|
|
144
187
|
time_str = the_date + " " + the_time
|
145
188
|
|
146
189
|
if shared_vars["last_freq"] != freq:
|
147
|
-
self.push_to_dump(
|
148
|
-
"the detected freq has been changed from {} to {} Hz".format(
|
190
|
+
self.push_to_dump(
|
191
|
+
"the detected freq has been changed from {} to {} Hz".format(
|
192
|
+
shared_vars["last_freq"], freq
|
193
|
+
)
|
194
|
+
)
|
149
195
|
shared_vars["last_freq"] = freq
|
150
196
|
|
151
197
|
thresh = 10 if self.target_freq else 1
|
@@ -154,29 +200,42 @@ class AATAppToneDetectorThread(ToneDetectorThread):
|
|
154
200
|
if self.event_counter == 1:
|
155
201
|
shared_vars["start_time"] = time_str
|
156
202
|
if self.event_counter == thresh:
|
157
|
-
if
|
158
|
-
|
203
|
+
if (
|
204
|
+
not shared_vars["last_event"]
|
205
|
+
or shared_vars["last_event"] != ToneDetector.Event.TONE_DETECTED
|
206
|
+
):
|
207
|
+
Logger.log(
|
208
|
+
self.get_tag(),
|
209
|
+
"send_cb({}, TONE_DETECTED)".format(shared_vars["start_time"]),
|
210
|
+
)
|
159
211
|
self.cb((shared_vars["start_time"], ToneDetector.Event.TONE_DETECTED))
|
160
212
|
shared_vars["last_event"] = ToneDetector.Event.TONE_DETECTED
|
161
213
|
|
162
214
|
else:
|
163
215
|
if self.event_counter > thresh:
|
164
216
|
shared_vars["start_time"] = None
|
165
|
-
self.push_to_dump(
|
166
|
-
|
167
|
-
|
217
|
+
self.push_to_dump(
|
218
|
+
"the tone is not detected and the event_counter is over the threshold"
|
219
|
+
)
|
220
|
+
self.push_to_dump('last_event: "{}"'.format(shared_vars["last_event"]))
|
221
|
+
if (
|
222
|
+
not shared_vars["last_event"]
|
223
|
+
or shared_vars["last_event"] != ToneDetector.Event.TONE_MISSING
|
224
|
+
):
|
168
225
|
Logger.log(self.get_tag(), "send_cb({}, TONE_MISSING)".format(time_str))
|
169
226
|
self.cb((time_str, ToneDetector.Event.TONE_MISSING))
|
170
227
|
shared_vars["last_event"] = ToneDetector.Event.TONE_MISSING
|
171
228
|
self.event_counter = 0
|
172
229
|
|
173
|
-
if self.event_counter <= thresh:
|
230
|
+
if self.event_counter <= thresh:
|
231
|
+
self.push_to_dump("event_counter: {}".format(self.event_counter))
|
174
232
|
|
175
233
|
# Adb.execute(cmd= \
|
176
234
|
# ["shell", "am", "broadcast", "-a", "audio.htc.com.intent.print.properties.enable", "--ez", "v", "1"], \
|
177
235
|
# serialno=self.serialno)
|
178
236
|
|
179
237
|
from pyaatlibs.timeutils import TicToc, TimeUtils
|
238
|
+
|
180
239
|
freq_cb_tictoc = TicToc()
|
181
240
|
adb_tictoc = TicToc()
|
182
241
|
|
@@ -184,12 +243,18 @@ class AATAppToneDetectorThread(ToneDetectorThread):
|
|
184
243
|
freq_cb_tictoc.tic()
|
185
244
|
while not self.stoprequest.isSet():
|
186
245
|
adb_tictoc.tic()
|
187
|
-
msg, _ = Adb.execute(
|
188
|
-
|
246
|
+
msg, _ = Adb.execute(
|
247
|
+
cmd=["shell", "cat", "sdcard/AudioFunctionsDemo-record-prop.txt"],
|
248
|
+
serialno=self.serialno,
|
249
|
+
tolog=False,
|
250
|
+
)
|
189
251
|
elapsed = adb_tictoc.toc()
|
190
252
|
if tcount == 0:
|
191
|
-
Adb.execute(
|
192
|
-
|
253
|
+
Adb.execute(
|
254
|
+
cmd=["shell", "rm", "-f", "sdcard/AudioFunctionsDemo-record-prop.txt"],
|
255
|
+
serialno=self.serialno,
|
256
|
+
tolog=False,
|
257
|
+
)
|
193
258
|
|
194
259
|
if not "," in msg:
|
195
260
|
msg = "0,-30"
|
@@ -200,6 +265,7 @@ class AATAppToneDetectorThread(ToneDetectorThread):
|
|
200
265
|
if "," in msg:
|
201
266
|
msg = msg.replace("\n", "")
|
202
267
|
import datetime
|
268
|
+
|
203
269
|
msg = "{} {}".format(TimeUtils.now_str(), msg)
|
204
270
|
|
205
271
|
try:
|
@@ -1,8 +1,11 @@
|
|
1
1
|
class ActivityStateMachine(object):
|
2
|
+
|
2
3
|
def __init__(self, device, serialno):
|
3
4
|
self.device = device
|
4
5
|
self.serialno = serialno
|
5
6
|
self.cache = None
|
6
7
|
|
7
8
|
def get_state(self):
|
8
|
-
raise NotImplementedError(
|
9
|
+
raise NotImplementedError(
|
10
|
+
"the ActivityStateMachine.get_state() is not defined in the base class."
|
11
|
+
)
|
pyaatlibs/adbutils.py
CHANGED
@@ -5,7 +5,9 @@ import re
|
|
5
5
|
import time
|
6
6
|
from pyaatlibs.logger import Logger
|
7
7
|
|
8
|
+
|
8
9
|
class AdbScreenRecordingThread(threading.Thread):
|
10
|
+
|
9
11
|
def __init__(self, serialno):
|
10
12
|
super(AdbScreenRecordingThread, self).__init__()
|
11
13
|
self.serialno = serialno
|
@@ -23,9 +25,12 @@ class AdbScreenRecordingThread(threading.Thread):
|
|
23
25
|
shell_cmd = "screenrecord /sdcard/screenrecord.mp4"
|
24
26
|
cmd = ["adb", "-s", self.serialno, "shell", shell_cmd]
|
25
27
|
Logger.log(
|
26
|
-
"AdbScreenRecordingThread", "threadloop is running with the command '{}'".format(cmd)
|
28
|
+
"AdbScreenRecordingThread", "threadloop is running with the command '{}'".format(cmd)
|
29
|
+
)
|
27
30
|
self.proc = subprocess.Popen(
|
28
|
-
cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
31
|
+
cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
32
|
+
)
|
33
|
+
|
29
34
|
|
30
35
|
class Adb(object):
|
31
36
|
HAS_BEEN_INIT = False
|
@@ -54,8 +59,11 @@ class Adb(object):
|
|
54
59
|
def execute(child, cmd, serialno=None, tolog=True, timeoutsec=None):
|
55
60
|
child._check_init()
|
56
61
|
|
57
|
-
if
|
58
|
-
|
62
|
+
if (
|
63
|
+
serialno
|
64
|
+
and not serialno in child.get_devices(tolog=tolog)
|
65
|
+
and child.is_device_available(serialno=serialno, tolog=tolog)
|
66
|
+
):
|
59
67
|
ip_info = Adb.SERIAL_TO_IP_INFO[serialno]
|
60
68
|
ip_addr = "{}:{}".format(ip_info["addr"], ip_info["port"])
|
61
69
|
child._log("use Wifi adb: addr[{}] of serialno '{}'".format(ip_addr, serialno), tolog)
|
@@ -74,9 +82,9 @@ class Adb(object):
|
|
74
82
|
|
75
83
|
cmd = cmd_prefix + cmd
|
76
84
|
child._log("exec: {}".format(cmd), tolog)
|
77
|
-
out, err =
|
78
|
-
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
|
79
|
-
|
85
|
+
out, err = subprocess.Popen(
|
86
|
+
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
|
87
|
+
).communicate(timeout=timeoutsec)
|
80
88
|
|
81
89
|
return out, err
|
82
90
|
|
@@ -95,7 +103,7 @@ class Adb(object):
|
|
95
103
|
time.sleep(1)
|
96
104
|
|
97
105
|
if retry == 0:
|
98
|
-
raise(RuntimeError("
|
106
|
+
raise (RuntimeError('"adb device" might have some problems.'))
|
99
107
|
|
100
108
|
devices = [l.split()[0] for l in lines if l.split()[1] == "device"]
|
101
109
|
return devices
|
@@ -115,7 +123,8 @@ class Adb(object):
|
|
115
123
|
continue
|
116
124
|
|
117
125
|
out, err = child.execute(
|
118
|
-
["shell", "getprop ro.serialno"], serialno=device, tolog=tolog, **kwargs
|
126
|
+
["shell", "getprop ro.serialno"], serialno=device, tolog=tolog, **kwargs
|
127
|
+
)
|
119
128
|
if len(err) > 0:
|
120
129
|
continue
|
121
130
|
|
@@ -136,7 +145,8 @@ class Adb(object):
|
|
136
145
|
@classmethod
|
137
146
|
def get_wifi_status(child, serialno, tolog=True, **kwargs):
|
138
147
|
out, err = child.execute(
|
139
|
-
["shell", "cmd wifi status"], serialno=serialno, tolog=tolog, **kwargs
|
148
|
+
["shell", "cmd wifi status"], serialno=serialno, tolog=tolog, **kwargs
|
149
|
+
)
|
140
150
|
if len(err) > 0:
|
141
151
|
child._log("got error: {}".format(err.strip()), tolog)
|
142
152
|
return None
|
@@ -145,7 +155,7 @@ class Adb(object):
|
|
145
155
|
child._log("get_wifi_status: ret:\n{}".format(out), tolog)
|
146
156
|
|
147
157
|
if not out.startswith("Wifi is "):
|
148
|
-
child._log(
|
158
|
+
child._log('get_wifi_status: not starts with "Wifi is".', tolog)
|
149
159
|
return None
|
150
160
|
|
151
161
|
lines = out.splitlines()
|
@@ -165,10 +175,11 @@ class Adb(object):
|
|
165
175
|
return info
|
166
176
|
detail_str = m.group()
|
167
177
|
|
168
|
-
key_strings = detail_str[len("WifiInfo: "):].split(", ")
|
178
|
+
key_strings = detail_str[len("WifiInfo: ") :].split(", ")
|
169
179
|
matches = [re.match("(?P<key>[\\d\\w\\s\\-]+): (?P<value>.*)", s) for s in key_strings]
|
170
180
|
info.update(
|
171
|
-
{d["key"]: d["value"] for d in [m.groupdict() for m in matches if m is not None]}
|
181
|
+
{d["key"]: d["value"] for d in [m.groupdict() for m in matches if m is not None]}
|
182
|
+
)
|
172
183
|
|
173
184
|
for k, v in info.items():
|
174
185
|
try:
|
@@ -215,8 +226,9 @@ class Adb(object):
|
|
215
226
|
def enable_wifi_adb(child, serialno, port=5555, tolog=True, **kwargs):
|
216
227
|
child._check_init()
|
217
228
|
|
218
|
-
if not serialno in Adb.SERIAL_TO_IP_INFO
|
219
|
-
|
229
|
+
if not serialno in Adb.SERIAL_TO_IP_INFO and not child.is_wifi_adb_supported(
|
230
|
+
serialno=serialno, tolog=tolog, **kwargs
|
231
|
+
):
|
220
232
|
child._log("Wifi adb is not supported on device '{}'".format(serialno), tolog)
|
221
233
|
return False
|
222
234
|
|
@@ -251,8 +263,11 @@ class Adb(object):
|
|
251
263
|
|
252
264
|
if not "port" in ip_info:
|
253
265
|
child._log(
|
254
|
-
(
|
255
|
-
|
266
|
+
(
|
267
|
+
"Wifi adb might not be connected on device '{}', the port cannot be found."
|
268
|
+
).format(serialno),
|
269
|
+
tolog,
|
270
|
+
)
|
256
271
|
return False
|
257
272
|
|
258
273
|
ip_addr = "{}:{}".format(ip_info["addr"], ip_info["port"])
|
@@ -271,8 +286,9 @@ class Adb(object):
|
|
271
286
|
|
272
287
|
@classmethod
|
273
288
|
def get_wifi_adb_ip_addr(child, serialno, tolog=True, **kwargs):
|
274
|
-
if not serialno in Adb.SERIAL_TO_IP_INFO
|
275
|
-
|
289
|
+
if not serialno in Adb.SERIAL_TO_IP_INFO and not child.is_wifi_adb_supported(
|
290
|
+
serialno=serialno, tolog=tolog, **kwargs
|
291
|
+
):
|
276
292
|
child._log("Wifi adb is not supported on device '{}'".format(serialno), tolog)
|
277
293
|
return None
|
278
294
|
|
@@ -283,18 +299,23 @@ class Adb(object):
|
|
283
299
|
|
284
300
|
ip_addr = "{}:{}".format(ip_info["addr"], ip_info["port"])
|
285
301
|
child._log(
|
286
|
-
"get_wifi_adb_ip_addr: addr[{}] of serialno '{}'".format(ip_addr, serialno), tolog
|
302
|
+
"get_wifi_adb_ip_addr: addr[{}] of serialno '{}'".format(ip_addr, serialno), tolog
|
303
|
+
)
|
287
304
|
|
288
305
|
out, err = child.execute(
|
289
|
-
["shell", "getprop ro.serialno"], serialno=ip_addr, tolog=tolog, **kwargs
|
306
|
+
["shell", "getprop ro.serialno"], serialno=ip_addr, tolog=tolog, **kwargs
|
307
|
+
)
|
290
308
|
out = out.strip()
|
291
309
|
if len(err):
|
292
310
|
child._log("get_wifi_adb_ip_addr: get error: {}".format(err), tolog)
|
293
311
|
return None
|
294
312
|
|
295
313
|
if out != serialno:
|
296
|
-
child._log(
|
297
|
-
"
|
314
|
+
child._log(
|
315
|
+
"get_wifi_adb_ip_addr: the serialno does not match: "
|
316
|
+
"detected[{}], expected[{}]".format(serialno, out),
|
317
|
+
tolog,
|
318
|
+
)
|
298
319
|
return None
|
299
320
|
|
300
321
|
return ip_addr
|
@@ -308,21 +329,24 @@ class Adb(object):
|
|
308
329
|
@classmethod
|
309
330
|
def device_fingerprint(child, serialno=None, **kwargs):
|
310
331
|
return child.execute(
|
311
|
-
["shell", "getprop", "ro.vendor.build.fingerprint"], serialno=serialno, **kwargs
|
332
|
+
["shell", "getprop", "ro.vendor.build.fingerprint"], serialno=serialno, **kwargs
|
333
|
+
)
|
312
334
|
|
313
335
|
@classmethod
|
314
336
|
def device_stayon(child, serialno=None, on=None, **kwargs):
|
315
337
|
if on == None or type(on) is not bool:
|
316
338
|
return
|
317
339
|
return child.execute(
|
318
|
-
["shell", "svc", "power", "stayon", str(on).lower()], serialno=serialno, **kwargs
|
340
|
+
["shell", "svc", "power", "stayon", str(on).lower()], serialno=serialno, **kwargs
|
341
|
+
)
|
319
342
|
|
320
343
|
@classmethod
|
321
344
|
def device_keyevent(child, serialno=None, keyevent=None, **kwargs):
|
322
345
|
if not keyevent:
|
323
346
|
return
|
324
347
|
return child.execute(
|
325
|
-
["shell", "input", "keyevent", str(keyevent)], serialno=serialno, **kwargs
|
348
|
+
["shell", "input", "keyevent", str(keyevent)], serialno=serialno, **kwargs
|
349
|
+
)
|
326
350
|
|
327
351
|
@classmethod
|
328
352
|
def device_keyevent_menu(child, serialno=None, **kwargs):
|
@@ -379,26 +403,31 @@ class Adb(object):
|
|
379
403
|
time.sleep(1)
|
380
404
|
if pullto:
|
381
405
|
Adb.execute(
|
382
|
-
["pull", "/sdcard/screenrecord.mp4", pullto], serialno=serialno, tolog=tolog
|
406
|
+
["pull", "/sdcard/screenrecord.mp4", pullto], serialno=serialno, tolog=tolog
|
407
|
+
)
|
383
408
|
return True
|
384
409
|
|
410
|
+
|
385
411
|
try:
|
386
412
|
import functools
|
413
|
+
|
387
414
|
reduce = functools.reduce
|
388
415
|
except:
|
389
416
|
pass
|
390
417
|
|
391
418
|
import time
|
392
419
|
|
420
|
+
|
393
421
|
class AudioAdb(Adb):
|
394
422
|
TAG = "AudioAdb"
|
395
423
|
|
396
424
|
@staticmethod
|
397
425
|
def get_stream_volumes(serialno=None, **kwargs):
|
398
426
|
out, _ = AudioAdb.execute(["shell", "dumpsys audio"], serialno=serialno, **kwargs)
|
399
|
-
lines = [
|
400
|
-
if isinstance(line, str)
|
401
|
-
|
427
|
+
lines = [
|
428
|
+
line.strip() if isinstance(line, str) else line.decode("utf-8").strip()
|
429
|
+
for line in out.splitlines()
|
430
|
+
]
|
402
431
|
idices = [idx for idx, line in enumerate(lines) if line.startswith("- STREAM")]
|
403
432
|
if len(idices) < 2:
|
404
433
|
return None
|
@@ -421,7 +450,7 @@ class AudioAdb(Adb):
|
|
421
450
|
for idx in idices:
|
422
451
|
stream = lines[idx].split()[1][:-1]
|
423
452
|
volumes[stream] = {}
|
424
|
-
for line in lines[idx+1:idx+nlines]:
|
453
|
+
for line in lines[idx + 1 : idx + nlines]:
|
425
454
|
result = [fragment.split(",") for fragment in line.split(":")]
|
426
455
|
result = reduce(lambda x, y: x + y, result)
|
427
456
|
if len(result) == 2:
|
@@ -431,7 +460,7 @@ class AudioAdb(Adb):
|
|
431
460
|
k = result[0]
|
432
461
|
volumes[stream][k] = {}
|
433
462
|
for idx in range(1, len(result), 2):
|
434
|
-
subk, v = result[idx], result[idx+1]
|
463
|
+
subk, v = result[idx], result[idx + 1]
|
435
464
|
volumes[stream][k][subk.strip()] = parse_str_v(v)
|
436
465
|
|
437
466
|
return volumes
|
@@ -444,9 +473,8 @@ class AudioAdb(Adb):
|
|
444
473
|
|
445
474
|
@staticmethod
|
446
475
|
def inc_volume(serialno=None, volume_steps=1, **kwargs):
|
447
|
-
AudioAdb.adj_volume(serialno=serialno, keycode=24, times=volume_steps+1, **kwargs)
|
476
|
+
AudioAdb.adj_volume(serialno=serialno, keycode=24, times=volume_steps + 1, **kwargs)
|
448
477
|
|
449
478
|
@staticmethod
|
450
479
|
def dec_volume(serialno=None, volume_steps=1, **kwargs):
|
451
|
-
AudioAdb.adj_volume(serialno=serialno, keycode=25, times=volume_steps+1, **kwargs)
|
452
|
-
|
480
|
+
AudioAdb.adj_volume(serialno=serialno, keycode=25, times=volume_steps + 1, **kwargs)
|
pyaatlibs/apk/audioworker.apk
CHANGED
Binary file
|
pyaatlibs/appinterface.py
CHANGED
@@ -1,26 +1,28 @@
|
|
1
1
|
from pyaatlibs.adbutils import Adb
|
2
2
|
from pyaatlibs.logger import Logger
|
3
3
|
|
4
|
+
|
4
5
|
class AppInterface(object):
|
6
|
+
|
5
7
|
@classmethod
|
6
8
|
def log(child, msg):
|
7
9
|
Logger.log(child.TAG, msg)
|
8
10
|
|
9
11
|
@staticmethod
|
10
12
|
def get_apk_version():
|
11
|
-
raise(NotImplementedError("not implemented"))
|
13
|
+
raise (NotImplementedError("not implemented"))
|
12
14
|
|
13
15
|
@staticmethod
|
14
16
|
def get_apk_path():
|
15
|
-
raise(NotImplementedError("not implemented"))
|
17
|
+
raise (NotImplementedError("not implemented"))
|
16
18
|
|
17
19
|
@staticmethod
|
18
20
|
def get_launch_component():
|
19
|
-
raise(NotImplementedError("not implemented"))
|
21
|
+
raise (NotImplementedError("not implemented"))
|
20
22
|
|
21
23
|
@staticmethod
|
22
24
|
def get_package():
|
23
|
-
raise(NotImplementedError("not implemented"))
|
25
|
+
raise (NotImplementedError("not implemented"))
|
24
26
|
|
25
27
|
@classmethod
|
26
28
|
def clear_data(child, serialno=None, tolog=True):
|
@@ -29,7 +31,9 @@ class AppInterface(object):
|
|
29
31
|
@classmethod
|
30
32
|
def installed(child, serialno=None, tolog=True):
|
31
33
|
out, _ = Adb.execute(["shell", "pm list packages"], serialno=serialno, tolog=tolog)
|
32
|
-
packages = [
|
34
|
+
packages = [
|
35
|
+
line.split(":")[-1].strip() for line in out.splitlines() if line.startswith("package:")
|
36
|
+
]
|
33
37
|
return child.get_package() in packages
|
34
38
|
|
35
39
|
@classmethod
|
@@ -50,27 +54,54 @@ class AppInterface(object):
|
|
50
54
|
child.log("{} should be installed on the device.".format(child.TAG))
|
51
55
|
return None
|
52
56
|
|
53
|
-
out, _ = Adb.execute(
|
57
|
+
out, _ = Adb.execute(
|
58
|
+
["shell", "dumpsys package {}".format(child.get_package())],
|
59
|
+
serialno=serialno,
|
60
|
+
tolog=tolog,
|
61
|
+
)
|
54
62
|
lines = out.splitlines()
|
55
|
-
requested_perm_idx = [
|
56
|
-
if "requested permissions:" == line.strip()
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
requested_perm_idx = [
|
64
|
+
idx for idx, line in enumerate(lines) if "requested permissions:" == line.strip()
|
65
|
+
][0]
|
66
|
+
install_perm_idx = [
|
67
|
+
idx for idx, line in enumerate(lines) if "install permissions:" == line.strip()
|
68
|
+
][0]
|
69
|
+
install_perm_idx_end = (
|
70
|
+
[
|
71
|
+
idx
|
72
|
+
for idx, line in enumerate(lines[install_perm_idx + 1 :])
|
73
|
+
if not "android.permission." in line
|
74
|
+
][0]
|
75
|
+
+ install_perm_idx
|
76
|
+
+ 1
|
77
|
+
)
|
78
|
+
|
79
|
+
runtime_perm_idx = [
|
80
|
+
idx for idx, line in enumerate(lines) if "runtime permissions:" == line.strip()
|
81
|
+
][0]
|
64
82
|
|
65
83
|
try:
|
66
|
-
runtime_perm_idx_end =
|
67
|
-
|
84
|
+
runtime_perm_idx_end = (
|
85
|
+
[
|
86
|
+
idx
|
87
|
+
for idx, line in enumerate(lines[runtime_perm_idx + 1 :])
|
88
|
+
if not "android.permission." in line
|
89
|
+
][0]
|
90
|
+
+ runtime_perm_idx
|
91
|
+
+ 1
|
92
|
+
)
|
68
93
|
except IndexError:
|
69
94
|
runtime_perm_idx_end = len(lines)
|
70
95
|
|
71
|
-
requested_perms = [
|
72
|
-
|
73
|
-
|
96
|
+
requested_perms = [
|
97
|
+
line.strip() for line in lines[requested_perm_idx + 1 : install_perm_idx]
|
98
|
+
]
|
99
|
+
install_perms = [
|
100
|
+
line.strip() for line in lines[install_perm_idx + 1 : install_perm_idx_end]
|
101
|
+
]
|
102
|
+
runtime_perms = [
|
103
|
+
line.strip() for line in lines[runtime_perm_idx + 1 : runtime_perm_idx_end]
|
104
|
+
]
|
74
105
|
|
75
106
|
perms = {}
|
76
107
|
for perm in requested_perms:
|
@@ -82,7 +113,9 @@ class AppInterface(object):
|
|
82
113
|
for perm in runtime_perms:
|
83
114
|
if not "granted=" in perm:
|
84
115
|
continue
|
85
|
-
perms[perm.split(":")[0]] =
|
116
|
+
perms[perm.split(":")[0]] = (
|
117
|
+
perm.split(":")[-1].split(",")[0].split("granted=")[-1].lower() == "true"
|
118
|
+
)
|
86
119
|
|
87
120
|
return perms
|
88
121
|
|
@@ -98,7 +131,9 @@ class AppInterface(object):
|
|
98
131
|
|
99
132
|
@classmethod
|
100
133
|
def launch_app(child, device=None, serialno=None):
|
101
|
-
Adb.execute(
|
134
|
+
Adb.execute(
|
135
|
+
["shell", "am start -n {}".format(child.get_launch_component())], serialno=serialno
|
136
|
+
)
|
102
137
|
|
103
138
|
@classmethod
|
104
139
|
def stop_app(child, device=None, serialno=None):
|