Commit d52c4a88 authored by tonyg's avatar tonyg Committed by Commit bot

[Telemetry] Implement CanLaunchApplication and InstallApplication for Android.

This is in preparation for implementing the Trepn profiler.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#292543}
parent 5980590f
......@@ -70,22 +70,6 @@ class AdbCommands(object):
'forward %s %s' % (local, remote))
assert ret == ''
def Install(self, apk_path):
"""Installs specified package if necessary.
Args:
apk_path: Path to .apk file to install.
"""
if (os.path.exists(os.path.join(
constants.GetOutDirectory('Release'), 'md5sum_bin_host'))):
constants.SetBuildType('Release')
elif (os.path.exists(os.path.join(
constants.GetOutDirectory('Debug'), 'md5sum_bin_host'))):
constants.SetBuildType('Debug')
self._device.Install(apk_path)
def IsUserBuild(self):
return self._device.GetProp('ro.build.type') == 'user'
......
......@@ -64,12 +64,15 @@ CHROME_PACKAGE_NAMES = {
class PossibleAndroidBrowser(possible_browser.PossibleBrowser):
"""A launchable android browser instance."""
def __init__(self, browser_type, finder_options, backend_settings, apk_name):
def __init__(self, browser_type, finder_options, android_platform,
platform_backend, backend_settings, apk_name):
super(PossibleAndroidBrowser, self).__init__(browser_type, 'android',
finder_options, backend_settings.supports_tab_control)
assert browser_type in FindAllBrowserTypes(finder_options), \
('Please add %s to android_browser_finder.FindAllBrowserTypes' %
browser_type)
self._platform = android_platform
self._platform_backend = platform_backend
self._backend_settings = backend_settings
self._local_apk = None
......@@ -88,18 +91,11 @@ class PossibleAndroidBrowser(possible_browser.PossibleBrowser):
newest_apk_path = sorted(candidate_apks)[-1][1]
self._local_apk = newest_apk_path
def __repr__(self):
return 'PossibleAndroidBrowser(browser_type=%s)' % self.browser_type
def _InitPlatformIfNeeded(self):
if self._platform:
return
self._platform_backend = android_platform_backend.AndroidPlatformBackend(
self._backend_settings.adb.device(),
self.finder_options.no_performance_mode)
self._platform = platform.Platform(self._platform_backend)
pass
def Create(self):
self._InitPlatformIfNeeded()
......@@ -127,9 +123,8 @@ class PossibleAndroidBrowser(possible_browser.PossibleBrowser):
@decorators.Cache
def UpdateExecutableIfNeeded(self):
if self.HaveLocalAPK():
real_logging.warn(
'Refreshing %s on device if needed.' % self._local_apk)
self._backend_settings.adb.Install(self._local_apk)
real_logging.warn('Installing %s on device if needed.' % self._local_apk)
self.platform.InstallApplication(self._local_apk)
def last_modification_time(self):
if self.HaveLocalAPK():
......@@ -228,16 +223,16 @@ Waiting for device...
return []
device = devices[0]
adb = adb_commands.AdbCommands(device=device)
# Trying to root the device, if possible.
if not adb.IsRootEnabled():
# Ignore result.
adb.EnableAdbRoot()
# Host side workaround for crbug.com/268450 (adb instability).
# The adb server has a race which is mitigated by binding to a single core.
if psutil:
# Host side workaround for crbug.com/268450 (adb instability).
# The adb server has a race which is mitigated by binding to a single core.
for proc in psutil.process_iter():
try:
if 'adb' in proc.name:
......@@ -252,18 +247,20 @@ Waiting for device...
except (psutil.NoSuchProcess, psutil.AccessDenied):
logging.warn('Failed to set adb process CPU affinity')
packages = adb.RunShellCommand('pm list packages')
possible_browsers = []
platform_backend = android_platform_backend.AndroidPlatformBackend(
adb.device(), finder_options.no_performance_mode)
android_platform = platform.Platform(platform_backend)
possible_browsers = []
for name, package_info in CHROME_PACKAGE_NAMES.iteritems():
[package, backend_settings, local_apk] = package_info
b = PossibleAndroidBrowser(
name,
finder_options,
backend_settings(adb, package),
local_apk)
if 'package:' + package in packages or b.HaveLocalAPK():
b = PossibleAndroidBrowser(name,
finder_options,
android_platform,
platform_backend,
backend_settings(adb, package),
local_apk)
if b.platform.CanLaunchApplication(package) or b.HaveLocalAPK():
possible_browsers.append(b)
if possible_browsers:
......
......@@ -33,7 +33,7 @@ class AndroidBrowserFinderTest(unittest.TestCase):
def test_no_adb(self):
finder_options = browser_options.BrowserFinderOptions()
def NoAdb(*args, **kargs): # pylint: disable=W0613
def NoAdb(*args, **kargs): # pylint: disable=W0613
raise OSError('not found')
self._stubs.subprocess.Popen = NoAdb
browsers = android_browser_finder.FindAllAvailableBrowsers(
......@@ -86,7 +86,11 @@ class AndroidBrowserFinderTest(unittest.TestCase):
return ['package:org.chromium.content_shell_apk',
'package.com.google.android.setupwizard']
def OnLs(_):
return ['/sys/devices/system/cpu/cpu0']
self._stubs.adb_commands.shell_command_handlers['pm'] = OnPM
self._stubs.adb_commands.shell_command_handlers['ls'] = OnLs
browsers = android_browser_finder.FindAllAvailableBrowsers(
finder_options, self._log_stub)
......
......@@ -46,6 +46,7 @@ class BrowserFinderOptions(optparse.Values):
self.output_file = None
self.android_rndis = False
self.no_performance_mode = False
def __repr__(self):
return str(sorted(self.__dict__.items()))
......
......@@ -51,6 +51,7 @@ class AndroidPlatformBackend(
self._power_monitor = android_temperature_monitor.AndroidTemperatureMonitor(
power_controller, device)
self._video_recorder = None
self._installed_applications = None
if self._no_performance_mode:
logging.warning('CPU governor will not be set!')
......@@ -182,21 +183,36 @@ class AndroidPlatformBackend(
def LaunchApplication(
self, application, parameters=None, elevate_privilege=False):
"""Launches the given |application| with a list of |parameters| on the OS.
Args:
application: The full package name string of the application to launch.
parameters: A list of parameters to be passed to the ActivityManager.
elevate_privilege: Currently unimplemented on Android.
"""
if elevate_privilege:
raise NotImplementedError("elevate_privilege isn't supported on android.")
if not parameters:
parameters = ''
self._device.RunShellCommand('am start ' + parameters + ' ' + application)
result_lines = self._device.RunShellCommand('am start %s %s' %
(parameters, application))
for line in result_lines:
if line.startswith('Error: '):
raise ValueError('Failed to start "%s" with error\n %s' %
(application, line))
def IsApplicationRunning(self, application):
return len(self._device.GetPids(application)) > 0
def CanLaunchApplication(self, application):
return True
if not self._installed_applications:
self._installed_applications = self._device.RunShellCommand(
'pm list packages')
return 'package:' + application in self._installed_applications
def InstallApplication(self, application):
raise NotImplementedError(
'Please teach Telemetry how to install ' + application)
self._installed_applications = None
self._device.Install(application)
@decorators.Cache
def CanCaptureVideo(self):
......
......@@ -36,7 +36,9 @@ class OOMKillerProfiler(profiler.Profiler):
os.path.join('apks', 'MemConsumer.apk'), 'android')
assert mem_consumer_path, ('Could not find memconsumer app. Please build '
'memconsumer target.')
self._browser_backend.adb.Install(mem_consumer_path)
if not self._platform_backend.CanLaunchApplication(
'org.chromium.memconsumerg'):
self._platform_backend.InstallApplication(mem_consumer_path)
self._browser_backend.adb.device().GoHome()
self._platform_backend.LaunchApplication(
'org.chromium.memconsumer/.MemConsumer',
......
......@@ -50,18 +50,40 @@ class Override(object):
self._overrides = {}
class AndroidCommands(object):
def CanAccessProtectedFileContents(self):
return False
class AdbDevice(object):
def __init__(self, shell_command_handlers):
self._shell_command_handlers = shell_command_handlers
def RunShellCommand(self, args):
if isinstance(args, basestring):
args = shlex.split(args)
handler = self._shell_command_handlers[args[0]]
return handler(args)
def FileExists(self, _):
return False
@property
def old_interface(self):
return AndroidCommands()
class AdbCommandsModuleStub(object):
class AdbCommandsStub(object):
def __init__(self, module, device):
self._module = module
self._device = device
self.is_root_enabled = True
def RunShellCommand(self, args):
if isinstance(args, basestring):
args = shlex.split(args)
handler = self._module.shell_command_handlers[args[0]]
return handler(args)
self._adb_device = AdbDevice(module.shell_command_handlers)
def IsRootEnabled(self):
return self.is_root_enabled
......@@ -75,9 +97,12 @@ class AdbCommandsModuleStub(object):
def WaitForDevicePm(self):
pass
def device(self):
return self._adb_device
def __init__(self):
self.attached_devices = []
self.shell_command_handlers = {}
self.attached_devices = []
def AdbCommandsStubConstructor(device=None):
return AdbCommandsModuleStub.AdbCommandsStub(self, device)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment