Chromium Code Reviews| 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 |