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 |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 self._potential_push_size = 0 | 290 self._potential_push_size = 0 |
| 291 self._actual_push_size = 0 | 291 self._actual_push_size = 0 |
| 292 self._external_storage = '' | 292 self._external_storage = '' |
| 293 self._util_wrapper = '' | 293 self._util_wrapper = '' |
| 294 self._system_properties = system_properties.SystemProperties(self.Adb()) | 294 self._system_properties = system_properties.SystemProperties(self.Adb()) |
| 295 self._push_if_needed_cache = {} | 295 self._push_if_needed_cache = {} |
| 296 self._control_usb_charging_command = { | 296 self._control_usb_charging_command = { |
| 297 'command': None, | 297 'command': None, |
| 298 'cached': False, | 298 'cached': False, |
| 299 } | 299 } |
| 300 self._protected_file_access_method = None | |
| 300 | 301 |
| 301 @property | 302 @property |
| 302 def system_properties(self): | 303 def system_properties(self): |
| 303 return self._system_properties | 304 return self._system_properties |
| 304 | 305 |
| 305 def _LogShell(self, cmd): | 306 def _LogShell(self, cmd): |
| 306 """Logs the adb shell command.""" | 307 """Logs the adb shell command.""" |
| 307 if self._device: | 308 if self._device: |
| 308 device_repr = self._device[-4:] | 309 device_repr = self._device[-4:] |
| 309 else: | 310 else: |
| (...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 def _GetDeviceTempFileName(self, base_name): | 1097 def _GetDeviceTempFileName(self, base_name): |
| 1097 i = 0 | 1098 i = 0 |
| 1098 while self.FileExistsOnDevice( | 1099 while self.FileExistsOnDevice( |
| 1099 self.GetExternalStorage() + '/' + base_name % i): | 1100 self.GetExternalStorage() + '/' + base_name % i): |
| 1100 i += 1 | 1101 i += 1 |
| 1101 return self.GetExternalStorage() + '/' + base_name % i | 1102 return self.GetExternalStorage() + '/' + base_name % i |
| 1102 | 1103 |
| 1103 def RunShellCommandWithSU(self, command, timeout_time=20, log_result=False): | 1104 def RunShellCommandWithSU(self, command, timeout_time=20, log_result=False): |
| 1104 return self.RunShellCommand('su -c %s' % command, timeout_time, log_result) | 1105 return self.RunShellCommand('su -c %s' % command, timeout_time, log_result) |
| 1105 | 1106 |
| 1107 _ACCESS_METHOD_NO_ACCESS = 0 | |
|
bulach
2014/04/29 10:21:39
nit: you may as well start with 1 (and if you like
| |
| 1108 _ACCESS_METHOD_AS_ROOT = 1 | |
| 1109 _ACCESS_METHOD_WITH_SU = 2 | |
| 1110 | |
| 1106 def CanAccessProtectedFileContents(self): | 1111 def CanAccessProtectedFileContents(self): |
| 1107 """Returns True if Get/SetProtectedFileContents would work via "su". | 1112 """Returns True if Get/SetProtectedFileContents would work via "su" or adb |
| 1113 shell running as root. | |
| 1108 | 1114 |
| 1109 Devices running user builds don't have adb root, but may provide "su" which | 1115 Devices running user builds don't have adb root, but may provide "su" which |
| 1110 can be used for accessing protected files. | 1116 can be used for accessing protected files. |
| 1111 """ | 1117 """ |
| 1112 r = self.RunShellCommandWithSU('cat /dev/null') | 1118 return (self._ProtectedFileAccessMethod() != |
| 1113 return r == [] or r[0].strip() == '' | 1119 AndroidCommands._ACCESS_METHOD_NO_ACCESS) |
| 1120 | |
| 1121 def _ProtectedFileAccessMethod(self): | |
| 1122 """Tests for the best method to access protected files on the device. | |
| 1123 | |
| 1124 Returns: | |
| 1125 _ACCESS_METHOD_NO_ACCESS: if protected files cannot be accessed | |
| 1126 _ACCESS_METHOD_AS_ROOT: if the adb shell has root privileges | |
| 1127 _ACCESS_METHOD_WITH_SU: if the 'su' command properly works on the device | |
| 1128 """ | |
| 1129 if self._protected_file_access_method is not None: | |
| 1130 return self._protected_file_access_method | |
| 1131 | |
| 1132 def IsValidAuxContents(contents): | |
|
bulach
2014/04/29 10:21:39
I'm not sure it'd be more readable, but how about:
pasko
2014/04/29 12:57:38
Maybe. This method is elegant, but introduces a si
| |
| 1133 # The leading 4 or 8-bytes of auxv vector is a_type. There are not many | |
| 1134 # reserved a_type values, hence byte 2 must always be '\0' for a realistic | |
| 1135 # auxv. See /usr/include/elf.h. | |
| 1136 return len(contents) > 0 and (contents[0][2] == '\0') | |
| 1137 | |
| 1138 self._protected_file_access_method = ( | |
| 1139 AndroidCommands._ACCESS_METHOD_NO_ACCESS) | |
| 1140 | |
| 1141 # Get contents of the auxv vector for the init(8) process from a small | |
| 1142 # binary file that always exists on linux and is always read-protected. | |
| 1143 contents = self.RunShellCommand('cat /proc/1/auxv') | |
| 1144 if IsValidAuxContents(contents): | |
| 1145 # Protected data is available without SU, hence adb is running as root. | |
| 1146 self._protected_file_access_method = ( | |
| 1147 AndroidCommands._ACCESS_METHOD_AS_ROOT) | |
| 1148 else: | |
| 1149 contents = self.RunShellCommandWithSU('cat /proc/1/auxv') | |
| 1150 if IsValidAuxContents(contents): | |
| 1151 # Protected data is available when asked with SU. | |
| 1152 self._protected_file_access_method = ( | |
| 1153 AndroidCommands._ACCESS_METHOD_WITH_SU) | |
| 1154 return self._protected_file_access_method | |
| 1114 | 1155 |
| 1115 def GetProtectedFileContents(self, filename): | 1156 def GetProtectedFileContents(self, filename): |
| 1116 """Gets contents from the protected file specified by |filename|. | 1157 """Gets contents from the protected file specified by |filename|. |
| 1117 | 1158 |
| 1118 This is less efficient than GetFileContents, but will work for protected | 1159 This is potentially less efficient than GetFileContents. |
| 1119 files and device files. | |
| 1120 """ | 1160 """ |
| 1121 # Run the script as root | 1161 command = 'cat "%s" 2> /dev/null' % filename |
| 1122 return self.RunShellCommandWithSU('cat "%s" 2> /dev/null' % filename) | 1162 access_method = self._ProtectedFileAccessMethod() |
| 1163 if access_method == AndroidCommands._ACCESS_METHOD_WITH_SU: | |
| 1164 return self.RunShellCommandWithSU(command) | |
| 1165 elif access_method == AndroidCommands._ACCESS_METHOD_AS_ROOT: | |
| 1166 return self.RunShellCommand(command) | |
| 1167 else: | |
| 1168 logging.warning('Could not access protected file: %s' % filename) | |
| 1169 return [] | |
| 1123 | 1170 |
| 1124 def SetProtectedFileContents(self, filename, contents): | 1171 def SetProtectedFileContents(self, filename, contents): |
| 1125 """Writes |contents| to the protected file specified by |filename|. | 1172 """Writes |contents| to the protected file specified by |filename|. |
| 1126 | 1173 |
| 1127 This is less efficient than SetFileContents, but will work for protected | 1174 This is less efficient than SetFileContents. |
| 1128 files and device files. | |
| 1129 """ | 1175 """ |
| 1130 temp_file = self._GetDeviceTempFileName(AndroidCommands._TEMP_FILE_BASE_FMT) | 1176 temp_file = self._GetDeviceTempFileName(AndroidCommands._TEMP_FILE_BASE_FMT) |
| 1131 temp_script = self._GetDeviceTempFileName( | 1177 temp_script = self._GetDeviceTempFileName( |
| 1132 AndroidCommands._TEMP_SCRIPT_FILE_BASE_FMT) | 1178 AndroidCommands._TEMP_SCRIPT_FILE_BASE_FMT) |
| 1133 | 1179 |
| 1134 # Put the contents in a temporary file | 1180 # Put the contents in a temporary file |
| 1135 self.SetFileContents(temp_file, contents) | 1181 self.SetFileContents(temp_file, contents) |
| 1136 # Create a script to copy the file contents to its final destination | 1182 # Create a script to copy the file contents to its final destination |
| 1137 self.SetFileContents(temp_script, 'cat %s > %s' % (temp_file, filename)) | 1183 self.SetFileContents(temp_script, 'cat %s > %s' % (temp_file, filename)) |
| 1138 # Run the script as root | 1184 |
| 1139 self.RunShellCommandWithSU('sh %s' % temp_script) | 1185 command = 'sh %s' % temp_script |
| 1186 access_method = self._ProtectedFileAccessMethod() | |
| 1187 if access_method == AndroidCommands._ACCESS_METHOD_WITH_SU: | |
| 1188 return self.RunShellCommandWithSU(command) | |
| 1189 elif access_method == AndroidCommands._ACCESS_METHOD_AS_ROOT: | |
| 1190 return self.RunShellCommand(command) | |
| 1191 else: | |
| 1192 logging.warning('Could not set contents of protected file: %s' % filename) | |
| 1193 | |
| 1140 # And remove the temporary files | 1194 # And remove the temporary files |
| 1141 self.RunShellCommand('rm ' + temp_file) | 1195 self.RunShellCommand('rm ' + temp_file) |
| 1142 self.RunShellCommand('rm ' + temp_script) | 1196 self.RunShellCommand('rm ' + temp_script) |
| 1143 | 1197 |
| 1144 def RemovePushedFiles(self): | 1198 def RemovePushedFiles(self): |
| 1145 """Removes all files pushed with PushIfNeeded() from the device.""" | 1199 """Removes all files pushed with PushIfNeeded() from the device.""" |
| 1146 for p in self._pushed_files: | 1200 for p in self._pushed_files: |
| 1147 self.RunShellCommand('rm -r %s' % p, timeout_time=2 * 60) | 1201 self.RunShellCommand('rm -r %s' % p, timeout_time=2 * 60) |
| 1148 | 1202 |
| 1149 def ListPathContents(self, path): | 1203 def ListPathContents(self, path): |
| (...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1924 """ | 1978 """ |
| 1925 def __init__(self, output): | 1979 def __init__(self, output): |
| 1926 self._output = output | 1980 self._output = output |
| 1927 | 1981 |
| 1928 def write(self, data): | 1982 def write(self, data): |
| 1929 data = data.replace('\r\r\n', '\n') | 1983 data = data.replace('\r\r\n', '\n') |
| 1930 self._output.write(data) | 1984 self._output.write(data) |
| 1931 | 1985 |
| 1932 def flush(self): | 1986 def flush(self): |
| 1933 self._output.flush() | 1987 self._output.flush() |
| OLD | NEW |