| 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 21 matching lines...) Expand all Loading... |
| 32 except ImportError: | 32 except ImportError: |
| 33 pexpect = None | 33 pexpect = None |
| 34 | 34 |
| 35 sys.path.append(os.path.join( | 35 sys.path.append(os.path.join( |
| 36 constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner')) | 36 constants.DIR_SOURCE_ROOT, 'third_party', 'android_testrunner')) |
| 37 import adb_interface | 37 import adb_interface |
| 38 import am_instrument_parser | 38 import am_instrument_parser |
| 39 import errors | 39 import errors |
| 40 | 40 |
| 41 from pylib.device import device_blacklist | 41 from pylib.device import device_blacklist |
| 42 from pylib.device import device_errors |
| 42 | 43 |
| 43 # Pattern to search for the next whole line of pexpect output and capture it | 44 # Pattern to search for the next whole line of pexpect output and capture it |
| 44 # into a match group. We can't use ^ and $ for line start end with pexpect, | 45 # into a match group. We can't use ^ and $ for line start end with pexpect, |
| 45 # see http://www.noah.org/python/pexpect/#doc for explanation why. | 46 # see http://www.noah.org/python/pexpect/#doc for explanation why. |
| 46 PEXPECT_LINE_RE = re.compile('\n([^\r]*)\r') | 47 PEXPECT_LINE_RE = re.compile('\n([^\r]*)\r') |
| 47 | 48 |
| 48 # Set the adb shell prompt to be a unique marker that will [hopefully] not | 49 # Set the adb shell prompt to be a unique marker that will [hopefully] not |
| 49 # appear at the start of any line of a command's output. | 50 # appear at the start of any line of a command's output. |
| 50 SHELL_PROMPT = '~+~PQ\x17RS~+~' | 51 SHELL_PROMPT = '~+~PQ\x17RS~+~' |
| 51 | 52 |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 self._adb.SendCommand('wait-for-device') | 381 self._adb.SendCommand('wait-for-device') |
| 381 return return_value | 382 return return_value |
| 382 | 383 |
| 383 def GetDeviceYear(self): | 384 def GetDeviceYear(self): |
| 384 """Returns the year information of the date on device.""" | 385 """Returns the year information of the date on device.""" |
| 385 return self.RunShellCommand('date +%Y')[0] | 386 return self.RunShellCommand('date +%Y')[0] |
| 386 | 387 |
| 387 def GetExternalStorage(self): | 388 def GetExternalStorage(self): |
| 388 if not self._external_storage: | 389 if not self._external_storage: |
| 389 self._external_storage = self.RunShellCommand('echo $EXTERNAL_STORAGE')[0] | 390 self._external_storage = self.RunShellCommand('echo $EXTERNAL_STORAGE')[0] |
| 390 assert self._external_storage, 'Unable to find $EXTERNAL_STORAGE' | 391 if not self._external_storage: |
| 392 raise device_errors.CommandFailedError( |
| 393 ['shell', "'echo $EXTERNAL_STORAGE'"], |
| 394 'Unable to find $EXTERNAL_STORAGE') |
| 391 return self._external_storage | 395 return self._external_storage |
| 392 | 396 |
| 393 def WaitForDevicePm(self): | 397 def WaitForDevicePm(self): |
| 394 """Blocks until the device's package manager is available. | 398 """Blocks until the device's package manager is available. |
| 395 | 399 |
| 396 To workaround http://b/5201039, we restart the shell and retry if the | 400 To workaround http://b/5201039, we restart the shell and retry if the |
| 397 package manager isn't back after 120 seconds. | 401 package manager isn't back after 120 seconds. |
| 398 | 402 |
| 399 Raises: | 403 Raises: |
| 400 errors.WaitForResponseTimedOutError after max retries reached. | 404 errors.WaitForResponseTimedOutError after max retries reached. |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 output = self.RunShellCommand('ls ' + external_storage) | 645 output = self.RunShellCommand('ls ' + external_storage) |
| 642 if output: | 646 if output: |
| 643 sdcard_ready = True | 647 sdcard_ready = True |
| 644 else: | 648 else: |
| 645 time.sleep(wait_period) | 649 time.sleep(wait_period) |
| 646 attempts += 1 | 650 attempts += 1 |
| 647 if not sdcard_ready: | 651 if not sdcard_ready: |
| 648 raise errors.WaitForResponseTimedOutError( | 652 raise errors.WaitForResponseTimedOutError( |
| 649 'SD card not ready after %s seconds' % timeout_time) | 653 'SD card not ready after %s seconds' % timeout_time) |
| 650 | 654 |
| 651 def _CheckCommandIsValid(self, command): | |
| 652 """Raises a ValueError if the command is not valid.""" | |
| 653 | |
| 654 # A dict of commands the user should not run directly and a mapping to the | |
| 655 # API they should use instead. | |
| 656 preferred_apis = { | |
| 657 'getprop': 'system_properties[<PROPERTY>]', | |
| 658 'setprop': 'system_properties[<PROPERTY>]', | |
| 659 } | |
| 660 | |
| 661 # A dict of commands to methods that may call them. | |
| 662 whitelisted_callers = { | |
| 663 'getprop': 'ProvisionDevices', | |
| 664 } | |
| 665 | |
| 666 base_command = shlex.split(command)[0].strip(';') | |
| 667 if (base_command in preferred_apis and | |
| 668 (base_command not in whitelisted_callers or | |
| 669 whitelisted_callers[base_command] not in [ | |
| 670 f[3] for f in inspect.stack()])): | |
| 671 error_msg = ('%s should not be run directly. Instead use: %s' % | |
| 672 (base_command, preferred_apis[base_command])) | |
| 673 raise ValueError(error_msg) | |
| 674 | |
| 675 def GetAndroidToolStatusAndOutput(self, command, lib_path=None, *args, **kw): | 655 def GetAndroidToolStatusAndOutput(self, command, lib_path=None, *args, **kw): |
| 676 """Runs a native Android binary, wrapping the command as necessary. | 656 """Runs a native Android binary, wrapping the command as necessary. |
| 677 | 657 |
| 678 This is a specialization of GetShellCommandStatusAndOutput, which is meant | 658 This is a specialization of GetShellCommandStatusAndOutput, which is meant |
| 679 for running tools/android/ binaries and handle properly: (1) setting the | 659 for running tools/android/ binaries and handle properly: (1) setting the |
| 680 lib path (for component=shared_library), (2) using the PIE wrapper on ICS. | 660 lib path (for component=shared_library), (2) using the PIE wrapper on ICS. |
| 681 See crbug.com/373219 for more context. | 661 See crbug.com/373219 for more context. |
| 682 | 662 |
| 683 Args: | 663 Args: |
| 684 command: String containing the command to send. | 664 command: String containing the command to send. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 command: String containing the shell command to send. Must not include | 697 command: String containing the shell command to send. Must not include |
| 718 the single quotes as we use them to escape the whole command. | 698 the single quotes as we use them to escape the whole command. |
| 719 timeout_time: Number of seconds to wait for command to respond before | 699 timeout_time: Number of seconds to wait for command to respond before |
| 720 retrying, used by AdbInterface.SendShellCommand. | 700 retrying, used by AdbInterface.SendShellCommand. |
| 721 log_result: Boolean to indicate whether we should log the result of the | 701 log_result: Boolean to indicate whether we should log the result of the |
| 722 shell command. | 702 shell command. |
| 723 | 703 |
| 724 Returns: | 704 Returns: |
| 725 list containing the lines of output received from running the command | 705 list containing the lines of output received from running the command |
| 726 """ | 706 """ |
| 727 self._CheckCommandIsValid(command) | |
| 728 self._LogShell(command) | 707 self._LogShell(command) |
| 729 if "'" in command: | 708 if "'" in command: |
| 730 logging.warning(command + " contains ' quotes") | 709 logging.warning(command + " contains ' quotes") |
| 731 result = self._adb.SendShellCommand( | 710 result = self._adb.SendShellCommand( |
| 732 "'%s'" % command, timeout_time).splitlines() | 711 "'%s'" % command, timeout_time).splitlines() |
| 733 # TODO(b.kelemen): we should really be able to drop the stderr of the | 712 # TODO(b.kelemen): we should really be able to drop the stderr of the |
| 734 # command or raise an exception based on what the caller wants. | 713 # command or raise an exception based on what the caller wants. |
| 735 result = [ l for l in result if not l.startswith('WARNING') ] | 714 result = [ l for l in result if not l.startswith('WARNING') ] |
| 736 if ['error: device not found'] == result: | 715 if ['error: device not found'] == result: |
| 737 raise errors.DeviceUnresponsiveError('device not found') | 716 raise errors.DeviceUnresponsiveError('device not found') |
| (...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 dest: absolute path of destination directory | 1876 dest: absolute path of destination directory |
| 1898 """ | 1877 """ |
| 1899 logging.info('In EfficientDeviceDirectoryCopy %s %s', source, dest) | 1878 logging.info('In EfficientDeviceDirectoryCopy %s %s', source, dest) |
| 1900 with DeviceTempFile(self, suffix=".sh") as temp_script_file: | 1879 with DeviceTempFile(self, suffix=".sh") as temp_script_file: |
| 1901 host_script_path = os.path.join(constants.DIR_SOURCE_ROOT, | 1880 host_script_path = os.path.join(constants.DIR_SOURCE_ROOT, |
| 1902 'build', | 1881 'build', |
| 1903 'android', | 1882 'android', |
| 1904 'pylib', | 1883 'pylib', |
| 1905 'efficient_android_directory_copy.sh') | 1884 'efficient_android_directory_copy.sh') |
| 1906 self._adb.Push(host_script_path, temp_script_file.name) | 1885 self._adb.Push(host_script_path, temp_script_file.name) |
| 1907 self.EnableAdbRoot | |
| 1908 out = self.RunShellCommand( | 1886 out = self.RunShellCommand( |
| 1909 'sh %s %s %s' % (temp_script_file.name, source, dest), | 1887 'sh %s %s %s' % (temp_script_file.name, source, dest), |
| 1910 timeout_time=120) | 1888 timeout_time=120) |
| 1911 if self._device: | 1889 if self._device: |
| 1912 device_repr = self._device[-4:] | 1890 device_repr = self._device[-4:] |
| 1913 else: | 1891 else: |
| 1914 device_repr = '????' | 1892 device_repr = '????' |
| 1915 for line in out: | 1893 for line in out: |
| 1916 logging.info('[%s]> %s', device_repr, line) | 1894 logging.info('[%s]> %s', device_repr, line) |
| 1917 | 1895 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1983 """ | 1961 """ |
| 1984 def __init__(self, output): | 1962 def __init__(self, output): |
| 1985 self._output = output | 1963 self._output = output |
| 1986 | 1964 |
| 1987 def write(self, data): | 1965 def write(self, data): |
| 1988 data = data.replace('\r\r\n', '\n') | 1966 data = data.replace('\r\r\n', '\n') |
| 1989 self._output.write(data) | 1967 self._output.write(data) |
| 1990 | 1968 |
| 1991 def flush(self): | 1969 def flush(self): |
| 1992 self._output.flush() | 1970 self._output.flush() |
| OLD | NEW |