| OLD | NEW |
| 1 # Copyright 2015 Google Inc. All rights reserved. | 1 # Copyright 2015 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. |
| 5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at |
| 6 # | 6 # |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 # | 8 # |
| 9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
| 10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 def ConnectDevice(cls, port_path, **kwargs): | 134 def ConnectDevice(cls, port_path, **kwargs): |
| 135 """Return a AdbCommandsSafe for a USB device referenced by the port path. | 135 """Return a AdbCommandsSafe for a USB device referenced by the port path. |
| 136 | 136 |
| 137 Arguments: | 137 Arguments: |
| 138 - port_path: str in form '1/2' to refer to a connected but unopened USB | 138 - port_path: str in form '1/2' to refer to a connected but unopened USB |
| 139 device. | 139 device. |
| 140 - The rest are the same as __init__(). | 140 - The rest are the same as __init__(). |
| 141 """ | 141 """ |
| 142 # pylint: disable=protected-access | 142 # pylint: disable=protected-access |
| 143 obj = cls(port_path=port_path, handle=None, **kwargs) | 143 obj = cls(port_path=port_path, handle=None, **kwargs) |
| 144 obj._WaitUntilFound(use_serial=False) | 144 if obj._WaitUntilFound(use_serial=False): |
| 145 if obj._OpenHandle(): | 145 if obj._OpenHandle(): |
| 146 obj._Connect(use_serial=False) | 146 obj._Connect(use_serial=False) |
| 147 return obj | 147 return obj |
| 148 | 148 |
| 149 @classmethod | 149 @classmethod |
| 150 def Connect(cls, handle, **kwargs): | 150 def Connect(cls, handle, **kwargs): |
| 151 """Return a AdbCommandsSafe for a USB device referenced by a handle. | 151 """Return a AdbCommandsSafe for a USB device referenced by a handle. |
| 152 | 152 |
| 153 Arguments: | 153 Arguments: |
| 154 - handle: an opened or unopened common.UsbHandle. | 154 - handle: an opened or unopened common.UsbHandle. |
| 155 - The rest are the same as __init__(). | 155 - The rest are the same as __init__(). |
| 156 | 156 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 return False | 330 return False |
| 331 | 331 |
| 332 if not self._Reboot(): | 332 if not self._Reboot(): |
| 333 return False | 333 return False |
| 334 | 334 |
| 335 # There's no need to loop initially too fast. Restarting the phone | 335 # There's no need to loop initially too fast. Restarting the phone |
| 336 # always take several tens of seconds at best. | 336 # always take several tens of seconds at best. |
| 337 time.sleep(5.) | 337 time.sleep(5.) |
| 338 | 338 |
| 339 i = 0 | 339 i = 0 |
| 340 for i in self._Loop(): | 340 for i in self._Loop(timeout=60000): |
| 341 if not self._Reconnect(True): | 341 if not self._Reconnect(True, timeout=60000): |
| 342 continue | 342 continue |
| 343 uptime = self.GetUptime() | 343 uptime = self.GetUptime() |
| 344 if uptime and uptime < previous_uptime: | 344 if uptime and uptime < previous_uptime: |
| 345 return True | 345 return True |
| 346 time.sleep(0.1) | 346 time.sleep(0.1) |
| 347 _LOG.error( | 347 _LOG.error( |
| 348 '%s.Reboot(): Failed to id after %d tries', self.port_path, i+1) | 348 '%s.Reboot(): Failed to reboot after %d tries', self.port_path, i+1) |
| 349 return False | 349 return False |
| 350 | 350 |
| 351 def Remount(self): | 351 def Remount(self): |
| 352 """Remount / as read-write.""" | 352 """Remount / as read-write.""" |
| 353 if self._adb_cmd: | 353 if self._adb_cmd: |
| 354 for _ in self._Loop(): | 354 for _ in self._Loop(): |
| 355 try: | 355 try: |
| 356 out = self._adb_cmd.Remount() | 356 out = self._adb_cmd.Remount() |
| 357 # TODO(maruel): Wait for the remount operation to be completed. | 357 # TODO(maruel): Wait for the remount operation to be completed. |
| 358 _LOG.info('%s.Remount(): %s', self.port_path, out) | 358 _LOG.info('%s.Remount(): %s', self.port_path, out) |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 return out.startswith('uid=0(root)') | 488 return out.startswith('uid=0(root)') |
| 489 | 489 |
| 490 # Protected methods. | 490 # Protected methods. |
| 491 | 491 |
| 492 def _Reboot(self): | 492 def _Reboot(self): |
| 493 """Reboots the phone.""" | 493 """Reboots the phone.""" |
| 494 i = 0 | 494 i = 0 |
| 495 for i in self._Loop(): | 495 for i in self._Loop(): |
| 496 try: | 496 try: |
| 497 out = self._adb_cmd.Reboot() | 497 out = self._adb_cmd.Reboot() |
| 498 except usb_exceptions.ReadFailedError: |
| 499 # It looks like it's possible that adbd restarts the device so fast that |
| 500 # it close the USB connection before adbd has the time to reply (yay for |
| 501 # race conditions). In that case there's no way to know if the command |
| 502 # worked too fast or something went wrong and the command didn't go |
| 503 # through. |
| 504 # Assume it worked, which is nasty. |
| 505 out = '' |
| 498 except self._ERRORS as e: | 506 except self._ERRORS as e: |
| 499 if not self._Reset('(): %s', e, use_serial=True): | 507 if not self._Reset('(): %s', e, use_serial=True): |
| 500 break | 508 break |
| 501 continue | 509 continue |
| 502 | 510 |
| 503 _LOG.info('%s._Reboot(): %r', self.port_path, out) | 511 _LOG.info('%s._Reboot(): %s: %r', self.port_path, self.serial, out) |
| 504 if out == '': | 512 if out == '': |
| 505 # reboot doesn't reply anything. | 513 # reboot doesn't reply anything. |
| 506 return True | 514 return True |
| 507 assert False, repr(out) | 515 assert False, repr(out) |
| 508 _LOG.error('%s._Reboot(): Failed after %d tries', self.port_path, i+1) | 516 _LOG.error('%s._Reboot(): Failed after %d tries', self.port_path, i+1) |
| 509 return False | 517 return False |
| 510 | 518 |
| 511 def _Root(self): | 519 def _Root(self): |
| 512 """Upgrades adbd from shell user context (uid 2000) to root.""" | 520 """Upgrades adbd from shell user context (uid 2000) to root.""" |
| 513 i = 0 | 521 i = 0 |
| 514 for i in self._Loop(): | 522 for i in self._Loop(): |
| 515 try: | 523 try: |
| 516 out = self._adb_cmd.Root() | 524 out = self._adb_cmd.Root() |
| 525 except usb_exceptions.ReadFailedError: |
| 526 # It looks like it's possible that adbd restarts itself so fast that it |
| 527 # close the USB connection before adbd has the time to reply (yay for |
| 528 # race conditions). In that case there's no way to know if the command |
| 529 # worked too fast or something went wrong and the command didn't go |
| 530 # through. |
| 531 # Assume it worked, which is nasty. |
| 532 out = 'restarting adbd as root\n' |
| 517 except self._ERRORS as e: | 533 except self._ERRORS as e: |
| 518 if not self._Reset('(): %s', e, use_serial=True): | 534 if not self._Reset('(): %s', e, use_serial=True): |
| 519 break | 535 break |
| 520 continue | 536 continue |
| 521 | 537 |
| 522 _LOG.info('%s._Root(): %r', self.port_path, out) | 538 _LOG.info('%s._Root(): %r', self.port_path, out) |
| 523 # Hardcoded strings in platform_system_core/adb/services.cpp | 539 # Hardcoded strings in platform_system_core/adb/services.cpp |
| 524 if out == 'adbd is already running as root\n': | 540 if out == 'adbd is already running as root\n': |
| 525 return True | 541 return True |
| 526 if out == 'adbd cannot run as root in production builds\n': | 542 if out == 'adbd cannot run as root in production builds\n': |
| (...skipping 11 matching lines...) Expand all Loading... |
| 538 """Reduces adbd from root to shell user context (uid 2000). | 554 """Reduces adbd from root to shell user context (uid 2000). |
| 539 | 555 |
| 540 Doing so has the effect of having the device switch USB port. As such, the | 556 Doing so has the effect of having the device switch USB port. As such, the |
| 541 device has to be found back by the serial number, not by self.port_path | 557 device has to be found back by the serial number, not by self.port_path |
| 542 """ | 558 """ |
| 543 assert self._serial | 559 assert self._serial |
| 544 i = 0 | 560 i = 0 |
| 545 for i in self._Loop(): | 561 for i in self._Loop(): |
| 546 try: | 562 try: |
| 547 out = self._adb_cmd.Unroot() | 563 out = self._adb_cmd.Unroot() |
| 564 except usb_exceptions.ReadFailedError: |
| 565 # Unroot() is special (compared to Reboot and Root) as it's mostly |
| 566 # guaranteed that the output was sent before the USB connection is torn |
| 567 # down. But the exception still swallows the output (!) |
| 568 # Assume it worked, which is nasty. |
| 569 out = 'restarting adbd as non root\n' |
| 548 except self._ERRORS as e: | 570 except self._ERRORS as e: |
| 549 if not self._Reset('(): %s', e, use_serial=True): | 571 if not self._Reset('(): %s', e, use_serial=True): |
| 550 break | 572 break |
| 551 continue | 573 continue |
| 552 | 574 |
| 553 _LOG.info('%s.Unroot(): %r', self.port_path, out) | 575 _LOG.info('%s.Unroot(): %r', self.port_path, out) |
| 554 # Hardcoded strings in platform_system_core/adb/services.cpp | 576 # Hardcoded strings in platform_system_core/adb/services.cpp |
| 555 if out in ('adbd not running as root\n', 'restarting adbd as non root\n'): | 577 if out in ('adbd not running as root\n', 'restarting adbd as non root\n'): |
| 556 return True | 578 return True |
| 557 assert False, repr(out) | 579 assert False, repr(out) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 577 self._port_path = self._handle.port_path_str | 599 self._port_path = self._handle.port_path_str |
| 578 else: | 600 else: |
| 579 self._handle = common.UsbHandle.Find( | 601 self._handle = common.UsbHandle.Find( |
| 580 adb_commands.DeviceIsAvailable, port_path=self.port_path, | 602 adb_commands.DeviceIsAvailable, port_path=self.port_path, |
| 581 timeout_ms=self._default_timeout_ms) | 603 timeout_ms=self._default_timeout_ms) |
| 582 _LOG.info( | 604 _LOG.info( |
| 583 '%s._Find(%s) %s = %s', | 605 '%s._Find(%s) %s = %s', |
| 584 previous_port_path, use_serial, self._serial, | 606 previous_port_path, use_serial, self._serial, |
| 585 self.port_path if self._handle else 'None') | 607 self.port_path if self._handle else 'None') |
| 586 except (common.usb1.USBError, usb_exceptions.DeviceNotFoundError) as e: | 608 except (common.usb1.USBError, usb_exceptions.DeviceNotFoundError) as e: |
| 587 _LOG.info( | 609 _LOG.debug( |
| 588 '%s._Find(%s) %s : %s', self.port_path, use_serial, self._serial, e) | 610 '%s._Find(%s) %s : %s', self.port_path, use_serial, self._serial, e) |
| 611 return bool(self._handle) |
| 589 | 612 |
| 590 def _WaitUntilFound(self, use_serial): | 613 def _WaitUntilFound(self, use_serial, timeout=None): |
| 591 """Loops until the device is found on the USB bus. | 614 """Loops until the device is found on the USB bus. |
| 592 | 615 |
| 593 The handle is left unopened. | 616 The handle is left unopened. |
| 594 | 617 |
| 595 This function should normally be called when either adbd or the phone is | 618 This function should normally be called when either adbd or the phone is |
| 596 rebooting. | 619 rebooting. |
| 597 """ | 620 """ |
| 598 assert not self._handle | 621 assert not self._handle |
| 599 _LOG.debug('%s._WaitUntilFound(%s)', self.port_path, use_serial) | 622 _LOG.debug( |
| 623 '%s._WaitUntilFound(%s)', |
| 624 self.port_path, self.serial if use_serial else use_serial) |
| 600 i = 0 | 625 i = 0 |
| 601 for i in self._Loop(): | 626 for i in self._Loop(timeout=timeout): |
| 602 try: | 627 if self._Find(use_serial=use_serial): |
| 603 self._Find(use_serial=use_serial) | 628 return True |
| 604 return | 629 # Enumerate the devices present to help. |
| 605 except usb_exceptions.DeviceNotFoundError as e: | 630 def fn(h): |
| 606 _LOG.info( | 631 return '%s:%s' % (h.port_path, h.serial_number) |
| 607 '%s._WaitUntilFound(): Retrying _Find() due to %s', | 632 devices = '; '.join( |
| 608 self.port_path, e) | 633 fn(h) for h in |
| 634 common.UsbHandle.FindDevicesSafe(DeviceIsAvailable, timeout_ms=1000)) |
| 609 _LOG.warning( | 635 _LOG.warning( |
| 610 '%s._WaitUntilFound() gave up after %d tries', self.port_path, i+1) | 636 '%s._WaitUntilFound(%s) gave up after %d tries; found %s.', |
| 637 self.port_path, self.serial if use_serial else use_serial, i+1, devices) |
| 638 |
| 639 return False |
| 611 | 640 |
| 612 def _OpenHandle(self): | 641 def _OpenHandle(self): |
| 613 """Opens the unopened self._handle.""" | 642 """Opens the unopened self._handle.""" |
| 614 #_LOG.debug('%s._OpenHandle()', self.port_path) | 643 #_LOG.debug('%s._OpenHandle()', self.port_path) |
| 615 if self._handle: | 644 if self._handle: |
| 616 assert not self._handle.is_open | 645 assert not self._handle.is_open |
| 617 i = 0 | 646 i = 0 |
| 618 for i in self._Loop(): | 647 for i in self._Loop(): |
| 619 try: | 648 try: |
| 620 # If this succeeds, this initializes self._handle._handle, which is a | 649 # If this succeeds, this initializes self._handle._handle, which is a |
| 621 # usb1.USBDeviceHandle. | 650 # usb1.USBDeviceHandle. |
| 622 self._handle.Open() | 651 self._handle.Open() |
| 623 break | 652 return True |
| 624 except common.usb1.USBErrorNoDevice as e: | 653 except common.usb1.USBErrorNoDevice as e: |
| 625 _LOG.warning( | 654 _LOG.warning( |
| 626 '%s._OpenHandle(): USBErrorNoDevice: %s', self.port_path, e) | 655 '%s._OpenHandle(): USBErrorNoDevice: %s', self.port_path, e) |
| 627 # Do not kill adb, it just means the USB host is likely resetting and | 656 # Do not kill adb, it just means the USB host is likely resetting and |
| 628 # the device is temporarily unavailable. We can't use | 657 # the device is temporarily unavailable. We can't use |
| 629 # handle.serial_number since this communicates with the device. | 658 # handle.serial_number since this communicates with the device. |
| 630 except common.usb1.USBErrorBusy as e: | 659 except common.usb1.USBErrorBusy as e: |
| 631 _LOG.warning('%s._OpenHandle(): USBErrorBusy: %s', self.port_path, e) | 660 _LOG.warning('%s._OpenHandle(): USBErrorBusy: %s', self.port_path, e) |
| 632 KillADB() | 661 KillADB() |
| 633 except common.usb1.USBErrorAccess as e: | 662 except common.usb1.USBErrorAccess as e: |
| 634 # Do not try to use serial_number, since we can't even access the | 663 # Do not try to use serial_number, since we can't even access the |
| 635 # port. | 664 # port. |
| 636 _LOG.warning( | 665 _LOG.error( |
| 637 '%s._OpenHandle(): Try rebooting the host: %s', self.port_path, e) | 666 '%s._OpenHandle(): No access, maybe change udev rule or add ' |
| 667 'yourself to plugdev: %s', self.port_path, e) |
| 668 # Not worth retrying, exit early. |
| 638 break | 669 break |
| 639 else: | 670 else: |
| 640 _LOG.error( | 671 _LOG.error( |
| 641 '%s._OpenHandle(): Failed after %d tries', self.port_path, i+1) | 672 '%s._OpenHandle(): Failed after %d tries', self.port_path, i+1) |
| 642 self.Close() | 673 self.Close() |
| 643 return bool(self._handle) | 674 return False |
| 644 | 675 |
| 645 def _Connect(self, use_serial): | 676 def _Connect(self, use_serial): |
| 646 """Initializes self._adb_cmd from the opened self._handle. | 677 """Initializes self._adb_cmd from the opened self._handle. |
| 647 | 678 |
| 648 Returns True on success. | 679 Returns True on success. |
| 649 """ | 680 """ |
| 650 assert not self._adb_cmd | 681 assert not self._adb_cmd |
| 651 _LOG.debug('%s._Connect(%s)', self.port_path, use_serial) | 682 _LOG.debug('%s._Connect(%s)', self.port_path, use_serial) |
| 652 if self._handle: | 683 if self._handle: |
| 653 assert self._handle.is_open | 684 assert self._handle.is_open |
| 654 for _ in self._Loop(): | 685 for _ in self._Loop(): |
| 655 # On the first access with an open handle, try to set self._serial to | 686 # On the first access with an open handle, try to set self._serial to |
| 656 # the serial number of the device. This means communicating to the USB | 687 # the serial number of the device. This means communicating to the USB |
| 657 # device, so it may throw. | 688 # device, so it may throw. |
| 658 if not self._handle: | 689 if not self._handle: |
| 659 # It may happen on a retry. | 690 # It may happen on a retry. |
| 660 self._WaitUntilFound(use_serial=use_serial) | 691 if self._WaitUntilFound(use_serial=use_serial): |
| 661 self._OpenHandle() | 692 self._OpenHandle() |
| 662 if not self._handle: | 693 if not self._handle: |
| 663 break | 694 break |
| 664 | 695 |
| 665 if not self._serial or use_serial: | 696 if not self._serial or use_serial: |
| 666 try: | 697 try: |
| 667 # The serial number is attached to common.UsbHandle, no | 698 # The serial number is attached to common.UsbHandle, no |
| 668 # adb_commands.AdbCommands. | 699 # adb_commands.AdbCommands. |
| 669 self._serial = self._handle.serial_number | 700 self._serial = self._handle.serial_number |
| 670 except self._ERRORS as e: | 701 except self._ERRORS as e: |
| 671 self.Close() | 702 self.Close() |
| (...skipping 18 matching lines...) Expand all Loading... |
| 690 finally: | 721 finally: |
| 691 # Do not leak the USB handle when we can't talk to the device. | 722 # Do not leak the USB handle when we can't talk to the device. |
| 692 if not self._adb_cmd: | 723 if not self._adb_cmd: |
| 693 self.Close() | 724 self.Close() |
| 694 | 725 |
| 695 if not self._adb_cmd and self._handle: | 726 if not self._adb_cmd and self._handle: |
| 696 _LOG.error('Unexpected close') | 727 _LOG.error('Unexpected close') |
| 697 self.Close() | 728 self.Close() |
| 698 return bool(self._adb_cmd) | 729 return bool(self._adb_cmd) |
| 699 | 730 |
| 700 def _Loop(self): | 731 def _Loop(self, timeout=None): |
| 701 """Yields a loop until it's too late.""" | 732 """Yields a loop until it's too late.""" |
| 733 timeout = timeout or self._lost_timeout_ms |
| 702 start = time.time() | 734 start = time.time() |
| 703 for i in xrange(self._tries): | 735 for i in xrange(self._tries): |
| 704 if ((time.time() - start) * 1000) >= self._lost_timeout_ms: | 736 if ((time.time() - start) * 1000) >= timeout: |
| 705 return | 737 return |
| 706 yield i | 738 yield i |
| 707 if ((time.time() - start) * 1000) >= self._lost_timeout_ms: | 739 if ((time.time() - start) * 1000) >= timeout: |
| 708 return | 740 return |
| 709 time.sleep(self._sleep) | 741 time.sleep(self._sleep) |
| 710 | 742 |
| 711 def _Reset(self, fmt, *args, **kwargs): | 743 def _Reset(self, fmt, *args, **kwargs): |
| 712 """When a self._ERRORS occurred, try to reset the device. | 744 """When a self._ERRORS occurred, try to reset the device. |
| 713 | 745 |
| 714 Returns True on success. | 746 Returns True on success. |
| 715 """ | 747 """ |
| 716 items = [self.port_path, inspect.stack()[1][3]] | 748 items = [self.port_path, inspect.stack()[1][3]] |
| 717 items.extend(args) | 749 items.extend(args) |
| 718 msg = ('%s.%s' + fmt) % tuple(items) | 750 msg = ('%s.%s' + fmt) % tuple(items) |
| 719 _LOG.error(msg) | 751 _LOG.error(msg) |
| 720 if self._on_error: | 752 if self._on_error: |
| 721 self._on_error(msg) | 753 self._on_error(msg) |
| 722 | 754 |
| 723 # Reset the adbd and USB connections with a new connection. | 755 # Reset the adbd and USB connections with a new connection. |
| 724 return self._Reconnect(kwargs.get('use_serial', False)) | 756 return self._Reconnect(kwargs.get('use_serial', False)) |
| 725 | 757 |
| 726 def _Reconnect(self, use_serial): | 758 def _Reconnect(self, use_serial, timeout=None): |
| 727 """Disconnects and reconnect. | 759 """Disconnects and reconnect. |
| 728 | 760 |
| 729 Arguments: | 761 Arguments: |
| 730 - use_serial: If True, search the device by the serial number instead of the | 762 - use_serial: If True, search the device by the serial number instead of the |
| 731 port number. This is necessary when downgrading adbd from root to user | 763 port number. This is necessary when downgrading adbd from root to user |
| 732 context. | 764 context. |
| 733 | 765 |
| 734 Returns True on success. | 766 Returns True on success. |
| 735 """ | 767 """ |
| 736 self.Close() | 768 self.Close() |
| 737 self._WaitUntilFound(use_serial=use_serial) | 769 if not self._WaitUntilFound(use_serial=use_serial, timeout=timeout): |
| 770 return False |
| 738 if not self._OpenHandle(): | 771 if not self._OpenHandle(): |
| 739 return False | 772 return False |
| 740 return self._Connect(use_serial=use_serial) | 773 return self._Connect(use_serial=use_serial) |
| 741 | 774 |
| 742 def __repr__(self): | 775 def __repr__(self): |
| 743 return '<Device %s %s>' % ( | 776 return '<Device %s %s>' % ( |
| 744 self.port_path, self.serial if self.is_valid else '(broken)') | 777 self.port_path, self.serial if self.is_valid else '(broken)') |
| OLD | NEW |