Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1300)

Unified Diff: build/android/pylib/device/device_utils.py

Issue 645093002: Revert of [Android] Add zip pushing and refine push mode selection. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 57164ed13f93fef65a2e93e9f066f795035a3ff1..fccdd619d02322e10763424405f78aa477e82c6a 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -8,21 +8,15 @@ Eventually, this will be based on adb_wrapper.
"""
# pylint: disable=W0613
-import multiprocessing
-import os
import pipes
import sys
-import tempfile
import time
-import zipfile
import pylib.android_commands
from pylib.device import adb_wrapper
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 host_utils
from pylib.utils import parallelizer
_DEFAULT_TIMEOUT = 30
@@ -67,23 +61,17 @@ class DeviceUtils(object):
operation should be retried on failure if no explicit
value is provided.
"""
- self.adb = None
self.old_interface = None
if isinstance(device, basestring):
- self.adb = adb_wrapper.AdbWrapper(device)
self.old_interface = pylib.android_commands.AndroidCommands(device)
elif isinstance(device, adb_wrapper.AdbWrapper):
- self.adb = device
self.old_interface = pylib.android_commands.AndroidCommands(str(device))
elif isinstance(device, pylib.android_commands.AndroidCommands):
- self.adb = adb_wrapper.AdbWrapper(device.GetDevice())
self.old_interface = device
elif not device:
- self.adb = adb_wrapper.AdbWrapper('')
self.old_interface = pylib.android_commands.AndroidCommands()
else:
raise ValueError('Unsupported type passed for argument "device"')
- self._commands_installed = False
self._default_timeout = default_timeout
self._default_retries = default_retries
assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR))
@@ -103,9 +91,6 @@ class DeviceUtils(object):
Raises:
CommandTimeoutError on timeout.
"""
- return self._IsOnlineImpl()
-
- def _IsOnlineImpl(self):
return self.old_interface.IsOnline()
@decorators.WithTimeoutAndRetriesFromInstance()
@@ -126,6 +111,17 @@ class DeviceUtils(object):
return self._HasRootImpl()
def _HasRootImpl(self):
+ """Implementation of HasRoot.
+
+ This is split from HasRoot to allow other DeviceUtils methods to call
+ HasRoot without spawning a new timeout thread.
+
+ Returns:
+ Same as for |HasRoot|.
+
+ Raises:
+ Same as for |HasRoot|.
+ """
return self.old_interface.IsRootEnabled()
@decorators.WithTimeoutAndRetriesFromInstance()
@@ -160,9 +156,6 @@ class DeviceUtils(object):
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
- return self._GetExternalStoragePathImpl()
-
- def _GetExternalStoragePathImpl(self):
try:
return self.old_interface.GetExternalStorage()
except AssertionError as e:
@@ -190,6 +183,21 @@ class DeviceUtils(object):
self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout)
def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None):
+ """Implementation of WaitUntilFullyBooted.
+
+ This is split from WaitUntilFullyBooted to allow other DeviceUtils methods
+ to call WaitUntilFullyBooted without spawning a new timeout thread.
+
+ TODO(jbudorick) Remove the timeout parameter once this is no longer
+ implemented via AndroidCommands.
+
+ Args:
+ wifi: Same as for |WaitUntilFullyBooted|.
+ timeout: timeout in seconds
+
+ Raises:
+ Same as for |WaitUntilFullyBooted|.
+ """
if timeout is None:
timeout = self._default_timeout
self.old_interface.WaitForSystemBootCompleted(timeout)
@@ -273,8 +281,8 @@ class DeviceUtils(object):
str(e), device=str(self)), None, sys.exc_info()[2]
@decorators.WithTimeoutAndRetriesFromInstance()
- def RunShellCommand(self, cmd, check_return=False, as_root=False, cwd=None,
- env=None, timeout=None, retries=None):
+ def RunShellCommand(self, cmd, check_return=False, as_root=False,
+ timeout=None, retries=None):
"""Run an ADB shell command.
TODO(jbudorick) Switch the default value of check_return to True after
@@ -286,8 +294,6 @@ class DeviceUtils(object):
be checked.
as_root: A boolean indicating whether the shell command should be run
with root privileges.
- cwd: The device directory in which the command should be run.
- env: The environment variables with which the command should be run.
timeout: timeout in seconds
retries: number of retries
@@ -299,23 +305,35 @@ class DeviceUtils(object):
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
- return self._RunShellCommandImpl(
- cmd, check_return=check_return, as_root=as_root, cwd=cwd, env=env,
- timeout=timeout)
+ return self._RunShellCommandImpl(cmd, check_return=check_return,
+ as_root=as_root, timeout=timeout)
def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False,
- cwd=None, env=None, timeout=None):
- # TODO(jbudorick): Remove the timeout parameter once this is no longer
- # backed by AndroidCommands.
+ timeout=None):
+ """Implementation of RunShellCommand.
+
+ This is split from RunShellCommand to allow other DeviceUtils methods to
+ call RunShellCommand without spawning a new timeout thread.
+
+ TODO(jbudorick) Remove the timeout parameter once this is no longer
+ implemented via AndroidCommands.
+
+ Args:
+ cmd: Same as for |RunShellCommand|.
+ check_return: Same as for |RunShellCommand|.
+ as_root: Same as for |RunShellCommand|.
+ timeout: timeout in seconds
+
+ Raises:
+ Same as for |RunShellCommand|.
+
+ Returns:
+ Same as for |RunShellCommand|.
+ """
if isinstance(cmd, list):
cmd = ' '.join(cmd)
- if as_root and not self._HasRootImpl():
+ if as_root and not self.HasRoot():
cmd = 'su -c %s' % cmd
- if env:
- cmd = '%s %s' % (
- ' '.join('%s=%s' % (k, v) for k, v in env.iteritems()), cmd)
- if cwd:
- cmd = 'cd %s && %s' % (cwd, cmd)
if check_return:
code, output = self.old_interface.GetShellCommandStatusAndOutput(
cmd, timeout_time=timeout)
@@ -483,15 +501,15 @@ class DeviceUtils(object):
@decorators.WithTimeoutAndRetriesDefaults(
PUSH_CHANGED_FILES_DEFAULT_TIMEOUT,
PUSH_CHANGED_FILES_DEFAULT_RETRIES)
- def PushChangedFiles(self, host_device_tuples, timeout=None,
+ def PushChangedFiles(self, host_path, device_path, timeout=None,
retries=None):
"""Push files to the device, skipping files that don't need updating.
Args:
- host_device_tuples: A list of (host_path, device_path) tuples, where
- |host_path| is an absolute path of a file or directory on the host
- that should be minimially pushed to the device, and |device_path| is
- an absolute path of the destination on the device.
+ host_path: A string containing the absolute path to the file or directory
+ on the host that should be minimally pushed to the device.
+ device_path: A string containing the absolute path of the destination on
+ the device.
timeout: timeout in seconds
retries: number of retries
@@ -500,125 +518,7 @@ class DeviceUtils(object):
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
-
- files = []
- for h, d in host_device_tuples:
- if os.path.isdir(h):
- self._RunShellCommandImpl(['mkdir', '-p', '"%s"' % d],
- check_return=True)
- files += self.old_interface.GetFilesChanged(h, d)
-
- if not files:
- return
-
- size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files)
- file_count = len(files)
- dir_size = sum(host_utils.GetRecursiveDiskUsage(h)
- for h, _ in host_device_tuples)
- dir_file_count = 0
- for h, _ in host_device_tuples:
- if os.path.isdir(h):
- dir_file_count += sum(len(f) for _r, _d, f in os.walk(h))
- else:
- dir_file_count += 1
-
- push_duration = self._ApproximateDuration(
- file_count, file_count, size, False)
- dir_push_duration = self._ApproximateDuration(
- len(host_device_tuples), dir_file_count, dir_size, False)
- zip_duration = self._ApproximateDuration(1, 1, size, True)
-
- if dir_push_duration < push_duration and dir_push_duration < zip_duration:
- self._PushChangedFilesIndividually(host_device_tuples)
- elif push_duration < zip_duration:
- self._PushChangedFilesIndividually(files)
- else:
- self._PushChangedFilesZipped(files)
- self._RunShellCommandImpl(
- ['chmod', '-R', '777'] + [d for _, d in host_device_tuples],
- as_root=True)
-
- @staticmethod
- def _ApproximateDuration(adb_calls, file_count, byte_count, is_zipping):
- # We approximate the time to push a set of files to a device as:
- # t = c1 * a + c2 * f + c3 + b / c4 + b / (c5 * c6), where
- # t: total time (sec)
- # c1: adb call time delay (sec)
- # a: number of times adb is called (unitless)
- # c2: push time delay (sec)
- # f: number of files pushed via adb (unitless)
- # c3: zip time delay (sec)
- # c4: zip rate (bytes/sec)
- # b: total number of bytes (bytes)
- # c5: transfer rate (bytes/sec)
- # c6: compression ratio (unitless)
-
- # All of these are approximations.
- ADB_CALL_PENALTY = 0.1 # seconds
- ADB_PUSH_PENALTY = 0.01 # seconds
- ZIP_PENALTY = 2.0 # seconds
- ZIP_RATE = 10000000.0 # bytes / second
- TRANSFER_RATE = 2000000.0 # bytes / second
- COMPRESSION_RATIO = 2.0 # unitless
-
- adb_call_time = ADB_CALL_PENALTY * adb_calls
- adb_push_setup_time = ADB_PUSH_PENALTY * file_count
- if is_zipping:
- zip_time = ZIP_PENALTY + byte_count / ZIP_RATE
- transfer_time = byte_count / (TRANSFER_RATE * COMPRESSION_RATIO)
- else:
- zip_time = 0
- transfer_time = byte_count / TRANSFER_RATE
- return (adb_call_time + adb_push_setup_time + zip_time + transfer_time)
-
- def _PushChangedFilesIndividually(self, files):
- for h, d in files:
- self.adb.Push(h, d)
-
- def _PushChangedFilesZipped(self, files):
- if not files:
- return
-
- self._InstallCommands()
-
- with tempfile.NamedTemporaryFile(suffix='.zip') as zip_file:
- zip_proc = multiprocessing.Process(
- target=DeviceUtils._CreateDeviceZip,
- args=(zip_file.name, files))
- zip_proc.start()
- zip_proc.join()
-
- zip_on_device = '%s/tmp.zip' % self._GetExternalStoragePathImpl()
- try:
- self.adb.Push(zip_file.name, zip_on_device)
- self._RunShellCommandImpl(
- ['unzip', zip_on_device],
- as_root=True, check_return=True,
- env={'PATH': '$PATH:%s' % install_commands.BIN_DIR})
- finally:
- if zip_proc.is_alive():
- zip_proc.terminate()
- if self._IsOnlineImpl():
- self._RunShellCommandImpl(['rm', zip_on_device])
-
- def _InstallCommands(self):
- if not self._commands_installed and not install_commands.Installed(self):
- install_commands.InstallCommands(self)
- self._commands_installed = True
-
- @staticmethod
- def _CreateDeviceZip(zip_path, host_device_tuples):
- with zipfile.ZipFile(zip_path, 'w') as zip_file:
- for host_path, device_path in host_device_tuples:
- if os.path.isfile(host_path):
- zip_file.write(host_path, device_path, zipfile.ZIP_DEFLATED)
- else:
- for hd, _, files in os.walk(host_path):
- dd = '%s/%s' % (device_path, os.path.relpath(host_path, hd))
- zip_file.write(hd, dd, zipfile.ZIP_STORED)
- for f in files:
- zip_file.write(os.path.join(hd, f), '%s/%s' % (dd, f),
- zipfile.ZIP_DEFLATED)
+ self.old_interface.PushIfNeeded(host_path, device_path)
@decorators.WithTimeoutAndRetriesFromInstance()
def FileExists(self, device_path, timeout=None, retries=None):
@@ -637,6 +537,23 @@ class DeviceUtils(object):
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
+ return self._FileExistsImpl(device_path)
+
+ def _FileExistsImpl(self, device_path):
+ """Implementation of FileExists.
+
+ This is split from FileExists to allow other DeviceUtils methods to call
+ FileExists without spawning a new timeout thread.
+
+ Args:
+ device_path: Same as for |FileExists|.
+
+ Returns:
+ True if the file exists on the device, False otherwise.
+
+ Raises:
+ Same as for |FileExists|.
+ """
return self.old_interface.FileExistsOnDevice(device_path)
@decorators.WithTimeoutAndRetriesFromInstance()
@@ -681,7 +598,7 @@ class DeviceUtils(object):
CommandTimeoutError on timeout.
DeviceUnreachableError on missing device.
"""
- # TODO(jbudorick) Evaluate whether we want to return a list of lines after
+ # TODO(jbudorick) Evaluate whether we awant to return a list of lines after
# the implementation switch, and if file not found should raise exception.
if as_root:
if not self.old_interface.CanAccessProtectedFileContents():
@@ -838,6 +755,21 @@ class DeviceUtils(object):
return self._GetPidsImpl(process_name)
def _GetPidsImpl(self, process_name):
+ """Implementation of GetPids.
+
+ This is split from GetPids to allow other DeviceUtils methods to call
+ GetPids without spawning a new timeout thread.
+
+ Args:
+ process_name: A string containing the process name to get the PIDs for.
+
+ Returns:
+ A dict mapping process name to PID for each process that contained the
+ provided |process_name|.
+
+ Raises:
+ DeviceUnreachableError on missing device.
+ """
procs_pids = {}
for line in self._RunShellCommandImpl('ps'):
try:

Powered by Google App Engine
This is Rietveld 408576698