| Index: build/android/pylib/device/device_utils.py
|
| diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
|
| index 334b74c41dc02b0a0015d93bce4d0b66dc5fe540..845d5801bf7db51cd7bef8a5919842c8a70d5767 100644
|
| --- a/build/android/pylib/device/device_utils.py
|
| +++ b/build/android/pylib/device/device_utils.py
|
| @@ -24,7 +24,9 @@ from pylib.device import decorators
|
| from pylib.device import device_errors
|
| from pylib.device.commands import install_commands
|
| from pylib.utils import apk_helper
|
| +from pylib.utils import device_temp_file
|
| from pylib.utils import host_utils
|
| +from pylib.utils import md5sum
|
| from pylib.utils import parallelizer
|
| from pylib.utils import timeout_retry
|
|
|
| @@ -92,8 +94,8 @@ class DeviceUtils(object):
|
| self._default_timeout = default_timeout
|
| self._default_retries = default_retries
|
| self._cache = {}
|
| - assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR))
|
| - assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR))
|
| + assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)
|
| + assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR)
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| def IsOnline(self, timeout=None, retries=None):
|
| @@ -429,13 +431,14 @@ class DeviceUtils(object):
|
|
|
| if not isinstance(cmd, basestring):
|
| cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
|
| - if as_root and self.NeedsSU():
|
| - cmd = 'su -c %s' % cmd
|
| if env:
|
| env = ' '.join(env_quote(k, v) for k, v in env.iteritems())
|
| cmd = '%s %s' % (env, cmd)
|
| if cwd:
|
| cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd)
|
| + if as_root and self.NeedsSU():
|
| + # "su -c sh -c" allows using shell features in |cmd|
|
| + cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd)
|
| if timeout is None:
|
| timeout = self._default_timeout
|
|
|
| @@ -699,12 +702,13 @@ class DeviceUtils(object):
|
| if not real_device_path:
|
| return [(host_path, device_path)]
|
|
|
| - # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base
|
| - # this function on mtime.
|
| - # pylint: disable=W0212
|
| - host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum(
|
| - real_host_path, real_device_path)
|
| - # pylint: enable=W0212
|
| + host_hash_tuples = md5sum.CalculateHostMd5Sums([real_host_path])
|
| + device_paths_to_md5 = (
|
| + real_device_path if os.path.isfile(real_host_path)
|
| + else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path))
|
| + for _, p in host_hash_tuples))
|
| + device_hash_tuples = md5sum.CalculateDeviceMd5Sums(
|
| + device_paths_to_md5, self)
|
|
|
| if os.path.isfile(host_path):
|
| if (not device_hash_tuples
|
| @@ -765,7 +769,7 @@ class DeviceUtils(object):
|
| else:
|
| zip_time = 0
|
| transfer_time = byte_count / TRANSFER_RATE
|
| - return (adb_call_time + adb_push_setup_time + zip_time + transfer_time)
|
| + return adb_call_time + adb_push_setup_time + zip_time + transfer_time
|
|
|
| def _PushChangedFilesIndividually(self, files):
|
| for h, d in files:
|
| @@ -882,16 +886,19 @@ class DeviceUtils(object):
|
| return self.old_interface.GetFileContents(device_path)
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| - def WriteFile(self, device_path, contents, as_root=False, timeout=None,
|
| - retries=None):
|
| + def WriteFile(self, device_path, contents, as_root=False, force_push=False,
|
| + timeout=None, retries=None):
|
| """Writes |contents| to a file on the device.
|
|
|
| Args:
|
| device_path: A string containing the absolute path to the file to write
|
| - on the device.
|
| + on the device.
|
| contents: A string containing the data to write to the device.
|
| as_root: A boolean indicating whether the write should be executed with
|
| - root privileges.
|
| + root privileges (if available).
|
| + force_push: A boolean indicating whether to force the operation to be
|
| + performed by pushing a file to the device. The default is, when the
|
| + contents are short, to pass the contents using a shell script instead.
|
| timeout: timeout in seconds
|
| retries: number of retries
|
|
|
| @@ -900,39 +907,24 @@ class DeviceUtils(object):
|
| CommandTimeoutError on timeout.
|
| DeviceUnreachableError on missing device.
|
| """
|
| - if as_root:
|
| - if not self.old_interface.CanAccessProtectedFileContents():
|
| - raise device_errors.CommandFailedError(
|
| - 'Cannot write to %s with root privileges.' % device_path)
|
| - self.old_interface.SetProtectedFileContents(device_path, contents)
|
| + if len(contents) < 512 and not force_push:
|
| + cmd = 'echo -n %s > %s' % (cmd_helper.SingleQuote(contents),
|
| + cmd_helper.SingleQuote(device_path))
|
| + self.RunShellCommand(cmd, as_root=as_root, check_return=True)
|
| else:
|
| - self.old_interface.SetFileContents(device_path, contents)
|
| -
|
| - @decorators.WithTimeoutAndRetriesFromInstance()
|
| - def WriteTextFile(self, device_path, text, as_root=False, timeout=None,
|
| - retries=None):
|
| - """Writes |text| to a file on the device.
|
| -
|
| - Assuming that |text| is a small string, this is typically more efficient
|
| - than |WriteFile|, as no files are pushed into the device.
|
| -
|
| - Args:
|
| - device_path: A string containing the absolute path to the file to write
|
| - on the device.
|
| - text: A short string of text to write to the file on the device.
|
| - as_root: A boolean indicating whether the write should be executed with
|
| - root privileges.
|
| - timeout: timeout in seconds
|
| - retries: number of retries
|
| -
|
| - Raises:
|
| - CommandFailedError if the file could not be written on the device.
|
| - CommandTimeoutError on timeout.
|
| - DeviceUnreachableError on missing device.
|
| - """
|
| - cmd = 'echo %s > %s' % (cmd_helper.SingleQuote(text),
|
| - cmd_helper.SingleQuote(device_path))
|
| - self.RunShellCommand(cmd, as_root=as_root, check_return=True)
|
| + with tempfile.NamedTemporaryFile() as host_temp:
|
| + host_temp.write(contents)
|
| + host_temp.flush()
|
| + if as_root and self.NeedsSU():
|
| + with device_temp_file.DeviceTempFile(self) as device_temp:
|
| + self.adb.Push(host_temp.name, device_temp.name)
|
| + # Here we need 'cp' rather than 'mv' because the temp and
|
| + # destination files might be on different file systems (e.g.
|
| + # on internal storage and an external sd card)
|
| + self.RunShellCommand(['cp', device_temp.name, device_path],
|
| + as_root=True, check_return=True)
|
| + else:
|
| + self.adb.Push(host_temp.name, device_path)
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| def Ls(self, device_path, timeout=None, retries=None):
|
|
|