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=''): | |
| 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' % ( | |
|
craigdh
2014/05/09 20:18:25
optional nit: it might not hurt to throw time().ti
cjhopman
2014/05/09 20:51:03
Done. Rounded to an int so that we don't put a '.'
| |
| 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 close(self): | |
| 109 self.android_commands.RunShellCommand('rm ' + self.name) | |
| 110 | |
| 111 | |
| 85 def GetAVDs(): | 112 def GetAVDs(): |
| 86 """Returns a list of AVDs.""" | 113 """Returns a list of AVDs.""" |
| 87 re_avd = re.compile('^[ ]+Name: ([a-zA-Z0-9_:.-]+)', re.MULTILINE) | 114 re_avd = re.compile('^[ ]+Name: ([a-zA-Z0-9_:.-]+)', re.MULTILINE) |
| 88 avds = re_avd.findall(cmd_helper.GetCmdOutput(['android', 'list', 'avd'])) | 115 avds = re_avd.findall(cmd_helper.GetCmdOutput(['android', 'list', 'avd'])) |
| 89 return avds | 116 return avds |
| 90 | 117 |
| 91 def ResetBadDevices(): | 118 def ResetBadDevices(): |
| 92 """Removes the blacklist that keeps track of bad devices for a current | 119 """Removes the blacklist that keeps track of bad devices for a current |
| 93 build. | 120 build. |
| 94 """ | 121 """ |
| (...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1086 return self.RunShellCommand('cat "%s" 2>/dev/null' % filename, | 1113 return self.RunShellCommand('cat "%s" 2>/dev/null' % filename, |
| 1087 log_result=log_result) | 1114 log_result=log_result) |
| 1088 | 1115 |
| 1089 def SetFileContents(self, filename, contents): | 1116 def SetFileContents(self, filename, contents): |
| 1090 """Writes |contents| to the file specified by |filename|.""" | 1117 """Writes |contents| to the file specified by |filename|.""" |
| 1091 with tempfile.NamedTemporaryFile() as f: | 1118 with tempfile.NamedTemporaryFile() as f: |
| 1092 f.write(contents) | 1119 f.write(contents) |
| 1093 f.flush() | 1120 f.flush() |
| 1094 self._adb.Push(f.name, filename) | 1121 self._adb.Push(f.name, filename) |
| 1095 | 1122 |
| 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): | 1123 def RunShellCommandWithSU(self, command, timeout_time=20, log_result=False): |
| 1107 return self.RunShellCommand('su -c %s' % command, timeout_time, log_result) | 1124 return self.RunShellCommand('su -c %s' % command, timeout_time, log_result) |
| 1108 | 1125 |
| 1109 def CanAccessProtectedFileContents(self): | 1126 def CanAccessProtectedFileContents(self): |
| 1110 """Returns True if Get/SetProtectedFileContents would work via "su" or adb | 1127 """Returns True if Get/SetProtectedFileContents would work via "su" or adb |
| 1111 shell running as root. | 1128 shell running as root. |
| 1112 | 1129 |
| 1113 Devices running user builds don't have adb root, but may provide "su" which | 1130 Devices running user builds don't have adb root, but may provide "su" which |
| 1114 can be used for accessing protected files. | 1131 can be used for accessing protected files. |
| 1115 """ | 1132 """ |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1153 return command_runner(command) | 1170 return command_runner(command) |
| 1154 else: | 1171 else: |
| 1155 logging.warning('Could not access protected file: %s' % filename) | 1172 logging.warning('Could not access protected file: %s' % filename) |
| 1156 return [] | 1173 return [] |
| 1157 | 1174 |
| 1158 def SetProtectedFileContents(self, filename, contents): | 1175 def SetProtectedFileContents(self, filename, contents): |
| 1159 """Writes |contents| to the protected file specified by |filename|. | 1176 """Writes |contents| to the protected file specified by |filename|. |
| 1160 | 1177 |
| 1161 This is less efficient than SetFileContents. | 1178 This is less efficient than SetFileContents. |
| 1162 """ | 1179 """ |
| 1163 temp_file = self._GetDeviceTempFileName(AndroidCommands._TEMP_FILE_BASE_FMT) | 1180 with DeviceTempFile(self), DeviceTempFile(self, suffix=".sh") as ( |
| 1164 temp_script = self._GetDeviceTempFileName( | 1181 temp_file, temp_script): |
| 1165 AndroidCommands._TEMP_SCRIPT_FILE_BASE_FMT) | 1182 # Put the contents in a temporary file |
| 1183 self.SetFileContents(temp_file.name, contents) | |
| 1184 # Create a script to copy the file contents to its final destination | |
| 1185 self.SetFileContents(temp_script.name, | |
| 1186 'cat %s > %s' % (temp_file.name, filename)) | |
| 1166 | 1187 |
| 1167 # Put the contents in a temporary file | 1188 command = 'sh %s' % temp_script.name |
| 1168 self.SetFileContents(temp_file, contents) | 1189 command_runner = self._GetProtectedFileCommandRunner() |
| 1169 # Create a script to copy the file contents to its final destination | 1190 if command_runner: |
| 1170 self.SetFileContents(temp_script, 'cat %s > %s' % (temp_file, filename)) | 1191 return command_runner(command) |
| 1192 else: | |
| 1193 logging.warning( | |
| 1194 'Could not set contents of protected file: %s' % filename) | |
| 1171 | 1195 |
| 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 | 1196 |
| 1183 def RemovePushedFiles(self): | 1197 def RemovePushedFiles(self): |
| 1184 """Removes all files pushed with PushIfNeeded() from the device.""" | 1198 """Removes all files pushed with PushIfNeeded() from the device.""" |
| 1185 for p in self._pushed_files: | 1199 for p in self._pushed_files: |
| 1186 self.RunShellCommand('rm -r %s' % p, timeout_time=2 * 60) | 1200 self.RunShellCommand('rm -r %s' % p, timeout_time=2 * 60) |
| 1187 | 1201 |
| 1188 def ListPathContents(self, path): | 1202 def ListPathContents(self, path): |
| 1189 """Lists files in all subdirectories of |path|. | 1203 """Lists files in all subdirectories of |path|. |
| 1190 | 1204 |
| 1191 Args: | 1205 Args: |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1877 | 1891 |
| 1878 Uses a shell script running on the target to copy new and changed files the | 1892 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 | 1893 source directory to the destination directory and remove added files. This |
| 1880 is in some cases much faster than cp -r. | 1894 is in some cases much faster than cp -r. |
| 1881 | 1895 |
| 1882 Args: | 1896 Args: |
| 1883 source: absolute path of source directory | 1897 source: absolute path of source directory |
| 1884 dest: absolute path of destination directory | 1898 dest: absolute path of destination directory |
| 1885 """ | 1899 """ |
| 1886 logging.info('In EfficientDeviceDirectoryCopy %s %s', source, dest) | 1900 logging.info('In EfficientDeviceDirectoryCopy %s %s', source, dest) |
| 1887 temp_script_file = self._GetDeviceTempFileName( | 1901 with DeviceTempFile(self, suffix=".sh") as temp_script_file: |
| 1888 AndroidCommands._TEMP_SCRIPT_FILE_BASE_FMT) | 1902 host_script_path = os.path.join(constants.DIR_SOURCE_ROOT, |
| 1889 host_script_path = os.path.join(constants.DIR_SOURCE_ROOT, | 1903 'build', |
| 1890 'build', | 1904 'android', |
| 1891 'android', | 1905 'pylib', |
| 1892 'pylib', | 1906 'efficient_android_directory_copy.sh') |
| 1893 'efficient_android_directory_copy.sh') | 1907 self._adb.Push(host_script_path, temp_script_file.name) |
| 1894 self._adb.Push(host_script_path, temp_script_file) | 1908 self.EnableAdbRoot |
| 1895 self.EnableAdbRoot | 1909 out = self.RunShellCommand( |
| 1896 out = self.RunShellCommand('sh %s %s %s' % (temp_script_file, source, dest), | 1910 'sh %s %s %s' % (temp_script_file.name, source, dest), |
| 1897 timeout_time=120) | 1911 timeout_time=120) |
| 1898 if self._device: | 1912 if self._device: |
| 1899 device_repr = self._device[-4:] | 1913 device_repr = self._device[-4:] |
| 1900 else: | 1914 else: |
| 1901 device_repr = '????' | 1915 device_repr = '????' |
| 1902 for line in out: | 1916 for line in out: |
| 1903 logging.info('[%s]> %s', device_repr, line) | 1917 logging.info('[%s]> %s', device_repr, line) |
| 1904 self.RunShellCommand('rm %s' % temp_script_file) | |
| 1905 | 1918 |
| 1906 def _GetControlUsbChargingCommand(self): | 1919 def _GetControlUsbChargingCommand(self): |
| 1907 if self._control_usb_charging_command['cached']: | 1920 if self._control_usb_charging_command['cached']: |
| 1908 return self._control_usb_charging_command['command'] | 1921 return self._control_usb_charging_command['command'] |
| 1909 self._control_usb_charging_command['cached'] = True | 1922 self._control_usb_charging_command['cached'] = True |
| 1910 for command in CONTROL_USB_CHARGING_COMMANDS: | 1923 for command in CONTROL_USB_CHARGING_COMMANDS: |
| 1911 # Assert command is valid. | 1924 # Assert command is valid. |
| 1912 assert 'disable_command' in command | 1925 assert 'disable_command' in command |
| 1913 assert 'enable_command' in command | 1926 assert 'enable_command' in command |
| 1914 assert 'witness_file' in command | 1927 assert 'witness_file' in command |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1963 """ | 1976 """ |
| 1964 def __init__(self, output): | 1977 def __init__(self, output): |
| 1965 self._output = output | 1978 self._output = output |
| 1966 | 1979 |
| 1967 def write(self, data): | 1980 def write(self, data): |
| 1968 data = data.replace('\r\r\n', '\n') | 1981 data = data.replace('\r\r\n', '\n') |
| 1969 self._output.write(data) | 1982 self._output.write(data) |
| 1970 | 1983 |
| 1971 def flush(self): | 1984 def flush(self): |
| 1972 self._output.flush() | 1985 self._output.flush() |
| OLD | NEW |