0

Revert of [Android] Remove adb_commands from telemetry. (patchset id:240001 of https://codereview.chromium.org/1141833003/)

Reason for revert:
On 2015/06/03 at 03:23:53, commit-bot wrote:
> Patchset 13 (id:??) landed as https://crrev.com/c951c9e158d55d2be18f8226200679aee55f336d
> Cr-Commit-Position: refs/heads/master@{#332538}

This change breaks --browser=list when non-rooted Android devices are attached.

$ tools/perf/run_benchmark --browser=list
ERROR:root:Fail to create platform instance for Android device 04f120591b9223e1.

Traceback (most recent call last):
  <module> at tools/perf/run_benchmark:20
    sys.exit(benchmark_runner.main(config))
  main at tools/telemetry/telemetry/benchmark_runner.py:433
    options, args = parser.parse_args()
  ParseArgs at tools/telemetry/telemetry/core/browser_options.py:179
    device)
  Cacher at tools/telemetry/telemetry/decorators.py:30
    cacher.__cache[key] = obj(*args, **kwargs)
  GetAllAvailableBrowsers at tools/telemetry/telemetry/core/browser_finder.py:147
    browser_finder.FindAllAvailableBrowsers(options, device))
  FindAllAvailableBrowsers at tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py:217
    android_platform = platform.GetPlatformForDevice(device, finder_options)
  GetPlatformForDevice at tools/telemetry/telemetry/core/platform/__init__.py:58
    finder_options))
  CreatePlatformForDevice at tools/telemetry/telemetry/core/platform/android_platform_backend.py:186
    platform_backend = AndroidPlatformBackend(device, finder_options)
  __init__ at tools/telemetry/telemetry/core/platform/android_platform_backend.py:148
    self._device.EnableRoot()
  TimeoutRetryWrapper at build/android/pylib/device/decorators.py:57
    return timeout_retry.Run(impl, timeout, retries)
  Run at build/android/pylib/utils/timeout_retry.py:161
    thread_group.JoinAll(child_thread.GetWatcher())
  JoinAll at build/android/pylib/utils/reraiser_thread.py:143
    self._JoinAll(watcher)
  _JoinAll at build/android/pylib/utils/reraiser_thread.py:130
    thread.ReraiseIfException()
  run at build/android/pylib/utils/reraiser_thread.py:76
    self._ret = self._func(*self._args, **self._kwargs)
  RunOnTimeoutThread at build/android/pylib/utils/timeout_retry.py:150
    ret[0] = func(*args, **kwargs)
  impl at build/android/pylib/device/decorators.py:51
    return f(*args, **kwargs)
  EnableRoot at build/android/pylib/device/device_utils.py:289
    'Cannot enable root in user builds.', str(self))
CommandFailedError: (device: 04f120591b9223e1) Cannot enable root in user builds.

Locals:
  retries : 3
  timeout : 30

Original issue's description:
> [Android] Remove adb_commands from telemetry.
>
> ...because it's an abomination.
>
> BUG=476709
>
> Committed: https://crrev.com/c951c9e158d55d2be18f8226200679aee55f336d
> Cr-Commit-Position: refs/heads/master@{#332538}

TBR=dtu@chromium.org,nednguyen@google.com,primiano@chromium.org,skyostil@chromium.org,sullivan@chromium.org,picksi@chromium.org,zhenw@chromium.org,jbudorick@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=476709

Review URL: https://codereview.chromium.org/1145153005

Cr-Commit-Position: refs/heads/master@{#332560}
This commit is contained in:
alancutter
2015-06-02 22:41:40 -07:00
committed by Commit bot
parent 585d2566e7
commit 79bdcb66e8
28 changed files with 596 additions and 483 deletions

@ -1381,6 +1381,22 @@ class DeviceUtils(object):
'Unable to set property %r on the device to %r'
% (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.

@ -8,7 +8,6 @@ import tempfile
import time
from pylib import cmd_helper
from pylib import constants
from pylib import device_signal
from pylib.device import device_errors
@ -41,7 +40,7 @@ class VideoRecorder(object):
self._recorder_stdout = None
self._is_started = False
self._args = [constants.GetAdbPath()]
self._args = ['adb']
if str(self._device):
self._args += ['-s', str(self._device)]
self._args += ['shell', 'screenrecord', '--verbose']

@ -2,17 +2,10 @@
# 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
@ -23,7 +16,7 @@ class AndroidProcess(object):
self._app_backend = app_backend
self._pid = pid
self._name = name
self._local_port = ports.AllocateTestServerPort()
self._local_port = adb_commands.AllocateTestServerPort()
self._devtools_client = None
@property

@ -0,0 +1,142 @@
# 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

@ -24,8 +24,8 @@ class AndroidAppBackend(app_backend.AppBackend):
self._existing_processes_by_pid = {}
@property
def _device(self):
return self.platform_backend.device
def _adb(self):
return self.platform_backend.adb
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._device, backend_settings, webview_startup_args):
self._adb, 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._device.StartActivity(self._start_intent, blocking=False)
self._adb.device().StartActivity(self._start_intent, blocking=False)
util.WaitFor(self._IsAppReady, timeout=60)
self._is_running = True

@ -35,12 +35,12 @@ class SetUpCommandLineFlags(object):
Example usage:
with android_command_line_backend.SetUpCommandLineFlags(
device, backend_settings, startup_args):
adb, backend_settings, startup_args):
# Something to run while the command line flags are set appropriately.
"""
def __init__(self, device, backend_settings, startup_args):
def __init__(self, adb, backend_settings, startup_args):
self._android_command_line_backend = _AndroidCommandLineBackend(
device, backend_settings, startup_args)
adb, backend_settings, startup_args)
def __enter__(self):
self._android_command_line_backend.SetUpCommandLineFlags()
@ -59,15 +59,15 @@ class _AndroidCommandLineBackend(object):
functionality.
"""
def __init__(self, device, backend_settings, startup_args):
self._device = device
def __init__(self, adb, backend_settings, startup_args):
self._adb = adb
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._device.IsUserBuild())
return self._backend_settings.GetCommandLineFile(self._adb.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._device.ReadFile(self.command_line_file, as_root=True)
return self._adb.device().ReadFile(self.command_line_file, as_root=True)
def _WriteFile(self, contents):
self._device.WriteFile(self.command_line_file, contents, as_root=True)
self._adb.device().WriteFile(self.command_line_file, contents, as_root=True)
def _RemoveFile(self):
self._device.RunShellCommand(['rm', '-f', self.command_line_file],
as_root=True, check_return=True)
self._adb.device().RunShellCommand(['rm', '-f', self.command_line_file],
as_root=True, check_return=True)

@ -5,15 +5,10 @@
import unittest
from telemetry import benchmark
from telemetry.core import util
from telemetry.core.backends import adb_commands
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'
@ -54,19 +49,16 @@ class AndroidCommandLineBackendTest(unittest.TestCase):
Requires a device connected to the host.
"""
serial = options_for_unittests.GetCopy().device
if serial:
device = device_utils.DeviceUtils(serial)
else:
devices = device_utils.DeviceUtils.HealthyDevices()
if not devices:
raise device_errors.NoDevicesError()
device = devices[0]
if not serial:
serial = adb_commands.GetAttachedDevices()[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(
device, backend_settings, startup_args):
adb, backend_settings, startup_args):
self.assertEqual('chrome --some --test --args',
device.ReadFile(cmd_file).strip())
self.assertEqual('chrome --args --to --save',
@ -80,19 +72,16 @@ class AndroidCommandLineBackendTest(unittest.TestCase):
Requires a device connected to the host.
"""
serial = options_for_unittests.GetCopy().device
if serial:
device = device_utils.DeviceUtils(serial)
else:
devices = device_utils.DeviceUtils.HealthyDevices()
if not devices:
raise device_errors.NoDevicesError()
device = devices[0]
if not serial:
serial = adb_commands.GetAttachedDevices()[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(
device, backend_settings, startup_args):
adb, backend_settings, startup_args):
self.assertEqual('chrome --some --test --args',
device.ReadFile(cmd_file).strip())
self.assertFalse(device.FileExists(cmd_file))

@ -5,6 +5,7 @@
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
@ -15,11 +16,7 @@ from telemetry.core.platform import android_platform_backend as \
from telemetry.core import util
util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
try:
from pylib import ports # pylint: disable=import-error
except ImportError:
ports = None
from pylib.device import intent # pylint: disable=import-error
from pylib.device import intent # pylint: disable=F0401
class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
@ -46,7 +43,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 = ports.AllocateTestServerPort()
self._port = adb_commands.AllocateTestServerPort()
# TODO(wuhu): Move to network controller backend.
self.platform_backend.InstallTestCa()
@ -54,7 +51,7 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
# Kill old browser.
self._KillBrowser()
if self.device.old_interface.CanAccessProtectedFileContents():
if self._adb.device().old_interface.CanAccessProtectedFileContents():
if self.browser_options.profile_dir:
self.platform_backend.PushProfile(
self._backend_settings.package,
@ -76,17 +73,17 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
self.platform_backend.SetDebugApp(self._backend_settings.package)
@property
def device(self):
return self.platform_backend.device
def _adb(self):
return self.platform_backend.adb
def _KillBrowser(self):
if self.device.IsUserBuild():
if self._adb.device().IsUserBuild():
self.platform_backend.StopApplication(self._backend_settings.package)
else:
self.platform_backend.KillApplication(self._backend_settings.package)
def Start(self):
self.device.RunShellCommand('logcat -c')
self._adb.device().RunShellCommand('logcat -c')
if self.browser_options.startup_url:
url = self.browser_options.startup_url
elif self.browser_options.profile_dir:
@ -100,15 +97,15 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
browser_startup_args = self.GetBrowserStartupArgs()
with android_command_line_backend.SetUpCommandLineFlags(
self.device, self._backend_settings, browser_startup_args):
self.device.StartActivity(
self._adb, self._backend_settings, browser_startup_args):
self._adb.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.device)
self._adb)
self.platform_backend.ForwardHostToDevice(self._port,
remote_devtools_port)
try:
@ -116,7 +113,8 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
self._InitDevtoolsClientBackend(remote_devtools_port)
except exceptions.BrowserGoneException:
logging.critical('Failed to connect to browser.')
if not self.device.old_interface.CanAccessProtectedFileContents():
device = self._adb.device()
if not device.old_interface.CanAccessProtectedFileContents():
logging.critical(
'Resolve this by either: '
'(1) Flashing to a userdebug build OR '
@ -136,12 +134,16 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
args.append('--disable-external-intent-requests')
return args
@property
def adb(self):
return self._adb
@property
def pid(self):
pids = self.device.GetPids(self._backend_settings.package)
if not pids or self._backend_settings.package not in pids:
pids = self._adb.ExtractPid(self._backend_settings.package)
if not pids:
raise exceptions.BrowserGoneException(self.browser)
return int(pids[self._backend_settings.package])
return int(pids[0])
@property
def browser_directory(self):

@ -7,6 +7,7 @@
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
@ -17,9 +18,6 @@ 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':
@ -172,7 +170,7 @@ def _FindAllPossibleBrowsers(finder_options, android_platform):
CanPossiblyHandlePath(finder_options.browser_executable)):
normalized_path = os.path.expanduser(finder_options.browser_executable)
exact_package = apk_helper.GetPackageName(normalized_path)
exact_package = adb_commands.GetPackageName(normalized_path)
if not exact_package:
raise exceptions.PackageDetectionError(
'Unable to find package for %s specified by --browser-executable' %

@ -6,12 +6,8 @@ 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):
@ -28,7 +24,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, ['os'])
android_browser_finder, ['adb_commands', 'os'])
def tearDown(self):
self._android_browser_finder_stub.Restore()
@ -54,39 +50,37 @@ 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'
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]))
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'
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)
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'
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)
fake_platform = FakeAndroidPlatform(can_launch=True)
self.assertRaises(Exception,
android_browser_finder._FindAllPossibleBrowsers,
self.finder_options, fake_platform)
class FakePossibleBrowser(object):

@ -9,6 +9,7 @@ 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
@ -16,28 +17,27 @@ from telemetry.util import support_binaries
util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
try:
from pylib import forwarder # pylint: disable=import-error
from pylib import forwarder # pylint: disable=F0401
except ImportError:
forwarder = None
from pylib.device import device_errors # pylint: disable=import-error
from pylib.device import device_utils # pylint: disable=import-error
from pylib.device import device_errors # pylint: disable=F0401
class AndroidForwarderFactory(forwarders.ForwarderFactory):
def __init__(self, device, use_rndis):
def __init__(self, adb, use_rndis):
super(AndroidForwarderFactory, self).__init__()
self._device = device
self._adb = adb
self._rndis_configurator = None
if use_rndis:
self._rndis_configurator = AndroidRndisConfigurator(self._device)
self._rndis_configurator = AndroidRndisConfigurator(self._adb)
def Create(self, port_pairs):
if self._rndis_configurator:
return AndroidRndisForwarder(self._device, self._rndis_configurator,
return AndroidRndisForwarder(self._adb, self._rndis_configurator,
port_pairs)
return AndroidForwarder(self._device, port_pairs)
return AndroidForwarder(self._adb, port_pairs)
@property
def host_ip(self):
@ -52,9 +52,9 @@ class AndroidForwarderFactory(forwarders.ForwarderFactory):
class AndroidForwarder(forwarders.Forwarder):
def __init__(self, device, port_pairs):
def __init__(self, adb, port_pairs):
super(AndroidForwarder, self).__init__(port_pairs)
self._device = device
self._device = adb.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, device, rndis_configurator, port_pairs):
def __init__(self, adb, rndis_configurator, port_pairs):
super(AndroidRndisForwarder, self).__init__(port_pairs)
self._device = device
self._adb = adb
self._rndis_configurator = rndis_configurator
self._device_iface = rndis_configurator.device_iface
self._host_ip = rndis_configurator.host_ip
@ -103,13 +103,12 @@ class AndroidRndisForwarder(forwarders.Forwarder):
def _RedirectPorts(self, port_pairs):
"""Sets the local to remote pair mappings to use for RNDIS."""
# Flush any old nat rules.
self._device.RunShellCommand('iptables -F -t nat')
self._adb.RunShellCommand('iptables -F -t nat') # Flush any old nat rules.
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._device.RunShellCommand(
self._adb.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))
@ -130,27 +129,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._device.SetProp('net.dns1', dns1)
self._device.SetProp('net.dns2', dns2)
dnschange = self._device.GetProp('net.dnschange')
self._adb.device().SetProp('net.dns1', dns1)
self._adb.device().SetProp('net.dns2', dns2)
dnschange = self._adb.device().GetProp('net.dnschange')
if dnschange:
self._device.SetProp('net.dnschange', str(int(dnschange) + 1))
self._adb.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._device.RunShellCommand('netd resolver setifdns %s %s %s' %
(iface, dns1, dns2))
self._adb.RunShellCommand('netd resolver setifdns %s %s %s' %
(iface, dns1, dns2))
# TODO(szym): if we know the package UID, we could setifaceforuidrange
self._device.RunShellCommand('netd resolver setdefaultif %s' % iface)
self._adb.RunShellCommand('netd resolver setdefaultif %s' % iface)
def _GetCurrentDns(self):
"""Returns current gateway, dns1, and dns2."""
routes = self._device.RunShellCommand('cat /proc/net/route')[1:]
routes = self._adb.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._device.GetProp('net.dns1'),
self._device.GetProp('net.dns2'),
self._adb.device().GetProp('net.dns1'),
self._adb.device().GetProp('net.dns2'),
)
def _OverrideDefaultGateway(self):
@ -163,11 +162,11 @@ class AndroidRndisForwarder(forwarders.Forwarder):
(e.g. Telemetry crashes). A power cycle or "adb reboot" is a simple
workaround around in that case.
"""
self._device.RunShellCommand('route add default gw %s dev %s' %
self._adb.RunShellCommand('route add default gw %s dev %s' %
(self.host_ip, self._device_iface))
def _RestoreDefaultGateway(self):
self._device.RunShellCommand('netcfg %s down' % self._device_iface)
self._adb.RunShellCommand('netcfg %s down' % self._device_iface)
class AndroidRndisConfigurator(object):
@ -183,8 +182,8 @@ class AndroidRndisConfigurator(object):
_INTERFACES_INCLUDE = 'source /etc/network/interfaces.d/*.conf'
_TELEMETRY_INTERFACE_FILE = '/etc/network/interfaces.d/telemetry-{}.conf'
def __init__(self, device):
self._device = device
def __init__(self, adb):
self._device = adb.device()
try:
self._device.EnableRoot()
@ -387,8 +386,9 @@ doit &
"""
my_device = str(self._device)
addresses = []
for device in device_utils.DeviceUtils.HealthyDevices():
if device.adb.GetDeviceSerial() == my_device:
for device_serial in adb_commands.GetAttachedDevices():
device = adb_commands.AdbCommands(device_serial).device()
if device_serial == my_device:
excluded = excluded_iface
else:
excluded = 'no interfaces excluded on other devices'

@ -67,7 +67,7 @@ class AndroidActionRunner(object):
Args:
string: The string to send to the device.
"""
self._platform_backend.device.RunShellCommand('input text %s' % string)
self._platform_backend.adb.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.device.SendKeyEvent(key)
self._platform_backend.adb.RunShellCommand('input keyevent %s' % 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.device.RunShellCommand(
'input tap %s %s' % (x_coord, y_coord))
self._platform_backend.adb.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.device.RunShellCommand(
self._platform_backend.adb.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.device.RunShellCommand('input press')
self._platform_backend.adb.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.device.RunShellCommand('input roll %s %s' % (dx, dy))
self._platform_backend.adb.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.device.SendKeyEvent(82)
self._platform_backend.adb.RunShellCommand('input keyevent 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.device.SendKeyEvent(26)
self._platform_backend.adb.RunShellCommand('input keyevent 26')

@ -1,19 +1,17 @@
# 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.
@ -46,8 +44,7 @@ class AndroidDevice(device.Device):
def GetDeviceSerials():
device_serials = [d.adb.GetDeviceSerial()
for d in device_utils.DeviceUtils.HealthyDevices()]
device_serials = adb_commands.GetAttachedDevices()
# 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.
@ -68,9 +65,8 @@ The Monsoon's power output has been enabled. Please now ensure that:
Waiting for device...
""")
util.WaitFor(device_utils.DeviceUtils.HealthyDevices, 600)
device_serials = [d.adb.GetDeviceSerial()
for d in device_utils.DeviceUtils.HealthyDevices()]
util.WaitFor(adb_commands.GetAttachedDevices, 600)
device_serials = adb_commands.GetAttachedDevices()
except IOError:
return []
return device_serials
@ -102,16 +98,33 @@ def GetDevice(finder_options):
def CanDiscoverDevices():
"""Returns true if devices are discoverable via adb."""
adb_path = constants.GetAdbPath()
if os.path.isabs(adb_path) and not os.path.exists(adb_path):
if not adb_commands.IsAndroidSupported():
logging.info(
'Android build commands unavailable on this machine. '
'Have you installed Android build dependencies?')
return False
try:
device_utils.DeviceUtils.HealthyDevices()
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 (device_errors.CommandFailedError, device_errors.CommandTimeoutError,
OSError):
return False
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']])
return True
return False
def FindAllAvailableDevices(_):

@ -5,142 +5,135 @@
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):
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()))
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()
class GetDeviceTest(unittest.TestCase):
def setUp(self):
self._android_device_stub = system_stub.Override(
android_device, ['subprocess', 'logging'])
android_device, ['adb_commands', 'os', 'subprocess', 'logging'])
self._apb_stub = system_stub.Override(
android_platform_backend, ['adb_commands'])
def tearDown(self):
self._android_device_stub.Restore()
self._apb_stub.Restore()
def testNoAdbReturnsNone(self):
finder_options = browser_options.BrowserFinderOptions()
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 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))
def testAdbNoDevicesReturnsNone(self):
finder_options = browser_options.BrowserFinderOptions()
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))
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)
def testAdbTwoDevicesReturnsNone(self):
finder_options = browser_options.BrowserFinderOptions()
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)
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)
def testAdbPickOneDeviceReturnsDeviceInstance(self):
finder_options = browser_options.BrowserFinderOptions()
finder_options.device = '555d14fecddddddd' # pick one
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)
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)
def testAdbOneDeviceReturnsDeviceInstance(self):
finder_options = browser_options.BrowserFinderOptions()
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)
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)
class FindAllAvailableDevicesTest(unittest.TestCase):
def setUp(self):
self._android_device_stub = system_stub.Override(
android_device, ['subprocess', 'logging'])
android_device, ['adb_commands', 'os', 'subprocess', 'logging'])
self._apb_stub = system_stub.Override(
android_platform_backend, ['adb_commands'])
def tearDown(self):
self._android_device_stub.Restore()
self._apb_stub.Restore()
def testAdbNoDeviceReturnsEmptyList(self):
finder_options = browser_options.BrowserFinderOptions()
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)
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()
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)
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)
def testAdbMultipleDevicesReturnsListWithAllDeviceInstances(self):
finder_options = browser_options.BrowserFinderOptions()
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')
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')

@ -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,7 +27,6 @@ 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(),
@ -38,15 +37,14 @@ 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.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 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
@ -61,81 +59,14 @@ _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._device = device_utils.DeviceUtils(device.device_id)
installed_prebuilt_tools = _SetupPrebuiltTools(self._device)
self._adb = adb_commands.AdbCommands(device=device.device_id)
installed_prebuilt_tools = adb_commands.SetupPrebuiltTools(self._adb)
if not installed_prebuilt_tools:
logging.error(
'%s detected, however prebuilt android tools could not '
@ -143,9 +74,10 @@ class AndroidPlatformBackend(
' $ ninja -C out/Release android_tools' % device.name)
raise exceptions.PlatformError()
# Trying to root the device, if possible.
if not self._device.HasRoot():
if not self._adb.IsRootEnabled():
# Ignore result.
self._device.EnableRoot()
self._adb.EnableAdbRoot()
self._device = self._adb.device()
self._battery = battery_utils.BatteryUtils(self._device)
self._enable_performance_mode = device.enable_performance_mode
self._surface_stats_collector = None
@ -190,7 +122,7 @@ class AndroidPlatformBackend(
def forwarder_factory(self):
if not self._forwarder_factory:
self._forwarder_factory = android_forwarder.AndroidForwarderFactory(
self._device, self._use_rndis_forwarder)
self._adb, self._use_rndis_forwarder)
return self._forwarder_factory
@ -199,8 +131,8 @@ class AndroidPlatformBackend(
return self._use_rndis_forwarder
@property
def device(self):
return self._device
def adb(self):
return self._adb
def IsDisplayTracingSupported(self):
return bool(self.GetOSVersionName() >= 'J')
@ -491,7 +423,7 @@ class AndroidPlatformBackend(
return old_flag
def ForwardHostToDevice(self, host_port, device_port):
self._device.adb.Forward('tcp:%d' % host_port, device_port)
self._adb.Forward('tcp:%d' % host_port, device_port)
def DismissCrashDialogIfNeeded(self):
"""Dismiss any error dialogs.
@ -508,7 +440,8 @@ class AndroidPlatformBackend(
Args:
process_name: The full package name string of the process.
"""
return bool(self._device.GetPids(process_name))
pids = self._adb.ExtractPid(process_name)
return len(pids) != 0
@property
def wpr_ca_cert_path(self):
@ -544,9 +477,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._device.adb.GetDeviceSerial(), None, self._wpr_ca_cert_path)
self._adb.device_serial(), None, self._wpr_ca_cert_path)
logging.info('Installing test certificate authority on device: %s',
str(self._device))
self._adb.device_serial())
self._device_cert_util.install_cert(overwrite_cert=True)
self._is_test_ca_installed = True
except Exception as e:
@ -555,7 +488,7 @@ class AndroidPlatformBackend(
logging.warning(
'Unable to install test certificate authority on device: %s. '
'Will fallback to ignoring certificate errors. Install error: %s',
str(self._device), e)
self._adb.device_serial(), e)
@property
def is_test_ca_installed(self):
@ -576,7 +509,7 @@ class AndroidPlatformBackend(
# Best effort cleanup - show the error and continue.
exception_formatter.PrintFormattedException(
msg=('Error while trying to remove certificate authority: %s. '
% str(self._device)))
% self._adb.device_serial()))
self._is_test_ca_installed = False
shutil.rmtree(os.path.dirname(self._wpr_ca_cert_path), ignore_errors=True)
@ -687,7 +620,7 @@ class AndroidPlatformBackend(
Args:
package: The full package name string of the application.
"""
if self._device.IsUserBuild():
if self._adb.IsUserBuild():
logging.debug('User build device, setting debug app')
self._device.RunShellCommand('am set-debug-app --persistent %s' % package)
@ -731,7 +664,7 @@ class AndroidPlatformBackend(
if os.path.exists(tombstones):
ret += Decorate('Tombstones',
subprocess.Popen([tombstones, '-w', '--device',
self._device.adb.GetDeviceSerial()],
self._adb.device_serial()],
stdout=subprocess.PIPE).communicate()[0])
return ret

@ -12,17 +12,16 @@ 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=import-error
import mock # pylint: disable=F0401
util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
from pylib.device import battery_utils # pylint: disable=import-error
from pylib.device import device_utils # pylint: disable=import-error
from pylib.device import battery_utils # pylint: disable=F0401
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', 'certutils',
['perf_control', 'thermal_throttle', 'adb_commands', 'certutils',
'adb_install_cert', 'platformsettings'])
# Skip _FixPossibleAdbInstability by setting psutil to None.
@ -31,25 +30,9 @@ 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')
@ -60,23 +43,20 @@ 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')
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})
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})
@decorators.Disabled('chromeos')
def testGetCpuStatsInvalidPID(self):
# Mock an empty /proc/pid/stat.
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, {})
backend = android_platform_backend.AndroidPlatformBackend(
android_device.AndroidDevice('1234'), self._options)
cpu_stats = backend.GetCpuStats('7702')
self.assertEquals(cpu_stats, {})
def testAndroidParseCpuStates(self):
cstate = {
@ -182,33 +162,15 @@ class AndroidPlatformBackendPsutilTest(unittest.TestCase):
def setUp(self):
self._options = options_for_unittests.GetCopy()
self._stubs = system_stub.Override(
android_platform_backend, ['perf_control'])
android_platform_backend,
['perf_control', 'adb_commands'])
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')
@ -217,13 +179,11 @@ class AndroidPlatformBackendPsutilTest(unittest.TestCase):
android_platform_backend.psutil = psutil
# Mock an empty /proc/pid/stat.
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)
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):
@ -231,10 +191,8 @@ class AndroidPlatformBackendPsutilTest(unittest.TestCase):
android_platform_backend.psutil = psutil
# Mock an empty /proc/pid/stat.
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)
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)

@ -19,7 +19,7 @@ def GetDevicePath(profiler_binary):
@decorators.Cache
def InstallOnDevice(device, profiler_binary):
arch_name = device.product_cpu_abi
arch_name = device.GetABI()
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',

@ -22,7 +22,7 @@ class AndroidScreenRecordingProfiler(profiler.Profiler):
'screenshot.py'),
'--video',
'--file', self._output_path,
'--device', browser_backend.device.adb.GetDeviceSerial()],
'--device', browser_backend.adb.device_serial()],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
@classmethod

@ -24,21 +24,21 @@ class AndroidTraceviewProfiler(profiler.Profiler):
super(AndroidTraceviewProfiler, self).__init__(
browser_backend, platform_backend, output_path, state)
if self._browser_backend.device.FileExists(self._DEFAULT_DEVICE_DIR):
self._browser_backend.device.RunShellCommand(
if self._browser_backend.adb.device().FileExists(self._DEFAULT_DEVICE_DIR):
self._browser_backend.adb.RunShellCommand(
'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
else:
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.RunShellCommand(
'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.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.device.RunShellCommand(
'am profile %s start %s' % (pid, device_dump_file))
self._browser_backend.adb.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.device.RunShellCommand('am profile %s stop' % pid)
self._browser_backend.adb.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.device.PullFile(
self._browser_backend.adb.device().PullFile(
self._DEFAULT_DEVICE_DIR, self._output_path)
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.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.device.Stat(file_name).st_size
return self._browser_backend.adb.device().Stat(file_name).st_size
except device_errors.CommandFailedError:
return 0

@ -48,9 +48,9 @@ class JavaHeapProfiler(profiler.Profiler):
def CollectProfile(self):
self._timer.cancel()
self._DumpJavaHeap(True)
self._browser_backend.device.PullFile(
self._browser_backend.adb.device().PullFile(
self._DEFAULT_DEVICE_DIR, self._output_path)
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.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.device.FileExists(
if not self._browser_backend.adb.device().FileExists(
self._DEFAULT_DEVICE_DIR):
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.RunShellCommand(
'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.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.device.RunShellCommand(
'am dumpheap %s %s' % (pid, device_dump_file))
self._browser_backend.adb.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.device.Stat(file_name).st_size
return self._browser_backend.adb.device().Stat(file_name).st_size
except device_errors.CommandFailedError:
return 0

@ -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.device.PullFile(output_file, host_output_file)
self._browser_backend.adb.device().PullFile(output_file, host_output_file)
# Clean the device
self._browser_backend.device.RunShellCommand('rm %s' % output_file)
self._browser_backend.adb.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'

@ -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.device.product_cpu_abi
arch_name = self._browser_backend.adb.device().GetABI()
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.device.GoHome()
self._browser_backend.adb.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.device.StartActivity(
self._browser_backend.adb.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.device.ForceStop('org.chromium.memconsumer')
browser_backend.adb.device().ForceStop('org.chromium.memconsumer')
def CollectProfile(self):
missing_applications = self._MissingApplications()

@ -80,16 +80,15 @@ class _SingleProcessPerfProfiler(object):
cmd_prefix = []
perf_args = ['record', '--pid', str(pid)]
if self._is_android:
cmd_prefix = ['adb', '-s', browser_backend.device.adb.GetDeviceSerial(),
'shell', perf_binary]
cmd_prefix = ['adb', '-s', browser_backend.adb.device_serial(), '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.device.RunShellCommand(
browser_backend.adb.RunShellCommand(
'mkdir -p ' + os.path.dirname(self._device_output_file))
browser_backend.device.RunShellCommand(
'rm -f ' + self._device_output_file)
browser_backend.adb.RunShellCommand('rm -f ' + self._device_output_file)
else:
cmd_prefix = [perf_binary]
perf_args += ['--output', output_file] + _PERF_OPTIONS
@ -104,10 +103,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)
self._browser_backend.device.KillAll(
binary_name, signum=signal.SIGINT, blocking=True)
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)
@ -128,15 +127,16 @@ 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:
self._browser_backend.device.PullFile(
self._device_output_file, self._output_file)
required_libs = (
device = self._browser_backend.adb.device()
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(
self._browser_backend.device, symfs_root, required_libs,
use_symlinks=True)
kallsyms = android_profiling_helper.CreateSymFs(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,10 +173,9 @@ class PerfProfiler(profiler.Profiler):
perf_binary = perfhost_binary = _InstallPerfHost()
try:
if platform_backend.GetOSName() == 'android':
perf_binary = android_profiling_helper.PrepareDeviceForPerf(
browser_backend.device)
self._perf_control = perf_control.PerfControl(
browser_backend.device)
device = browser_backend.adb.device()
perf_binary = android_profiling_helper.PrepareDeviceForPerf(device)
self._perf_control = perf_control.PerfControl(device)
self._perf_control.SetPerfProfilingMode()
else:
_PrepareHostForPerf()

@ -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.device.EnableRoot()
self._browser_backend.adb.device().EnableRoot()
for values in properties.itervalues():
device_property = self._browser_backend.device.GetProp(values[0])
device_property = self._browser_backend.adb.device().GetProp(values[0])
if not device_property or not device_property.strip():
self._browser_backend.device.SetProp(values[0], values[1])
self._browser_backend.adb.device().SetProp(values[0], values[1])
device_configured = True
if not self._browser_backend.device.FileExists(
if not self._browser_backend.adb.device().FileExists(
self._DEFAULT_DEVICE_DIR):
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.RunShellCommand(
'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.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.device.PullFile(
self._browser_backend.adb.device().PullFile(
self._DEFAULT_DEVICE_DIR, self._output_path)
self._browser_backend.device.RunShellCommand(
self._browser_backend.adb.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)

@ -2,21 +2,15 @@
# 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']
@ -29,30 +23,28 @@ class _TCPDumpProfilerAndroid(object):
_DEVICE_DUMP_FILE = '/sdcard/tcpdump_profiles/capture.pcap'
def __init__(self, device, output_path):
self._device = device
def __init__(self, adb, output_path):
self._adb = adb
self._output_path = output_path
self._device.RunShellCommand('mkdir -p ' +
os.path.dirname(self._DEVICE_DUMP_FILE))
self._adb.RunShellCommand('mkdir -p ' +
os.path.dirname(self._DEVICE_DUMP_FILE))
self._proc = subprocess.Popen(
['adb', '-s', self._device.adb.GetDeviceSerial(),
['adb', '-s', self._adb.device_serial(),
'shell', android_prebuilt_profiler_helper.GetDevicePath('tcpdump')] +
_TCP_DUMP_BASE_OPTS +
[self._DEVICE_DUMP_FILE])
def CollectProfile(self):
try:
self._device.KillAll('tcpdump', signum=device_signal.SIGTERM)
except device_errors.CommandFailedError:
logging.exception('Unable to kill TCPDump.')
tcpdump_pid = self._adb.ExtractPid('tcpdump')
if not tcpdump_pid or not tcpdump_pid[0]:
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._device.PullFile(self._DEVICE_DUMP_FILE, host_dump)
self._adb.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
@ -106,9 +98,9 @@ class TCPDumpProfiler(profiler.Profiler):
browser_backend, platform_backend, output_path, state)
if platform_backend.GetOSName() == 'android':
android_prebuilt_profiler_helper.InstallOnDevice(
browser_backend.device, 'tcpdump')
browser_backend.adb.device(), 'tcpdump')
self._platform_profiler = _TCPDumpProfilerAndroid(
browser_backend.device, output_path)
browser_backend.adb, output_path)
else:
self._platform_profiler = _TCPDumpProfilerLinux(output_path)

@ -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.device.PullFile(output_file, host_output_file)
self._browser_backend.adb.device().PullFile(output_file, host_output_file)
# Clean the device
self._browser_backend.device.RunShellCommand('rm %s' % output_file)
self._browser_backend.adb.device().RunShellCommand('rm %s' % output_file)
output_file = host_output_file
print 'V8 profile saved as %s' % output_file
print 'To view, open in ' \

@ -57,14 +57,16 @@ 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(
self._browser_backend.device, symfs_root, required_libs,
use_symlinks=True)
android_profiling_helper.CreateSymFs(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])
@ -128,8 +130,6 @@ 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)

@ -9,12 +9,14 @@ 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 = {'cloud_storage': CloudStorageModuleStub,
stubs = {'adb_commands': AdbCommandsModuleStub,
'cloud_storage': CloudStorageModuleStub,
'open': OpenFunctionStub,
'os': OsModuleStub,
'perf_control': PerfControlModuleStub,
@ -58,6 +60,96 @@ 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'