OLD | NEW |
---|---|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Provides an interface to communicate with the device via the adb command. | 5 """Provides an interface to communicate with the device via the adb command. |
6 | 6 |
7 Assumes adb binary is currently on system path. | 7 Assumes adb binary is currently on system path. |
8 """ | 8 """ |
9 # pylint: disable-all | 9 # pylint: disable-all |
10 | 10 |
11 import collections | 11 import collections |
12 import datetime | 12 import datetime |
13 import inspect | 13 import inspect |
14 import json | 14 import json |
15 import logging | 15 import logging |
16 import os | 16 import os |
17 import random | |
17 import re | 18 import re |
18 import shlex | 19 import shlex |
19 import signal | 20 import signal |
20 import subprocess | 21 import subprocess |
21 import sys | 22 import sys |
22 import tempfile | 23 import tempfile |
23 import time | 24 import time |
24 | 25 |
25 import cmd_helper | 26 import cmd_helper |
26 import constants | 27 import constants |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 CONTROL_USB_CHARGING_COMMANDS = [ | 76 CONTROL_USB_CHARGING_COMMANDS = [ |
76 { | 77 { |
77 # Nexus 4 | 78 # Nexus 4 |
78 'witness_file': '/sys/module/pm8921_charger/parameters/disabled', | 79 'witness_file': '/sys/module/pm8921_charger/parameters/disabled', |
79 'enable_command': 'echo 0 > /sys/module/pm8921_charger/parameters/disabled', | 80 'enable_command': 'echo 0 > /sys/module/pm8921_charger/parameters/disabled', |
80 'disable_command': | 81 'disable_command': |
81 'echo 1 > /sys/module/pm8921_charger/parameters/disabled', | 82 'echo 1 > /sys/module/pm8921_charger/parameters/disabled', |
82 }, | 83 }, |
83 ] | 84 ] |
84 | 85 |
86 class DeviceTempFile(object): | |
87 def __init__(self, android_commands, prefix="temp_file", suffix=""): | |
jbudorick
2014/05/09 15:57:03
nit: single quotes
cjhopman
2014/05/09 18:55:14
Done.
| |
88 """Find an unused temporary file path in the devices external directory. | |
89 | |
90 When this object is closed, the file will be deleted on the device. | |
91 """ | |
92 self.android_commands = android_commands | |
93 while True: | |
94 # TODO(cjhopman): This could actually return the same file in multiple | |
95 # calls if the caller doesn't write to the files immediately. | |
96 i = random.randint(0, 1000000) | |
97 self.name = '%s/%s-%010d%s' % ( | |
98 android_commands.GetExternalStorage(), prefix, i, suffix) | |
99 if not android_commands.FileExistsOnDevice(self.name): | |
100 break | |
101 | |
102 def __enter__(self): | |
103 return self | |
104 | |
105 def __exit__(self, type, value, traceback): | |
106 self.close() | |
107 | |
108 def Name(self): | |
jbudorick
2014/05/09 15:57:03
nit: unused?
cjhopman
2014/05/09 18:55:14
Done.
| |
109 return self.name | |
110 | |
111 def close(self): | |
112 self.android_commands.RunShellCommand('rm ' + self.name) | |
113 | |
114 | |
85 def GetAVDs(): | 115 def GetAVDs(): |
86 """Returns a list of AVDs.""" | 116 """Returns a list of AVDs.""" |
87 re_avd = re.compile('^[ ]+Name: ([a-zA-Z0-9_:.-]+)', re.MULTILINE) | 117 re_avd = re.compile('^[ ]+Name: ([a-zA-Z0-9_:.-]+)', re.MULTILINE) |
88 avds = re_avd.findall(cmd_helper.GetCmdOutput(['android', 'list', 'avd'])) | 118 avds = re_avd.findall(cmd_helper.GetCmdOutput(['android', 'list', 'avd'])) |
89 return avds | 119 return avds |
90 | 120 |
91 def ResetBadDevices(): | 121 def ResetBadDevices(): |
92 """Removes the blacklist that keeps track of bad devices for a current | 122 """Removes the blacklist that keeps track of bad devices for a current |
93 build. | 123 build. |
94 """ | 124 """ |
(...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1086 return self.RunShellCommand('cat "%s" 2>/dev/null' % filename, | 1116 return self.RunShellCommand('cat "%s" 2>/dev/null' % filename, |
1087 log_result=log_result) | 1117 log_result=log_result) |
1088 | 1118 |
1089 def SetFileContents(self, filename, contents): | 1119 def SetFileContents(self, filename, contents): |
1090 """Writes |contents| to the file specified by |filename|.""" | 1120 """Writes |contents| to the file specified by |filename|.""" |
1091 with tempfile.NamedTemporaryFile() as f: | 1121 with tempfile.NamedTemporaryFile() as f: |
1092 f.write(contents) | 1122 f.write(contents) |
1093 f.flush() | 1123 f.flush() |
1094 self._adb.Push(f.name, filename) | 1124 self._adb.Push(f.name, filename) |
1095 | 1125 |
1096 _TEMP_FILE_BASE_FMT = 'temp_file_%d' | |
1097 _TEMP_SCRIPT_FILE_BASE_FMT = 'temp_script_file_%d.sh' | |
1098 | |
1099 def _GetDeviceTempFileName(self, base_name): | |
1100 i = 0 | |
1101 while self.FileExistsOnDevice( | |
1102 self.GetExternalStorage() + '/' + base_name % i): | |
1103 i += 1 | |
1104 return self.GetExternalStorage() + '/' + base_name % i | |
1105 | |
1106 def RunShellCommandWithSU(self, command, timeout_time=20, log_result=False): | 1126 def RunShellCommandWithSU(self, command, timeout_time=20, log_result=False): |
1107 return self.RunShellCommand('su -c %s' % command, timeout_time, log_result) | 1127 return self.RunShellCommand('su -c %s' % command, timeout_time, log_result) |
1108 | 1128 |
1109 def CanAccessProtectedFileContents(self): | 1129 def CanAccessProtectedFileContents(self): |
1110 """Returns True if Get/SetProtectedFileContents would work via "su" or adb | 1130 """Returns True if Get/SetProtectedFileContents would work via "su" or adb |
1111 shell running as root. | 1131 shell running as root. |
1112 | 1132 |
1113 Devices running user builds don't have adb root, but may provide "su" which | 1133 Devices running user builds don't have adb root, but may provide "su" which |
1114 can be used for accessing protected files. | 1134 can be used for accessing protected files. |
1115 """ | 1135 """ |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1153 return command_runner(command) | 1173 return command_runner(command) |
1154 else: | 1174 else: |
1155 logging.warning('Could not access protected file: %s' % filename) | 1175 logging.warning('Could not access protected file: %s' % filename) |
1156 return [] | 1176 return [] |
1157 | 1177 |
1158 def SetProtectedFileContents(self, filename, contents): | 1178 def SetProtectedFileContents(self, filename, contents): |
1159 """Writes |contents| to the protected file specified by |filename|. | 1179 """Writes |contents| to the protected file specified by |filename|. |
1160 | 1180 |
1161 This is less efficient than SetFileContents. | 1181 This is less efficient than SetFileContents. |
1162 """ | 1182 """ |
1163 temp_file = self._GetDeviceTempFileName(AndroidCommands._TEMP_FILE_BASE_FMT) | 1183 with DeviceTempFile(self) as temp_file: |
craigdh
2014/05/09 16:02:40
I don't think we need to support pre-2.7 Python, s
cjhopman
2014/05/09 18:55:14
Done.
cjhopman
2014/05/16 01:15:19
Undone. So, making this one with statement means t
| |
1164 temp_script = self._GetDeviceTempFileName( | 1184 with DeviceTempFile(self, suffix=".sh") as temp_script: |
1165 AndroidCommands._TEMP_SCRIPT_FILE_BASE_FMT) | 1185 # Put the contents in a temporary file |
1186 self.SetFileContents(temp_file.name, contents) | |
1187 # Create a script to copy the file contents to its final destination | |
1188 self.SetFileContents(temp_script.name, | |
1189 'cat %s > %s' % (temp_file.name, filename)) | |
1166 | 1190 |
1167 # Put the contents in a temporary file | 1191 command = 'sh %s' % temp_script.name |
1168 self.SetFileContents(temp_file, contents) | 1192 command_runner = self._GetProtectedFileCommandRunner() |
1169 # Create a script to copy the file contents to its final destination | 1193 if command_runner: |
1170 self.SetFileContents(temp_script, 'cat %s > %s' % (temp_file, filename)) | 1194 return command_runner(command) |
1195 else: | |
1196 logging.warning( | |
1197 'Could not set contents of protected file: %s' % filename) | |
1171 | 1198 |
1172 command = 'sh %s' % temp_script | |
1173 command_runner = self._GetProtectedFileCommandRunner() | |
1174 if command_runner: | |
1175 return command_runner(command) | |
1176 else: | |
1177 logging.warning('Could not set contents of protected file: %s' % filename) | |
1178 | |
1179 # And remove the temporary files | |
1180 self.RunShellCommand('rm ' + temp_file) | |
1181 self.RunShellCommand('rm ' + temp_script) | |
1182 | 1199 |
1183 def RemovePushedFiles(self): | 1200 def RemovePushedFiles(self): |
1184 """Removes all files pushed with PushIfNeeded() from the device.""" | 1201 """Removes all files pushed with PushIfNeeded() from the device.""" |
1185 for p in self._pushed_files: | 1202 for p in self._pushed_files: |
1186 self.RunShellCommand('rm -r %s' % p, timeout_time=2 * 60) | 1203 self.RunShellCommand('rm -r %s' % p, timeout_time=2 * 60) |
1187 | 1204 |
1188 def ListPathContents(self, path): | 1205 def ListPathContents(self, path): |
1189 """Lists files in all subdirectories of |path|. | 1206 """Lists files in all subdirectories of |path|. |
1190 | 1207 |
1191 Args: | 1208 Args: |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1877 | 1894 |
1878 Uses a shell script running on the target to copy new and changed files the | 1895 Uses a shell script running on the target to copy new and changed files the |
1879 source directory to the destination directory and remove added files. This | 1896 source directory to the destination directory and remove added files. This |
1880 is in some cases much faster than cp -r. | 1897 is in some cases much faster than cp -r. |
1881 | 1898 |
1882 Args: | 1899 Args: |
1883 source: absolute path of source directory | 1900 source: absolute path of source directory |
1884 dest: absolute path of destination directory | 1901 dest: absolute path of destination directory |
1885 """ | 1902 """ |
1886 logging.info('In EfficientDeviceDirectoryCopy %s %s', source, dest) | 1903 logging.info('In EfficientDeviceDirectoryCopy %s %s', source, dest) |
1887 temp_script_file = self._GetDeviceTempFileName( | 1904 with DeviceTempFile(self, suffix=".sh") as temp_script_file: |
1888 AndroidCommands._TEMP_SCRIPT_FILE_BASE_FMT) | 1905 host_script_path = os.path.join(constants.DIR_SOURCE_ROOT, |
1889 host_script_path = os.path.join(constants.DIR_SOURCE_ROOT, | 1906 'build', |
1890 'build', | 1907 'android', |
1891 'android', | 1908 'pylib', |
1892 'pylib', | 1909 'efficient_android_directory_copy.sh') |
1893 'efficient_android_directory_copy.sh') | 1910 self._adb.Push(host_script_path, temp_script_file.name) |
1894 self._adb.Push(host_script_path, temp_script_file) | 1911 self.EnableAdbRoot |
1895 self.EnableAdbRoot | 1912 out = self.RunShellCommand( |
1896 out = self.RunShellCommand('sh %s %s %s' % (temp_script_file, source, dest), | 1913 'sh %s %s %s' % (temp_script_file.name, source, dest), |
1897 timeout_time=120) | 1914 timeout_time=120) |
1898 if self._device: | 1915 if self._device: |
1899 device_repr = self._device[-4:] | 1916 device_repr = self._device[-4:] |
1900 else: | 1917 else: |
1901 device_repr = '????' | 1918 device_repr = '????' |
1902 for line in out: | 1919 for line in out: |
1903 logging.info('[%s]> %s', device_repr, line) | 1920 logging.info('[%s]> %s', device_repr, line) |
1904 self.RunShellCommand('rm %s' % temp_script_file) | |
1905 | 1921 |
1906 def _GetControlUsbChargingCommand(self): | 1922 def _GetControlUsbChargingCommand(self): |
1907 if self._control_usb_charging_command['cached']: | 1923 if self._control_usb_charging_command['cached']: |
1908 return self._control_usb_charging_command['command'] | 1924 return self._control_usb_charging_command['command'] |
1909 self._control_usb_charging_command['cached'] = True | 1925 self._control_usb_charging_command['cached'] = True |
1910 for command in CONTROL_USB_CHARGING_COMMANDS: | 1926 for command in CONTROL_USB_CHARGING_COMMANDS: |
1911 # Assert command is valid. | 1927 # Assert command is valid. |
1912 assert 'disable_command' in command | 1928 assert 'disable_command' in command |
1913 assert 'enable_command' in command | 1929 assert 'enable_command' in command |
1914 assert 'witness_file' in command | 1930 assert 'witness_file' in command |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1963 """ | 1979 """ |
1964 def __init__(self, output): | 1980 def __init__(self, output): |
1965 self._output = output | 1981 self._output = output |
1966 | 1982 |
1967 def write(self, data): | 1983 def write(self, data): |
1968 data = data.replace('\r\r\n', '\n') | 1984 data = data.replace('\r\r\n', '\n') |
1969 self._output.write(data) | 1985 self._output.write(data) |
1970 | 1986 |
1971 def flush(self): | 1987 def flush(self): |
1972 self._output.flush() | 1988 self._output.flush() |
OLD | NEW |