[Android] Convert to DeviceUtils versions of IsOnline, HasRoot, and EnableRoot.

BUG=267773

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271213 0039d316-1c4b-4281-b951-d872f2087c98
parent 2b8710cc
......@@ -30,6 +30,7 @@ from pylib import android_commands
from pylib import constants
from pylib.cmd_helper import GetCmdOutput
from pylib.device import device_blacklist
from pylib.device import device_errors
from pylib.device import device_utils
def DeviceInfo(serial, options):
......@@ -95,7 +96,13 @@ def DeviceInfo(serial, options):
# Turn off devices with low battery.
if battery_level < 15:
device_adb.old_interface.EnableAdbRoot()
try:
device_adb.EnableRoot()
except device_errors.CommandFailedError as e:
# Attempt shutdown anyway.
# TODO(jbudorick) Handle this exception appropriately after interface
# conversions are finished.
logging.error(str(e))
device_adb.old_interface.Shutdown()
full_report = '\n'.join(report)
return device_type, device_build, battery_level, full_report, errors, True
......
......@@ -17,6 +17,7 @@ BUILD_ANDROID_DIR = os.path.join(os.path.dirname(__file__), '..', '..')
sys.path.append(BUILD_ANDROID_DIR)
from pylib import android_commands
from pylib.device import device_errors
from pylib.device import device_utils
GetAttachedDevices = android_commands.GetAttachedDevices
......@@ -57,16 +58,21 @@ def GetConfigurationForDevice(device_id):
device = device_utils.DeviceUtils(device_id)
configuration = None
has_root = False
is_online = device.old_interface.IsOnline()
is_online = device.IsOnline()
if is_online:
cmd = 'ls -l /data/app; getprop ro.build.description'
cmd_output = device.old_interface.RunShellCommand(cmd)
has_root = not 'Permission denied' in cmd_output[0]
if not has_root:
# Disable warning log messages from EnableAdbRoot()
# Disable warning log messages from EnableRoot()
logging.getLogger().disabled = True
has_root = device.old_interface.EnableAdbRoot()
logging.getLogger().disabled = False
try:
device.EnableRoot()
has_root = True
except device_errors.CommandFailedError:
has_root = False
finally:
logging.getLogger().disabled = False
cmd_output = device.old_interface.RunShellCommand(cmd)
configuration = {
......
......@@ -7,11 +7,20 @@ Function/method decorators that provide timeout and retry logic.
"""
import functools
import os
import sys
from pylib import constants
from pylib.device import device_errors
from pylib.utils import reraiser_thread
from pylib.utils import timeout_retry
# TODO(jbudorick) Remove once the DeviceUtils implementations are no longer
# backed by AndroidCommands / android_testrunner.
sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'third_party',
'android_testrunner'))
import errors as old_errors
def _TimeoutRetryWrapper(f, timeout_func, retries_func):
@functools.wraps(f)
......@@ -22,6 +31,10 @@ def _TimeoutRetryWrapper(f, timeout_func, retries_func):
return f(*args, **kwargs)
try:
return timeout_retry.Run(impl, timeout, retries)
except old_errors.WaitForResponseTimedOutError as e:
raise device_errors.CommandTimeoutError(str(e))
except old_errors.DeviceUnresponsiveError as e:
raise device_errors.DeviceUnreachableError(str(e))
except reraiser_thread.TimeoutError as e:
raise device_errors.CommandTimeoutError(str(e))
return TimeoutRetryWrapper
......
......@@ -16,6 +16,7 @@ import sys
import pylib.android_commands
from pylib.device import adb_wrapper
from pylib.device import decorators
from pylib.device import device_errors
CHROME_SRC_DIR = os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
......@@ -78,7 +79,20 @@ def RestartServer():
class DeviceUtils(object):
def __init__(self, device):
def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
default_retries=_DEFAULT_RETRIES):
""" DeviceUtils constructor.
Args:
device: Either a device serial, an existing AdbWrapper instance, an
an existing AndroidCommands instance, or nothing.
default_timeout: An integer containing the default number of seconds to
wait for an operation to complete if no explicit value
is provided.
default_retries: An integer containing the default number or times an
operation should be retried on failure if no explicit
value is provided.
"""
self.old_interface = None
if isinstance(device, basestring):
self.old_interface = pylib.android_commands.AndroidCommands(device)
......@@ -88,4 +102,51 @@ class DeviceUtils(object):
self.old_interface = device
elif not device:
self.old_interface = pylib.android_commands.AndroidCommands()
else:
raise ValueError('Unsupported type passed for argument "device"')
self._default_timeout = default_timeout
self._default_retries = default_retries
@decorators.WithTimeoutAndRetriesFromInstance(
'_default_timeout', '_default_retries')
def IsOnline(self, timeout=None, retries=None):
""" Checks whether the device is online.
Args:
timeout: An integer containing the number of seconds to wait for the
operation to complete.
retries: An integer containing the number of times the operation should
be retried if it fails.
Returns:
True if the device is online, False otherwise.
"""
return self.old_interface.IsOnline()
@decorators.WithTimeoutAndRetriesFromInstance(
'_default_timeout', '_default_retries')
def HasRoot(self, timeout=None, retries=None):
""" Checks whether or not adbd has root privileges.
Args:
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
Returns:
True if adbd has root privileges, False otherwise.
"""
return self.old_interface.IsRootEnabled()
@decorators.WithTimeoutAndRetriesFromInstance(
'_default_timeout', '_default_retries')
def EnableRoot(self, timeout=None, retries=None):
""" Restarts adbd with root privileges.
Args:
timeout: Same as for |IsOnline|.
retries: Same as for |IsOnline|.
Raises:
CommandFailedError if root could not be enabled.
"""
if not self.old_interface.EnableAdbRoot():
raise device_errors.CommandFailedError(
'adb root', 'Could not enable root.')
......@@ -9,10 +9,13 @@ Unit tests for the contents of device_utils.py (mostly DeviceUtils).
# pylint: disable=W0212
# pylint: disable=W0613
import random
import unittest
from pylib import android_commands
from pylib import cmd_helper
from pylib.device import adb_wrapper
from pylib.device import device_errors
from pylib.device import device_utils
......@@ -21,9 +24,10 @@ class DeviceUtilsTest(unittest.TestCase):
pass
def testRestartServerNotRunning(self):
# TODO(jbudorick) If these fail, it's not DeviceUtils's fault.
self.assertEqual(0, cmd_helper.RunCmd(['pkill', 'adb']))
self.assertNotEqual(0, cmd_helper.RunCmd(['pgrep', 'adb']))
self.assertEqual(0, cmd_helper.RunCmd(['pkill', 'adb']),
msg='Unable to kill adb during setup.')
self.assertNotEqual(0, cmd_helper.RunCmd(['pgrep', 'adb']),
msg='Unexpectedly found adb during setup.')
device_utils.RestartServer()
self.assertEqual(0, cmd_helper.RunCmd(['pgrep', 'adb']))
......@@ -63,7 +67,83 @@ class DeviceUtilsTest(unittest.TestCase):
d = device_utils.DeviceUtils(None)
self.assertIsNone(d.old_interface.GetDevice())
@staticmethod
def _getTestAdbWrapper():
devices = adb_wrapper.AdbWrapper.GetDevices()
if devices:
return random.choice(devices)
return None
@staticmethod
def _getUnusedSerial():
used_devices = [str(d) for d in adb_wrapper.AdbWrapper.GetDevices()]
while True:
serial = ''
for _ in xrange(0, 16):
serial += random.choice('0123456789abcdef')
if serial not in used_devices:
return serial
def testIsOnline(self):
d = device_utils.DeviceUtils(self._getTestAdbWrapper())
self.assertTrue(d is None or d.IsOnline())
d = device_utils.DeviceUtils(self._getUnusedSerial())
self.assertFalse(d.IsOnline())
def testHasRoot(self):
a = self._getTestAdbWrapper()
d = device_utils.DeviceUtils(a)
secure_prop = a.Shell('getprop ro.secure').strip()
if secure_prop == '1':
build_type_prop = a.Shell('getprop ro.build.type').strip()
if build_type_prop == 'userdebug':
adb_root_prop = a.Shell('getprop service.adb.root').strip()
if adb_root_prop is None or adb_root_prop == '0':
self.assertFalse(d.HasRoot())
else:
self.assertTrue(d.HasRoot())
else:
self.assertFalse(d.HasRoot())
else:
self.assertTrue(d.HasRoot())
def testEnableRoot(self):
a = self._getTestAdbWrapper()
d = device_utils.DeviceUtils(a)
secure_prop = a.Shell('getprop ro.secure').strip()
if secure_prop == '1':
build_type_prop = a.Shell('getprop ro.build.type').strip()
if build_type_prop == 'userdebug':
# Turn off the adb root property
adb_root_prop = a.Shell('getprop service.adb.root').strip()
if adb_root_prop == '1':
a.Shell('setprop service.adb.root 0')
# Make sure that adbd is running without root by restarting it
ps_out = a.Shell('ps')
adbd_pids = []
for line in ps_out.splitlines():
if 'adbd' in line:
pid = line.split()[1]
adbd_pids.append(pid)
for pid in adbd_pids:
a.Shell('kill %s' % str(pid))
a.WaitForDevice()
self.assertFalse(d.HasRoot())
d.EnableRoot()
self.assertTrue(d.HasRoot())
else:
self.assertFalse(d.HasRoot())
with self.assertRaises(device_errors.CommandFailedError):
d.EnableRoot()
else:
self.assertTrue(d.HasRoot())
d.EnableRoot()
self.assertTrue(d.HasRoot())
if __name__ == '__main__':
unittest.main()
unittest.main(verbosity=2, buffer=True)
......@@ -128,7 +128,7 @@ class TestRunner(base_test_runner.BaseTestRunner):
logging.error('Test terminated - EOF')
# We're here because either the device went offline, or the test harness
# crashed without outputting the CRASHED marker (crbug.com/175538).
if not self.device.old_interface.IsOnline():
if not self.device.IsOnline():
raise device_errors.DeviceUnreachableError(
'Device %s went offline.' % self.device.old_interface.GetDevice())
if full_test_name:
......
......@@ -147,7 +147,7 @@ class TestRunner(base_test_runner.BaseTestRunner):
def SetUp(self):
"""Sets up the test harness and device before all tests are run."""
super(TestRunner, self).SetUp()
if not self.device.old_interface.IsRootEnabled():
if not self.device.HasRoot():
logging.warning('Unable to enable java asserts for %s, non rooted device',
str(self.device))
else:
......
......@@ -7,8 +7,10 @@ import psutil
import signal
from pylib import android_commands
from pylib.device import device_errors
from pylib.device import device_utils
def _KillWebServers():
for s in [signal.SIGTERM, signal.SIGINT, signal.SIGQUIT, signal.SIGKILL]:
signalled = []
......@@ -41,6 +43,11 @@ def CleanupLeftoverProcesses():
device_utils.RestartServer()
did_restart_host_adb = True
device.old_interface.RestartAdbdOnDevice()
device.old_interface.EnableAdbRoot()
try:
device.EnableRoot()
except device_errors.CommandFailedError as e:
# TODO(jbudorick) Handle this exception appropriately after interface
# conversions are finished.
logging.error(str(e))
device.old_interface.WaitForDevicePm()
......@@ -23,11 +23,13 @@ Call tool.CleanUpEnvironment().
# pylint: disable=R0201
import glob
import logging
import os.path
import subprocess
import sys
from pylib.constants import DIR_SOURCE_ROOT
from pylib.device import device_errors
def SetChromeTimeoutScale(device, scale):
......@@ -132,7 +134,13 @@ class AddressSanitizerTool(BaseTool):
return self.GetTestWrapper()
def SetupEnvironment(self):
self._device.old_interface.EnableAdbRoot()
try:
self._device.EnableRoot()
except device_errors.CommandFailedError as e:
# Try to set the timeout scale anyway.
# TODO(jbudorick) Handle this exception appropriately after interface
# conversions are finished.
logging.error(str(e))
SetChromeTimeoutScale(self._device, self.GetTimeoutScale())
def CleanUpEnvironment(self):
......
......@@ -4,6 +4,7 @@
# found in the LICENSE file.
import collections
import logging
import optparse
import os
import sys
......@@ -86,7 +87,13 @@ def main(argv):
device = device_utils.DeviceUtils(None)
device.old_interface.EnableAdbRoot()
try:
device.EnableRoot()
except device_errors.CommandFailedError as e:
# Try to change the flags and start the activity anyway.
# TODO(jbudorick) Handle this exception appropriately after interface
# conversions are finished.
logging.error(str(e))
flags = flag_changer.FlagChanger(device, package_info.cmdline_file)
if ENABLE_TEST_INTENTS_FLAG not in flags.Get():
flags.AddFlags([ENABLE_TEST_INTENTS_FLAG])
......
......@@ -11,6 +11,7 @@ import datetime
import glob
import hashlib
import json
import logging
import os
import posixpath
......@@ -26,6 +27,7 @@ from memory_inspector.core import symbol
# The memory_inspector/__init__ module will add the <CHROME_SRC>/build/android
# deps to the PYTHONPATH for pylib.
from pylib import android_commands
from pylib.device import device_errors
from pylib.device import device_utils
from pylib.symbols import elf_symbolizer
......@@ -173,7 +175,13 @@ class AndroidDevice(backends.Device):
def Initialize(self):
"""Starts adb root and deploys the prebuilt binaries on initialization."""
self.underlying_device.old_interface.EnableAdbRoot()
try:
self.underlying_device.EnableRoot()
except device_errors.CommandFailedError as e:
# Try to deploy memdump and ps_ext anyway.
# TODO(jbudorick) Handle this exception appropriately after interface
# conversions are finished.
logging.error(str(e))
# Download (from GCS) and deploy prebuilt helper binaries on the device.
self._DeployPrebuiltOnDeviceIfNeeded(_MEMDUMP_PREBUILT_PATH,
......
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