blob: 64fcbb175d00dfb52f7565acae0a547a8ffb54ef [file] [log] [blame]
Karsten Tausche81ffea22018-06-19 15:34:01 +02001#!/usr/bin/env python3
2
3import re
4import subprocess
5import time
6
7
8ADB_DEVICES_PATTERN = re.compile(r"^([a-z0-9-]+)\s+device$", flags=re.M)
9
10
11class DeviceCommandError(BaseException):
12 """An error happened while sending a command to a device."""
13
14 def __init__(self, serial, command, error_message):
15 self.serial = serial
16 self.command = command
17 self.error_message = error_message
18 message = "Command `{}` failed on {}: {}".format(
19 command, serial, error_message
20 )
21 super(DeviceCommandError, self).__init__(message)
22
23
24def adb(*args, serial=None, raise_on_error=True):
25 """Run ADB command attached to serial.
26
27 Example:
28 >>> process = adb('shell', 'getprop', 'ro.build.fingerprint', serial='aserialnumber')
29 >>> process.returncode
30 0
31 >>> process.stdout.strip()
32 'ExampleVendor/Device/version/tags'
33
34 :param *args:
35 List of options to ADB (including command).
36 :param str serial:
37 Identifier for ADB connection to device.
38 :param raise_on_error bool:
39 Whether to raise a DeviceCommandError exception if the return code is
40 less than 0.
41 :returns subprocess.CompletedProcess:
42 Completed process.
43 :raises DeviceCommandError:
44 If the command failed.
45 """
46
47 # Make sure the adb server is started to avoid the infamous "out of date"
48 # message that pollutes stdout.
49 ret = subprocess.run(
50 ["adb", "start-server"],
51 stdout=subprocess.PIPE,
52 stderr=subprocess.PIPE,
53 universal_newlines=True,
54 )
55 if ret.returncode < 0:
56 if raise_on_error:
57 raise DeviceCommandError(
58 serial if serial else "??", str(args), ret.stderr
59 )
60 else:
61 return None
62
63 command = ["adb"]
64 if serial:
65 command += ["-s", serial]
66 if args:
67 command += list(args)
68 ret = subprocess.run(
69 command,
70 stdout=subprocess.PIPE,
71 stderr=subprocess.PIPE,
72 universal_newlines=True,
73 )
74
75 if raise_on_error and ret.returncode < 0:
76 raise DeviceCommandError(
77 serial if serial else "??", str(args), ret.stderr
78 )
79
80 return ret
81
82
83def list_devices():
84 """List serial numbers of devices attached to adb.
85
86 Raises:
87 DeviceCommandError: If the underlying adb command failed.
88 """
89 process = adb("devices")
90 return ADB_DEVICES_PATTERN.findall(process.stdout)
91
92
93def unlock(dut):
94 """Wake-up the device and unlock it.
95
96 Raises:
97 DeviceCommandError: If the underlying adb commands failed.
98 """
99 if not dut.info["screenOn"]:
100 adb("shell", "input keyevent KEYCODE_POWER", serial=dut.serial)
101 time.sleep(1)
102
103 # Make sure we are on the home screen.
104 adb("shell", "input keyevent KEYCODE_HOME", serial=dut.serial)
105 # The KEYCODE_MENU input is enough to unlock a "swipe up to unlock"
106 # lockscreen on Android 6, but unfortunately not Android 7. So we use a
107 # swipe up (that depends on the screen resolution) instead.
108 adb("shell", "input touchscreen swipe 930 880 930 380", serial=dut.serial)
109 time.sleep(1)
110 adb("shell", "input keyevent KEYCODE_HOME", serial=dut.serial)