Revert of [Android] Remove adb_commands from telemetry. (patchset #13 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:
build/android/pylib
tools/telemetry/telemetry
core
android_process.py
backends
adb_commands.pyandroid_app_backend.pyandroid_command_line_backend.pyandroid_command_line_backend_unittest.py
chrome
forwarders
platform
unittest_util
@ -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
|
||||
|
142
tools/telemetry/telemetry/core/backends/adb_commands.py
Normal file
142
tools/telemetry/telemetry/core/backends/adb_commands.py
Normal file
@ -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'
|
||||
|
Reference in New Issue
Block a user