| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 a variety of device interactions based on adb. | 5 """Provides a variety of device interactions based on adb. |
| 6 | 6 |
| 7 Eventually, this will be based on adb_wrapper. | 7 Eventually, this will be based on adb_wrapper. |
| 8 """ | 8 """ |
| 9 # pylint: disable=unused-argument | 9 # pylint: disable=unused-argument |
| 10 | 10 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 else: | 168 else: |
| 169 raise ValueError('Unsupported device value: %r' % device) | 169 raise ValueError('Unsupported device value: %r' % device) |
| 170 self._commands_installed = None | 170 self._commands_installed = None |
| 171 self._default_timeout = default_timeout | 171 self._default_timeout = default_timeout |
| 172 self._default_retries = default_retries | 172 self._default_retries = default_retries |
| 173 self._cache = {} | 173 self._cache = {} |
| 174 self._client_caches = {} | 174 self._client_caches = {} |
| 175 assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR) | 175 assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR) |
| 176 assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR) | 176 assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR) |
| 177 | 177 |
| 178 def __eq__(self, other): |
| 179 """Checks whether |other| refers to the same device as |self|. |
| 180 |
| 181 Args: |
| 182 other: The object to compare to. This can be a basestring, an instance |
| 183 of adb_wrapper.AdbWrapper, or an instance of DeviceUtils. |
| 184 Returns: |
| 185 Whether |other| refers to the same device as |self|. |
| 186 """ |
| 187 return self.adb.GetDeviceSerial() == str(other) |
| 188 |
| 189 def __lt__(self, other): |
| 190 """Compares two instances of DeviceUtils. |
| 191 |
| 192 This merely compares their serial numbers. |
| 193 |
| 194 Args: |
| 195 other: The instance of DeviceUtils to compare to. |
| 196 Returns: |
| 197 Whether |self| is less than |other|. |
| 198 """ |
| 199 return self.adb.GetDeviceSerial() < other.adb.GetDeviceSerial() |
| 200 |
| 178 def __str__(self): | 201 def __str__(self): |
| 179 """Returns the device serial.""" | 202 """Returns the device serial.""" |
| 180 return self.adb.GetDeviceSerial() | 203 return self.adb.GetDeviceSerial() |
| 181 | 204 |
| 182 @decorators.WithTimeoutAndRetriesFromInstance() | 205 @decorators.WithTimeoutAndRetriesFromInstance() |
| 183 def IsOnline(self, timeout=None, retries=None): | 206 def IsOnline(self, timeout=None, retries=None): |
| 184 """Checks whether the device is online. | 207 """Checks whether the device is online. |
| 185 | 208 |
| 186 Args: | 209 Args: |
| 187 timeout: timeout in seconds | 210 timeout: timeout in seconds |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 self._WriteFileWithPush(script.name, cmd) | 551 self._WriteFileWithPush(script.name, cmd) |
| 529 logging.info('Large shell command will be run from file: %s ...', | 552 logging.info('Large shell command will be run from file: %s ...', |
| 530 cmd[:100]) | 553 cmd[:100]) |
| 531 return handle_check_return('sh %s' % script.name_quoted) | 554 return handle_check_return('sh %s' % script.name_quoted) |
| 532 | 555 |
| 533 def handle_large_output(cmd, large_output_mode): | 556 def handle_large_output(cmd, large_output_mode): |
| 534 if large_output_mode: | 557 if large_output_mode: |
| 535 with device_temp_file.DeviceTempFile(self.adb) as large_output_file: | 558 with device_temp_file.DeviceTempFile(self.adb) as large_output_file: |
| 536 cmd = '%s > %s' % (cmd, large_output_file.name) | 559 cmd = '%s > %s' % (cmd, large_output_file.name) |
| 537 logging.info('Large output mode enabled. Will write output to device ' | 560 logging.info('Large output mode enabled. Will write output to device ' |
| 538 ' and read results from file.') | 561 'and read results from file.') |
| 539 handle_large_command(cmd) | 562 handle_large_command(cmd) |
| 540 return self.ReadFile(large_output_file.name) | 563 return self.ReadFile(large_output_file.name, force_pull=True) |
| 541 else: | 564 else: |
| 542 try: | 565 try: |
| 543 return handle_large_command(cmd) | 566 return handle_large_command(cmd) |
| 544 except device_errors.AdbCommandFailedError as exc: | 567 except device_errors.AdbCommandFailedError as exc: |
| 545 if exc.status is None: | 568 if exc.status is None: |
| 546 logging.exception('No output found for %s', cmd) | 569 logging.exception('No output found for %s', cmd) |
| 547 logging.warning('Attempting to run in large_output mode.') | 570 logging.warning('Attempting to run in large_output mode.') |
| 548 logging.warning('Use RunShellCommand(..., large_output=True) for ' | 571 logging.warning('Use RunShellCommand(..., large_output=True) for ' |
| 549 'shell commands that expect a lot of output.') | 572 'shell commands that expect a lot of output.') |
| 550 return handle_large_output(cmd, True) | 573 return handle_large_output(cmd, True) |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 def _GetChangedFilesImpl(self, host_path, device_path): | 869 def _GetChangedFilesImpl(self, host_path, device_path): |
| 847 real_host_path = os.path.realpath(host_path) | 870 real_host_path = os.path.realpath(host_path) |
| 848 try: | 871 try: |
| 849 real_device_path = self.RunShellCommand( | 872 real_device_path = self.RunShellCommand( |
| 850 ['realpath', device_path], single_line=True, check_return=True) | 873 ['realpath', device_path], single_line=True, check_return=True) |
| 851 except device_errors.CommandFailedError: | 874 except device_errors.CommandFailedError: |
| 852 real_device_path = None | 875 real_device_path = None |
| 853 if not real_device_path: | 876 if not real_device_path: |
| 854 return [(host_path, device_path)] | 877 return [(host_path, device_path)] |
| 855 | 878 |
| 856 host_checksums = md5sum.CalculateHostMd5Sums([real_host_path]) | 879 try: |
| 857 device_paths_to_md5 = ( | 880 host_checksums = md5sum.CalculateHostMd5Sums([real_host_path]) |
| 858 real_device_path if os.path.isfile(real_host_path) | 881 device_paths_to_md5 = ( |
| 859 else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path)) | 882 real_device_path if os.path.isfile(real_host_path) |
| 860 for p in host_checksums.iterkeys())) | 883 else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path)) |
| 861 device_checksums = md5sum.CalculateDeviceMd5Sums( | 884 for p in host_checksums.iterkeys())) |
| 862 device_paths_to_md5, self) | 885 device_checksums = md5sum.CalculateDeviceMd5Sums( |
| 886 device_paths_to_md5, self) |
| 887 except EnvironmentError as e: |
| 888 logging.warning('Error calculating md5: %s', e) |
| 889 return [(host_path, device_path)] |
| 863 | 890 |
| 864 if os.path.isfile(host_path): | 891 if os.path.isfile(host_path): |
| 865 host_checksum = host_checksums.get(real_host_path) | 892 host_checksum = host_checksums.get(real_host_path) |
| 866 device_checksum = device_checksums.get(real_device_path) | 893 device_checksum = device_checksums.get(real_device_path) |
| 867 if host_checksum != device_checksum: | 894 if host_checksum != device_checksum: |
| 868 return [(host_path, device_path)] | 895 return [(host_path, device_path)] |
| 869 else: | 896 else: |
| 870 return [] | 897 return [] |
| 871 else: | 898 else: |
| 872 to_push = [] | 899 to_push = [] |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1009 return host_temp.read() | 1036 return host_temp.read() |
| 1010 finally: | 1037 finally: |
| 1011 if os.path.exists(d): | 1038 if os.path.exists(d): |
| 1012 shutil.rmtree(d) | 1039 shutil.rmtree(d) |
| 1013 | 1040 |
| 1014 _LS_RE = re.compile( | 1041 _LS_RE = re.compile( |
| 1015 r'(?P<perms>\S+) +(?P<owner>\S+) +(?P<group>\S+) +(?:(?P<size>\d+) +)?' | 1042 r'(?P<perms>\S+) +(?P<owner>\S+) +(?P<group>\S+) +(?:(?P<size>\d+) +)?' |
| 1016 + r'(?P<date>\S+) +(?P<time>\S+) +(?P<name>.+)$') | 1043 + r'(?P<date>\S+) +(?P<time>\S+) +(?P<name>.+)$') |
| 1017 | 1044 |
| 1018 @decorators.WithTimeoutAndRetriesFromInstance() | 1045 @decorators.WithTimeoutAndRetriesFromInstance() |
| 1019 def ReadFile(self, device_path, as_root=False, | 1046 def ReadFile(self, device_path, as_root=False, force_pull=False, |
| 1020 timeout=None, retries=None): | 1047 timeout=None, retries=None): |
| 1021 """Reads the contents of a file from the device. | 1048 """Reads the contents of a file from the device. |
| 1022 | 1049 |
| 1023 Args: | 1050 Args: |
| 1024 device_path: A string containing the absolute path of the file to read | 1051 device_path: A string containing the absolute path of the file to read |
| 1025 from the device. | 1052 from the device. |
| 1026 as_root: A boolean indicating whether the read should be executed with | 1053 as_root: A boolean indicating whether the read should be executed with |
| 1027 root privileges. | 1054 root privileges. |
| 1055 force_pull: A boolean indicating whether to force the operation to be |
| 1056 performed by pulling a file from the device. The default is, when the |
| 1057 contents are short, to retrieve the contents using cat instead. |
| 1028 timeout: timeout in seconds | 1058 timeout: timeout in seconds |
| 1029 retries: number of retries | 1059 retries: number of retries |
| 1030 | 1060 |
| 1031 Returns: | 1061 Returns: |
| 1032 The contents of |device_path| as a string. Contents are intepreted using | 1062 The contents of |device_path| as a string. Contents are intepreted using |
| 1033 universal newlines, so the caller will see them encoded as '\n'. Also, | 1063 universal newlines, so the caller will see them encoded as '\n'. Also, |
| 1034 all lines will be terminated. | 1064 all lines will be terminated. |
| 1035 | 1065 |
| 1036 Raises: | 1066 Raises: |
| 1037 AdbCommandFailedError if the file can't be read. | 1067 AdbCommandFailedError if the file can't be read. |
| 1038 CommandTimeoutError on timeout. | 1068 CommandTimeoutError on timeout. |
| 1039 DeviceUnreachableError on missing device. | 1069 DeviceUnreachableError on missing device. |
| 1040 """ | 1070 """ |
| 1041 # TODO(jbudorick): Implement a generic version of Stat() that handles | 1071 def get_size(path): |
| 1042 # as_root=True, then switch this implementation to use that. | 1072 # TODO(jbudorick): Implement a generic version of Stat() that handles |
| 1043 size = None | 1073 # as_root=True, then switch this implementation to use that. |
| 1044 ls_out = self.RunShellCommand(['ls', '-l', device_path], as_root=as_root, | 1074 ls_out = self.RunShellCommand(['ls', '-l', device_path], as_root=as_root, |
| 1045 check_return=True) | 1075 check_return=True) |
| 1046 for line in ls_out: | 1076 for line in ls_out: |
| 1047 m = self._LS_RE.match(line) | 1077 m = self._LS_RE.match(line) |
| 1048 if m and m.group('name') == posixpath.basename(device_path): | 1078 if m and m.group('name') == posixpath.basename(device_path): |
| 1049 size = int(m.group('size')) | 1079 return int(m.group('size')) |
| 1050 break | |
| 1051 else: | |
| 1052 logging.warning('Could not determine size of %s.', device_path) | 1080 logging.warning('Could not determine size of %s.', device_path) |
| 1081 return None |
| 1053 | 1082 |
| 1054 if 0 < size <= self._MAX_ADB_OUTPUT_LENGTH: | 1083 if (not force_pull |
| 1084 and 0 < get_size(device_path) <= self._MAX_ADB_OUTPUT_LENGTH): |
| 1055 return _JoinLines(self.RunShellCommand( | 1085 return _JoinLines(self.RunShellCommand( |
| 1056 ['cat', device_path], as_root=as_root, check_return=True)) | 1086 ['cat', device_path], as_root=as_root, check_return=True)) |
| 1057 elif as_root and self.NeedsSU(): | 1087 elif as_root and self.NeedsSU(): |
| 1058 with device_temp_file.DeviceTempFile(self.adb) as device_temp: | 1088 with device_temp_file.DeviceTempFile(self.adb) as device_temp: |
| 1059 self.RunShellCommand(['cp', device_path, device_temp.name], | 1089 self.RunShellCommand(['cp', device_path, device_temp.name], |
| 1060 as_root=True, check_return=True) | 1090 as_root=True, check_return=True) |
| 1061 return self._ReadFileWithPull(device_temp.name) | 1091 return self._ReadFileWithPull(device_temp.name) |
| 1062 else: | 1092 else: |
| 1063 return self._ReadFileWithPull(device_path) | 1093 return self._ReadFileWithPull(device_path) |
| 1064 | 1094 |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1584 blacklist = device_blacklist.ReadBlacklist() | 1614 blacklist = device_blacklist.ReadBlacklist() |
| 1585 def blacklisted(adb): | 1615 def blacklisted(adb): |
| 1586 if adb.GetDeviceSerial() in blacklist: | 1616 if adb.GetDeviceSerial() in blacklist: |
| 1587 logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial()) | 1617 logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial()) |
| 1588 return True | 1618 return True |
| 1589 return False | 1619 return False |
| 1590 | 1620 |
| 1591 return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices() | 1621 return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices() |
| 1592 if not blacklisted(adb)] | 1622 if not blacklisted(adb)] |
| 1593 | 1623 |
| OLD | NEW |