summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/android/pylib/device/device_utils.py16
-rw-r--r--build/android/pylib/screenshot.py3
-rw-r--r--tools/telemetry/telemetry/core/android_process.py11
-rw-r--r--tools/telemetry/telemetry/core/backends/adb_commands.py142
-rw-r--r--tools/telemetry/telemetry/core/backends/android_app_backend.py8
-rw-r--r--tools/telemetry/telemetry/core/backends/android_command_line_backend.py20
-rw-r--r--tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py33
-rw-r--r--tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py38
-rw-r--r--tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py6
-rw-r--r--tools/telemetry/telemetry/core/backends/chrome/android_browser_finder_unittest.py48
-rw-r--r--tools/telemetry/telemetry/core/forwarders/android_forwarder.py62
-rw-r--r--tools/telemetry/telemetry/core/platform/android_action_runner.py18
-rw-r--r--tools/telemetry/telemetry/core/platform/android_device.py49
-rw-r--r--tools/telemetry/telemetry/core/platform/android_device_unittest.py175
-rw-r--r--tools/telemetry/telemetry/core/platform/android_platform_backend.py113
-rw-r--r--tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py92
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/android_prebuilt_profiler_helper.py2
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py2
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/android_traceview_profiler.py20
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py16
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/netlog_profiler.py4
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/oomkiller_profiler.py8
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py35
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py16
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py30
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/v8_profiler.py4
-rw-r--r--tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py14
-rw-r--r--tools/telemetry/telemetry/unittest_util/system_stub.py94
28 files changed, 483 insertions, 596 deletions
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index 967809f..8709d15 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -1382,22 +1382,6 @@ class DeviceUtils(object):
% (property_name, value), str(self))
@decorators.WithTimeoutAndRetriesFromInstance()
- def GetABI(self, timeout=None, retries=None):
- """Gets the device main ABI.
-
- Args:
- timeout: timeout in seconds
- retries: number of retries
-
- Returns:
- The device's main ABI name.
-
- Raises:
- CommandTimeoutError on timeout.
- """
- return self.GetProp('ro.product.cpu.abi')
-
- @decorators.WithTimeoutAndRetriesFromInstance()
def GetPids(self, process_name, timeout=None, retries=None):
"""Returns the PIDs of processes with the given name.
diff --git a/build/android/pylib/screenshot.py b/build/android/pylib/screenshot.py
index 0fcc590..35edf3c 100644
--- a/build/android/pylib/screenshot.py
+++ b/build/android/pylib/screenshot.py
@@ -8,6 +8,7 @@ import tempfile
import time
from pylib import cmd_helper
+from pylib import constants
from pylib import device_signal
from pylib.device import device_errors
@@ -40,7 +41,7 @@ class VideoRecorder(object):
self._recorder_stdout = None
self._is_started = False
- self._args = ['adb']
+ self._args = [constants.GetAdbPath()]
if str(self._device):
self._args += ['-s', str(self._device)]
self._args += ['shell', 'screenrecord', '--verbose']
diff --git a/tools/telemetry/telemetry/core/android_process.py b/tools/telemetry/telemetry/core/android_process.py
index 62134c2..bfbd293 100644
--- a/tools/telemetry/telemetry/core/android_process.py
+++ b/tools/telemetry/telemetry/core/android_process.py
@@ -2,10 +2,17 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-from telemetry.core.backends import adb_commands
from telemetry.core.backends.chrome_inspector import devtools_client_backend
+from telemetry.core import util
from telemetry.core import web_contents
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
+try:
+ from pylib import ports # pylint: disable=import-error
+except ImportError:
+ ports = None
+
+
class WebViewNotFoundException(Exception):
pass
@@ -16,7 +23,7 @@ class AndroidProcess(object):
self._app_backend = app_backend
self._pid = pid
self._name = name
- self._local_port = adb_commands.AllocateTestServerPort()
+ self._local_port = ports.AllocateTestServerPort()
self._devtools_client = None
@property
diff --git a/tools/telemetry/telemetry/core/backends/adb_commands.py b/tools/telemetry/telemetry/core/backends/adb_commands.py
deleted file mode 100644
index 42eeb43..0000000
--- a/tools/telemetry/telemetry/core/backends/adb_commands.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Brings in Chrome Android's android_commands module, which itself is a
-thin(ish) wrapper around adb."""
-
-import logging
-import os
-import shutil
-import stat
-
-from telemetry.core import platform
-from telemetry.core import util
-from telemetry.util import support_binaries
-
-# This is currently a thin wrapper around Chrome Android's
-# build scripts, located in chrome/build/android. This file exists mainly to
-# deal with locating the module.
-
-util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
-from pylib import android_commands # pylint: disable=F0401
-from pylib import constants # pylint: disable=F0401
-try:
- from pylib import ports # pylint: disable=F0401
-except Exception:
- ports = None
-from pylib.device import device_utils # pylint: disable=F0401
-from pylib.utils import apk_helper # pylint: disable=F0401
-
-
-def IsAndroidSupported():
- return device_utils != None
-
-def GetPackageName(apk_path):
- return apk_helper.GetPackageName(apk_path)
-
-def GetAttachedDevices():
- """Returns a list of attached, online android devices.
-
- If a preferred device has been set with ANDROID_SERIAL, it will be first in
- the returned list."""
- return android_commands.GetAttachedDevices()
-
-
-def AllocateTestServerPort():
- return ports.AllocateTestServerPort()
-
-
-def ResetTestServerPortAllocation():
- return ports.ResetTestServerPortAllocation()
-
-
-class AdbCommands(object):
- """A thin wrapper around ADB"""
-
- def __init__(self, device):
- self._device = device_utils.DeviceUtils(device)
- self._device_serial = device
-
- def device_serial(self):
- return self._device_serial
-
- def device(self):
- return self._device
-
- def __getattr__(self, name):
- """Delegate all unknown calls to the underlying AndroidCommands object."""
- return getattr(self._device.old_interface, name)
-
- def Forward(self, local, remote):
- self._device.adb.Forward(local, remote)
-
- def IsUserBuild(self):
- return self._device.GetProp('ro.build.type') == 'user'
-
-
-def GetBuildTypeOfPath(path):
- if not path:
- return None
- for build_dir, build_type in util.GetBuildDirectories():
- if os.path.join(build_dir, build_type) in path:
- return build_type
- return None
-
-
-def SetupPrebuiltTools(adb):
- """Some of the android pylib scripts we depend on are lame and expect
- binaries to be in the out/ directory. So we copy any prebuilt binaries there
- as a prereq."""
-
- # TODO(bulach): Build the targets for x86/mips.
- device_tools = [
- 'file_poller',
- 'forwarder_dist/device_forwarder',
- 'md5sum_dist/md5sum_bin',
- 'purge_ashmem',
- 'run_pie',
- ]
-
- host_tools = [
- 'bitmaptools',
- 'md5sum_bin_host',
- ]
-
- if platform.GetHostPlatform().GetOSName() == 'linux':
- host_tools.append('host_forwarder')
-
- arch_name = adb.device().GetABI()
- has_device_prebuilt = (arch_name.startswith('armeabi')
- or arch_name.startswith('arm64'))
- if not has_device_prebuilt:
- logging.warning('Unknown architecture type: %s' % arch_name)
- return all([support_binaries.FindLocallyBuiltPath(t) for t in device_tools])
-
- build_type = None
- for t in device_tools + host_tools:
- executable = os.path.basename(t)
- locally_built_path = support_binaries.FindLocallyBuiltPath(t)
- if not build_type:
- build_type = GetBuildTypeOfPath(locally_built_path) or 'Release'
- constants.SetBuildType(build_type)
- dest = os.path.join(constants.GetOutDirectory(), t)
- if not locally_built_path:
- logging.info('Setting up prebuilt %s', dest)
- if not os.path.exists(os.path.dirname(dest)):
- os.makedirs(os.path.dirname(dest))
- platform_name = ('android' if t in device_tools else
- platform.GetHostPlatform().GetOSName())
- bin_arch_name = (arch_name if t in device_tools else
- platform.GetHostPlatform().GetArchName())
- prebuilt_path = support_binaries.FindPath(
- executable, bin_arch_name, platform_name)
- if not prebuilt_path or not os.path.exists(prebuilt_path):
- raise NotImplementedError("""
-%s must be checked into cloud storage.
-Instructions:
-http://www.chromium.org/developers/telemetry/upload_to_cloud_storage
-""" % t)
- shutil.copyfile(prebuilt_path, dest)
- os.chmod(dest, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
- return True
diff --git a/tools/telemetry/telemetry/core/backends/android_app_backend.py b/tools/telemetry/telemetry/core/backends/android_app_backend.py
index b2c56f2..c0654eb 100644
--- a/tools/telemetry/telemetry/core/backends/android_app_backend.py
+++ b/tools/telemetry/telemetry/core/backends/android_app_backend.py
@@ -24,8 +24,8 @@ class AndroidAppBackend(app_backend.AppBackend):
self._existing_processes_by_pid = {}
@property
- def _adb(self):
- return self.platform_backend.adb
+ def _device(self):
+ return self.platform_backend.device
def _IsAppReady(self):
if self._is_app_ready_predicate is None:
@@ -42,10 +42,10 @@ class AndroidAppBackend(app_backend.AppBackend):
backend_settings = android_browser_backend_settings.WebviewBackendSettings(
'android-webview')
with android_command_line_backend.SetUpCommandLineFlags(
- self._adb, backend_settings, webview_startup_args):
+ self._device, backend_settings, webview_startup_args):
# TODO(slamm): check if can use "blocking=True" instead of needing to
# sleep. If "blocking=True" does not work, switch sleep to "ps" check.
- self._adb.device().StartActivity(self._start_intent, blocking=False)
+ self._device.StartActivity(self._start_intent, blocking=False)
util.WaitFor(self._IsAppReady, timeout=60)
self._is_running = True
diff --git a/tools/telemetry/telemetry/core/backends/android_command_line_backend.py b/tools/telemetry/telemetry/core/backends/android_command_line_backend.py
index e05c0bb..2636fe6 100644
--- a/tools/telemetry/telemetry/core/backends/android_command_line_backend.py
+++ b/tools/telemetry/telemetry/core/backends/android_command_line_backend.py
@@ -35,12 +35,12 @@ class SetUpCommandLineFlags(object):
Example usage:
with android_command_line_backend.SetUpCommandLineFlags(
- adb, backend_settings, startup_args):
+ device, backend_settings, startup_args):
# Something to run while the command line flags are set appropriately.
"""
- def __init__(self, adb, backend_settings, startup_args):
+ def __init__(self, device, backend_settings, startup_args):
self._android_command_line_backend = _AndroidCommandLineBackend(
- adb, backend_settings, startup_args)
+ device, backend_settings, startup_args)
def __enter__(self):
self._android_command_line_backend.SetUpCommandLineFlags()
@@ -59,15 +59,15 @@ class _AndroidCommandLineBackend(object):
functionality.
"""
- def __init__(self, adb, backend_settings, startup_args):
- self._adb = adb
+ def __init__(self, device, backend_settings, startup_args):
+ self._device = device
self._backend_settings = backend_settings
self._startup_args = startup_args
self._saved_command_line_file_contents = None
@property
def command_line_file(self):
- return self._backend_settings.GetCommandLineFile(self._adb.IsUserBuild())
+ return self._backend_settings.GetCommandLineFile(self._device.IsUserBuild())
def SetUpCommandLineFlags(self):
args = [self._backend_settings.pseudo_exec_name]
@@ -100,11 +100,11 @@ class _AndroidCommandLineBackend(object):
self._WriteFile(self._saved_command_line_file_contents)
def _ReadFile(self):
- return self._adb.device().ReadFile(self.command_line_file, as_root=True)
+ return self._device.ReadFile(self.command_line_file, as_root=True)
def _WriteFile(self, contents):
- self._adb.device().WriteFile(self.command_line_file, contents, as_root=True)
+ self._device.WriteFile(self.command_line_file, contents, as_root=True)
def _RemoveFile(self):
- self._adb.device().RunShellCommand(['rm', '-f', self.command_line_file],
- as_root=True, check_return=True)
+ self._device.RunShellCommand(['rm', '-f', self.command_line_file],
+ as_root=True, check_return=True)
diff --git a/tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py b/tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py
index da57d09..c03b3c9 100644
--- a/tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py
+++ b/tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py
@@ -5,10 +5,15 @@
import unittest
from telemetry import benchmark
-from telemetry.core.backends import adb_commands
+from telemetry.core import util
from telemetry.core.backends import android_command_line_backend
from telemetry.unittest_util import options_for_unittests
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
+from pylib.device import device_errors # pylint: disable=import-error
+from pylib.device import device_utils # pylint: disable=import-error
+
+
class _MockBackendSettings(object):
pseudo_exec_name = 'chrome'
@@ -49,16 +54,19 @@ class AndroidCommandLineBackendTest(unittest.TestCase):
Requires a device connected to the host.
"""
serial = options_for_unittests.GetCopy().device
- if not serial:
- serial = adb_commands.GetAttachedDevices()[0]
+ if serial:
+ device = device_utils.DeviceUtils(serial)
+ else:
+ devices = device_utils.DeviceUtils.HealthyDevices()
+ if not devices:
+ raise device_errors.NoDevicesError()
+ device = devices[0]
cmd_file = '/data/local/tmp/test_cmd'
- adb = adb_commands.AdbCommands(device=serial)
backend_settings = _MockBackendSettings('/data/local/tmp/test_cmd')
startup_args = ['--some', '--test', '--args']
- device = adb.device()
device.WriteFile(cmd_file, 'chrome --args --to --save')
with android_command_line_backend.SetUpCommandLineFlags(
- adb, backend_settings, startup_args):
+ device, backend_settings, startup_args):
self.assertEqual('chrome --some --test --args',
device.ReadFile(cmd_file).strip())
self.assertEqual('chrome --args --to --save',
@@ -72,16 +80,19 @@ class AndroidCommandLineBackendTest(unittest.TestCase):
Requires a device connected to the host.
"""
serial = options_for_unittests.GetCopy().device
- if not serial:
- serial = adb_commands.GetAttachedDevices()[0]
+ if serial:
+ device = device_utils.DeviceUtils(serial)
+ else:
+ devices = device_utils.DeviceUtils.HealthyDevices()
+ if not devices:
+ raise device_errors.NoDevicesError()
+ device = devices[0]
cmd_file = '/data/local/tmp/test_cmd'
- adb = adb_commands.AdbCommands(device=serial)
backend_settings = _MockBackendSettings('/data/local/tmp/test_cmd')
startup_args = ['--some', '--test', '--args']
- device = adb.device()
device.RunShellCommand(['rm', '-f', cmd_file], check_return=True)
with android_command_line_backend.SetUpCommandLineFlags(
- adb, backend_settings, startup_args):
+ device, backend_settings, startup_args):
self.assertEqual('chrome --some --test --args',
device.ReadFile(cmd_file).strip())
self.assertFalse(device.FileExists(cmd_file))
diff --git a/tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py b/tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py
index 1f914db..adf0997 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py
@@ -5,7 +5,6 @@
import logging
import sys
-from telemetry.core.backends import adb_commands
from telemetry.core.backends import android_command_line_backend
from telemetry.core.backends import browser_backend
from telemetry.core.backends.chrome import chrome_browser_backend
@@ -16,7 +15,11 @@ from telemetry.core.platform import android_platform_backend as \
from telemetry.core import util
util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
-from pylib.device import intent # pylint: disable=F0401
+try:
+ from pylib import ports # pylint: disable=import-error
+except ImportError:
+ ports = None
+from pylib.device import intent # pylint: disable=import-error
class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
@@ -43,7 +46,7 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
# TODO(tonyg): This is flaky because it doesn't reserve the port that it
# allocates. Need to fix this.
- self._port = adb_commands.AllocateTestServerPort()
+ self._port = ports.AllocateTestServerPort()
# TODO(wuhu): Move to network controller backend.
self.platform_backend.InstallTestCa()
@@ -51,7 +54,7 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
# Kill old browser.
self._KillBrowser()
- if self._adb.device().old_interface.CanAccessProtectedFileContents():
+ if self.device.old_interface.CanAccessProtectedFileContents():
if self.browser_options.profile_dir:
self.platform_backend.PushProfile(
self._backend_settings.package,
@@ -73,17 +76,17 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
self.platform_backend.SetDebugApp(self._backend_settings.package)
@property
- def _adb(self):
- return self.platform_backend.adb
+ def device(self):
+ return self.platform_backend.device
def _KillBrowser(self):
- if self._adb.device().IsUserBuild():
+ if self.device.IsUserBuild():
self.platform_backend.StopApplication(self._backend_settings.package)
else:
self.platform_backend.KillApplication(self._backend_settings.package)
def Start(self):
- self._adb.device().RunShellCommand('logcat -c')
+ self.device.RunShellCommand('logcat -c')
if self.browser_options.startup_url:
url = self.browser_options.startup_url
elif self.browser_options.profile_dir:
@@ -97,15 +100,15 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
browser_startup_args = self.GetBrowserStartupArgs()
with android_command_line_backend.SetUpCommandLineFlags(
- self._adb, self._backend_settings, browser_startup_args):
- self._adb.device().StartActivity(
+ self.device, self._backend_settings, browser_startup_args):
+ self.device.StartActivity(
intent.Intent(package=self._backend_settings.package,
activity=self._backend_settings.activity,
action=None, data=url, category=None),
blocking=True)
remote_devtools_port = self._backend_settings.GetDevtoolsRemotePort(
- self._adb)
+ self.device)
self.platform_backend.ForwardHostToDevice(self._port,
remote_devtools_port)
try:
@@ -113,8 +116,7 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
self._InitDevtoolsClientBackend(remote_devtools_port)
except exceptions.BrowserGoneException:
logging.critical('Failed to connect to browser.')
- device = self._adb.device()
- if not device.old_interface.CanAccessProtectedFileContents():
+ if not self.device.old_interface.CanAccessProtectedFileContents():
logging.critical(
'Resolve this by either: '
'(1) Flashing to a userdebug build OR '
@@ -135,15 +137,11 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
return args
@property
- def adb(self):
- return self._adb
-
- @property
def pid(self):
- pids = self._adb.ExtractPid(self._backend_settings.package)
- if not pids:
+ pids = self.device.GetPids(self._backend_settings.package)
+ if not pids or self._backend_settings.package not in pids:
raise exceptions.BrowserGoneException(self.browser)
- return int(pids[0])
+ return int(pids[self._backend_settings.package])
@property
def browser_directory(self):
diff --git a/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py b/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py
index d4402a4..8091cd0 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py
@@ -7,7 +7,6 @@
import logging
import os
-from telemetry.core.backends import adb_commands
from telemetry.core.backends import android_browser_backend_settings
from telemetry.core.backends.chrome import android_browser_backend
from telemetry.core import browser
@@ -18,6 +17,9 @@ from telemetry.core import possible_browser
from telemetry.core import util
from telemetry import decorators
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
+from pylib.utils import apk_helper # pylint: disable=import-error
+
CHROME_PACKAGE_NAMES = {
'android-content-shell':
@@ -170,7 +172,7 @@ def _FindAllPossibleBrowsers(finder_options, android_platform):
CanPossiblyHandlePath(finder_options.browser_executable)):
normalized_path = os.path.expanduser(finder_options.browser_executable)
- exact_package = adb_commands.GetPackageName(normalized_path)
+ exact_package = apk_helper.GetPackageName(normalized_path)
if not exact_package:
raise exceptions.PackageDetectionError(
'Unable to find package for %s specified by --browser-executable' %
diff --git a/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder_unittest.py b/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder_unittest.py
index ae6660f..d85a298 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder_unittest.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder_unittest.py
@@ -6,8 +6,12 @@ import unittest
from telemetry.core.backends.chrome import android_browser_finder
from telemetry.core import browser_options
+from telemetry.core import util
from telemetry.unittest_util import system_stub
+util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'mock')
+import mock # pylint: disable=import-error
+
class FakeAndroidPlatform(object):
def __init__(self, can_launch):
@@ -24,7 +28,7 @@ class AndroidBrowserFinderTest(unittest.TestCase):
# Mock out what's needed for testing with exact APKs
self._android_browser_finder_stub = system_stub.Override(
- android_browser_finder, ['adb_commands', 'os'])
+ android_browser_finder, ['os'])
def tearDown(self):
self._android_browser_finder_stub.Restore()
@@ -50,37 +54,39 @@ class AndroidBrowserFinderTest(unittest.TestCase):
self._android_browser_finder_stub.os.path.files.append(
'/foo/content-shell.apk')
self.finder_options.browser_executable = '/foo/content-shell.apk'
- self._android_browser_finder_stub.adb_commands.apk_package_name = \
- 'org.chromium.content_shell_apk'
- fake_platform = FakeAndroidPlatform(can_launch=True)
- expected_types = set(
- android_browser_finder.FindAllBrowserTypes(self.finder_options))
- possible_browsers = android_browser_finder._FindAllPossibleBrowsers(
- self.finder_options, fake_platform)
- self.assertEqual(
- expected_types,
- set([b.browser_type for b in possible_browsers]))
+ with mock.patch('pylib.utils.apk_helper.GetPackageName',
+ return_value='org.chromium.content_shell_apk'):
+ fake_platform = FakeAndroidPlatform(can_launch=True)
+ expected_types = set(
+ android_browser_finder.FindAllBrowserTypes(self.finder_options))
+ possible_browsers = android_browser_finder._FindAllPossibleBrowsers(
+ self.finder_options, fake_platform)
+ self.assertEqual(
+ expected_types,
+ set([b.browser_type for b in possible_browsers]))
def testErrorWithUnknownExactApk(self):
self._android_browser_finder_stub.os.path.files.append(
'/foo/content-shell.apk')
self.finder_options.browser_executable = '/foo/content-shell.apk'
- self._android_browser_finder_stub.adb_commands.apk_package_name = \
- 'org.unknown.app'
- fake_platform = FakeAndroidPlatform(can_launch=True)
- self.assertRaises(Exception,
- android_browser_finder._FindAllPossibleBrowsers,
- self.finder_options, fake_platform)
+ with mock.patch('pylib.utils.apk_helper.GetPackageName',
+ return_value='org.unknown.app'):
+ fake_platform = FakeAndroidPlatform(can_launch=True)
+ self.assertRaises(Exception,
+ android_browser_finder._FindAllPossibleBrowsers,
+ self.finder_options, fake_platform)
def testErrorWithNonExistantExactApk(self):
self.finder_options.browser_executable = '/foo/content-shell.apk'
- fake_platform = FakeAndroidPlatform(can_launch=True)
- self.assertRaises(Exception,
- android_browser_finder._FindAllPossibleBrowsers,
- self.finder_options, fake_platform)
+ with mock.patch('pylib.utils.apk_helper.GetPackageName',
+ return_value='org.chromium.content_shell_apk'):
+ fake_platform = FakeAndroidPlatform(can_launch=True)
+ self.assertRaises(Exception,
+ android_browser_finder._FindAllPossibleBrowsers,
+ self.finder_options, fake_platform)
class FakePossibleBrowser(object):
diff --git a/tools/telemetry/telemetry/core/forwarders/android_forwarder.py b/tools/telemetry/telemetry/core/forwarders/android_forwarder.py
index ed8ed7b..d0c9eda 100644
--- a/tools/telemetry/telemetry/core/forwarders/android_forwarder.py
+++ b/tools/telemetry/telemetry/core/forwarders/android_forwarder.py
@@ -9,7 +9,6 @@ import socket
import struct
import subprocess
-from telemetry.core.backends import adb_commands
from telemetry.core import forwarders
from telemetry.core import platform
from telemetry.core import util
@@ -17,27 +16,28 @@ from telemetry.util import support_binaries
util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
try:
- from pylib import forwarder # pylint: disable=F0401
+ from pylib import forwarder # pylint: disable=import-error
except ImportError:
forwarder = None
-from pylib.device import device_errors # pylint: disable=F0401
+from pylib.device import device_errors # pylint: disable=import-error
+from pylib.device import device_utils # pylint: disable=import-error
class AndroidForwarderFactory(forwarders.ForwarderFactory):
- def __init__(self, adb, use_rndis):
+ def __init__(self, device, use_rndis):
super(AndroidForwarderFactory, self).__init__()
- self._adb = adb
+ self._device = device
self._rndis_configurator = None
if use_rndis:
- self._rndis_configurator = AndroidRndisConfigurator(self._adb)
+ self._rndis_configurator = AndroidRndisConfigurator(self._device)
def Create(self, port_pairs):
if self._rndis_configurator:
- return AndroidRndisForwarder(self._adb, self._rndis_configurator,
+ return AndroidRndisForwarder(self._device, self._rndis_configurator,
port_pairs)
- return AndroidForwarder(self._adb, port_pairs)
+ return AndroidForwarder(self._device, port_pairs)
@property
def host_ip(self):
@@ -52,9 +52,9 @@ class AndroidForwarderFactory(forwarders.ForwarderFactory):
class AndroidForwarder(forwarders.Forwarder):
- def __init__(self, adb, port_pairs):
+ def __init__(self, device, port_pairs):
super(AndroidForwarder, self).__init__(port_pairs)
- self._device = adb.device()
+ self._device = device
forwarder.Forwarder.Map([(p.remote_port, p.local_port)
for p in port_pairs if p], self._device)
self._port_pairs = forwarders.PortPairs(*[
@@ -74,10 +74,10 @@ class AndroidForwarder(forwarders.Forwarder):
class AndroidRndisForwarder(forwarders.Forwarder):
"""Forwards traffic using RNDIS. Assumes the device has root access."""
- def __init__(self, adb, rndis_configurator, port_pairs):
+ def __init__(self, device, rndis_configurator, port_pairs):
super(AndroidRndisForwarder, self).__init__(port_pairs)
- self._adb = adb
+ self._device = device
self._rndis_configurator = rndis_configurator
self._device_iface = rndis_configurator.device_iface
self._host_ip = rndis_configurator.host_ip
@@ -103,12 +103,13 @@ class AndroidRndisForwarder(forwarders.Forwarder):
def _RedirectPorts(self, port_pairs):
"""Sets the local to remote pair mappings to use for RNDIS."""
- self._adb.RunShellCommand('iptables -F -t nat') # Flush any old nat rules.
+ # Flush any old nat rules.
+ self._device.RunShellCommand('iptables -F -t nat')
for port_pair in port_pairs:
if not port_pair or port_pair.local_port == port_pair.remote_port:
continue
protocol = 'udp' if port_pair.remote_port == 53 else 'tcp'
- self._adb.RunShellCommand(
+ self._device.RunShellCommand(
'iptables -t nat -A OUTPUT -p %s --dport %d'
' -j DNAT --to-destination %s:%d' %
(protocol, port_pair.remote_port, self.host_ip, port_pair.local_port))
@@ -129,27 +130,27 @@ class AndroidRndisForwarder(forwarders.Forwarder):
return # If there is no route, then nobody cares about DNS.
# DNS proxy in older versions of Android is configured via properties.
# TODO(szym): run via su -c if necessary.
- self._adb.device().SetProp('net.dns1', dns1)
- self._adb.device().SetProp('net.dns2', dns2)
- dnschange = self._adb.device().GetProp('net.dnschange')
+ self._device.SetProp('net.dns1', dns1)
+ self._device.SetProp('net.dns2', dns2)
+ dnschange = self._device.GetProp('net.dnschange')
if dnschange:
- self._adb.device().SetProp('net.dnschange', str(int(dnschange) + 1))
+ self._device.SetProp('net.dnschange', str(int(dnschange) + 1))
# Since commit 8b47b3601f82f299bb8c135af0639b72b67230e6 to frameworks/base
# the net.dns1 properties have been replaced with explicit commands for netd
- self._adb.RunShellCommand('netd resolver setifdns %s %s %s' %
- (iface, dns1, dns2))
+ self._device.RunShellCommand('netd resolver setifdns %s %s %s' %
+ (iface, dns1, dns2))
# TODO(szym): if we know the package UID, we could setifaceforuidrange
- self._adb.RunShellCommand('netd resolver setdefaultif %s' % iface)
+ self._device.RunShellCommand('netd resolver setdefaultif %s' % iface)
def _GetCurrentDns(self):
"""Returns current gateway, dns1, and dns2."""
- routes = self._adb.RunShellCommand('cat /proc/net/route')[1:]
+ routes = self._device.RunShellCommand('cat /proc/net/route')[1:]
routes = [route.split() for route in routes]
default_routes = [route[0] for route in routes if route[1] == '00000000']
return (
default_routes[0] if default_routes else None,
- self._adb.device().GetProp('net.dns1'),
- self._adb.device().GetProp('net.dns2'),
+ self._device.GetProp('net.dns1'),
+ self._device.GetProp('net.dns2'),
)
def _OverrideDefaultGateway(self):
@@ -162,11 +163,11 @@ class AndroidRndisForwarder(forwarders.Forwarder):
(e.g. Telemetry crashes). A power cycle or "adb reboot" is a simple
workaround around in that case.
"""
- self._adb.RunShellCommand('route add default gw %s dev %s' %
+ self._device.RunShellCommand('route add default gw %s dev %s' %
(self.host_ip, self._device_iface))
def _RestoreDefaultGateway(self):
- self._adb.RunShellCommand('netcfg %s down' % self._device_iface)
+ self._device.RunShellCommand('netcfg %s down' % self._device_iface)
class AndroidRndisConfigurator(object):
@@ -182,8 +183,8 @@ class AndroidRndisConfigurator(object):
_INTERFACES_INCLUDE = 'source /etc/network/interfaces.d/*.conf'
_TELEMETRY_INTERFACE_FILE = '/etc/network/interfaces.d/telemetry-{}.conf'
- def __init__(self, adb):
- self._device = adb.device()
+ def __init__(self, device):
+ self._device = device
try:
self._device.EnableRoot()
@@ -386,9 +387,8 @@ doit &
"""
my_device = str(self._device)
addresses = []
- for device_serial in adb_commands.GetAttachedDevices():
- device = adb_commands.AdbCommands(device_serial).device()
- if device_serial == my_device:
+ for device in device_utils.DeviceUtils.HealthyDevices():
+ if device.adb.GetDeviceSerial() == my_device:
excluded = excluded_iface
else:
excluded = 'no interfaces excluded on other devices'
diff --git a/tools/telemetry/telemetry/core/platform/android_action_runner.py b/tools/telemetry/telemetry/core/platform/android_action_runner.py
index c2f79b4..1e87445 100644
--- a/tools/telemetry/telemetry/core/platform/android_action_runner.py
+++ b/tools/telemetry/telemetry/core/platform/android_action_runner.py
@@ -67,7 +67,7 @@ class AndroidActionRunner(object):
Args:
string: The string to send to the device.
"""
- self._platform_backend.adb.RunShellCommand('input text %s' % string)
+ self._platform_backend.device.RunShellCommand('input text %s' % string)
def InputKeyEvent(self, key):
"""Send a single key input to the device.
@@ -75,7 +75,7 @@ class AndroidActionRunner(object):
Args:
key: A key code number or name that will be sent to the device
"""
- self._platform_backend.adb.RunShellCommand('input keyevent %s' % key)
+ self._platform_backend.device.SendKeyEvent(key)
def InputTap(self, x_coord, y_coord):
"""Perform a tap input at the given coordinates.
@@ -84,8 +84,8 @@ class AndroidActionRunner(object):
x_coord: The x coordinate of the tap event.
y_coord: The y coordinate of the tap event.
"""
- self._platform_backend.adb.RunShellCommand('input tap %s %s' % (x_coord,
- y_coord))
+ self._platform_backend.device.RunShellCommand(
+ 'input tap %s %s' % (x_coord, y_coord))
def InputSwipe(self, left_start_coord, top_start_coord, left_end_coord,
top_end_coord, duration):
@@ -98,14 +98,14 @@ class AndroidActionRunner(object):
top_end_coord: The vertical ending coordinate of the gesture
duration: The length of time of the swipe in milliseconds
"""
- self._platform_backend.adb.RunShellCommand(
+ self._platform_backend.device.RunShellCommand(
'input swipe %s %s %s %s %s' % (left_start_coord, top_start_coord,
left_end_coord, top_end_coord,
duration))
def InputPress(self):
"""Perform a press input."""
- self._platform_backend.adb.RunShellCommand('input press')
+ self._platform_backend.device.RunShellCommand('input press')
def InputRoll(self, dx, dy):
"""Perform a roll input. This sends a simple zero-pressure move event.
@@ -114,7 +114,7 @@ class AndroidActionRunner(object):
dx: Change in the x coordinate due to move.
dy: Change in the y coordinate due to move.
"""
- self._platform_backend.adb.RunShellCommand('input roll %s %s' % (dx, dy))
+ self._platform_backend.device.RunShellCommand('input roll %s %s' % (dx, dy))
def EnsureScreenOn(self):
"""If device screen is off, turn screen on.
@@ -173,7 +173,7 @@ class AndroidActionRunner(object):
return not self._platform_backend.IsScreenLocked()
if self._platform_backend.IsScreenLocked():
- self._platform_backend.adb.RunShellCommand('input keyevent 82')
+ self._platform_backend.device.SendKeyEvent(82)
else:
logging.warning('Screen not locked when expected.')
return
@@ -181,4 +181,4 @@ class AndroidActionRunner(object):
util.WaitFor(is_screen_unlocked, 5)
def _ToggleScreenOn(self):
- self._platform_backend.adb.RunShellCommand('input keyevent 26')
+ self._platform_backend.device.SendKeyEvent(26)
diff --git a/tools/telemetry/telemetry/core/platform/android_device.py b/tools/telemetry/telemetry/core/platform/android_device.py
index c7dc378..1c5fac4 100644
--- a/tools/telemetry/telemetry/core/platform/android_device.py
+++ b/tools/telemetry/telemetry/core/platform/android_device.py
@@ -1,17 +1,19 @@
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+
import logging
import os
-import re
-import subprocess
-import sys
-from telemetry.core.backends import adb_commands
from telemetry.core.platform import device
from telemetry.core.platform.profiler import monsoon
from telemetry.core import util
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
+from pylib import constants # pylint: disable=import-error
+from pylib.device import device_errors # pylint: disable=import-error
+from pylib.device import device_utils # pylint: disable=import-error
+
class AndroidDevice(device.Device):
""" Class represents information for connecting to an android device.
@@ -44,7 +46,8 @@ class AndroidDevice(device.Device):
def GetDeviceSerials():
- device_serials = adb_commands.GetAttachedDevices()
+ device_serials = [d.adb.GetDeviceSerial()
+ for d in device_utils.DeviceUtils.HealthyDevices()]
# The monsoon provides power for the device, so for devices with no
# real battery, we need to turn them on after the monsoon enables voltage
# output to the device.
@@ -65,8 +68,9 @@ The Monsoon's power output has been enabled. Please now ensure that:
Waiting for device...
""")
- util.WaitFor(adb_commands.GetAttachedDevices, 600)
- device_serials = adb_commands.GetAttachedDevices()
+ util.WaitFor(device_utils.DeviceUtils.HealthyDevices, 600)
+ device_serials = [d.adb.GetDeviceSerial()
+ for d in device_utils.DeviceUtils.HealthyDevices()]
except IOError:
return []
return device_serials
@@ -98,33 +102,16 @@ def GetDevice(finder_options):
def CanDiscoverDevices():
"""Returns true if devices are discoverable via adb."""
- if not adb_commands.IsAndroidSupported():
- logging.info(
- 'Android build commands unavailable on this machine. '
- 'Have you installed Android build dependencies?')
+ adb_path = constants.GetAdbPath()
+ if os.path.isabs(adb_path) and not os.path.exists(adb_path):
return False
+
try:
- with open(os.devnull, 'w') as devnull:
- adb_process = subprocess.Popen(
- ['adb', 'devices'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- stdin=devnull)
- stdout = adb_process.communicate()[0]
- if re.search(re.escape('????????????\tno permissions'), stdout) != None:
- logging.warn('adb devices gave a permissions error. '
- 'Consider running adb as root:')
- logging.warn(' adb kill-server')
- logging.warn(' sudo `which adb` devices\n\n')
- return True
- except OSError:
- pass
- chromium_adb_path = os.path.join(
- util.GetChromiumSrcDir(), 'third_party', 'android_tools', 'sdk',
- 'platform-tools', 'adb')
- if sys.platform.startswith('linux') and os.path.exists(chromium_adb_path):
- os.environ['PATH'] = os.pathsep.join(
- [os.path.dirname(chromium_adb_path), os.environ['PATH']])
+ device_utils.DeviceUtils.HealthyDevices()
return True
- return False
+ except (device_errors.CommandFailedError, device_errors.CommandTimeoutError,
+ OSError):
+ return False
def FindAllAvailableDevices(_):
diff --git a/tools/telemetry/telemetry/core/platform/android_device_unittest.py b/tools/telemetry/telemetry/core/platform/android_device_unittest.py
index b8a61dd..ffc09cf 100644
--- a/tools/telemetry/telemetry/core/platform/android_device_unittest.py
+++ b/tools/telemetry/telemetry/core/platform/android_device_unittest.py
@@ -5,135 +5,142 @@
import unittest
from telemetry.core import browser_options
+from telemetry.core import util
from telemetry.core.platform import android_device
-from telemetry.core.platform import android_platform_backend
from telemetry.unittest_util import system_stub
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
+from pylib.device import device_utils # pylint: disable=import-error
+
+util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'mock')
+import mock # pylint: disable=import-error
+
class AndroidDeviceTest(unittest.TestCase):
- def setUp(self):
- self._android_device_stub = system_stub.Override(
- android_device, ['adb_commands'])
def testGetAllAttachedAndroidDevices(self):
- self._android_device_stub.adb_commands.attached_devices = [
- '01', '02']
- self.assertEquals(
- set(['01', '02']),
- set(device.device_id for device in
- android_device.AndroidDevice.GetAllConnectedDevices()
- ))
-
- def tearDown(self):
- self._android_device_stub.Restore()
+ with mock.patch('pylib.device.device_utils.DeviceUtils.HealthyDevices',
+ return_value=[
+ device_utils.DeviceUtils('01'),
+ device_utils.DeviceUtils('02')]):
+ self.assertEquals(
+ set(['01', '02']),
+ set(device.device_id for device in
+ android_device.AndroidDevice.GetAllConnectedDevices()))
class GetDeviceTest(unittest.TestCase):
def setUp(self):
self._android_device_stub = system_stub.Override(
- android_device, ['adb_commands', 'os', 'subprocess', 'logging'])
- self._apb_stub = system_stub.Override(
- android_platform_backend, ['adb_commands'])
+ android_device, ['subprocess', 'logging'])
def tearDown(self):
self._android_device_stub.Restore()
- self._apb_stub.Restore()
def testNoAdbReturnsNone(self):
finder_options = browser_options.BrowserFinderOptions()
-
- def NoAdb(*_1, **_2):
- raise OSError('not found')
- self._android_device_stub.subprocess.Popen = NoAdb
-
- self.assertEquals([], self._android_device_stub.logging.warnings)
- self.assertIsNone(android_device.GetDevice(finder_options))
+ with (
+ mock.patch('os.path.isabs', return_value=True)), (
+ mock.patch('os.path.exists', return_value=False)):
+ self.assertEquals([], self._android_device_stub.logging.warnings)
+ self.assertIsNone(android_device.GetDevice(finder_options))
def testAdbNoDevicesReturnsNone(self):
finder_options = browser_options.BrowserFinderOptions()
- self.assertEquals([], self._android_device_stub.logging.warnings)
- self.assertIsNone(android_device.GetDevice(finder_options))
-
- def testAdbPermissionsErrorReturnsNone(self):
- finder_options = browser_options.BrowserFinderOptions()
- self._android_device_stub.subprocess.Popen.communicate_result = (
- 'List of devices attached\n????????????\tno permissions\n',
- '* daemon not running. starting it now on port 5037 *\n'
- '* daemon started successfully *\n')
- device = android_device.GetDevice(finder_options)
- self.assertEquals([
- 'adb devices gave a permissions error. Consider running adb as root:',
- ' adb kill-server',
- ' sudo `which adb` devices\n\n'],
- self._android_device_stub.logging.warnings)
- self.assertIsNone(device)
+ with (
+ mock.patch('os.path.isabs', return_value=False)), (
+ mock.patch('pylib.device.device_utils.DeviceUtils.HealthyDevices',
+ return_value=[])):
+ self.assertEquals([], self._android_device_stub.logging.warnings)
+ self.assertIsNone(android_device.GetDevice(finder_options))
def testAdbTwoDevicesReturnsNone(self):
finder_options = browser_options.BrowserFinderOptions()
- self._android_device_stub.adb_commands.attached_devices = [
- '015d14fec128220c', '015d14fec128220d']
- device = android_device.GetDevice(finder_options)
- self.assertEquals([
- 'Multiple devices attached. Please specify one of the following:\n'
- ' --device=015d14fec128220c\n'
- ' --device=015d14fec128220d'],
- self._android_device_stub.logging.warnings)
- self.assertIsNone(device)
+ with (
+ mock.patch('os.path.isabs', return_value=False)), (
+ mock.patch('pylib.device.device_utils.DeviceUtils.HealthyDevices',
+ return_value=[
+ device_utils.DeviceUtils('015d14fec128220c'),
+ device_utils.DeviceUtils('015d14fec128220d')])):
+ device = android_device.GetDevice(finder_options)
+ self.assertEquals([
+ 'Multiple devices attached. Please specify one of the following:\n'
+ ' --device=015d14fec128220c\n'
+ ' --device=015d14fec128220d'],
+ self._android_device_stub.logging.warnings)
+ self.assertIsNone(device)
def testAdbPickOneDeviceReturnsDeviceInstance(self):
finder_options = browser_options.BrowserFinderOptions()
finder_options.device = '555d14fecddddddd' # pick one
- self._android_device_stub.adb_commands.attached_devices = [
- '015d14fec128220c', '555d14fecddddddd']
- device = android_device.GetDevice(finder_options)
- self.assertEquals([], self._android_device_stub.logging.warnings)
- self.assertEquals('555d14fecddddddd', device.device_id)
+ with (
+ mock.patch('os.path.isabs', return_value=False)), (
+ mock.patch('pylib.device.device_utils.DeviceUtils.HealthyDevices',
+ return_value=[
+ device_utils.DeviceUtils('015d14fec128220c'),
+ device_utils.DeviceUtils('555d14fecddddddd')])):
+ device = android_device.GetDevice(finder_options)
+ self.assertEquals([], self._android_device_stub.logging.warnings)
+ self.assertEquals('555d14fecddddddd', device.device_id)
def testAdbOneDeviceReturnsDeviceInstance(self):
finder_options = browser_options.BrowserFinderOptions()
- self._android_device_stub.adb_commands.attached_devices = (
- ['015d14fec128220c'])
- device = android_device.GetDevice(finder_options)
- self.assertEquals([], self._android_device_stub.logging.warnings)
- self.assertEquals('015d14fec128220c', device.device_id)
+ with (
+ mock.patch('os.path.isabs', return_value=False)), (
+ mock.patch('pylib.device.device_utils.DeviceUtils.HealthyDevices',
+ return_value=[
+ device_utils.DeviceUtils('015d14fec128220c')])):
+ device = android_device.GetDevice(finder_options)
+ self.assertEquals([], self._android_device_stub.logging.warnings)
+ self.assertEquals('015d14fec128220c', device.device_id)
class FindAllAvailableDevicesTest(unittest.TestCase):
def setUp(self):
self._android_device_stub = system_stub.Override(
- android_device, ['adb_commands', 'os', 'subprocess', 'logging'])
- self._apb_stub = system_stub.Override(
- android_platform_backend, ['adb_commands'])
+ android_device, ['subprocess', 'logging'])
def tearDown(self):
self._android_device_stub.Restore()
- self._apb_stub.Restore()
def testAdbNoDeviceReturnsEmptyList(self):
finder_options = browser_options.BrowserFinderOptions()
- devices = android_device.FindAllAvailableDevices(finder_options)
- self.assertEquals([], self._android_device_stub.logging.warnings)
- self.assertIsNotNone(devices)
- self.assertEquals(len(devices), 0)
+ with (
+ mock.patch('os.path.isabs', return_value=False)), (
+ mock.patch(
+ 'pylib.device.device_utils.DeviceUtils.HealthyDevices',
+ return_value=[])):
+ devices = android_device.FindAllAvailableDevices(finder_options)
+ self.assertEquals([], self._android_device_stub.logging.warnings)
+ self.assertIsNotNone(devices)
+ self.assertEquals(len(devices), 0)
def testAdbOneDeviceReturnsListWithOneDeviceInstance(self):
finder_options = browser_options.BrowserFinderOptions()
- self._android_device_stub.adb_commands.attached_devices = (
- ['015d14fec128220c'])
- devices = android_device.FindAllAvailableDevices(finder_options)
- self.assertEquals([], self._android_device_stub.logging.warnings)
- self.assertIsNotNone(devices)
- self.assertEquals(len(devices), 1)
- self.assertEquals('015d14fec128220c', devices[0].device_id)
+ with (
+ mock.patch('os.path.isabs', return_value=False)), (
+ mock.patch('pylib.device.device_utils.DeviceUtils.HealthyDevices',
+ return_value=[
+ device_utils.DeviceUtils('015d14fec128220c')])):
+ devices = android_device.FindAllAvailableDevices(finder_options)
+ self.assertEquals([], self._android_device_stub.logging.warnings)
+ self.assertIsNotNone(devices)
+ self.assertEquals(len(devices), 1)
+ self.assertEquals('015d14fec128220c', devices[0].device_id)
def testAdbMultipleDevicesReturnsListWithAllDeviceInstances(self):
finder_options = browser_options.BrowserFinderOptions()
- self._android_device_stub.adb_commands.attached_devices = [
- '015d14fec128220c', '015d14fec128220d', '015d14fec128220e']
- devices = android_device.FindAllAvailableDevices(finder_options)
- self.assertEquals([], self._android_device_stub.logging.warnings)
- self.assertIsNotNone(devices)
- self.assertEquals(len(devices), 3)
- self.assertEquals(devices[0].guid, '015d14fec128220c')
- self.assertEquals(devices[1].guid, '015d14fec128220d')
- self.assertEquals(devices[2].guid, '015d14fec128220e')
+ with (
+ mock.patch('os.path.isabs', return_value=False)), (
+ mock.patch('pylib.device.device_utils.DeviceUtils.HealthyDevices',
+ return_value=[
+ device_utils.DeviceUtils('015d14fec128220c'),
+ device_utils.DeviceUtils('015d14fec128220d'),
+ device_utils.DeviceUtils('015d14fec128220e')])):
+ devices = android_device.FindAllAvailableDevices(finder_options)
+ self.assertEquals([], self._android_device_stub.logging.warnings)
+ self.assertIsNotNone(devices)
+ self.assertEquals(len(devices), 3)
+ self.assertEquals(devices[0].guid, '015d14fec128220c')
+ self.assertEquals(devices[1].guid, '015d14fec128220d')
+ self.assertEquals(devices[2].guid, '015d14fec128220e')
diff --git a/tools/telemetry/telemetry/core/platform/android_platform_backend.py b/tools/telemetry/telemetry/core/platform/android_platform_backend.py
index 579f43d..67a8b29 100644
--- a/tools/telemetry/telemetry/core/platform/android_platform_backend.py
+++ b/tools/telemetry/telemetry/core/platform/android_platform_backend.py
@@ -6,10 +6,10 @@ import logging
import os
import re
import shutil
+import stat
import subprocess
import tempfile
-from telemetry.core.backends import adb_commands
from telemetry.core import exceptions
from telemetry.core.forwarders import android_forwarder
from telemetry.core import platform
@@ -27,6 +27,7 @@ from telemetry.core import video
from telemetry import decorators
from telemetry.util import exception_formatter
from telemetry.util import external_modules
+from telemetry.util import support_binaries
psutil = external_modules.ImportOptionalModule('psutil')
util.AddDirToPythonPath(util.GetChromiumSrcDir(),
@@ -37,14 +38,15 @@ import platformsettings # pylint: disable=import-error
# Get build/android scripts into our path.
util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
-from pylib import constants # pylint: disable=import-error
+from pylib import constants # pylint: disable=import-error
from pylib import screenshot # pylint: disable=import-error
-from pylib.device import battery_utils # pylint: disable=import-error
+from pylib.device import battery_utils # pylint: disable=import-error
from pylib.device import device_errors # pylint: disable=import-error
-from pylib.perf import cache_control # pylint: disable=import-error
-from pylib.perf import perf_control # pylint: disable=import-error
+from pylib.device import device_utils # pylint: disable=import-error
+from pylib.perf import cache_control # pylint: disable=import-error
+from pylib.perf import perf_control # pylint: disable=import-error
from pylib.perf import thermal_throttle # pylint: disable=import-error
-from pylib.utils import device_temp_file # pylint: disable=import-error
+from pylib.utils import device_temp_file # pylint: disable=import-error
try:
from pylib.perf import surface_stats_collector # pylint: disable=import-error
@@ -59,14 +61,81 @@ _DEVICE_COPY_SCRIPT_LOCATION = (
'/data/local/tmp/efficient_android_directory_copy.sh')
+def _SetupPrebuiltTools(device):
+ """Some of the android pylib scripts we depend on are lame and expect
+ binaries to be in the out/ directory. So we copy any prebuilt binaries there
+ as a prereq."""
+
+ # TODO(bulach): Build the targets for x86/mips.
+ device_tools = [
+ 'file_poller',
+ 'forwarder_dist/device_forwarder',
+ 'md5sum_dist/md5sum_bin',
+ 'purge_ashmem',
+ 'run_pie',
+ ]
+
+ host_tools = [
+ 'bitmaptools',
+ 'md5sum_bin_host',
+ ]
+
+ if platform.GetHostPlatform().GetOSName() == 'linux':
+ host_tools.append('host_forwarder')
+
+ arch_name = device.product_cpu_abi
+ has_device_prebuilt = (arch_name.startswith('armeabi')
+ or arch_name.startswith('arm64'))
+ if not has_device_prebuilt:
+ logging.warning('Unknown architecture type: %s' % arch_name)
+ return all([support_binaries.FindLocallyBuiltPath(t) for t in device_tools])
+
+ build_type = None
+ for t in device_tools + host_tools:
+ executable = os.path.basename(t)
+ locally_built_path = support_binaries.FindLocallyBuiltPath(t)
+ if not build_type:
+ build_type = _GetBuildTypeOfPath(locally_built_path) or 'Release'
+ constants.SetBuildType(build_type)
+ dest = os.path.join(constants.GetOutDirectory(), t)
+ if not locally_built_path:
+ logging.info('Setting up prebuilt %s', dest)
+ if not os.path.exists(os.path.dirname(dest)):
+ os.makedirs(os.path.dirname(dest))
+ platform_name = ('android' if t in device_tools else
+ platform.GetHostPlatform().GetOSName())
+ bin_arch_name = (arch_name if t in device_tools else
+ platform.GetHostPlatform().GetArchName())
+ prebuilt_path = support_binaries.FindPath(
+ executable, bin_arch_name, platform_name)
+ if not prebuilt_path or not os.path.exists(prebuilt_path):
+ raise NotImplementedError("""
+%s must be checked into cloud storage.
+Instructions:
+http://www.chromium.org/developers/telemetry/upload_to_cloud_storage
+""" % t)
+ shutil.copyfile(prebuilt_path, dest)
+ os.chmod(dest, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
+ return True
+
+
+def _GetBuildTypeOfPath(path):
+ if not path:
+ return None
+ for build_dir, build_type in util.GetBuildDirectories():
+ if os.path.join(build_dir, build_type) in path:
+ return build_type
+ return None
+
+
class AndroidPlatformBackend(
linux_based_platform_backend.LinuxBasedPlatformBackend):
def __init__(self, device, finder_options):
assert device, (
'AndroidPlatformBackend can only be initialized from remote device')
super(AndroidPlatformBackend, self).__init__(device)
- self._adb = adb_commands.AdbCommands(device=device.device_id)
- installed_prebuilt_tools = adb_commands.SetupPrebuiltTools(self._adb)
+ self._device = device_utils.DeviceUtils(device.device_id)
+ installed_prebuilt_tools = _SetupPrebuiltTools(self._device)
if not installed_prebuilt_tools:
logging.error(
'%s detected, however prebuilt android tools could not '
@@ -74,10 +143,9 @@ class AndroidPlatformBackend(
' $ ninja -C out/Release android_tools' % device.name)
raise exceptions.PlatformError()
# Trying to root the device, if possible.
- if not self._adb.IsRootEnabled():
+ if not self._device.HasRoot():
# Ignore result.
- self._adb.EnableAdbRoot()
- self._device = self._adb.device()
+ self._device.EnableRoot()
self._battery = battery_utils.BatteryUtils(self._device)
self._enable_performance_mode = device.enable_performance_mode
self._surface_stats_collector = None
@@ -122,7 +190,7 @@ class AndroidPlatformBackend(
def forwarder_factory(self):
if not self._forwarder_factory:
self._forwarder_factory = android_forwarder.AndroidForwarderFactory(
- self._adb, self._use_rndis_forwarder)
+ self._device, self._use_rndis_forwarder)
return self._forwarder_factory
@@ -131,8 +199,8 @@ class AndroidPlatformBackend(
return self._use_rndis_forwarder
@property
- def adb(self):
- return self._adb
+ def device(self):
+ return self._device
def IsDisplayTracingSupported(self):
return bool(self.GetOSVersionName() >= 'J')
@@ -423,7 +491,7 @@ class AndroidPlatformBackend(
return old_flag
def ForwardHostToDevice(self, host_port, device_port):
- self._adb.Forward('tcp:%d' % host_port, device_port)
+ self._device.adb.Forward('tcp:%d' % host_port, device_port)
def DismissCrashDialogIfNeeded(self):
"""Dismiss any error dialogs.
@@ -440,8 +508,7 @@ class AndroidPlatformBackend(
Args:
process_name: The full package name string of the process.
"""
- pids = self._adb.ExtractPid(process_name)
- return len(pids) != 0
+ return bool(self._device.GetPids(process_name))
@property
def wpr_ca_cert_path(self):
@@ -477,9 +544,9 @@ class AndroidPlatformBackend(
certutils.write_dummy_ca_cert(*certutils.generate_dummy_ca_cert(),
cert_path=self._wpr_ca_cert_path)
self._device_cert_util = adb_install_cert.AndroidCertInstaller(
- self._adb.device_serial(), None, self._wpr_ca_cert_path)
+ self._device.adb.GetDeviceSerial(), None, self._wpr_ca_cert_path)
logging.info('Installing test certificate authority on device: %s',
- self._adb.device_serial())
+ str(self._device))
self._device_cert_util.install_cert(overwrite_cert=True)
self._is_test_ca_installed = True
except Exception as e:
@@ -488,7 +555,7 @@ class AndroidPlatformBackend(
logging.warning(
'Unable to install test certificate authority on device: %s. '
'Will fallback to ignoring certificate errors. Install error: %s',
- self._adb.device_serial(), e)
+ str(self._device), e)
@property
def is_test_ca_installed(self):
@@ -509,7 +576,7 @@ class AndroidPlatformBackend(
# Best effort cleanup - show the error and continue.
exception_formatter.PrintFormattedException(
msg=('Error while trying to remove certificate authority: %s. '
- % self._adb.device_serial()))
+ % str(self._device)))
self._is_test_ca_installed = False
shutil.rmtree(os.path.dirname(self._wpr_ca_cert_path), ignore_errors=True)
@@ -620,7 +687,7 @@ class AndroidPlatformBackend(
Args:
package: The full package name string of the application.
"""
- if self._adb.IsUserBuild():
+ if self._device.IsUserBuild():
logging.debug('User build device, setting debug app')
self._device.RunShellCommand('am set-debug-app --persistent %s' % package)
@@ -664,7 +731,7 @@ class AndroidPlatformBackend(
if os.path.exists(tombstones):
ret += Decorate('Tombstones',
subprocess.Popen([tombstones, '-w', '--device',
- self._adb.device_serial()],
+ self._device.adb.GetDeviceSerial()],
stdout=subprocess.PIPE).communicate()[0])
return ret
diff --git a/tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py b/tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py
index 1db861b..c883e28 100644
--- a/tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py
+++ b/tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py
@@ -12,16 +12,17 @@ from telemetry.unittest_util import options_for_unittests
from telemetry.unittest_util import system_stub
util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'mock')
-import mock # pylint: disable=F0401
+import mock # pylint: disable=import-error
util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
-from pylib.device import battery_utils # pylint: disable=F0401
+from pylib.device import battery_utils # pylint: disable=import-error
+from pylib.device import device_utils # pylint: disable=import-error
class AndroidPlatformBackendTest(unittest.TestCase):
def setUp(self):
self._options = options_for_unittests.GetCopy()
self._stubs = system_stub.Override(
android_platform_backend,
- ['perf_control', 'thermal_throttle', 'adb_commands', 'certutils',
+ ['perf_control', 'thermal_throttle', 'certutils',
'adb_install_cert', 'platformsettings'])
# Skip _FixPossibleAdbInstability by setting psutil to None.
@@ -30,9 +31,25 @@ class AndroidPlatformBackendTest(unittest.TestCase):
self.battery_patcher = mock.patch.object(battery_utils, 'BatteryUtils')
self.battery_patcher.start()
+ def get_prop(name, cache=None):
+ return {'ro.product.cpu.abi': 'armeabi-v7a'}.get(name)
+
+ self.helper_patcher = mock.patch(
+ 'telemetry.core.platform.android_platform_backend._SetupPrebuiltTools',
+ return_value=True)
+ self.helper_patcher.start()
+
+ self.device_patcher = mock.patch.multiple(
+ device_utils.DeviceUtils,
+ HasRoot=mock.MagicMock(return_value=True),
+ GetProp=mock.MagicMock(side_effect=get_prop))
+ self.device_patcher.start()
+
def tearDown(self):
self._stubs.Restore()
android_platform_backend.psutil = self._actual_ps_util
+ self.device_patcher.stop()
+ self.helper_patcher.stop()
self.battery_patcher.stop()
@decorators.Disabled('chromeos')
@@ -43,20 +60,23 @@ class AndroidPlatformBackendTest(unittest.TestCase):
'4294967295 1074458624 1074463824 3197495984 3197494152 '
'1074767676 0 4612 0 38136 4294967295 0 0 17 0 0 0 0 0 0 '
'1074470376 1074470912 1102155776\n')
- self._stubs.adb_commands.adb_device.mock_content = proc_stat_content
- self._stubs.adb_commands.adb_device.has_root = True
- backend = android_platform_backend.AndroidPlatformBackend(
- android_device.AndroidDevice('12345'), self._options)
- cpu_stats = backend.GetCpuStats('7702')
- self.assertEquals(cpu_stats, {'CpuProcessTime': 0.05})
+
+ with mock.patch('pylib.device.device_utils.DeviceUtils.ReadFile',
+ return_value=proc_stat_content):
+ backend = android_platform_backend.AndroidPlatformBackend(
+ android_device.AndroidDevice('12345'), self._options)
+ cpu_stats = backend.GetCpuStats('7702')
+ self.assertEquals(cpu_stats, {'CpuProcessTime': 0.05})
@decorators.Disabled('chromeos')
def testGetCpuStatsInvalidPID(self):
# Mock an empty /proc/pid/stat.
- backend = android_platform_backend.AndroidPlatformBackend(
- android_device.AndroidDevice('1234'), self._options)
- cpu_stats = backend.GetCpuStats('7702')
- self.assertEquals(cpu_stats, {})
+ with mock.patch('pylib.device.device_utils.DeviceUtils.ReadFile',
+ return_value=''):
+ backend = android_platform_backend.AndroidPlatformBackend(
+ android_device.AndroidDevice('1234'), self._options)
+ cpu_stats = backend.GetCpuStats('7702')
+ self.assertEquals(cpu_stats, {})
def testAndroidParseCpuStates(self):
cstate = {
@@ -162,15 +182,33 @@ class AndroidPlatformBackendPsutilTest(unittest.TestCase):
def setUp(self):
self._options = options_for_unittests.GetCopy()
self._stubs = system_stub.Override(
- android_platform_backend,
- ['perf_control', 'adb_commands'])
+ android_platform_backend, ['perf_control'])
+
self.battery_patcher = mock.patch.object(battery_utils, 'BatteryUtils')
self.battery_patcher.start()
+
+ def get_prop(name, cache=None):
+ return {'ro.product.cpu.abi': 'armeabi-v7a'}.get(name)
+
+ self.helper_patcher = mock.patch(
+ 'telemetry.core.platform.android_platform_backend._SetupPrebuiltTools',
+ return_value=True)
+ self.helper_patcher.start()
+
+ self.device_patcher = mock.patch.multiple(
+ device_utils.DeviceUtils,
+ FileExists=mock.MagicMock(return_value=False),
+ GetProp=mock.MagicMock(side_effect=get_prop),
+ HasRoot=mock.MagicMock(return_value=True))
+ self.device_patcher.start()
+
self._actual_ps_util = android_platform_backend.psutil
def tearDown(self):
self._stubs.Restore()
android_platform_backend.psutil = self._actual_ps_util
+ self.device_patcher.stop()
+ self.helper_patcher.stop()
self.battery_patcher.stop()
@decorators.Disabled('chromeos')
@@ -179,11 +217,13 @@ class AndroidPlatformBackendPsutilTest(unittest.TestCase):
android_platform_backend.psutil = psutil
# Mock an empty /proc/pid/stat.
- backend = android_platform_backend.AndroidPlatformBackend(
- android_device.AndroidDevice('1234'), self._options)
- cpu_stats = backend.GetCpuStats('7702')
- self.assertEquals({}, cpu_stats)
- self.assertEquals([[0]], psutil.set_cpu_affinity_args)
+ with mock.patch('pylib.device.device_utils.DeviceUtils.ReadFile',
+ return_value=''):
+ backend = android_platform_backend.AndroidPlatformBackend(
+ android_device.AndroidDevice('1234'), self._options)
+ cpu_stats = backend.GetCpuStats('7702')
+ self.assertEquals({}, cpu_stats)
+ self.assertEquals([[0]], psutil.set_cpu_affinity_args)
@decorators.Disabled('chromeos')
def testPsutil2(self):
@@ -191,8 +231,10 @@ class AndroidPlatformBackendPsutilTest(unittest.TestCase):
android_platform_backend.psutil = psutil
# Mock an empty /proc/pid/stat.
- backend = android_platform_backend.AndroidPlatformBackend(
- android_device.AndroidDevice('1234'), self._options)
- cpu_stats = backend.GetCpuStats('7702')
- self.assertEquals({}, cpu_stats)
- self.assertEquals([[0]], psutil.set_cpu_affinity_args)
+ with mock.patch('pylib.device.device_utils.DeviceUtils.ReadFile',
+ return_value=''):
+ backend = android_platform_backend.AndroidPlatformBackend(
+ android_device.AndroidDevice('1234'), self._options)
+ cpu_stats = backend.GetCpuStats('7702')
+ self.assertEquals({}, cpu_stats)
+ self.assertEquals([[0]], psutil.set_cpu_affinity_args)
diff --git a/tools/telemetry/telemetry/core/platform/profiler/android_prebuilt_profiler_helper.py b/tools/telemetry/telemetry/core/platform/profiler/android_prebuilt_profiler_helper.py
index 5974f1d..573df36 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/android_prebuilt_profiler_helper.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/android_prebuilt_profiler_helper.py
@@ -19,7 +19,7 @@ def GetDevicePath(profiler_binary):
@decorators.Cache
def InstallOnDevice(device, profiler_binary):
- arch_name = device.GetABI()
+ arch_name = device.product_cpu_abi
host_path = support_binaries.FindPath(profiler_binary, arch_name, 'android')
if not host_path:
logging.error('Profiler binary "%s" not found. Could not be installed',
diff --git a/tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py
index 5e3aad8..6ea83ff 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py
@@ -22,7 +22,7 @@ class AndroidScreenRecordingProfiler(profiler.Profiler):
'screenshot.py'),
'--video',
'--file', self._output_path,
- '--device', browser_backend.adb.device_serial()],
+ '--device', browser_backend.device.adb.GetDeviceSerial()],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
@classmethod
diff --git a/tools/telemetry/telemetry/core/platform/profiler/android_traceview_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/android_traceview_profiler.py
index 3f7a080..5ed86b6 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/android_traceview_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/android_traceview_profiler.py
@@ -24,21 +24,21 @@ class AndroidTraceviewProfiler(profiler.Profiler):
super(AndroidTraceviewProfiler, self).__init__(
browser_backend, platform_backend, output_path, state)
- if self._browser_backend.adb.device().FileExists(self._DEFAULT_DEVICE_DIR):
- self._browser_backend.adb.RunShellCommand(
+ if self._browser_backend.device.FileExists(self._DEFAULT_DEVICE_DIR):
+ self._browser_backend.device.RunShellCommand(
'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
else:
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'chmod 777 ' + self._DEFAULT_DEVICE_DIR)
self._trace_files = []
for pid in self._GetProcessOutputFileMap().iterkeys():
device_dump_file = '%s/%s.trace' % (self._DEFAULT_DEVICE_DIR, pid)
self._trace_files.append((pid, device_dump_file))
- self._browser_backend.adb.RunShellCommand('am profile %s start %s' %
- (pid, device_dump_file))
+ self._browser_backend.device.RunShellCommand(
+ 'am profile %s start %s' % (pid, device_dump_file))
@classmethod
@@ -54,13 +54,13 @@ class AndroidTraceviewProfiler(profiler.Profiler):
def CollectProfile(self):
output_files = []
for pid, trace_file in self._trace_files:
- self._browser_backend.adb.RunShellCommand('am profile %s stop' % pid)
+ self._browser_backend.device.RunShellCommand('am profile %s stop' % pid)
# pylint: disable=cell-var-from-loop
util.WaitFor(lambda: self._FileSize(trace_file) > 0, timeout=10)
output_files.append(trace_file)
- self._browser_backend.adb.device().PullFile(
+ self._browser_backend.device.PullFile(
self._DEFAULT_DEVICE_DIR, self._output_path)
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
print 'Traceview profiles available in ', self._output_path
print 'Use third_party/android_tools/sdk/tools/monitor '
@@ -69,6 +69,6 @@ class AndroidTraceviewProfiler(profiler.Profiler):
def _FileSize(self, file_name):
try:
- return self._browser_backend.adb.device().Stat(file_name).st_size
+ return self._browser_backend.device.Stat(file_name).st_size
except device_errors.CommandFailedError:
return 0
diff --git a/tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py
index 8719406..fc78127 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py
@@ -48,9 +48,9 @@ class JavaHeapProfiler(profiler.Profiler):
def CollectProfile(self):
self._timer.cancel()
self._DumpJavaHeap(True)
- self._browser_backend.adb.device().PullFile(
+ self._browser_backend.device.PullFile(
self._DEFAULT_DEVICE_DIR, self._output_path)
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
output_files = []
for f in os.listdir(self._output_path):
@@ -67,25 +67,25 @@ class JavaHeapProfiler(profiler.Profiler):
self._DumpJavaHeap(False)
def _DumpJavaHeap(self, wait_for_completion):
- if not self._browser_backend.adb.device().FileExists(
+ if not self._browser_backend.device.FileExists(
self._DEFAULT_DEVICE_DIR):
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'chmod 777 ' + self._DEFAULT_DEVICE_DIR)
device_dump_file = None
for pid in self._GetProcessOutputFileMap().iterkeys():
device_dump_file = '%s/%s.%s.aprof' % (self._DEFAULT_DEVICE_DIR, pid,
self._run_count)
- self._browser_backend.adb.RunShellCommand('am dumpheap %s %s' %
- (pid, device_dump_file))
+ self._browser_backend.device.RunShellCommand(
+ 'am dumpheap %s %s' % (pid, device_dump_file))
if device_dump_file and wait_for_completion:
util.WaitFor(lambda: self._FileSize(device_dump_file) > 0, timeout=2)
self._run_count += 1
def _FileSize(self, file_name):
try:
- return self._browser_backend.adb.device().Stat(file_name).st_size
+ return self._browser_backend.device.Stat(file_name).st_size
except device_errors.CommandFailedError:
return 0
diff --git a/tools/telemetry/telemetry/core/platform/profiler/netlog_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/netlog_profiler.py
index aa0070a..4cb7e0a 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/netlog_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/netlog_profiler.py
@@ -36,9 +36,9 @@ class NetLogProfiler(profiler.Profiler):
# On Android pull the output file to the host.
if self._platform_backend.GetOSName() == 'android':
host_output_file = '%s.json' % self._output_path
- self._browser_backend.adb.device().PullFile(output_file, host_output_file)
+ self._browser_backend.device.PullFile(output_file, host_output_file)
# Clean the device
- self._browser_backend.adb.device().RunShellCommand('rm %s' % output_file)
+ self._browser_backend.device.RunShellCommand('rm %s' % output_file)
output_file = host_output_file
print 'Net-internals log saved as %s' % output_file
print 'To view, open in chrome://net-internals'
diff --git a/tools/telemetry/telemetry/core/platform/profiler/oomkiller_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/oomkiller_profiler.py
index be4643d..a3c2639 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/oomkiller_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/oomkiller_profiler.py
@@ -32,7 +32,7 @@ class OOMKillerProfiler(profiler.Profiler):
browser_backend, platform_backend, output_path, state)
if not 'mem_consumer_launched' in state:
state['mem_consumer_launched'] = True
- arch_name = self._browser_backend.adb.device().GetABI()
+ arch_name = self._browser_backend.device.product_cpu_abi
mem_consumer_path = support_binaries.FindPath(
os.path.join('apks', 'MemConsumer.apk'), arch_name, 'android')
assert mem_consumer_path, ('Could not find memconsumer app. Please build '
@@ -40,12 +40,12 @@ class OOMKillerProfiler(profiler.Profiler):
if not self._platform_backend.CanLaunchApplication(
'org.chromium.memconsumerg'):
self._platform_backend.InstallApplication(mem_consumer_path)
- self._browser_backend.adb.device().GoHome()
+ self._browser_backend.device.GoHome()
self._platform_backend.LaunchApplication(
'org.chromium.memconsumer/.MemConsumer',
'--ei memory 20')
# Bring the browser to the foreground after launching the mem consumer
- self._browser_backend.adb.device().StartActivity(
+ self._browser_backend.device.StartActivity(
intent.Intent(package=browser_backend.package,
activity=browser_backend.activity),
blocking=True)
@@ -62,7 +62,7 @@ class OOMKillerProfiler(profiler.Profiler):
@classmethod
def WillCloseBrowser(cls, browser_backend, platform_backend):
- browser_backend.adb.device().ForceStop('org.chromium.memconsumer')
+ browser_backend.device.ForceStop('org.chromium.memconsumer')
def CollectProfile(self):
missing_applications = self._MissingApplications()
diff --git a/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
index f0982e6..159bf7a 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
@@ -80,15 +80,16 @@ class _SingleProcessPerfProfiler(object):
cmd_prefix = []
perf_args = ['record', '--pid', str(pid)]
if self._is_android:
- cmd_prefix = ['adb', '-s', browser_backend.adb.device_serial(), 'shell',
- perf_binary]
+ cmd_prefix = ['adb', '-s', browser_backend.device.adb.GetDeviceSerial(),
+ 'shell', perf_binary]
perf_args += _PERF_OPTIONS_ANDROID
output_file = os.path.join('/sdcard', 'perf_profiles',
os.path.basename(output_file))
self._device_output_file = output_file
- browser_backend.adb.RunShellCommand(
+ browser_backend.device.RunShellCommand(
'mkdir -p ' + os.path.dirname(self._device_output_file))
- browser_backend.adb.RunShellCommand('rm -f ' + self._device_output_file)
+ browser_backend.device.RunShellCommand(
+ 'rm -f ' + self._device_output_file)
else:
cmd_prefix = [perf_binary]
perf_args += ['--output', output_file] + _PERF_OPTIONS
@@ -103,10 +104,10 @@ class _SingleProcessPerfProfiler(object):
'To collect a full profile rerun with '
'"--extra-browser-args=--single-process"')
if self._is_android:
- device = self._browser_backend.adb.device()
try:
binary_name = os.path.basename(self._perf_binary)
- device.KillAll(binary_name, signum=signal.SIGINT, blocking=True)
+ self._browser_backend.device.KillAll(
+ binary_name, signum=signal.SIGINT, blocking=True)
except device_errors.CommandFailedError:
logging.warning('The perf process could not be killed on the device.')
self._proc.send_signal(signal.SIGINT)
@@ -127,16 +128,15 @@ Try rerunning this script under sudo or setting
cmd = '%s report -n -i %s' % (_NicePath(self._perfhost_binary),
self._output_file)
if self._is_android:
- device = self._browser_backend.adb.device()
- device.PullFile(self._device_output_file, self._output_file)
- required_libs = \
+ self._browser_backend.device.PullFile(
+ self._device_output_file, self._output_file)
+ required_libs = (
android_profiling_helper.GetRequiredLibrariesForPerfProfile(
- self._output_file)
+ self._output_file))
symfs_root = os.path.dirname(self._output_file)
- kallsyms = android_profiling_helper.CreateSymFs(device,
- symfs_root,
- required_libs,
- use_symlinks=True)
+ kallsyms = android_profiling_helper.CreateSymFs(
+ self._browser_backend.device, symfs_root, required_libs,
+ use_symlinks=True)
cmd += ' --symfs %s --kallsyms %s' % (symfs_root, kallsyms)
for lib in required_libs:
lib = os.path.join(symfs_root, lib[1:])
@@ -173,9 +173,10 @@ class PerfProfiler(profiler.Profiler):
perf_binary = perfhost_binary = _InstallPerfHost()
try:
if platform_backend.GetOSName() == 'android':
- device = browser_backend.adb.device()
- perf_binary = android_profiling_helper.PrepareDeviceForPerf(device)
- self._perf_control = perf_control.PerfControl(device)
+ perf_binary = android_profiling_helper.PrepareDeviceForPerf(
+ browser_backend.device)
+ self._perf_control = perf_control.PerfControl(
+ browser_backend.device)
self._perf_control.SetPerfProfilingMode()
else:
_PrepareHostForPerf()
diff --git a/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py
index 4fc3982..8c67284 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py
@@ -34,26 +34,26 @@ class _TCMallocHeapProfilerAndroid(object):
def _SetDeviceProperties(self, properties):
device_configured = False
# This profiler requires adb root to set properties.
- self._browser_backend.adb.device().EnableRoot()
+ self._browser_backend.device.EnableRoot()
for values in properties.itervalues():
- device_property = self._browser_backend.adb.device().GetProp(values[0])
+ device_property = self._browser_backend.device.GetProp(values[0])
if not device_property or not device_property.strip():
- self._browser_backend.adb.device().SetProp(values[0], values[1])
+ self._browser_backend.device.SetProp(values[0], values[1])
device_configured = True
- if not self._browser_backend.adb.device().FileExists(
+ if not self._browser_backend.device.FileExists(
self._DEFAULT_DEVICE_DIR):
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'chmod 777 ' + self._DEFAULT_DEVICE_DIR)
device_configured = True
if device_configured:
raise Exception('Device required special config, run again.')
def CollectProfile(self):
- self._browser_backend.adb.device().PullFile(
+ self._browser_backend.device.PullFile(
self._DEFAULT_DEVICE_DIR, self._output_path)
- self._browser_backend.adb.RunShellCommand(
+ self._browser_backend.device.RunShellCommand(
'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
if os.path.exists(self._output_path):
logging.info('TCMalloc dumps pulled to %s', self._output_path)
diff --git a/tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py
index 6ad22c4..16962c8 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py
@@ -2,15 +2,21 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import logging
import os
import signal
import subprocess
import sys
import tempfile
+from telemetry.core import util
from telemetry.core.platform import profiler
from telemetry.core.platform.profiler import android_prebuilt_profiler_helper
+util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
+from pylib import device_signal # pylint: disable=import-error
+from pylib.device import device_errors # pylint: disable=import-error
+
_TCP_DUMP_BASE_OPTS = ['-i', 'any', '-p', '-s', '0', '-w']
@@ -23,28 +29,30 @@ class _TCPDumpProfilerAndroid(object):
_DEVICE_DUMP_FILE = '/sdcard/tcpdump_profiles/capture.pcap'
- def __init__(self, adb, output_path):
- self._adb = adb
+ def __init__(self, device, output_path):
+ self._device = device
self._output_path = output_path
- self._adb.RunShellCommand('mkdir -p ' +
- os.path.dirname(self._DEVICE_DUMP_FILE))
+ self._device.RunShellCommand('mkdir -p ' +
+ os.path.dirname(self._DEVICE_DUMP_FILE))
self._proc = subprocess.Popen(
- ['adb', '-s', self._adb.device_serial(),
+ ['adb', '-s', self._device.adb.GetDeviceSerial(),
'shell', android_prebuilt_profiler_helper.GetDevicePath('tcpdump')] +
_TCP_DUMP_BASE_OPTS +
[self._DEVICE_DUMP_FILE])
def CollectProfile(self):
- tcpdump_pid = self._adb.ExtractPid('tcpdump')
- if not tcpdump_pid or not tcpdump_pid[0]:
+ try:
+ self._device.KillAll('tcpdump', signum=device_signal.SIGTERM)
+ except device_errors.CommandFailedError:
+ logging.exception('Unable to kill TCPDump.')
raise Exception('Unable to find TCPDump. Check your device is rooted '
'and tcpdump is installed at ' +
android_prebuilt_profiler_helper.GetDevicePath('tcpdump'))
- self._adb.RunShellCommand('kill -term ' + tcpdump_pid[0])
+
self._proc.terminate()
host_dump = os.path.join(self._output_path,
os.path.basename(self._DEVICE_DUMP_FILE))
- self._adb.device().PullFile(self._DEVICE_DUMP_FILE, host_dump)
+ self._device.PullFile(self._DEVICE_DUMP_FILE, host_dump)
print 'TCP dump available at: %s ' % host_dump
print 'Use Wireshark to open it.'
return host_dump
@@ -98,9 +106,9 @@ class TCPDumpProfiler(profiler.Profiler):
browser_backend, platform_backend, output_path, state)
if platform_backend.GetOSName() == 'android':
android_prebuilt_profiler_helper.InstallOnDevice(
- browser_backend.adb.device(), 'tcpdump')
+ browser_backend.device, 'tcpdump')
self._platform_profiler = _TCPDumpProfilerAndroid(
- browser_backend.adb, output_path)
+ browser_backend.device, output_path)
else:
self._platform_profiler = _TCPDumpProfilerLinux(output_path)
diff --git a/tools/telemetry/telemetry/core/platform/profiler/v8_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/v8_profiler.py
index 73e126e..ef065be 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/v8_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/v8_profiler.py
@@ -38,9 +38,9 @@ class V8Profiler(profiler.Profiler):
# On Android pull the output file to the host.
if self._platform_backend.GetOSName() == 'android':
host_output_file = '%s.log' % self._output_path
- self._browser_backend.adb.device().PullFile(output_file, host_output_file)
+ self._browser_backend.device.PullFile(output_file, host_output_file)
# Clean the device
- self._browser_backend.adb.device().RunShellCommand('rm %s' % output_file)
+ self._browser_backend.device.RunShellCommand('rm %s' % output_file)
output_file = host_output_file
print 'V8 profile saved as %s' % output_file
print 'To view, open in ' \
diff --git a/tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py
index 96f0878..11acb71 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py
@@ -57,16 +57,14 @@ class _SingleProcessVTuneProfiler(object):
return self._output_file
if self._is_android:
- required_libs = \
+ required_libs = (
android_profiling_helper.GetRequiredLibrariesForVTuneProfile(
- self._output_file)
+ self._output_file))
- device = self._browser_backend.adb.device()
symfs_root = os.path.dirname(self._output_file)
- android_profiling_helper.CreateSymFs(device,
- symfs_root,
- required_libs,
- use_symlinks=True)
+ android_profiling_helper.CreateSymFs(
+ self._browser_backend.device, symfs_root, required_libs,
+ use_symlinks=True)
logging.info('Resolving symbols in profile.')
subprocess.call(['amplxe-cl', '-finalize', '-r', self._output_file,
'-search-dir', symfs_root])
@@ -130,6 +128,8 @@ class VTuneProfiler(profiler.Profiler):
if browser_type.startswith('android'):
# VTune checks if 'su' is available on the device.
+ # TODO(jbudorick): Replace with DeviceUtils.HasRoot,
+ # DeviceUtils.NeedsSU, or some combination thereof.
proc = subprocess.Popen(['adb', 'shell', 'su', '-c', 'id'],
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE)
diff --git a/tools/telemetry/telemetry/unittest_util/system_stub.py b/tools/telemetry/telemetry/unittest_util/system_stub.py
index cb7c20d..27f3956 100644
--- a/tools/telemetry/telemetry/unittest_util/system_stub.py
+++ b/tools/telemetry/telemetry/unittest_util/system_stub.py
@@ -9,14 +9,12 @@ This test allows one to test code that itself uses os, sys, and subprocess.
import os
import re
-import shlex
import sys
class Override(object):
def __init__(self, base_module, module_list):
- stubs = {'adb_commands': AdbCommandsModuleStub,
- 'cloud_storage': CloudStorageModuleStub,
+ stubs = {'cloud_storage': CloudStorageModuleStub,
'open': OpenFunctionStub,
'os': OsModuleStub,
'perf_control': PerfControlModuleStub,
@@ -60,96 +58,6 @@ class Override(object):
self._overrides = {}
-class AdbDevice(object):
-
- def __init__(self):
- self.has_root = False
- self.needs_su = False
- self.shell_command_handlers = {}
- self.mock_content = []
- self.system_properties = {}
- if self.system_properties.get('ro.product.cpu.abi') == None:
- self.system_properties['ro.product.cpu.abi'] = 'armeabi-v7a'
-
- def HasRoot(self):
- return self.has_root
-
- def NeedsSU(self):
- return self.needs_su
-
- def RunShellCommand(self, args, **_kwargs):
- if isinstance(args, basestring):
- args = shlex.split(args)
- handler = self.shell_command_handlers[args[0]]
- return handler(args)
-
- def FileExists(self, _):
- return False
-
- def ReadFile(self, device_path, as_root=False): # pylint: disable=W0613
- return self.mock_content
-
- def GetProp(self, property_name):
- return self.system_properties[property_name]
-
- def SetProp(self, property_name, property_value):
- self.system_properties[property_name] = property_value
-
-
-class AdbCommandsModuleStub(object):
-
- class AdbCommandsStub(object):
-
- def __init__(self, module, device):
- self._module = module
- self._device = device
- self.is_root_enabled = True
- self._adb_device = module.adb_device
-
- def IsRootEnabled(self):
- return self.is_root_enabled
-
- def RestartAdbdOnDevice(self):
- pass
-
- def IsUserBuild(self):
- return False
-
- def WaitForDevicePm(self):
- pass
-
- def device(self):
- return self._adb_device
-
- def device_serial(self):
- return self._device
-
- def __init__(self):
- self.attached_devices = []
- self.apk_package_name = None
- self.adb_device = AdbDevice()
-
- def AdbCommandsStubConstructor(device=None):
- return AdbCommandsModuleStub.AdbCommandsStub(self, device)
- self.AdbCommands = AdbCommandsStubConstructor
-
- @staticmethod
- def IsAndroidSupported():
- return True
-
- def GetPackageName(self, _):
- return self.apk_package_name
-
- def GetAttachedDevices(self):
- return self.attached_devices
-
- def SetupPrebuiltTools(self, _):
- return True
-
- def CleanupLeftoverProcesses(self):
- pass
-
-
class CloudStorageModuleStub(object):
PUBLIC_BUCKET = 'chromium-telemetry'
PARTNER_BUCKET = 'chrome-partner-telemetry'