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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 elif isinstance(device, pylib.android_commands.AndroidCommands): | 169 elif isinstance(device, pylib.android_commands.AndroidCommands): |
| 170 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) | 170 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) |
| 171 self.old_interface = device | 171 self.old_interface = device |
| 172 else: | 172 else: |
| 173 raise ValueError('Unsupported device value: %r' % device) | 173 raise ValueError('Unsupported device value: %r' % device) |
| 174 self._commands_installed = None | 174 self._commands_installed = None |
| 175 self._default_timeout = default_timeout | 175 self._default_timeout = default_timeout |
| 176 self._default_retries = default_retries | 176 self._default_retries = default_retries |
| 177 self._cache = {} | 177 self._cache = {} |
| 178 self._client_caches = {} | 178 self._client_caches = {} |
| 179 self._package_to_device_apk_checksums_cache = {} | |
| 180 self._package_to_device_apk_paths_cache = {} | |
| 179 assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR) | 181 assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR) |
| 180 assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR) | 182 assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR) |
| 181 | 183 |
| 184 # We need to flush the cache on uninstall, so wrap self.adb.Uninstall | |
| 185 # in order to ensure we detect calls to it. | |
| 186 old_adb_uninstall = self.adb.Uninstall | |
| 187 def WrappedAdbUninstall(package_name, *args, **kwargs): | |
| 188 try: | |
| 189 old_adb_uninstall(package_name, *args, **kwargs) | |
| 190 except: | |
| 191 # Clear cache since we can't be sure of the state. | |
| 192 self._package_to_device_apk_paths_cache.pop(package_name, 0) | |
| 193 self._package_to_device_apk_checksums_cache.pop(package_name, 0) | |
| 194 raise | |
| 195 self._package_to_device_apk_paths_cache[package_name] = [] | |
|
jbudorick
2015/08/06 19:28:22
I would still prefer to use self._cache and do som
agrieve
2015/08/11 14:07:46
Done.
| |
| 196 self._package_to_device_apk_checksums_cache[package_name] = set() | |
| 197 self.adb.Uninstall = WrappedAdbUninstall | |
| 198 | |
| 182 def __eq__(self, other): | 199 def __eq__(self, other): |
| 183 """Checks whether |other| refers to the same device as |self|. | 200 """Checks whether |other| refers to the same device as |self|. |
| 184 | 201 |
| 185 Args: | 202 Args: |
| 186 other: The object to compare to. This can be a basestring, an instance | 203 other: The object to compare to. This can be a basestring, an instance |
| 187 of adb_wrapper.AdbWrapper, or an instance of DeviceUtils. | 204 of adb_wrapper.AdbWrapper, or an instance of DeviceUtils. |
| 188 Returns: | 205 Returns: |
| 189 Whether |other| refers to the same device as |self|. | 206 Whether |other| refers to the same device as |self|. |
| 190 """ | 207 """ |
| 191 return self.adb.GetDeviceSerial() == str(other) | 208 return self.adb.GetDeviceSerial() == str(other) |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 @decorators.WithTimeoutAndRetriesFromInstance() | 362 @decorators.WithTimeoutAndRetriesFromInstance() |
| 346 def GetApplicationPaths(self, package, timeout=None, retries=None): | 363 def GetApplicationPaths(self, package, timeout=None, retries=None): |
| 347 """Get the paths of the installed apks on the device for the given package. | 364 """Get the paths of the installed apks on the device for the given package. |
| 348 | 365 |
| 349 Args: | 366 Args: |
| 350 package: Name of the package. | 367 package: Name of the package. |
| 351 | 368 |
| 352 Returns: | 369 Returns: |
| 353 List of paths to the apks on the device for the given package. | 370 List of paths to the apks on the device for the given package. |
| 354 """ | 371 """ |
| 372 return self._GetApplicationPathsInternal(package) | |
| 373 | |
| 374 def _GetApplicationPathsInternal(self, package, skip_cache=False): | |
| 375 cached_result = self._package_to_device_apk_paths_cache.get(package) | |
| 376 if cached_result is not None and not skip_cache: | |
| 377 return list(cached_result) | |
| 355 # 'pm path' is liable to incorrectly exit with a nonzero number starting | 378 # 'pm path' is liable to incorrectly exit with a nonzero number starting |
| 356 # in Lollipop. | 379 # in Lollipop. |
| 357 # TODO(jbudorick): Check if this is fixed as new Android versions are | 380 # TODO(jbudorick): Check if this is fixed as new Android versions are |
| 358 # released to put an upper bound on this. | 381 # released to put an upper bound on this. |
| 359 should_check_return = (self.build_version_sdk < | 382 should_check_return = (self.build_version_sdk < |
| 360 constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP) | 383 constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP) |
| 361 output = self.RunShellCommand( | 384 output = self.RunShellCommand( |
| 362 ['pm', 'path', package], check_return=should_check_return) | 385 ['pm', 'path', package], check_return=should_check_return) |
| 363 apks = [] | 386 apks = [] |
| 364 for line in output: | 387 for line in output: |
| 365 if not line.startswith('package:'): | 388 if not line.startswith('package:'): |
| 366 raise device_errors.CommandFailedError( | 389 raise device_errors.CommandFailedError( |
| 367 'pm path returned: %r' % '\n'.join(output), str(self)) | 390 'pm path returned: %r' % '\n'.join(output), str(self)) |
| 368 apks.append(line[len('package:'):]) | 391 apks.append(line[len('package:'):]) |
| 392 self._package_to_device_apk_paths_cache[package] = list(apks) | |
| 369 return apks | 393 return apks |
| 370 | 394 |
| 371 @decorators.WithTimeoutAndRetriesFromInstance() | 395 @decorators.WithTimeoutAndRetriesFromInstance() |
| 372 def GetApplicationDataDirectory(self, package, timeout=None, retries=None): | 396 def GetApplicationDataDirectory(self, package, timeout=None, retries=None): |
| 373 """Get the data directory on the device for the given package. | 397 """Get the data directory on the device for the given package. |
| 374 | 398 |
| 375 Args: | 399 Args: |
| 376 package: Name of the package. | 400 package: Name of the package. |
| 377 | 401 |
| 378 Returns: | 402 Returns: |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 411 def sd_card_ready(): | 435 def sd_card_ready(): |
| 412 try: | 436 try: |
| 413 self.RunShellCommand(['test', '-d', self.GetExternalStoragePath()], | 437 self.RunShellCommand(['test', '-d', self.GetExternalStoragePath()], |
| 414 check_return=True) | 438 check_return=True) |
| 415 return True | 439 return True |
| 416 except device_errors.AdbCommandFailedError: | 440 except device_errors.AdbCommandFailedError: |
| 417 return False | 441 return False |
| 418 | 442 |
| 419 def pm_ready(): | 443 def pm_ready(): |
| 420 try: | 444 try: |
| 421 return self.GetApplicationPaths('android') | 445 return self._GetApplicationPathsInternal('android', skip_cache=True) |
| 422 except device_errors.CommandFailedError: | 446 except device_errors.CommandFailedError: |
| 423 return False | 447 return False |
| 424 | 448 |
| 425 def boot_completed(): | 449 def boot_completed(): |
| 426 return self.GetProp('sys.boot_completed') == '1' | 450 return self.GetProp('sys.boot_completed') == '1' |
| 427 | 451 |
| 428 def wifi_enabled(): | 452 def wifi_enabled(): |
| 429 return 'Wi-Fi is enabled' in self.RunShellCommand(['dumpsys', 'wifi'], | 453 return 'Wi-Fi is enabled' in self.RunShellCommand(['dumpsys', 'wifi'], |
| 430 check_return=False) | 454 check_return=False) |
| 431 | 455 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 481 reinstall: A boolean indicating if we should keep any existing app data. | 505 reinstall: A boolean indicating if we should keep any existing app data. |
| 482 timeout: timeout in seconds | 506 timeout: timeout in seconds |
| 483 retries: number of retries | 507 retries: number of retries |
| 484 | 508 |
| 485 Raises: | 509 Raises: |
| 486 CommandFailedError if the installation fails. | 510 CommandFailedError if the installation fails. |
| 487 CommandTimeoutError if the installation times out. | 511 CommandTimeoutError if the installation times out. |
| 488 DeviceUnreachableError on missing device. | 512 DeviceUnreachableError on missing device. |
| 489 """ | 513 """ |
| 490 package_name = apk_helper.GetPackageName(apk_path) | 514 package_name = apk_helper.GetPackageName(apk_path) |
| 491 device_paths = self.GetApplicationPaths(package_name) | 515 device_paths = self._GetApplicationPathsInternal(package_name) |
| 492 if device_paths: | 516 if device_paths: |
| 493 if len(device_paths) > 1: | 517 if len(device_paths) > 1: |
| 494 logging.warning( | 518 logging.warning( |
| 495 'Installing single APK (%s) when split APKs (%s) are currently ' | 519 'Installing single APK (%s) when split APKs (%s) are currently ' |
| 496 'installed.', apk_path, ' '.join(device_paths)) | 520 'installed.', apk_path, ' '.join(device_paths)) |
| 497 (files_to_push, _) = self._GetChangedAndStaleFiles( | 521 apks_to_install, host_checksums = ( |
| 498 apk_path, device_paths[0]) | 522 self._ComputeStaleApks(package_name, [apk_path])) |
| 499 should_install = bool(files_to_push) | 523 should_install = bool(apks_to_install) |
| 500 if should_install and not reinstall: | 524 if should_install and not reinstall: |
| 501 self.adb.Uninstall(package_name) | 525 self.adb.Uninstall(package_name) |
| 502 else: | 526 else: |
| 503 should_install = True | 527 should_install = True |
| 528 host_checksums = None | |
| 504 if should_install: | 529 if should_install: |
| 505 self.adb.Install(apk_path, reinstall=reinstall) | 530 # We won't know the resulting device apk names. |
| 531 self._package_to_device_apk_paths_cache.pop(package_name, 0) | |
| 532 try: | |
| 533 self.adb.Install(apk_path, reinstall=reinstall) | |
| 534 self._package_to_device_apk_checksums_cache[package_name] = ( | |
| 535 host_checksums) | |
| 536 except: | |
| 537 self._package_to_device_apk_paths_cache.pop(package_name, 0) | |
| 538 raise | |
| 506 | 539 |
| 507 @decorators.WithTimeoutAndRetriesDefaults( | 540 @decorators.WithTimeoutAndRetriesDefaults( |
| 508 INSTALL_DEFAULT_TIMEOUT, | 541 INSTALL_DEFAULT_TIMEOUT, |
| 509 INSTALL_DEFAULT_RETRIES) | 542 INSTALL_DEFAULT_RETRIES) |
| 510 def InstallSplitApk(self, base_apk, split_apks, reinstall=False, | 543 def InstallSplitApk(self, base_apk, split_apks, reinstall=False, |
| 511 timeout=None, retries=None): | 544 timeout=None, retries=None): |
| 512 """Install a split APK. | 545 """Install a split APK. |
| 513 | 546 |
| 514 Noop if all of the APK splits are already installed. | 547 Noop if all of the APK splits are already installed. |
| 515 | 548 |
| 516 Args: | 549 Args: |
| 517 base_apk: A string of the path to the base APK. | 550 base_apk: A string of the path to the base APK. |
| 518 split_apks: A list of strings of paths of all of the APK splits. | 551 split_apks: A list of strings of paths of all of the APK splits. |
| 519 reinstall: A boolean indicating if we should keep any existing app data. | 552 reinstall: A boolean indicating if we should keep any existing app data. |
| 520 timeout: timeout in seconds | 553 timeout: timeout in seconds |
| 521 retries: number of retries | 554 retries: number of retries |
| 522 | 555 |
| 523 Raises: | 556 Raises: |
| 524 CommandFailedError if the installation fails. | 557 CommandFailedError if the installation fails. |
| 525 CommandTimeoutError if the installation times out. | 558 CommandTimeoutError if the installation times out. |
| 526 DeviceUnreachableError on missing device. | 559 DeviceUnreachableError on missing device. |
| 527 DeviceVersionError if device SDK is less than Android L. | 560 DeviceVersionError if device SDK is less than Android L. |
| 528 """ | 561 """ |
| 529 self._CheckSdkLevel(constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP) | 562 self._CheckSdkLevel(constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP) |
| 530 | 563 |
| 531 all_apks = [base_apk] + split_select.SelectSplits( | 564 all_apks = [base_apk] + split_select.SelectSplits( |
| 532 self, base_apk, split_apks) | 565 self, base_apk, split_apks) |
| 533 package_name = apk_helper.GetPackageName(base_apk) | 566 package_name = apk_helper.GetPackageName(base_apk) |
| 534 device_apk_paths = self.GetApplicationPaths(package_name) | 567 device_apk_paths = self._GetApplicationPathsInternal(package_name) |
| 535 | 568 |
| 536 if device_apk_paths: | 569 if device_apk_paths: |
| 537 partial_install_package = package_name | 570 partial_install_package = package_name |
| 538 device_checksums = md5sum.CalculateDeviceMd5Sums(device_apk_paths, self) | 571 apks_to_install, host_checksums = ( |
| 539 host_checksums = md5sum.CalculateHostMd5Sums(all_apks) | 572 self._ComputeStaleApks(package_name, all_apks)) |
| 540 apks_to_install = [k for (k, v) in host_checksums.iteritems() | |
| 541 if v not in device_checksums.values()] | |
| 542 if apks_to_install and not reinstall: | 573 if apks_to_install and not reinstall: |
| 543 self.adb.Uninstall(package_name) | 574 self.adb.Uninstall(package_name) |
| 544 partial_install_package = None | 575 partial_install_package = None |
| 545 apks_to_install = all_apks | 576 apks_to_install = all_apks |
| 546 else: | 577 else: |
| 547 partial_install_package = None | 578 partial_install_package = None |
| 548 apks_to_install = all_apks | 579 apks_to_install = all_apks |
| 580 host_checksums = None | |
| 549 if apks_to_install: | 581 if apks_to_install: |
| 550 self.adb.InstallMultiple( | 582 # We won't know the resulting device apk names. |
| 551 apks_to_install, partial=partial_install_package, reinstall=reinstall) | 583 self._package_to_device_apk_paths_cache.pop(package_name, 0) |
| 584 try: | |
| 585 self.adb.InstallMultiple( | |
| 586 apks_to_install, partial=partial_install_package, | |
| 587 reinstall=reinstall) | |
| 588 self._package_to_device_apk_checksums_cache[package_name] = ( | |
| 589 host_checksums) | |
| 590 except: | |
| 591 self._package_to_device_apk_paths_cache.pop(package_name, 0) | |
|
jbudorick
2015/08/06 19:28:22
Do you need to do this? If we hit an exception in
agrieve
2015/08/11 14:07:46
Nice catch. Gone.
| |
| 592 raise | |
| 552 | 593 |
| 553 def _CheckSdkLevel(self, required_sdk_level): | 594 def _CheckSdkLevel(self, required_sdk_level): |
| 554 """Raises an exception if the device does not have the required SDK level. | 595 """Raises an exception if the device does not have the required SDK level. |
| 555 """ | 596 """ |
| 556 if self.build_version_sdk < required_sdk_level: | 597 if self.build_version_sdk < required_sdk_level: |
| 557 raise device_errors.DeviceVersionError( | 598 raise device_errors.DeviceVersionError( |
| 558 ('Requires SDK level %s, device is SDK level %s' % | 599 ('Requires SDK level %s, device is SDK level %s' % |
| 559 (required_sdk_level, self.build_version_sdk)), | 600 (required_sdk_level, self.build_version_sdk)), |
| 560 device_serial=self.adb.GetDeviceSerial()) | 601 device_serial=self.adb.GetDeviceSerial()) |
| 561 | 602 |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 | 927 |
| 887 Raises: | 928 Raises: |
| 888 CommandTimeoutError on timeout. | 929 CommandTimeoutError on timeout. |
| 889 DeviceUnreachableError on missing device. | 930 DeviceUnreachableError on missing device. |
| 890 """ | 931 """ |
| 891 # Check that the package exists before clearing it for android builds below | 932 # Check that the package exists before clearing it for android builds below |
| 892 # JB MR2. Necessary because calling pm clear on a package that doesn't exist | 933 # JB MR2. Necessary because calling pm clear on a package that doesn't exist |
| 893 # may never return. | 934 # may never return. |
| 894 if ((self.build_version_sdk >= | 935 if ((self.build_version_sdk >= |
| 895 constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN_MR2) | 936 constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN_MR2) |
| 896 or self.GetApplicationPaths(package)): | 937 or self._GetApplicationPathsInternal(package)): |
| 897 self.RunShellCommand(['pm', 'clear', package], check_return=True) | 938 self.RunShellCommand(['pm', 'clear', package], check_return=True) |
| 898 | 939 |
| 899 @decorators.WithTimeoutAndRetriesFromInstance() | 940 @decorators.WithTimeoutAndRetriesFromInstance() |
| 900 def SendKeyEvent(self, keycode, timeout=None, retries=None): | 941 def SendKeyEvent(self, keycode, timeout=None, retries=None): |
| 901 """Sends a keycode to the device. | 942 """Sends a keycode to the device. |
| 902 | 943 |
| 903 See the pylib.constants.keyevent module for suitable keycode values. | 944 See the pylib.constants.keyevent module for suitable keycode values. |
| 904 | 945 |
| 905 Args: | 946 Args: |
| 906 keycode: A integer keycode to send to the device. | 947 keycode: A integer keycode to send to the device. |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1010 to_push = [] | 1051 to_push = [] |
| 1011 for host_abs_path, host_checksum in host_checksums.iteritems(): | 1052 for host_abs_path, host_checksum in host_checksums.iteritems(): |
| 1012 device_abs_path = '%s/%s' % ( | 1053 device_abs_path = '%s/%s' % ( |
| 1013 real_device_path, os.path.relpath(host_abs_path, real_host_path)) | 1054 real_device_path, os.path.relpath(host_abs_path, real_host_path)) |
| 1014 device_checksum = device_checksums.pop(device_abs_path, None) | 1055 device_checksum = device_checksums.pop(device_abs_path, None) |
| 1015 if device_checksum != host_checksum: | 1056 if device_checksum != host_checksum: |
| 1016 to_push.append((host_abs_path, device_abs_path)) | 1057 to_push.append((host_abs_path, device_abs_path)) |
| 1017 to_delete = device_checksums.keys() | 1058 to_delete = device_checksums.keys() |
| 1018 return (to_push, to_delete) | 1059 return (to_push, to_delete) |
| 1019 | 1060 |
| 1061 def _ComputeDeviceChecksumsForApks(self, package_name): | |
| 1062 ret = self._package_to_device_apk_checksums_cache.get(package_name) | |
| 1063 if ret is None: | |
| 1064 device_paths = self._GetApplicationPathsInternal(package_name) | |
| 1065 file_to_checksums = md5sum.CalculateDeviceMd5Sums(device_paths, self) | |
| 1066 ret = set(file_to_checksums.values()) | |
| 1067 self._package_to_device_apk_checksums_cache[package_name] = ret | |
| 1068 return ret | |
| 1069 | |
| 1070 def _ComputeStaleApks(self, package_name, host_apk_paths): | |
|
jbudorick
2015/08/06 19:28:22
I'm curious about the component time savings of ca
agrieve
2015/08/11 14:07:46
When I first started down this path, I tried to ad
| |
| 1071 host_checksums = md5sum.CalculateHostMd5Sums(host_apk_paths) | |
| 1072 device_checksums = self._ComputeDeviceChecksumsForApks(package_name) | |
| 1073 stale_apks = [k for (k, v) in host_checksums.iteritems() | |
| 1074 if v not in device_checksums] | |
| 1075 return stale_apks, set(host_checksums.values()) | |
| 1076 | |
| 1020 def _PushFilesImpl(self, host_device_tuples, files): | 1077 def _PushFilesImpl(self, host_device_tuples, files): |
| 1021 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) | 1078 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) |
| 1022 file_count = len(files) | 1079 file_count = len(files) |
| 1023 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) | 1080 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) |
| 1024 for h, _ in host_device_tuples) | 1081 for h, _ in host_device_tuples) |
| 1025 dir_file_count = 0 | 1082 dir_file_count = 0 |
| 1026 for h, _ in host_device_tuples: | 1083 for h, _ in host_device_tuples: |
| 1027 if os.path.isdir(h): | 1084 if os.path.isdir(h): |
| 1028 dir_file_count += sum(len(f) for _r, _d, f in os.walk(h)) | 1085 dir_file_count += sum(len(f) for _r, _d, f in os.walk(h)) |
| 1029 else: | 1086 else: |
| (...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1705 """Returns client cache.""" | 1762 """Returns client cache.""" |
| 1706 if client_name not in self._client_caches: | 1763 if client_name not in self._client_caches: |
| 1707 self._client_caches[client_name] = {} | 1764 self._client_caches[client_name] = {} |
| 1708 return self._client_caches[client_name] | 1765 return self._client_caches[client_name] |
| 1709 | 1766 |
| 1710 def _ClearCache(self): | 1767 def _ClearCache(self): |
| 1711 """Clears all caches.""" | 1768 """Clears all caches.""" |
| 1712 for client in self._client_caches: | 1769 for client in self._client_caches: |
| 1713 self._client_caches[client].clear() | 1770 self._client_caches[client].clear() |
| 1714 self._cache.clear() | 1771 self._cache.clear() |
| 1772 self._package_to_device_apk_paths_cache.clear() | |
| 1773 self._package_to_device_apk_checksums_cache.clear() | |
| 1715 | 1774 |
| 1716 @classmethod | 1775 @classmethod |
| 1717 def parallel(cls, devices=None, async=False): | 1776 def parallel(cls, devices=None, async=False): |
| 1718 """Creates a Parallelizer to operate over the provided list of devices. | 1777 """Creates a Parallelizer to operate over the provided list of devices. |
| 1719 | 1778 |
| 1720 If |devices| is either |None| or an empty list, the Parallelizer will | 1779 If |devices| is either |None| or an empty list, the Parallelizer will |
| 1721 operate over all attached devices that have not been blacklisted. | 1780 operate over all attached devices that have not been blacklisted. |
| 1722 | 1781 |
| 1723 Args: | 1782 Args: |
| 1724 devices: A list of either DeviceUtils instances or objects from | 1783 devices: A list of either DeviceUtils instances or objects from |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1745 def HealthyDevices(cls): | 1804 def HealthyDevices(cls): |
| 1746 blacklist = device_blacklist.ReadBlacklist() | 1805 blacklist = device_blacklist.ReadBlacklist() |
| 1747 def blacklisted(adb): | 1806 def blacklisted(adb): |
| 1748 if adb.GetDeviceSerial() in blacklist: | 1807 if adb.GetDeviceSerial() in blacklist: |
| 1749 logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial()) | 1808 logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial()) |
| 1750 return True | 1809 return True |
| 1751 return False | 1810 return False |
| 1752 | 1811 |
| 1753 return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices() | 1812 return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices() |
| 1754 if not blacklisted(adb)] | 1813 if not blacklisted(adb)] |
| OLD | NEW |