Chromium Code Reviews| 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 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 retries: number of retries | 456 retries: number of retries |
| 457 | 457 |
| 458 Raises: | 458 Raises: |
| 459 CommandFailedError if the installation fails. | 459 CommandFailedError if the installation fails. |
| 460 CommandTimeoutError if the installation times out. | 460 CommandTimeoutError if the installation times out. |
| 461 DeviceUnreachableError on missing device. | 461 DeviceUnreachableError on missing device. |
| 462 """ | 462 """ |
| 463 package_name = apk_helper.GetPackageName(apk_path) | 463 package_name = apk_helper.GetPackageName(apk_path) |
| 464 device_path = self.GetApplicationPath(package_name) | 464 device_path = self.GetApplicationPath(package_name) |
| 465 if device_path is not None: | 465 if device_path is not None: |
| 466 should_install = bool(self._GetChangedFilesImpl(apk_path, device_path)) | 466 (files_to_push, _) = self._GetChangedAndStaleFiles( |
| 467 apk_path, device_path) | |
| 468 should_install = bool(files_to_push) | |
| 467 if should_install and not reinstall: | 469 if should_install and not reinstall: |
| 468 self.adb.Uninstall(package_name) | 470 self.adb.Uninstall(package_name) |
| 469 else: | 471 else: |
| 470 should_install = True | 472 should_install = True |
| 471 if should_install: | 473 if should_install: |
| 472 self.adb.Install(apk_path, reinstall=reinstall) | 474 self.adb.Install(apk_path, reinstall=reinstall) |
| 473 | 475 |
| 474 @decorators.WithTimeoutAndRetriesFromInstance() | 476 @decorators.WithTimeoutAndRetriesFromInstance() |
| 475 def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None, | 477 def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None, |
| 476 as_root=False, single_line=False, large_output=False, | 478 as_root=False, single_line=False, large_output=False, |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 803 self.RunShellCommand(['input', 'keyevent', format(keycode, 'd')], | 805 self.RunShellCommand(['input', 'keyevent', format(keycode, 'd')], |
| 804 check_return=True) | 806 check_return=True) |
| 805 | 807 |
| 806 PUSH_CHANGED_FILES_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT | 808 PUSH_CHANGED_FILES_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT |
| 807 PUSH_CHANGED_FILES_DEFAULT_RETRIES = _DEFAULT_RETRIES | 809 PUSH_CHANGED_FILES_DEFAULT_RETRIES = _DEFAULT_RETRIES |
| 808 | 810 |
| 809 @decorators.WithTimeoutAndRetriesDefaults( | 811 @decorators.WithTimeoutAndRetriesDefaults( |
| 810 PUSH_CHANGED_FILES_DEFAULT_TIMEOUT, | 812 PUSH_CHANGED_FILES_DEFAULT_TIMEOUT, |
| 811 PUSH_CHANGED_FILES_DEFAULT_RETRIES) | 813 PUSH_CHANGED_FILES_DEFAULT_RETRIES) |
| 812 def PushChangedFiles(self, host_device_tuples, timeout=None, | 814 def PushChangedFiles(self, host_device_tuples, timeout=None, |
| 813 retries=None): | 815 retries=None, delete_device_stale=False): |
| 814 """Push files to the device, skipping files that don't need updating. | 816 """Push files to the device, skipping files that don't need updating. |
| 817 If delete_device_stale option is True, delete stale files on device. | |
|
perezju
2015/06/10 09:24:23
Maybe explain in a bit more detail:
When pushing
Menglin
2015/06/10 21:22:16
Done.
| |
| 815 | 818 |
| 816 Args: | 819 Args: |
| 817 host_device_tuples: A list of (host_path, device_path) tuples, where | 820 host_device_tuples: A list of (host_path, device_path) tuples, where |
| 818 |host_path| is an absolute path of a file or directory on the host | 821 |host_path| is an absolute path of a file or directory on the host |
| 819 that should be minimially pushed to the device, and |device_path| is | 822 that should be minimially pushed to the device, and |device_path| is |
| 820 an absolute path of the destination on the device. | 823 an absolute path of the destination on the device. |
| 821 timeout: timeout in seconds | 824 timeout: timeout in seconds |
| 822 retries: number of retries | 825 retries: number of retries |
| 826 delete_device_stale: option to delete stale files on device | |
| 823 | 827 |
| 824 Raises: | 828 Raises: |
| 825 CommandFailedError on failure. | 829 CommandFailedError on failure. |
| 826 CommandTimeoutError on timeout. | 830 CommandTimeoutError on timeout. |
| 827 DeviceUnreachableError on missing device. | 831 DeviceUnreachableError on missing device. |
| 828 """ | 832 """ |
| 829 | 833 |
| 830 files = [] | 834 files = [] |
| 835 stale_files_on_device = [] | |
| 831 for h, d in host_device_tuples: | 836 for h, d in host_device_tuples: |
| 832 if os.path.isdir(h): | 837 if os.path.isdir(h): |
| 833 self.RunShellCommand(['mkdir', '-p', d], check_return=True) | 838 self.RunShellCommand(['mkdir', '-p', d], check_return=True) |
| 834 files += self._GetChangedFilesImpl(h, d) | 839 (file_tuples_to_push, stale_files) = self._GetChangedAndStaleFiles(h, d) |
| 840 files += file_tuples_to_push | |
| 841 stale_files_on_device += stale_files | |
|
perezju
2015/06/10 09:24:23
nit: maybe rename these variables to something lik
Menglin
2015/06/10 21:22:15
Done.
| |
| 842 | |
| 843 if delete_device_stale: | |
| 844 self._DeleteStaleFiles(stale_files_on_device) | |
| 835 | 845 |
| 836 if not files: | 846 if not files: |
| 837 return | 847 return |
| 838 | 848 |
| 849 self._PushFilesImpl(host_device_tuples, files) | |
| 850 | |
| 851 def _GetChangedAndStaleFiles(self, host_path, device_path): | |
| 852 """Get files to push and delete | |
| 853 | |
| 854 Args: | |
| 855 host_path: an absolute path of a file or directory on the host | |
| 856 device_path: an absolute path of a file or directory on the device | |
| 857 | |
| 858 Returns: | |
| 859 a two-element tuple | |
| 860 1st element: a list of (host_files_path, device_files_path) tuples to push | |
| 861 2nd element: a list of stale files under device_path | |
| 862 """ | |
| 863 real_host_path = os.path.realpath(host_path) | |
| 864 try: | |
| 865 real_device_path = self.RunShellCommand( | |
| 866 ['realpath', device_path], single_line=True, check_return=True) | |
| 867 except device_errors.CommandFailedError: | |
| 868 real_device_path = None | |
| 869 if not real_device_path: | |
| 870 return ([(host_path, device_path)], []) | |
| 871 | |
| 872 try: | |
| 873 host_checksums = md5sum.CalculateHostMd5Sums([real_host_path]) | |
| 874 device_checksums = md5sum.CalculateDeviceMd5Sums( | |
| 875 [real_device_path], self) | |
| 876 except EnvironmentError as e: | |
| 877 logging.warning('Error calculating md5: %s', e) | |
| 878 return ([(host_path, device_path)], []) | |
| 879 | |
| 880 if os.path.isfile(host_path): | |
| 881 host_checksum = host_checksums.get(real_host_path) | |
| 882 device_checksum = device_checksums.get(real_device_path) | |
| 883 if host_checksum != device_checksum: | |
| 884 return ([(host_path, device_path)], []) | |
| 885 else: | |
| 886 return ([], []) | |
| 887 else: | |
| 888 to_push = [] | |
| 889 to_delete = [] | |
| 890 for host_abs_path, host_checksum in host_checksums.iteritems(): | |
| 891 device_abs_path = '%s/%s' % ( | |
| 892 real_device_path, os.path.relpath(host_abs_path, real_host_path)) | |
| 893 device_checksum = device_checksums.get(device_abs_path) | |
| 894 if device_abs_path in device_checksums: | |
| 895 del device_checksums[device_abs_path] | |
|
perezju
2015/06/10 09:24:22
I think you can replace the last three lines with:
Menglin
2015/06/10 21:22:15
Done.
| |
| 896 if ((device_checksum) != host_checksum): | |
|
perezju
2015/06/10 09:24:23
nit: drop all the parentheses
Menglin
2015/06/10 21:22:15
Done.
| |
| 897 to_push.append((host_abs_path, device_abs_path)) | |
| 898 to_delete = [p for p in device_checksums.iterkeys()] | |
|
perezju
2015/06/10 09:24:22
nit: to_delete = device_checksums.keys()
Menglin
2015/06/10 21:22:15
Done.
| |
| 899 return (to_push, to_delete) | |
| 900 | |
| 901 def _PushFilesImpl(self, host_device_tuples, files): | |
| 839 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) | 902 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) |
| 840 file_count = len(files) | 903 file_count = len(files) |
| 841 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) | 904 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) |
| 842 for h, _ in host_device_tuples) | 905 for h, _ in host_device_tuples) |
| 843 dir_file_count = 0 | 906 dir_file_count = 0 |
| 844 for h, _ in host_device_tuples: | 907 for h, _ in host_device_tuples: |
| 845 if os.path.isdir(h): | 908 if os.path.isdir(h): |
| 846 dir_file_count += sum(len(f) for _r, _d, f in os.walk(h)) | 909 dir_file_count += sum(len(f) for _r, _d, f in os.walk(h)) |
| 847 else: | 910 else: |
| 848 dir_file_count += 1 | 911 dir_file_count += 1 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 859 dir_push_duration < zip_duration or not self._commands_installed): | 922 dir_push_duration < zip_duration or not self._commands_installed): |
| 860 self._PushChangedFilesIndividually(host_device_tuples) | 923 self._PushChangedFilesIndividually(host_device_tuples) |
| 861 elif push_duration < zip_duration or not self._commands_installed: | 924 elif push_duration < zip_duration or not self._commands_installed: |
| 862 self._PushChangedFilesIndividually(files) | 925 self._PushChangedFilesIndividually(files) |
| 863 else: | 926 else: |
| 864 self._PushChangedFilesZipped(files) | 927 self._PushChangedFilesZipped(files) |
| 865 self.RunShellCommand( | 928 self.RunShellCommand( |
| 866 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], | 929 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], |
| 867 as_root=True, check_return=True) | 930 as_root=True, check_return=True) |
| 868 | 931 |
| 869 def _GetChangedFilesImpl(self, host_path, device_path): | 932 def _DeleteStaleFiles(self, stale_files): |
| 870 real_host_path = os.path.realpath(host_path) | 933 for stale_file_path in stale_files: |
| 871 try: | 934 self.RunShellCommand(['rm', stale_file_path]) |
|
perezju
2015/06/10 09:24:22
do we really need this method? maybe just inline w
Menglin
2015/06/10 21:22:15
Done.
| |
| 872 real_device_path = self.RunShellCommand( | |
| 873 ['realpath', device_path], single_line=True, check_return=True) | |
| 874 except device_errors.CommandFailedError: | |
| 875 real_device_path = None | |
| 876 if not real_device_path: | |
| 877 return [(host_path, device_path)] | |
| 878 | |
| 879 try: | |
| 880 host_checksums = md5sum.CalculateHostMd5Sums([real_host_path]) | |
| 881 device_paths_to_md5 = ( | |
| 882 real_device_path if os.path.isfile(real_host_path) | |
| 883 else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path)) | |
| 884 for p in host_checksums.iterkeys())) | |
| 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)] | |
| 890 | |
| 891 if os.path.isfile(host_path): | |
| 892 host_checksum = host_checksums.get(real_host_path) | |
| 893 device_checksum = device_checksums.get(real_device_path) | |
| 894 if host_checksum != device_checksum: | |
| 895 return [(host_path, device_path)] | |
| 896 else: | |
| 897 return [] | |
| 898 else: | |
| 899 to_push = [] | |
| 900 for host_abs_path, host_checksum in host_checksums.iteritems(): | |
| 901 device_abs_path = '%s/%s' % ( | |
| 902 real_device_path, os.path.relpath(host_abs_path, real_host_path)) | |
| 903 if (device_checksums.get(device_abs_path) != host_checksum): | |
| 904 to_push.append((host_abs_path, device_abs_path)) | |
| 905 return to_push | |
| 906 | 935 |
| 907 def _InstallCommands(self): | 936 def _InstallCommands(self): |
| 908 if self._commands_installed is None: | 937 if self._commands_installed is None: |
| 909 try: | 938 try: |
| 910 if not install_commands.Installed(self): | 939 if not install_commands.Installed(self): |
| 911 install_commands.InstallCommands(self) | 940 install_commands.InstallCommands(self) |
| 912 self._commands_installed = True | 941 self._commands_installed = True |
| 913 except Exception as e: | 942 except Exception as e: |
| 914 logging.warning('unzip not available: %s' % str(e)) | 943 logging.warning('unzip not available: %s' % str(e)) |
| 915 self._commands_installed = False | 944 self._commands_installed = False |
| (...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1579 blacklist = device_blacklist.ReadBlacklist() | 1608 blacklist = device_blacklist.ReadBlacklist() |
| 1580 def blacklisted(adb): | 1609 def blacklisted(adb): |
| 1581 if adb.GetDeviceSerial() in blacklist: | 1610 if adb.GetDeviceSerial() in blacklist: |
| 1582 logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial()) | 1611 logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial()) |
| 1583 return True | 1612 return True |
| 1584 return False | 1613 return False |
| 1585 | 1614 |
| 1586 return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices() | 1615 return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices() |
| 1587 if not blacklisted(adb)] | 1616 if not blacklisted(adb)] |
| 1588 | 1617 |
| OLD | NEW |