aboutsummaryrefslogtreecommitdiff
path: root/catapult/devil
diff options
context:
space:
mode:
authorIsabelle Taylor <taylori@google.com>2018-10-31 11:57:24 +0000
committerIsabelle Taylor <taylori@google.com>2018-10-31 11:57:24 +0000
commit758efa702d67e7e8f7fce4e4b4d404fe36cf713c (patch)
tree4b32ed3904208724a5b1ec4a5481861c67677c99 /catapult/devil
parent42ec7d183c39a9f0b7d1c02c54711d92aaa2b0b8 (diff)
downloadchromium-trace-758efa702d67e7e8f7fce4e4b4d404fe36cf713c.tar.gz
Update to latest catapult (625dca847)
git log --oneline --no-merges eae13a4..625dca847 tracing systrace 625dca847 Handle perfetto protobuf files 00755b36f V8 GC metrics: Split of foreground, background, and total time 38b827049 Add support for metric abbreviation for physics units. c6a85907f Telemetry: migrate the rest of smoothness metrics df56c1dae Telemetry: detect telemetry target renderers 0339f0866 [tracing] Do not skip over entries when importing histograms b145370ba [CpuFCP] Support CPU time FCP 6292d2f5e androidStartupMetric: ignore the 2nd run 623a134fb Reland Migrate trace_viewer.gypi to gni b026043a4 Import perfetto json traces 4bcf107ea Add units for Ampers, Volts, Hertz, bytes per second 1922eb00b Update trace categories to reflect new trace names. 547a6910a Updating user timing argument regex to not parse on subsequent ':' chars. a10f776b1 [results.html] Speed up <histogram-json> parsing 2d4733846 V8 GC metrics: Add GC cycle time 519565187 Revert "Migrate trace_viewer.gypi to gni" fd3370d4a aura: filter out frames not submitted from browser 30824c537 Migrate trace_viewer.gypi to gni b273e0cd2 Add aggregate graphs to visualization tool. e302dcb5a event_finder_util: skip renderer events when no mainThread b8ae746e2 Telemetry: fix a bug in percentage_smooth c2f72b8a9 Fix top level scheduler task title 22c3e6c8f Telemetry: process all rendering pipeline events 6190da59c rendering: Generate metrics at the 95%ile. 1dc9e0a00 androidStartupMetric: re-introduce First Contentful Paint 0c42948b7 Clean up categories to match current tracing in Blink. 0480f8cae Telemetry: migrate frame_times & percentage_smooth cc7dfbec4 [tracing] Restore the minimum mutator utilization metric. 86bdcbf37 androidStartupMetric: slow fallback for incorrect process names e28148f1c Ignore forced Blink GCs in metrics 9ec8468cf Implementing firstContfulPaint metric using navigationId when present. 56216d783 Telemetry: pixel approximated/checkerboarded a7a24422d Telemetry: fix thread_other_cpu_time_per_frame_tbmv2 4c28d39fe Add more system stats to the UI tracing view 929a7f4eb Telemetry: clean up legacy surface flinger metrics bfe2c0046 androidStartupMetric: skip the first start 59297c6f7 Tracing: add java_base* executable memory metrics. 95ed233ed tracing: Avoid rAF callbacks when hidden. 2ba11d1c2 [Dashboard] Key histogram uploads by revision timestamp if necessary 5d1bdd129 trace-viewer: Add a close-button to hide a process. 97534cbfe Dashboard - Add a diagnostic for the build url. 9ba3159e0 tracing: Fix Blink metrics and add unified GC total sum 69f64b270 Allow bindId for separate begin/end slices as well a0faa9d4d Telemetry: cpu_per_frame metrics in TBMv2 7a4e890f2 Re-enable symbolize_trace_end_to_end_test_slow.SymbolizeTraceEndToEndTest.testMacv2 3cf15a9b4 Fix links in tracing/docs/ 8498332d3 trace-viewer: Fix crash in timeline process filter. 7931f7f4a Disable symbolize_trace_end_to_end_test_slow.SymbolizeTraceEndToEndTest.testMacv2 c51eb628d Telemetry: UI frame time metrics in TBMv2 cfc8160ac Telemetry: surface flinger metrics in TBMv2 64f2ed4bb Revert "Use vpython and remove vendored pymock." 23c67a511 Use vpython and remove vendored pymock. 5e9714532 trace-viewer: Allow filtering processes. 582a06eb7 Telemetry: don't fail when SF cannot find win name b7ae965a6 results2.html debounce search d282eec79 Fixing frames in animations following response. deef6ea33 androidStartupMetric: remove the FCP 356cb8473 rendering: Remove some redundant mean_ metrics. 703fd41ed rendering: Remove discrepancy metrics. 758dedc2a Telemetry: Fix SF events cc38544e3 androidStartupMetric: remove request_start_time from comments 945f73d77 VR: Restore metrics after refactoring 62c9dfc97 rendering: Ignore trace-events for canceled draws. 67653ff0e androidStartupMetric: Remove request_start_time 134ee3695 Allow cswitch version 4 as well as 2 916e932a9 Reland "[TBMv2] Support Chromium commit positions in legacy_json_converter" 6333b6741 Revert "[TBMv2] Support Chromium commit positions in legacy_json_converter" f633aa104 [TBMv2] Support Chromium commit positions in legacy_json_converter 66b08ec93 Display cswitch header version on errors 0c8cc6141 Fix a bug in console error metric. 106d366ce Add a metric that tracks the number of console error messages 0349b720c [Tracing] Add support for Optimize-Background bucket to V8's runtime call stats table 658e07ae3 Fix systrace/bin/OWNERS. 86b118ed9 Telemetry: first_gesture_scroll_update_latency 5167fb3f6 Telemetry: latency metrics in TBMv2 e0a3ea946 Tracing: Fix an input latency bug 18259e73a Update memory metric for the upcoming V8 memory dump provider changes. b6bda5336 rendering: Fix for null browser thread. 19aaaf25f [TBMv2] Add legacy JSON converter 7a1ed44d2 Telemetry: fix a rendering benchmark failure 4679c5508 [Tracing] Fix Pylint errors d55ab227c Fix search bug in metrics visualization tool 8eb323fab Telemetry: pixel metrics in TBMv2 68c00fdca Telemetry: rename metrics as per crbug.com/627461 b791754c7 Telemetry: break rendering_metric.html f62079a0f Telemetry: queueing_durations in TBMv2 ccd130b9a Add windows performance counters processing. 11877aab1 Make small fixes to metrics visualization tool 615ae9b6f Add tool for visualizing metrics times 58bf2845e Telemetry: fix Gesture IRs fe6031638 Fix propertyMode in ic_stats_entry d38bbdff0 rendering: Fix filtering events. Bug: 117587646 Test: ./systrace.py Merged-In: Iffd7f590796b07df49ed4fdfd8bc0f695ab9225f (cherry picked from commit 3f5bbbf437b9b03d42e87e60943f21a663f10421) Change-Id: Id88893c5807f91b4f0f1d84cf5b609b240414695
Diffstat (limited to 'catapult/devil')
-rw-r--r--catapult/devil/BUILD.gn21
-rw-r--r--catapult/devil/devil/android/battery_utils.py8
-rw-r--r--catapult/devil/devil/android/decorators.py2
-rw-r--r--catapult/devil/devil/android/device_errors.py4
-rw-r--r--catapult/devil/devil/android/device_utils.py56
-rwxr-xr-xcatapult/devil/devil/android/device_utils_test.py439
-rw-r--r--catapult/devil/devil/android/flag_changer.py7
-rw-r--r--catapult/devil/devil/android/perf/perf_control.py226
-rw-r--r--catapult/devil/devil/android/perf/perf_control_test.py105
-rw-r--r--catapult/devil/devil/android/perf/surface_stats_collector.py24
-rw-r--r--catapult/devil/devil/android/sdk/adb_wrapper.py35
-rw-r--r--catapult/devil/devil/android/sdk/shared_prefs.py11
-rwxr-xr-xcatapult/devil/devil/android/sdk/shared_prefs_test.py32
-rw-r--r--catapult/devil/devil/android/sdk/version_codes.py1
-rwxr-xr-xcatapult/devil/devil/android/tools/provision_devices.py29
-rwxr-xr-xcatapult/devil/devil/android/tools/system_app.py4
-rw-r--r--catapult/devil/devil/android/tools/system_app_test.py6
-rw-r--r--catapult/devil/devil/android/tools/unlock_bootloader.py2
-rw-r--r--catapult/devil/devil/devil_dependencies.json6
-rw-r--r--catapult/devil/devil/utils/cmd_helper.py4
-rw-r--r--catapult/devil/devil/utils/lazy/weak_constant_test.py4
21 files changed, 757 insertions, 269 deletions
diff --git a/catapult/devil/BUILD.gn b/catapult/devil/BUILD.gn
new file mode 100644
index 00000000..661a24fd
--- /dev/null
+++ b/catapult/devil/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2017 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("//build/symlink.gni")
+import("//testing/android/empty_apk/empty_apk.gni")
+
+empty_apk("empty_system_webview_apk") {
+ package_name = "com.android.webview"
+ apk_name = "EmptySystemWebView"
+}
+
+group("devil") {
+ testonly = true
+ deps = [
+ ":empty_system_webview_apk",
+ "//buildtools/third_party/libc++($host_toolchain)",
+ "//tools/android/forwarder2",
+ "//tools/android/md5sum",
+ ]
+}
diff --git a/catapult/devil/devil/android/battery_utils.py b/catapult/devil/devil/android/battery_utils.py
index a8a08a96..9c83b5b0 100644
--- a/catapult/devil/devil/android/battery_utils.py
+++ b/catapult/devil/devil/android/battery_utils.py
@@ -11,6 +11,7 @@ import contextlib
import csv
import logging
+from devil.android import crash_handler
from devil.android import decorators
from devil.android import device_errors
from devil.android import device_utils
@@ -374,7 +375,12 @@ class BatteryUtils(object):
Returns:
True if the device is charging, false otherwise.
"""
- battery_info = self.GetBatteryInfo()
+ # Wrapper function so that we can use `RetryOnSystemCrash`.
+ def GetBatteryInfoHelper(device):
+ return self.GetBatteryInfo()
+
+ battery_info = crash_handler.RetryOnSystemCrash(
+ GetBatteryInfoHelper, self._device)
for k in ('AC powered', 'USB powered', 'Wireless powered'):
if (k in battery_info and
battery_info[k].lower() in ('true', '1', 'yes')):
diff --git a/catapult/devil/devil/android/decorators.py b/catapult/devil/devil/android/decorators.py
index 3844b49a..93e10544 100644
--- a/catapult/devil/devil/android/decorators.py
+++ b/catapult/devil/devil/android/decorators.py
@@ -59,7 +59,7 @@ def _TimeoutRetryWrapper(
raise device_errors.CommandTimeoutError(str(e)), None, (
sys.exc_info()[2])
except cmd_helper.TimeoutError as e:
- raise device_errors.CommandTimeoutError(str(e)), None, (
+ raise device_errors.CommandTimeoutError(str(e), output=e.output), None, (
sys.exc_info()[2])
return timeout_retry_wrapper
diff --git a/catapult/devil/devil/android/device_errors.py b/catapult/devil/devil/android/device_errors.py
index cd0266c8..e6893a4f 100644
--- a/catapult/devil/devil/android/device_errors.py
+++ b/catapult/devil/devil/android/device_errors.py
@@ -148,7 +148,9 @@ class AdbShellCommandFailedError(AdbCommandFailedError):
class CommandTimeoutError(base_error.BaseError):
"""Exception for command timeouts."""
- pass
+ def __init__(self, message, is_infra_error=False, output=None):
+ super(CommandTimeoutError, self).__init__(message, is_infra_error)
+ self.output = output
class DeviceUnreachableError(base_error.BaseError):
diff --git a/catapult/devil/devil/android/device_utils.py b/catapult/devil/devil/android/device_utils.py
index 518e4393..575865bd 100644
--- a/catapult/devil/devil/android/device_utils.py
+++ b/catapult/devil/devil/android/device_utils.py
@@ -13,6 +13,7 @@ import collections
import fnmatch
import json
import logging
+import math
import os
import posixpath
import pprint
@@ -209,6 +210,7 @@ _SPECIAL_ROOT_DEVICE_LIST = [
'marlin', # Pixel XL
'sailfish', # Pixel
'taimen', # Pixel 2 XL
+ 'vega', # Lenovo Mirage Solo
'walleye', # Pixel 2
]
_IMEI_RE = re.compile(r' Device ID = (.+)$')
@@ -425,6 +427,20 @@ class DeviceUtils(object):
def HasRoot(self, timeout=None, retries=None):
"""Checks whether or not adbd has root privileges.
+ A device is considered to have root if all commands are implicitly run
+ with elevated privileges, i.e. without having to use "su" to run them.
+
+ Note that some devices do not allow this implicit privilige elevation,
+ but _can_ run commands as root just fine when done explicitly with "su".
+ To check if your device can run commands with elevated privileges at all
+ use:
+
+ device.HasRoot() or device.NeedsSU()
+
+ Luckily, for the most part you don't need to worry about this and using
+ RunShellCommand(cmd, as_root=True) will figure out for you the right
+ command incantation to run with elevated privileges.
+
Args:
timeout: timeout in seconds
retries: number of retries
@@ -1004,8 +1020,8 @@ class DeviceUtils(object):
@decorators.WithTimeoutAndRetriesFromInstance()
def RunShellCommand(self, cmd, shell=False, check_return=False, cwd=None,
env=None, run_as=None, as_root=False, single_line=False,
- large_output=False, raw_output=False, timeout=None,
- retries=None):
+ large_output=False, raw_output=False,
+ ensure_logs_on_timeout=False, timeout=None, retries=None):
"""Run an ADB shell command.
The command to run |cmd| should be a sequence of program arguments
@@ -1048,6 +1064,10 @@ class DeviceUtils(object):
this large output will be truncated.
raw_output: Whether to only return the raw output
(no splitting into lines).
+ ensure_logs_on_timeout: If True, will use a slightly smaller timeout for
+ the internal adb command, which allows to retrive logs on timeout.
+ Note that that logs are not guaranteed to be produced with this option
+ as adb command may still hang and fail to respect the reduced timeout.
timeout: timeout in seconds
retries: number of retries
@@ -1071,7 +1091,7 @@ class DeviceUtils(object):
return '%s=%s' % (key, cmd_helper.DoubleQuote(value))
def run(cmd):
- return self.adb.Shell(cmd)
+ return self.adb.Shell(cmd, ensure_logs_on_timeout=ensure_logs_on_timeout)
def handle_check_return(cmd):
try:
@@ -2805,7 +2825,7 @@ class DeviceUtils(object):
return parallelizer.SyncParallelizer(devices)
@classmethod
- def HealthyDevices(cls, blacklist=None, device_arg='default', retry=True,
+ def HealthyDevices(cls, blacklist=None, device_arg='default', retries=1,
abis=None, **kwargs):
"""Returns a list of DeviceUtils instances.
@@ -2828,8 +2848,9 @@ class DeviceUtils(object):
blacklisted.
['A', 'B', ...] -> Returns instances for the subset that is not
blacklisted.
- retry: If true, will attempt to restart adb server and query it again if
- no devices are found.
+ retries: Number of times to restart adb server and query it again if no
+ devices are found on the previous attempts, with exponential backoffs
+ up to 60s between each retry.
abis: A list of ABIs for which the device needs to support at least one of
(optional).
A device serial, or a list of device serials (optional).
@@ -2891,15 +2912,20 @@ class DeviceUtils(object):
raise device_errors.MultipleDevicesError(devices)
return sorted(devices)
- try:
- return _get_devices()
- except device_errors.NoDevicesError:
- if not retry:
- raise
- logger.warning(
- 'No devices found. Will try again after restarting adb server.')
- RestartServer()
- return _get_devices()
+ for attempt in xrange(retries+1):
+ try:
+ return _get_devices()
+ except device_errors.NoDevicesError:
+ if attempt == retries:
+ logging.error('No devices found after exhausting all retries.')
+ raise
+ # math.pow returns floats, so cast to int for easier testing
+ sleep_s = min(int(math.pow(2, attempt + 1)), 60)
+ logger.warning(
+ 'No devices found. Will try again after restarting adb server '
+ 'and a short nap of %d s.', sleep_s)
+ time.sleep(sleep_s)
+ RestartServer()
@decorators.WithTimeoutAndRetriesFromInstance()
def RestartAdbd(self, timeout=None, retries=None):
diff --git a/catapult/devil/devil/android/device_utils_test.py b/catapult/devil/devil/android/device_utils_test.py
index 88c91b51..e0ed666c 100755
--- a/catapult/devil/devil/android/device_utils_test.py
+++ b/catapult/devil/devil/android/device_utils_test.py
@@ -316,28 +316,32 @@ class DeviceUtilsHasRootTest(DeviceUtilsTest):
def testHasRoot_true(self):
with self.patch_call(self.call.device.product_name,
return_value='notasailfish'), (
- self.assertCall(self.call.adb.Shell('ls /root'), 'foo\n')):
+ self.assertCall(self.call.adb.Shell(
+ 'ls /root', ensure_logs_on_timeout=False), 'foo\n')):
self.assertTrue(self.device.HasRoot())
def testhasRootSpecial_true(self):
with self.patch_call(self.call.device.product_name,
return_value='sailfish'), (
- self.assertCall(self.call.adb.Shell('getprop service.adb.root'),
- '1\n')):
+ self.assertCall(
+ self.call.adb.Shell('getprop service.adb.root',
+ ensure_logs_on_timeout=False), '1\n')):
self.assertTrue(self.device.HasRoot())
def testHasRoot_false(self):
with self.patch_call(self.call.device.product_name,
return_value='notasailfish'), (
- self.assertCall(self.call.adb.Shell('ls /root'),
- self.ShellError())):
+ self.assertCall(
+ self.call.adb.Shell(
+ 'ls /root', ensure_logs_on_timeout=False), self.ShellError())):
self.assertFalse(self.device.HasRoot())
def testHasRootSpecial_false(self):
with self.patch_call(self.call.device.product_name,
return_value='sailfish'), (
- self.assertCall(self.call.adb.Shell('getprop service.adb.root'),
- '\n')):
+ self.assertCall(
+ self.call.adb.Shell(
+ 'getprop service.adb.root', ensure_logs_on_timeout=False), '\n')):
self.assertFalse(self.device.HasRoot())
@@ -445,7 +449,8 @@ class DeviceUtils_GetApplicationVersionTest(DeviceUtilsTest):
def test_GetApplicationVersion_exists(self):
with self.assertCalls(
- (self.call.adb.Shell('dumpsys package com.android.chrome'),
+ (self.call.adb.Shell(
+ 'dumpsys package com.android.chrome', ensure_logs_on_timeout=False),
'Packages:\n'
' Package [com.android.chrome] (3901ecfb):\n'
' userId=1234 gids=[123, 456, 789]\n'
@@ -456,13 +461,16 @@ class DeviceUtils_GetApplicationVersionTest(DeviceUtilsTest):
def test_GetApplicationVersion_notExists(self):
with self.assertCalls(
- (self.call.adb.Shell('dumpsys package com.android.chrome'), '')):
+ (self.call.adb.Shell(
+ 'dumpsys package com.android.chrome', ensure_logs_on_timeout=False),
+ '')):
self.assertEquals(None,
self.device.GetApplicationVersion('com.android.chrome'))
def test_GetApplicationVersion_fails(self):
with self.assertCalls(
- (self.call.adb.Shell('dumpsys package com.android.chrome'),
+ (self.call.adb.Shell(
+ 'dumpsys package com.android.chrome', ensure_logs_on_timeout=False),
'Packages:\n'
' Package [com.android.chrome] (3901ecfb):\n'
' userId=1234 gids=[123, 456, 789]\n'
@@ -520,7 +528,8 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
self.call.adb.WaitForDevice(),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), ''),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False), ''),
# pm_ready
(self.call.device._GetApplicationPathsInternal('android',
skip_cache=True),
@@ -534,7 +543,8 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
self.call.adb.WaitForDevice(),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), ''),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False), ''),
# pm_ready
(self.call.device._GetApplicationPathsInternal('android',
skip_cache=True),
@@ -542,7 +552,8 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
# boot_completed
(self.call.device.GetProp('sys.boot_completed', cache=False), '1'),
# wifi_enabled
- (self.call.adb.Shell('dumpsys wifi'),
+ (self.call.adb.Shell(
+ 'dumpsys wifi', ensure_logs_on_timeout=False),
'stuff\nWi-Fi is enabled\nmore stuff\n')):
self.device.WaitUntilFullyBooted(wifi=True)
@@ -559,7 +570,8 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
(self.call.device.GetExternalStoragePath(), self.AdbCommandError()),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), ''),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False), ''),
# pm_ready
(self.call.device._GetApplicationPathsInternal('android',
skip_cache=True),
@@ -573,7 +585,8 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
self.call.adb.WaitForDevice(),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), ''),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False), ''),
# pm_ready
(self.call.device._GetApplicationPathsInternal('android',
skip_cache=True),
@@ -598,13 +611,18 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
self.call.adb.WaitForDevice(),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), self.ShellError()),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False),
+ self.ShellError()),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), self.ShellError()),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False),
+ self.ShellError()),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False),
self.TimeoutError())):
with self.assertRaises(device_errors.CommandTimeoutError):
self.device.WaitUntilFullyBooted(wifi=False)
@@ -614,7 +632,8 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
self.call.adb.WaitForDevice(),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), ''),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False), ''),
# pm_ready
(self.call.device._GetApplicationPathsInternal('android',
skip_cache=True),
@@ -635,7 +654,8 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
self.call.adb.WaitForDevice(),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), ''),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False), ''),
# pm_ready
(self.call.device._GetApplicationPathsInternal('android',
skip_cache=True),
@@ -655,7 +675,8 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
self.call.adb.WaitForDevice(),
# sd_card_ready
(self.call.device.GetExternalStoragePath(), '/fake/storage/path'),
- (self.call.adb.Shell('test -d /fake/storage/path'), ''),
+ (self.call.adb.Shell(
+ 'test -d /fake/storage/path', ensure_logs_on_timeout=False), ''),
# pm_ready
(self.call.device._GetApplicationPathsInternal('android',
skip_cache=True),
@@ -663,11 +684,14 @@ class DeviceUtilsWaitUntilFullyBootedTest(DeviceUtilsTest):
# boot_completed
(self.call.device.GetProp('sys.boot_completed', cache=False), '1'),
# wifi_enabled
- (self.call.adb.Shell('dumpsys wifi'), 'stuff\nmore stuff\n'),
+ (self.call.adb.Shell(
+ 'dumpsys wifi', ensure_logs_on_timeout=False), 'stuff\nmore stuff\n'),
# wifi_enabled
- (self.call.adb.Shell('dumpsys wifi'), 'stuff\nmore stuff\n'),
+ (self.call.adb.Shell(
+ 'dumpsys wifi', ensure_logs_on_timeout=False), 'stuff\nmore stuff\n'),
# wifi_enabled
- (self.call.adb.Shell('dumpsys wifi'), self.TimeoutError())):
+ (self.call.adb.Shell(
+ 'dumpsys wifi', ensure_logs_on_timeout=False), self.TimeoutError())):
with self.assertRaises(device_errors.CommandTimeoutError):
self.device.WaitUntilFullyBooted(wifi=True)
@@ -930,30 +954,36 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
self.device.NeedsSU = mock.Mock(return_value=False)
def testRunShellCommand_commandAsList(self):
- with self.assertCall(self.call.adb.Shell('pm list packages'), ''):
+ with self.assertCall(self.call.adb.Shell(
+ 'pm list packages', ensure_logs_on_timeout=False), ''):
self.device.RunShellCommand(
['pm', 'list', 'packages'], check_return=True)
def testRunShellCommand_commandAsListQuoted(self):
- with self.assertCall(self.call.adb.Shell("echo 'hello world' '$10'"), ''):
+ with self.assertCall(self.call.adb.Shell(
+ "echo 'hello world' '$10'", ensure_logs_on_timeout=False), ''):
self.device.RunShellCommand(
['echo', 'hello world', '$10'], check_return=True)
def testRunShellCommand_commandAsString(self):
- with self.assertCall(self.call.adb.Shell('echo "$VAR"'), ''):
+ with self.assertCall(self.call.adb.Shell(
+ 'echo "$VAR"', ensure_logs_on_timeout=False), ''):
self.device.RunShellCommand(
'echo "$VAR"', shell=True, check_return=True)
def testNewRunShellImpl_withEnv(self):
with self.assertCall(
- self.call.adb.Shell('VAR=some_string echo "$VAR"'), ''):
+ self.call.adb.Shell(
+ 'VAR=some_string echo "$VAR"', ensure_logs_on_timeout=False), ''):
self.device.RunShellCommand(
'echo "$VAR"', shell=True, check_return=True,
env={'VAR': 'some_string'})
def testNewRunShellImpl_withEnvQuoted(self):
with self.assertCall(
- self.call.adb.Shell('PATH="$PATH:/other/path" run_this'), ''):
+ self.call.adb.Shell(
+ 'PATH="$PATH:/other/path" run_this', ensure_logs_on_timeout=False),
+ ''):
self.device.RunShellCommand(
['run_this'], check_return=True, env={'PATH': '$PATH:/other/path'})
@@ -963,13 +993,17 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
['some_cmd'], check_return=True, env={'INVALID NAME': 'value'})
def testNewRunShellImpl_withCwd(self):
- with self.assertCall(self.call.adb.Shell('cd /some/test/path && ls'), ''):
+ with self.assertCall(self.call.adb.Shell(
+ 'cd /some/test/path && ls', ensure_logs_on_timeout=False), ''):
self.device.RunShellCommand(
['ls'], check_return=True, cwd='/some/test/path')
def testNewRunShellImpl_withCwdQuoted(self):
with self.assertCall(
- self.call.adb.Shell("cd '/some test/path with/spaces' && ls"), ''):
+ self.call.adb.Shell(
+ "cd '/some test/path with/spaces' && ls",
+ ensure_logs_on_timeout=False),
+ ''):
self.device.RunShellCommand(
['ls'], check_return=True, cwd='/some test/path with/spaces')
@@ -980,7 +1014,9 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
(mock.call.devil.android.device_temp_file.DeviceTempFile(
self.adb, suffix='.sh'), MockTempFile('/sdcard/temp-123.sh')),
self.call.device._WriteFileWithPush('/sdcard/temp-123.sh', expected_cmd),
- (self.call.adb.Shell('sh /sdcard/temp-123.sh'), payload + '\n')):
+ (self.call.adb.Shell(
+ 'sh /sdcard/temp-123.sh', ensure_logs_on_timeout=False),
+ payload + '\n')):
self.assertEquals(
[payload],
self.device.RunShellCommand(['echo', payload], check_return=True))
@@ -995,7 +1031,9 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
(mock.call.devil.android.device_temp_file.DeviceTempFile(
self.adb, suffix='.sh'), MockTempFile('/sdcard/temp-123.sh')),
self.call.device._WriteFileWithPush('/sdcard/temp-123.sh', expected_cmd),
- (self.call.adb.Shell('sh /sdcard/temp-123.sh'), payload + '\n')):
+ (self.call.adb.Shell(
+ 'sh /sdcard/temp-123.sh', ensure_logs_on_timeout=False),
+ payload + '\n')):
self.assertEquals(
[payload],
self.device.RunShellCommand(
@@ -1007,7 +1045,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.NeedsSU(), True),
(self.call.device._Su(expected_cmd_without_su), expected_cmd),
- (self.call.adb.Shell(expected_cmd), '')):
+ (self.call.adb.Shell(
+ expected_cmd, ensure_logs_on_timeout=False), '')):
self.device.RunShellCommand(
['setprop', 'service.adb.root', '0'],
check_return=True, as_root=True)
@@ -1016,7 +1055,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
expected_cmd_without_run_as = "sh -c 'mkdir -p files'"
expected_cmd = (
'run-as org.devil.test_package %s' % expected_cmd_without_run_as)
- with self.assertCall(self.call.adb.Shell(expected_cmd), ''):
+ with self.assertCall(self.call.adb.Shell(
+ expected_cmd, ensure_logs_on_timeout=False), ''):
self.device.RunShellCommand(
['mkdir', '-p', 'files'],
check_return=True, run_as='org.devil.test_package')
@@ -1031,7 +1071,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.NeedsSU(), True),
(self.call.device._Su(expected_cmd_without_su), expected_cmd),
- (self.call.adb.Shell(expected_cmd), '')):
+ (self.call.adb.Shell(
+ expected_cmd, ensure_logs_on_timeout=False), '')):
self.device.RunShellCommand(
['mkdir', '-p', 'files'],
check_return=True, run_as='org.devil.test_package',
@@ -1039,14 +1080,16 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_manyLines(self):
cmd = 'ls /some/path'
- with self.assertCall(self.call.adb.Shell(cmd), 'file1\nfile2\nfile3\n'):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), 'file1\nfile2\nfile3\n'):
self.assertEquals(
['file1', 'file2', 'file3'],
self.device.RunShellCommand(cmd.split(), check_return=True))
def testRunShellCommand_manyLinesRawOutput(self):
cmd = 'ls /some/path'
- with self.assertCall(self.call.adb.Shell(cmd), '\rfile1\nfile2\r\nfile3\n'):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), '\rfile1\nfile2\r\nfile3\n'):
self.assertEquals(
'\rfile1\nfile2\r\nfile3\n',
self.device.RunShellCommand(
@@ -1054,7 +1097,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_singleLine_success(self):
cmd = 'echo $VALUE'
- with self.assertCall(self.call.adb.Shell(cmd), 'some value\n'):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), 'some value\n'):
self.assertEquals(
'some value',
self.device.RunShellCommand(
@@ -1062,7 +1106,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_singleLine_successEmptyLine(self):
cmd = 'echo $VALUE'
- with self.assertCall(self.call.adb.Shell(cmd), '\n'):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), '\n'):
self.assertEquals(
'',
self.device.RunShellCommand(
@@ -1070,7 +1115,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_singleLine_successWithoutEndLine(self):
cmd = 'echo -n $VALUE'
- with self.assertCall(self.call.adb.Shell(cmd), 'some value'):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), 'some value'):
self.assertEquals(
'some value',
self.device.RunShellCommand(
@@ -1078,7 +1124,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_singleLine_successNoOutput(self):
cmd = 'echo -n $VALUE'
- with self.assertCall(self.call.adb.Shell(cmd), ''):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), ''):
self.assertEquals(
'',
self.device.RunShellCommand(
@@ -1086,7 +1133,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_singleLine_failTooManyLines(self):
cmd = 'echo $VALUE'
- with self.assertCall(self.call.adb.Shell(cmd),
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False),
'some value\nanother value\n'):
with self.assertRaises(device_errors.CommandFailedError):
self.device.RunShellCommand(
@@ -1095,7 +1143,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_checkReturn_success(self):
cmd = 'echo $ANDROID_DATA'
output = '/data\n'
- with self.assertCall(self.call.adb.Shell(cmd), output):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), output):
self.assertEquals(
[output.rstrip()],
self.device.RunShellCommand(cmd, shell=True, check_return=True))
@@ -1103,14 +1152,16 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_checkReturn_failure(self):
cmd = 'ls /root'
output = 'opendir failed, Permission denied\n'
- with self.assertCall(self.call.adb.Shell(cmd), self.ShellError(output)):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), self.ShellError(output)):
with self.assertRaises(device_errors.AdbCommandFailedError):
self.device.RunShellCommand(cmd.split(), check_return=True)
def testRunShellCommand_checkReturn_disabled(self):
cmd = 'ls /root'
output = 'opendir failed, Permission denied\n'
- with self.assertCall(self.call.adb.Shell(cmd), self.ShellError(output)):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), self.ShellError(output)):
self.assertEquals(
[output.rstrip()],
self.device.RunShellCommand(cmd.split(), check_return=False))
@@ -1122,7 +1173,7 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
with self.assertCalls(
(mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb),
temp_file),
- (self.call.adb.Shell(cmd_redirect)),
+ (self.call.adb.Shell(cmd_redirect, ensure_logs_on_timeout=False)),
(self.call.device.ReadFile(temp_file.name, force_pull=True),
'something')):
self.assertEquals(
@@ -1132,7 +1183,8 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
def testRunShellCommand_largeOutput_disabledNoTrigger(self):
cmd = 'something'
- with self.assertCall(self.call.adb.Shell(cmd), self.ShellError('')):
+ with self.assertCall(self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), self.ShellError('')):
with self.assertRaises(device_errors.AdbCommandFailedError):
self.device.RunShellCommand([cmd], check_return=True)
@@ -1141,10 +1193,12 @@ class DeviceUtilsRunShellCommandTest(DeviceUtilsTest):
temp_file = MockTempFile('/sdcard/temp-123')
cmd_redirect = '( %s )>%s 2>&1' % (cmd, temp_file.name)
with self.assertCalls(
- (self.call.adb.Shell(cmd), self.ShellError('', None)),
+ (self.call.adb.Shell(
+ cmd, ensure_logs_on_timeout=False), self.ShellError('', None)),
(mock.call.devil.android.device_temp_file.DeviceTempFile(self.adb),
temp_file),
- (self.call.adb.Shell(cmd_redirect)),
+ (self.call.adb.Shell(
+ cmd_redirect, ensure_logs_on_timeout=False)),
(self.call.device.ReadFile(mock.ANY, force_pull=True),
'something')):
self.assertEquals(
@@ -1210,7 +1264,8 @@ class DeviceUtilsKillAllTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.ListProcesses('some.process'),
Processes(('some.process', 1234), ('some.process.thing', 5678))),
- (self.call.adb.Shell('kill -9 1234 5678'), '')):
+ (self.call.adb.Shell(
+ 'kill -9 1234 5678', ensure_logs_on_timeout=False), '')):
self.assertEquals(
2, self.device.KillAll('some.process', blocking=False))
@@ -1218,7 +1273,8 @@ class DeviceUtilsKillAllTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.ListProcesses('some.process'),
Processes(('some.process', 1234), ('some.process.thing', 5678))),
- (self.call.adb.Shell('kill -9 1234 5678'), ''),
+ (self.call.adb.Shell(
+ 'kill -9 1234 5678', ensure_logs_on_timeout=False), ''),
(self.call.device.ListProcesses('some.process'),
Processes(('some.process.thing', 5678))),
(self.call.device.ListProcesses('some.process'),
@@ -1231,7 +1287,8 @@ class DeviceUtilsKillAllTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.ListProcesses('some.process'),
Processes(('some.process', 1234), ('some.process.thing', 5678))),
- (self.call.adb.Shell('kill -9 1234'), '')):
+ (self.call.adb.Shell(
+ 'kill -9 1234', ensure_logs_on_timeout=False), '')):
self.assertEquals(
1, self.device.KillAll('some.process', exact=True, blocking=False))
@@ -1239,7 +1296,8 @@ class DeviceUtilsKillAllTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.ListProcesses('some.process'),
Processes(('some.process', 1234), ('some.process.thing', 5678))),
- (self.call.adb.Shell('kill -9 1234'), ''),
+ (self.call.adb.Shell(
+ 'kill -9 1234', ensure_logs_on_timeout=False), ''),
(self.call.device.ListProcesses('some.process'),
Processes(('some.process', 1234), ('some.process.thing', 5678))),
(self.call.device.ListProcesses('some.process'),
@@ -1254,7 +1312,8 @@ class DeviceUtilsKillAllTest(DeviceUtilsTest):
(self.call.device.NeedsSU(), True),
(self.call.device._Su("sh -c 'kill -9 1234'"),
"su -c sh -c 'kill -9 1234'"),
- (self.call.adb.Shell("su -c sh -c 'kill -9 1234'"), '')):
+ (self.call.adb.Shell(
+ "su -c sh -c 'kill -9 1234'", ensure_logs_on_timeout=False), '')):
self.assertEquals(
1, self.device.KillAll('some.process', as_root=True))
@@ -1262,7 +1321,8 @@ class DeviceUtilsKillAllTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.ListProcesses('some.process'),
Processes(('some.process', 1234))),
- (self.call.adb.Shell('kill -15 1234'), '')):
+ (self.call.adb.Shell(
+ 'kill -15 1234', ensure_logs_on_timeout=False), '')):
self.assertEquals(
1, self.device.KillAll('some.process', signum=device_signal.SIGTERM))
@@ -1270,7 +1330,8 @@ class DeviceUtilsKillAllTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.ListProcesses('some.process'),
Processes(('some.process', 1234), ('some.process', 4567))),
- (self.call.adb.Shell('kill -15 1234 4567'), '')):
+ (self.call.adb.Shell(
+ 'kill -15 1234 4567', ensure_logs_on_timeout=False), '')):
self.assertEquals(
2, self.device.KillAll('some.process', signum=device_signal.SIGTERM))
@@ -1280,8 +1341,10 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
def testStartActivity_actionOnly(self):
test_intent = intent.Intent(action='android.intent.action.VIEW')
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1290,9 +1353,11 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
package='test.package',
activity='.Main')
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1301,9 +1366,11 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
package='test.package',
activity='.Main')
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Error: Failed to start test activity'):
with self.assertRaises(device_errors.CommandFailedError):
self.device.StartActivity(test_intent)
@@ -1313,10 +1380,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
package='test.package',
activity='.Main')
with self.assertCall(
- self.call.adb.Shell('am start '
- '-W '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start '
+ '-W '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent, blocking=True)
@@ -1326,10 +1395,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
activity='.Main',
category='android.intent.category.HOME')
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-c android.intent.category.HOME '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-c android.intent.category.HOME '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1340,11 +1411,13 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
category=['android.intent.category.HOME',
'android.intent.category.BROWSABLE'])
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-c android.intent.category.HOME '
- '-c android.intent.category.BROWSABLE '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-c android.intent.category.HOME '
+ '-c android.intent.category.BROWSABLE '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1354,10 +1427,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
activity='.Main',
data='http://www.google.com/')
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-d http://www.google.com/ '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-d http://www.google.com/ '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1367,10 +1442,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
activity='.Main',
extras={'foo': 'test'})
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main '
- '--es foo test'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main '
+ '--es foo test',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1380,10 +1457,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
activity='.Main',
extras={'foo': True})
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main '
- '--ez foo True'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main '
+ '--ez foo True',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1393,10 +1472,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
activity='.Main',
extras={'foo': 123})
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main '
- '--ei foo 123'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main '
+ '--ei foo 123',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1405,10 +1486,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
package='test.package',
activity='.Main')
with self.assertCall(
- self.call.adb.Shell('am start '
- '--start-profiler test_trace_file.out '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start '
+ '--start-profiler test_trace_file.out '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent,
trace_file_name='test_trace_file.out')
@@ -1418,10 +1501,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
package='test.package',
activity='.Main')
with self.assertCall(
- self.call.adb.Shell('am start '
- '-S '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start '
+ '-S '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent, force_stop=True)
@@ -1434,10 +1519,12 @@ class DeviceUtilsStartActivityTest(DeviceUtilsTest):
intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
])
with self.assertCall(
- self.call.adb.Shell('am start '
- '-a android.intent.action.VIEW '
- '-n test.package/.Main '
- '-f 0x10200000'),
+ self.call.adb.Shell(
+ 'am start '
+ '-a android.intent.action.VIEW '
+ '-n test.package/.Main '
+ '-f 0x10200000',
+ ensure_logs_on_timeout=False),
'Starting: Intent { act=android.intent.action.VIEW }'):
self.device.StartActivity(test_intent)
@@ -1450,9 +1537,11 @@ class DeviceUtilsStartServiceTest(DeviceUtilsTest):
with self.patch_call(self.call.device.build_version_sdk,
return_value=version_codes.NOUGAT):
with self.assertCall(
- self.call.adb.Shell('am startservice '
- '-a android.intent.action.START '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am startservice '
+ '-a android.intent.action.START '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting service: Intent { act=android.intent.action.START }'):
self.device.StartService(test_intent)
@@ -1463,9 +1552,11 @@ class DeviceUtilsStartServiceTest(DeviceUtilsTest):
with self.patch_call(self.call.device.build_version_sdk,
return_value=version_codes.NOUGAT):
with self.assertCall(
- self.call.adb.Shell('am startservice '
- '-a android.intent.action.START '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am startservice '
+ '-a android.intent.action.START '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Error: Failed to start test service'):
with self.assertRaises(device_errors.CommandFailedError):
self.device.StartService(test_intent)
@@ -1477,10 +1568,12 @@ class DeviceUtilsStartServiceTest(DeviceUtilsTest):
with self.patch_call(self.call.device.build_version_sdk,
return_value=version_codes.NOUGAT):
with self.assertCall(
- self.call.adb.Shell('am startservice '
- '--user TestUser '
- '-a android.intent.action.START '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am startservice '
+ '--user TestUser '
+ '-a android.intent.action.START '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting service: Intent { act=android.intent.action.START }'):
self.device.StartService(test_intent, user_id='TestUser')
@@ -1491,9 +1584,11 @@ class DeviceUtilsStartServiceTest(DeviceUtilsTest):
with self.patch_call(self.call.device.build_version_sdk,
return_value=version_codes.OREO):
with self.assertCall(
- self.call.adb.Shell('am start-service '
- '-a android.intent.action.START '
- '-n test.package/.Main'),
+ self.call.adb.Shell(
+ 'am start-service '
+ '-a android.intent.action.START '
+ '-n test.package/.Main',
+ ensure_logs_on_timeout=False),
'Starting service: Intent { act=android.intent.action.START }'):
self.device.StartService(test_intent)
@@ -1546,7 +1641,9 @@ class DeviceUtilsBroadcastIntentTest(DeviceUtilsTest):
def testBroadcastIntent_noExtras(self):
test_intent = intent.Intent(action='test.package.with.an.INTENT')
with self.assertCall(
- self.call.adb.Shell('am broadcast -a test.package.with.an.INTENT'),
+ self.call.adb.Shell(
+ 'am broadcast -a test.package.with.an.INTENT',
+ ensure_logs_on_timeout=False),
'Broadcasting: Intent { act=test.package.with.an.INTENT } '):
self.device.BroadcastIntent(test_intent)
@@ -1555,7 +1652,8 @@ class DeviceUtilsBroadcastIntentTest(DeviceUtilsTest):
extras={'foo': 'bar value'})
with self.assertCall(
self.call.adb.Shell(
- "am broadcast -a test.package.with.an.INTENT --es foo 'bar value'"),
+ "am broadcast -a test.package.with.an.INTENT --es foo 'bar value'",
+ ensure_logs_on_timeout=False),
'Broadcasting: Intent { act=test.package.with.an.INTENT } '):
self.device.BroadcastIntent(test_intent)
@@ -1564,7 +1662,8 @@ class DeviceUtilsBroadcastIntentTest(DeviceUtilsTest):
extras={'foo': None})
with self.assertCall(
self.call.adb.Shell(
- 'am broadcast -a test.package.with.an.INTENT --esn foo'),
+ 'am broadcast -a test.package.with.an.INTENT --esn foo',
+ ensure_logs_on_timeout=False),
'Broadcasting: Intent { act=test.package.with.an.INTENT } '):
self.device.BroadcastIntent(test_intent)
@@ -1728,7 +1827,8 @@ class DeviceUtilsClearApplicationStateTest(DeviceUtilsTest):
class DeviceUtilsSendKeyEventTest(DeviceUtilsTest):
def testSendKeyEvent(self):
- with self.assertCall(self.call.adb.Shell('input keyevent 66'), ''):
+ with self.assertCall(self.call.adb.Shell(
+ 'input keyevent 66', ensure_logs_on_timeout=False), ''):
self.device.SendKeyEvent(66)
@@ -2067,12 +2167,14 @@ class DeviceUtilsWriteFileTest(DeviceUtilsTest):
def testWriteFile_withEcho(self):
with self.assertCall(self.call.adb.Shell(
- "echo -n the.contents > /test/file/to.write"), ''):
+ "echo -n the.contents > /test/file/to.write",
+ ensure_logs_on_timeout=False), ''):
self.device.WriteFile('/test/file/to.write', 'the.contents')
def testWriteFile_withEchoAndQuotes(self):
with self.assertCall(self.call.adb.Shell(
- "echo -n 'the contents' > '/test/file/to write'"), ''):
+ "echo -n 'the contents' > '/test/file/to write'",
+ ensure_logs_on_timeout=False), ''):
self.device.WriteFile('/test/file/to write', 'the contents')
def testWriteFile_withEchoAndSU(self):
@@ -2081,7 +2183,8 @@ class DeviceUtilsWriteFileTest(DeviceUtilsTest):
with self.assertCalls(
(self.call.device.NeedsSU(), True),
(self.call.device._Su(expected_cmd_without_su), expected_cmd),
- (self.call.adb.Shell(expected_cmd),
+ (self.call.adb.Shell(
+ expected_cmd, ensure_logs_on_timeout=False),
'')):
self.device.WriteFile('/test/file', 'contents', as_root=True)
@@ -2562,51 +2665,60 @@ class DeviceUtilsListProcessesTest(DeviceUtilsTest):
class DeviceUtilsGetSetEnforce(DeviceUtilsTest):
def testGetEnforce_Enforcing(self):
- with self.assertCall(self.call.adb.Shell('getenforce'), 'Enforcing'):
+ with self.assertCall(self.call.adb.Shell(
+ 'getenforce', ensure_logs_on_timeout=False), 'Enforcing'):
self.assertEqual(True, self.device.GetEnforce())
def testGetEnforce_Permissive(self):
- with self.assertCall(self.call.adb.Shell('getenforce'), 'Permissive'):
+ with self.assertCall(self.call.adb.Shell(
+ 'getenforce', ensure_logs_on_timeout=False), 'Permissive'):
self.assertEqual(False, self.device.GetEnforce())
def testGetEnforce_Disabled(self):
- with self.assertCall(self.call.adb.Shell('getenforce'), 'Disabled'):
+ with self.assertCall(self.call.adb.Shell(
+ 'getenforce', ensure_logs_on_timeout=False), 'Disabled'):
self.assertEqual(None, self.device.GetEnforce())
def testSetEnforce_Enforcing(self):
with self.assertCalls(
(self.call.device.NeedsSU(), False),
- (self.call.adb.Shell('setenforce 1'), '')):
+ (self.call.adb.Shell(
+ 'setenforce 1', ensure_logs_on_timeout=False), '')):
self.device.SetEnforce(enabled=True)
def testSetEnforce_Permissive(self):
with self.assertCalls(
(self.call.device.NeedsSU(), False),
- (self.call.adb.Shell('setenforce 0'), '')):
+ (self.call.adb.Shell(
+ 'setenforce 0', ensure_logs_on_timeout=False), '')):
self.device.SetEnforce(enabled=False)
def testSetEnforce_EnforcingWithInt(self):
with self.assertCalls(
(self.call.device.NeedsSU(), False),
- (self.call.adb.Shell('setenforce 1'), '')):
+ (self.call.adb.Shell(
+ 'setenforce 1', ensure_logs_on_timeout=False), '')):
self.device.SetEnforce(enabled=1)
def testSetEnforce_PermissiveWithInt(self):
with self.assertCalls(
(self.call.device.NeedsSU(), False),
- (self.call.adb.Shell('setenforce 0'), '')):
+ (self.call.adb.Shell(
+ 'setenforce 0', ensure_logs_on_timeout=False), '')):
self.device.SetEnforce(enabled=0)
def testSetEnforce_EnforcingWithStr(self):
with self.assertCalls(
(self.call.device.NeedsSU(), False),
- (self.call.adb.Shell('setenforce 1'), '')):
+ (self.call.adb.Shell(
+ 'setenforce 1', ensure_logs_on_timeout=False), '')):
self.device.SetEnforce(enabled='1')
def testSetEnforce_PermissiveWithStr(self):
with self.assertCalls(
(self.call.device.NeedsSU(), False),
- (self.call.adb.Shell('setenforce 0'), '')):
+ (self.call.adb.Shell(
+ 'setenforce 0', ensure_logs_on_timeout=False), '')):
self.device.SetEnforce(enabled='0') # Not recommended but it works!
@@ -2614,12 +2726,14 @@ class DeviceUtilsSetWebViewImplementationTest(DeviceUtilsTest):
def testSetWebViewImplementation_success(self):
with self.assertCall(self.call.adb.Shell(
- 'cmd webviewupdate set-webview-implementation foo.org'), 'Success'):
+ 'cmd webviewupdate set-webview-implementation foo.org',
+ ensure_logs_on_timeout=False), 'Success'):
self.device.SetWebViewImplementation('foo.org')
def testSetWebViewImplementation_failure(self):
with self.assertCall(self.call.adb.Shell(
- 'cmd webviewupdate set-webview-implementation foo.org'), 'Oops!'):
+ 'cmd webviewupdate set-webview-implementation foo.org',
+ ensure_logs_on_timeout=False), 'Oops!'):
with self.assertRaises(device_errors.CommandFailedError):
self.device.SetWebViewImplementation('foo.org')
@@ -2631,7 +2745,9 @@ class DeviceUtilsTakeScreenshotTest(DeviceUtilsTest):
(mock.call.devil.android.device_temp_file.DeviceTempFile(
self.adb, suffix='.png'),
MockTempFile('/tmp/path/temp-123.png')),
- (self.call.adb.Shell('/system/bin/screencap -p /tmp/path/temp-123.png'),
+ (self.call.adb.Shell(
+ '/system/bin/screencap -p /tmp/path/temp-123.png',
+ ensure_logs_on_timeout=False),
''),
self.call.device.PullFile('/tmp/path/temp-123.png',
'/test/host/screenshot.png')):
@@ -2775,7 +2891,7 @@ class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase):
(mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
[_AdbWrapperMock(s) for s in test_serials])):
with self.assertRaises(device_errors.NoDevicesError):
- device_utils.DeviceUtils.HealthyDevices(device_arg=None, retry=False)
+ device_utils.DeviceUtils.HealthyDevices(device_arg=None, retries=0)
def testHealthyDevices_noneDeviceArg_multiple_attached_ANDROID_SERIAL(self):
try:
@@ -2818,17 +2934,23 @@ class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase):
(mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
[_AdbWrapperMock(s) for s in test_serials])):
with self.assertRaises(device_errors.NoDevicesError):
- device_utils.DeviceUtils.HealthyDevices(device_arg=[], retry=False)
-
- def testHealthyDevices_EmptyListDeviceArg_no_attached_with_retry(self):
- test_serials = []
- with self.assertCalls(
- (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
- [_AdbWrapperMock(s) for s in test_serials]),
- (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(),
- [_AdbWrapperMock(s) for s in test_serials])):
+ device_utils.DeviceUtils.HealthyDevices(device_arg=[], retries=0)
+
+ @mock.patch('time.sleep')
+ @mock.patch('devil.android.device_utils.RestartServer')
+ def testHealthyDevices_EmptyListDeviceArg_no_attached_with_retry(
+ self, mock_restart, mock_sleep):
+ with self.assertCalls(
+ (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []),
+ (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []),
+ (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []),
+ (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), []),
+ (mock.call.devil.android.sdk.adb_wrapper.AdbWrapper.Devices(), [])):
with self.assertRaises(device_errors.NoDevicesError):
- device_utils.DeviceUtils.HealthyDevices(device_arg=[], retry=True)
+ device_utils.DeviceUtils.HealthyDevices(device_arg=[], retries=4)
+ self.assertEquals(mock_restart.call_count, 4)
+ self.assertEquals(mock_sleep.call_args_list, [
+ mock.call(2), mock.call(4), mock.call(8), mock.call(16)])
def testHealthyDevices_ListDeviceArg(self):
device_arg = ['0123456789abcdef', 'fedcba9876543210']
@@ -2850,7 +2972,7 @@ class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase):
(mock.call.devil.android.device_utils.DeviceUtils.GetABI(),
ARM32_ABI)):
with self.assertRaises(device_errors.NoDevicesError):
- device_utils.DeviceUtils.HealthyDevices(device_arg=[], retry=False,
+ device_utils.DeviceUtils.HealthyDevices(device_arg=[], retries=0,
abis=[ARM64_ABI])
def testHealthyDevices_abisArg_filter_on_abi(self):
@@ -2863,7 +2985,7 @@ class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase):
(mock.call.devil.android.device_utils.DeviceUtils.GetABI(),
ARM32_ABI)):
devices = device_utils.DeviceUtils.HealthyDevices(device_arg=[],
- retry=False,
+ retries=0,
abis=[ARM64_ABI])
self.assertEquals(1, len(devices))
@@ -3078,7 +3200,9 @@ class DeviceUtilsGetIMEITest(DeviceUtilsTest):
' Device ID = 123454321')
with self.assertCalls(
(self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'),
- (self.call.adb.Shell('dumpsys iphonesubinfo'), dumpsys_output)):
+ (self.call.adb.Shell(
+ 'dumpsys iphonesubinfo', ensure_logs_on_timeout=False),
+ dumpsys_output)):
self.assertEquals(self.device.GetIMEI(), '123454321')
def testSuccessfulServiceCall(self):
@@ -3090,20 +3214,25 @@ class DeviceUtilsGetIMEITest(DeviceUtilsTest):
"""
with self.assertCalls(
(self.call.device.GetProp('ro.build.version.sdk', cache=True), '24'),
- (self.call.adb.Shell('service call iphonesubinfo 1'), service_output)):
+ (self.call.adb.Shell(
+ 'service call iphonesubinfo 1', ensure_logs_on_timeout=False),
+ service_output)):
self.assertEquals(self.device.GetIMEI(), '765432101234567')
def testNoIMEI(self):
with self.assertCalls(
(self.call.device.GetProp('ro.build.version.sdk', cache=True), '19'),
- (self.call.adb.Shell('dumpsys iphonesubinfo'), 'no device id')):
+ (self.call.adb.Shell(
+ 'dumpsys iphonesubinfo', ensure_logs_on_timeout=False),
+ 'no device id')):
with self.assertRaises(device_errors.CommandFailedError):
self.device.GetIMEI()
def testAdbError(self):
with self.assertCalls(
(self.call.device.GetProp('ro.build.version.sdk', cache=True), '24'),
- (self.call.adb.Shell('service call iphonesubinfo 1'),
+ (self.call.adb.Shell(
+ 'service call iphonesubinfo 1', ensure_logs_on_timeout=False),
self.ShellError())):
with self.assertRaises(device_errors.CommandFailedError):
self.device.GetIMEI()
diff --git a/catapult/devil/devil/android/flag_changer.py b/catapult/devil/devil/android/flag_changer.py
index 9cb1c02e..c96dbadc 100644
--- a/catapult/devil/devil/android/flag_changer.py
+++ b/catapult/devil/devil/android/flag_changer.py
@@ -93,7 +93,8 @@ class FlagChanger(object):
A list of flags.
"""
if self._device.PathExists(self._cmdline_path):
- command_line = self._device.ReadFile(self._cmdline_path).strip()
+ command_line = self._device.ReadFile(
+ self._cmdline_path, as_root=True).strip()
else:
command_line = ''
flags = _ParseFlags(command_line)
@@ -216,9 +217,9 @@ class FlagChanger(object):
"""
command_line = _SerializeFlags(self._state_stack[-1])
if command_line is not None:
- self._device.WriteFile(self._cmdline_path, command_line)
+ self._device.WriteFile(self._cmdline_path, command_line, as_root=True)
else:
- self._device.RemovePath(self._cmdline_path, force=True)
+ self._device.RemovePath(self._cmdline_path, force=True, as_root=True)
current_flags = self.GetCurrentFlags()
logger.info('Flags now set on the device: %s', current_flags)
diff --git a/catapult/devil/devil/android/perf/perf_control.py b/catapult/devil/devil/android/perf/perf_control.py
index 9ac85ebc..2aa3b2f2 100644
--- a/catapult/devil/devil/android/perf/perf_control.py
+++ b/catapult/devil/devil/android/perf/perf_control.py
@@ -9,6 +9,84 @@ import re
from devil.android import device_errors
logger = logging.getLogger(__name__)
+_atexit_messages = set()
+
+
+# Defines how to switch between the default performance configuration
+# ('default_mode') and the mode for use when benchmarking ('high_perf_mode').
+# For devices not in the list the defaults are to set up the scaling governor to
+# 'performance' and reset it back to 'ondemand' when benchmarking is finished.
+#
+# The 'default_mode_governor' is mandatory to define, while
+# 'high_perf_mode_governor' is not taken into account. The latter is because the
+# governor 'performance' is currently used for all benchmarking on all devices.
+#
+# TODO(crbug.com/383566): Add definitions for all devices used in the perf
+# waterfall.
+_PERFORMANCE_MODE_DEFINITIONS = {
+ # Fire TV Edition - 4K
+ 'AFTKMST12': {
+ 'default_mode_governor': 'interactive',
+ },
+ 'GT-I9300': {
+ 'default_mode_governor': 'pegasusq',
+ },
+ 'Galaxy Nexus': {
+ 'default_mode_governor': 'interactive',
+ },
+ 'Nexus 7': {
+ 'default_mode_governor': 'interactive',
+ },
+ 'Nexus 10': {
+ 'default_mode_governor': 'interactive',
+ },
+ 'Nexus 4': {
+ 'high_perf_mode': {
+ 'bring_cpu_cores_online': True,
+ },
+ 'default_mode_governor': 'ondemand',
+ },
+ 'Nexus 5': {
+ # The list of possible GPU frequency values can be found in:
+ # /sys/class/kgsl/kgsl-3d0/gpu_available_frequencies.
+ # For CPU cores the possible frequency values are at:
+ # /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
+ 'high_perf_mode': {
+ 'bring_cpu_cores_online': True,
+ 'cpu_max_freq': 1190400,
+ 'gpu_max_freq': 200000000,
+ },
+ 'default_mode': {
+ 'cpu_max_freq': 2265600,
+ 'gpu_max_freq': 450000000,
+ },
+ 'default_mode_governor': 'ondemand',
+ },
+ 'Nexus 5X': {
+ 'high_perf_mode': {
+ 'bring_cpu_cores_online': True,
+ 'cpu_max_freq': 1248000,
+ 'gpu_max_freq': 300000000,
+ },
+ 'default_mode': {
+ 'governor': 'ondemand',
+ # The SoC is ARM big.LITTLE. The cores 4..5 are big, the 0..3 are LITTLE.
+ 'cpu_max_freq': {'0..3': 1440000, '4..5': 1824000},
+ 'gpu_max_freq': 600000000,
+ },
+ 'default_mode_governor': 'ondemand',
+ },
+}
+
+
+def _NoisyWarning(message):
+ message += ' Results may be NOISY!!'
+ logger.warning(message)
+ # Add an additional warning at exit, such that it's clear that any results
+ # may be different/noisy (due to the lack of intended performance mode).
+ if message not in _atexit_messages:
+ _atexit_messages.add(message)
+ atexit.register(logger.warning, message)
class PerfControl(object):
@@ -21,10 +99,10 @@ class PerfControl(object):
def __init__(self, device):
self._device = device
- self._cpu_files = [
- filename
- for filename in self._device.ListDirectory(self._CPU_PATH, as_root=True)
- if self._CPU_FILE_PATTERN.match(filename)]
+ self._cpu_files = []
+ for file_name in self._device.ListDirectory(self._CPU_PATH, as_root=True):
+ if self._CPU_FILE_PATTERN.match(file_name):
+ self._cpu_files.append(file_name)
assert self._cpu_files, 'Failed to detect CPUs.'
self._cpu_file_list = ' '.join(self._cpu_files)
logger.info('CPUs found: %s', self._cpu_file_list)
@@ -36,34 +114,75 @@ class PerfControl(object):
(cpu, raw_governors.strip().split() if not exit_code else None)
for cpu, raw_governors, exit_code in raw]
+ def _SetMaxFrequenciesFromMode(self, mode):
+ """Set maximum frequencies for GPU and CPU cores.
+
+ Args:
+ mode: A dictionary mapping optional keys 'cpu_max_freq' and 'gpu_max_freq'
+ to integer values of frequency supported by the device.
+ """
+ cpu_max_freq = mode.get('cpu_max_freq')
+ if cpu_max_freq:
+ if not isinstance(cpu_max_freq, dict):
+ self._SetScalingMaxFreqForCpus(cpu_max_freq, self._cpu_file_list)
+ else:
+ for key, max_frequency in cpu_max_freq.iteritems():
+ # Convert 'X' to 'cpuX' and 'X..Y' to 'cpuX cpu<X+1> .. cpuY'.
+ if '..' in key:
+ range_min, range_max = key.split('..')
+ range_min, range_max = int(range_min), int(range_max)
+ else:
+ range_min = range_max = int(key)
+ cpu_files = ['cpu%d' % number
+ for number in xrange(range_min, range_max + 1)]
+ # Set the |max_frequency| on requested subset of the cores.
+ self._SetScalingMaxFreqForCpus(max_frequency, ' '.join(cpu_files))
+ gpu_max_freq = mode.get('gpu_max_freq')
+ if gpu_max_freq:
+ self._SetMaxGpuClock(gpu_max_freq)
+
def SetHighPerfMode(self):
"""Sets the highest stable performance mode for the device."""
try:
self._device.EnableRoot()
except device_errors.CommandFailedError:
- message = 'Need root for performance mode. Results may be NOISY!!'
- logger.warning(message)
- # Add an additional warning at exit, such that it's clear that any results
- # may be different/noisy (due to the lack of intended performance mode).
- atexit.register(logger.warning, message)
+ _NoisyWarning('Need root for performance mode.')
return
-
- product_model = self._device.product_model
- # TODO(epenner): Enable on all devices (http://crbug.com/383566)
- if product_model == 'Nexus 4':
- self._ForceAllCpusOnline(True)
- if not self._AllCpusAreOnline():
- logger.warning('Failed to force CPUs online. Results may be NOISY!')
+ mode_definitions = _PERFORMANCE_MODE_DEFINITIONS.get(
+ self._device.product_model)
+ if not mode_definitions:
+ self.SetScalingGovernor('performance')
+ return
+ high_perf_mode = mode_definitions.get('high_perf_mode')
+ if not high_perf_mode:
self.SetScalingGovernor('performance')
- elif product_model == 'Nexus 5':
+ return
+ if high_perf_mode.get('bring_cpu_cores_online', False):
self._ForceAllCpusOnline(True)
if not self._AllCpusAreOnline():
- logger.warning('Failed to force CPUs online. Results may be NOISY!')
- self.SetScalingGovernor('performance')
- self._SetScalingMaxFreq(1190400)
- self._SetMaxGpuClock(200000000)
+ _NoisyWarning('Failed to force CPUs online.')
+ # Scaling governor must be set _after_ bringing all CPU cores online,
+ # otherwise it would not affect the cores that are currently offline.
+ self.SetScalingGovernor('performance')
+ self._SetMaxFrequenciesFromMode(high_perf_mode)
+
+ def SetDefaultPerfMode(self):
+ """Sets the performance mode for the device to its default mode."""
+ if not self._device.HasRoot():
+ return
+ mode_definitions = _PERFORMANCE_MODE_DEFINITIONS.get(
+ self._device.product_model)
+ if not mode_definitions:
+ self.SetScalingGovernor('ondemand')
else:
- self.SetScalingGovernor('performance')
+ default_mode_governor = mode_definitions.get('default_mode_governor')
+ assert default_mode_governor, ('Default mode governor must be provided '
+ 'for all perf mode definitions.')
+ self.SetScalingGovernor(default_mode_governor)
+ default_mode = mode_definitions.get('default_mode')
+ if default_mode:
+ self._SetMaxFrequenciesFromMode(default_mode)
+ self._ForceAllCpusOnline(False)
def SetPerfProfilingMode(self):
"""Enables all cores for reliable perf profiling."""
@@ -74,27 +193,6 @@ class PerfControl(object):
raise RuntimeError('Need root to force CPUs online.')
raise RuntimeError('Failed to force CPUs online.')
- def SetDefaultPerfMode(self):
- """Sets the performance mode for the device to its default mode."""
- if not self._device.HasRoot():
- return
- product_model = self._device.product_model
- if product_model == 'Nexus 5':
- if self._AllCpusAreOnline():
- self._SetScalingMaxFreq(2265600)
- self._SetMaxGpuClock(450000000)
-
- governor_mode = {
- 'GT-I9300': 'pegasusq',
- 'Galaxy Nexus': 'interactive',
- 'Nexus 4': 'ondemand',
- 'Nexus 5': 'ondemand',
- 'Nexus 7': 'interactive',
- 'Nexus 10': 'interactive'
- }.get(product_model, 'ondemand')
- self.SetScalingGovernor(governor_mode)
- self._ForceAllCpusOnline(False)
-
def GetCpuInfo(self):
online = (output.rstrip() == '1' and status == 0
for (_, output, status) in self._ForEachCpu('cat "$CPU/online"'))
@@ -103,9 +201,24 @@ class PerfControl(object):
in self._ForEachCpu('cat "$CPU/cpufreq/scaling_governor"'))
return zip(self._cpu_files, online, governor)
- def _ForEachCpu(self, cmd):
+ def _ForEachCpu(self, cmd, cpu_list=None):
+ """Runs a command on the device for each of the CPUs.
+
+ Args:
+ cmd: A string with a shell command, may may use shell expansion: "$CPU" to
+ refer to the current CPU in the string form (e.g. "cpu0", "cpu1",
+ and so on).
+ cpu_list: A space-separated string of CPU core names, like in the example
+ above
+ Returns:
+ A list of tuples in the form (cpu_string, command_output, exit_code), one
+ tuple per each command invocation. As usual, all lines of the output
+ command are joined into one line with spaces.
+ """
+ if cpu_list is None:
+ cpu_list = self._cpu_file_list
script = '; '.join([
- 'for CPU in %s' % self._cpu_file_list,
+ 'for CPU in %s' % cpu_list,
'do %s' % cmd,
'echo -n "%~%$?%~%"',
'done'
@@ -115,20 +228,20 @@ class PerfControl(object):
output = '\n'.join(output).split('%~%')
return zip(self._cpu_files, output[0::2], (int(c) for c in output[1::2]))
- def _WriteEachCpuFile(self, path, value):
- self._ConditionallyWriteEachCpuFile(path, value, condition='true')
-
- def _ConditionallyWriteEachCpuFile(self, path, value, condition):
+ def _ConditionallyWriteCpuFiles(self, path, value, cpu_files, condition):
template = (
'{condition} && test -e "$CPU/{path}" && echo {value} > "$CPU/{path}"')
results = self._ForEachCpu(
- template.format(path=path, value=value, condition=condition))
+ template.format(path=path, value=value, condition=condition), cpu_files)
cpus = ' '.join(cpu for (cpu, _, status) in results if status == 0)
if cpus:
logger.info('Successfully set %s to %r on: %s', path, value, cpus)
else:
logger.warning('Failed to set %s to %r on any cpus', path, value)
+ def _WriteCpuFiles(self, path, value, cpu_files):
+ self._ConditionallyWriteCpuFiles(path, value, cpu_files, condition='true')
+
def _ReadEachCpuFile(self, path):
return self._ForEachCpu(
'cat "$CPU/{path}"'.format(path=path))
@@ -145,8 +258,8 @@ class PerfControl(object):
condition = 'test -e "{path}" && grep -q {value} {path}'.format(
path=('${CPU}/%s' % self._AVAILABLE_GOVERNORS_REL_PATH),
value=value)
- self._ConditionallyWriteEachCpuFile(
- 'cpufreq/scaling_governor', value, condition)
+ self._ConditionallyWriteCpuFiles(
+ 'cpufreq/scaling_governor', value, self._cpu_file_list, condition)
def GetScalingGovernor(self):
"""Gets the currently set governor for each CPU.
@@ -169,8 +282,8 @@ class PerfControl(object):
"""
return self._available_governors
- def _SetScalingMaxFreq(self, value):
- self._WriteEachCpuFile('cpufreq/scaling_max_freq', '%d' % value)
+ def _SetScalingMaxFreqForCpus(self, value, cpu_files):
+ self._WriteCpuFiles('cpufreq/scaling_max_freq', '%d' % value, cpu_files)
def _SetMaxGpuClock(self, value):
self._device.WriteFile('/sys/class/kgsl/kgsl-3d0/max_gpuclk',
@@ -179,8 +292,9 @@ class PerfControl(object):
def _AllCpusAreOnline(self):
results = self._ForEachCpu('cat "$CPU/online"')
- # TODO(epenner): Investigate why file may be missing
- # (http://crbug.com/397118)
+ # The file 'cpu0/online' is missing on some devices (example: Nexus 9). This
+ # is likely because on these devices it is impossible to bring the cpu0
+ # offline. Assuming the same for all devices until proven otherwise.
return all(output.rstrip() == '1' and status == 0
for (cpu, output, status) in results
if cpu != 'cpu0')
diff --git a/catapult/devil/devil/android/perf/perf_control_test.py b/catapult/devil/devil/android/perf/perf_control_test.py
new file mode 100644
index 00000000..3832424c
--- /dev/null
+++ b/catapult/devil/devil/android/perf/perf_control_test.py
@@ -0,0 +1,105 @@
+# Copyright 2018 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 unittest
+
+from devil import devil_env
+from devil.android import device_utils
+from devil.android.perf import perf_control
+from devil.android.sdk import adb_wrapper
+
+with devil_env.SysPath(devil_env.PYMOCK_PATH):
+ import mock
+
+
+# pylint: disable=unused-argument
+def _ShellCommandHandler(cmd, shell=False, check_return=False,
+ cwd=None, env=None, run_as=None, as_root=False, single_line=False,
+ large_output=False, raw_output=False, timeout=None, retries=None):
+ if cmd.startswith('for CPU in '):
+ if 'scaling_available_governors' in cmd:
+ contents = 'interactive ondemand userspace powersave performance'
+ return [contents + '\n%~%0%~%'] * 4
+ if 'cat "$CPU/online"' in cmd:
+ return ['1\n%~%0%~%'] * 4
+ assert False, 'Should not be called with cmd: {}'.format(cmd)
+
+
+class PerfControlTest(unittest.TestCase):
+ @staticmethod
+ def _MockOutLowLevelPerfControlMethods(perf_control_object):
+ # pylint: disable=protected-access
+ perf_control_object.SetScalingGovernor = mock.Mock()
+ perf_control_object._ForceAllCpusOnline = mock.Mock()
+ perf_control_object._SetScalingMaxFreqForCpus = mock.Mock()
+ perf_control_object._SetMaxGpuClock = mock.Mock()
+
+ # pylint: disable=no-self-use
+ def testNexus5HighPerfMode(self):
+ # Mock out the device state for PerfControl.
+ cpu_list = ['cpu%d' % cpu for cpu in xrange(4)]
+ mock_device = mock.Mock(spec=device_utils.DeviceUtils)
+ mock_device.product_model = 'Nexus 5'
+ mock_device.adb = mock.Mock(spec=adb_wrapper.AdbWrapper)
+ mock_device.ListDirectory.return_value = cpu_list + ['cpufreq']
+ mock_device.FileExists.return_value = True
+ mock_device.RunShellCommand = mock.Mock(side_effect=_ShellCommandHandler)
+ pc = perf_control.PerfControl(mock_device)
+ self._MockOutLowLevelPerfControlMethods(pc)
+
+ # Verify.
+ # pylint: disable=protected-access
+ # pylint: disable=no-member
+ pc.SetHighPerfMode()
+ mock_device.EnableRoot.assert_called_once_with()
+ pc._ForceAllCpusOnline.assert_called_once_with(True)
+ pc.SetScalingGovernor.assert_called_once_with('performance')
+ pc._SetScalingMaxFreqForCpus.assert_called_once_with(
+ 1190400, ' '.join(cpu_list))
+ pc._SetMaxGpuClock.assert_called_once_with(200000000)
+
+ def testNexus5XHighPerfMode(self):
+ # Mock out the device state for PerfControl.
+ cpu_list = ['cpu%d' % cpu for cpu in xrange(6)]
+ mock_device = mock.Mock(spec=device_utils.DeviceUtils)
+ mock_device.product_model = 'Nexus 5X'
+ mock_device.adb = mock.Mock(spec=adb_wrapper.AdbWrapper)
+ mock_device.ListDirectory.return_value = cpu_list + ['cpufreq']
+ mock_device.FileExists.return_value = True
+ mock_device.RunShellCommand = mock.Mock(side_effect=_ShellCommandHandler)
+ pc = perf_control.PerfControl(mock_device)
+ self._MockOutLowLevelPerfControlMethods(pc)
+
+ # Verify.
+ # pylint: disable=protected-access
+ # pylint: disable=no-member
+ pc.SetHighPerfMode()
+ mock_device.EnableRoot.assert_called_once_with()
+ pc._ForceAllCpusOnline.assert_called_once_with(True)
+ pc.SetScalingGovernor.assert_called_once_with('performance')
+ pc._SetScalingMaxFreqForCpus.assert_called_once_with(
+ 1248000, ' '.join(cpu_list))
+ pc._SetMaxGpuClock.assert_called_once_with(300000000)
+
+ def testNexus5XDefaultPerfMode(self):
+ # Mock out the device state for PerfControl.
+ cpu_list = ['cpu%d' % cpu for cpu in xrange(6)]
+ mock_device = mock.Mock(spec=device_utils.DeviceUtils)
+ mock_device.product_model = 'Nexus 5X'
+ mock_device.adb = mock.Mock(spec=adb_wrapper.AdbWrapper)
+ mock_device.ListDirectory.return_value = cpu_list + ['cpufreq']
+ mock_device.FileExists.return_value = True
+ mock_device.RunShellCommand = mock.Mock(side_effect=_ShellCommandHandler)
+ pc = perf_control.PerfControl(mock_device)
+ self._MockOutLowLevelPerfControlMethods(pc)
+
+ # Verify.
+ # pylint: disable=protected-access
+ # pylint: disable=no-member
+ pc.SetDefaultPerfMode()
+ pc.SetScalingGovernor.assert_called_once_with('ondemand')
+ pc._SetScalingMaxFreqForCpus.assert_any_call(1440000, 'cpu0 cpu1 cpu2 cpu3')
+ pc._SetScalingMaxFreqForCpus.assert_any_call(1824000, 'cpu4 cpu5')
+ pc._SetMaxGpuClock.assert_called_once_with(600000000)
+ pc._ForceAllCpusOnline.assert_called_once_with(False)
diff --git a/catapult/devil/devil/android/perf/surface_stats_collector.py b/catapult/devil/devil/android/perf/surface_stats_collector.py
index eab493df..ea46a398 100644
--- a/catapult/devil/devil/android/perf/surface_stats_collector.py
+++ b/catapult/devil/devil/android/perf/surface_stats_collector.py
@@ -116,6 +116,14 @@ class SurfaceStatsCollector(object):
except StopIteration:
raise Exception('Unable to get surface flinger process id')
+ def _GetSurfaceViewWindowName(self):
+ results = self._device.RunShellCommand(
+ ['dumpsys', 'SurfaceFlinger', '--list'], check_return=True)
+ for window_name in results:
+ if window_name.startswith('SurfaceView'):
+ return window_name
+ return None
+
def _GetSurfaceFlingerFrameData(self):
"""Returns collected SurfaceFlinger frame timing data.
@@ -152,19 +160,21 @@ class SurfaceStatsCollector(object):
# (each time the number above changes, we have a "jank").
# If this happens a lot during an animation, the animation appears
# janky, even if it runs at 60 fps in average.
- #
- # We use the special "SurfaceView" window name because the statistics for
- # the activity's main window are not updated when the main web content is
- # composited into a SurfaceView.
- results = self._device.RunShellCommand(
- ['dumpsys', 'SurfaceFlinger', '--latency', 'SurfaceView'],
- check_return=True)
+ window_name = self._GetSurfaceViewWindowName()
+ command = ['dumpsys', 'SurfaceFlinger', '--latency']
+ # Even if we don't find the window name, run the command to get the refresh
+ # period.
+ if window_name:
+ command.append(window_name)
+ results = self._device.RunShellCommand(command, check_return=True)
if not len(results):
return (None, None)
timestamps = []
nanoseconds_per_millisecond = 1e6
refresh_period = long(results[0]) / nanoseconds_per_millisecond
+ if not window_name:
+ return (refresh_period, timestamps)
# If a fence associated with a frame is still pending when we query the
# latency data, SurfaceFlinger gives the frame a timestamp of INT64_MAX.
diff --git a/catapult/devil/devil/android/sdk/adb_wrapper.py b/catapult/devil/devil/android/sdk/adb_wrapper.py
index 099a0f8a..2fbe9638 100644
--- a/catapult/devil/devil/android/sdk/adb_wrapper.py
+++ b/catapult/devil/devil/android/sdk/adb_wrapper.py
@@ -19,6 +19,7 @@ import posixpath
import re
import subprocess
+from devil import base_error
from devil import devil_env
from devil.android import decorators
from devil.android import device_errors
@@ -96,7 +97,11 @@ def _GetVersion():
def _ShouldRetryAdbCmd(exc):
- return not isinstance(exc, device_errors.NoAdbError)
+ # Errors are potentially transient and should be retried, with the exception
+ # of NoAdbError. Exceptions [e.g. generated from SIGTERM handler] should be
+ # raised.
+ return (isinstance(exc, base_error.BaseError) and
+ not isinstance(exc, device_errors.NoAdbError))
DeviceStat = collections.namedtuple('DeviceStat',
@@ -257,13 +262,15 @@ class AdbWrapper(object):
@classmethod
@decorators.WithTimeoutAndConditionalRetries(_ShouldRetryAdbCmd)
def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None,
- check_error=True, cpu_affinity=None):
- # pylint: disable=no-member
+ check_error=True, cpu_affinity=None,
+ ensure_logs_on_timeout=False):
+ timeout = timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime()
+ if ensure_logs_on_timeout:
+ timeout = 0.95 * timeout
try:
status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
cls._BuildAdbCmd(args, device_serial, cpu_affinity=cpu_affinity),
- timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime(),
- env=cls._ADB_ENV)
+ timeout, env=cls._ADB_ENV)
except OSError as e:
if e.errno in (errno.ENOENT, errno.ENOEXEC):
raise device_errors.NoAdbError(msg=str(e))
@@ -287,7 +294,9 @@ class AdbWrapper(object):
return output
# pylint: enable=unused-argument
- def _RunDeviceAdbCmd(self, args, timeout, retries, check_error=True):
+ def _RunDeviceAdbCmd(
+ self, args, timeout, retries, check_error=True,
+ ensure_logs_on_timeout=False):
"""Runs an adb command on the device associated with this object.
Args:
@@ -302,7 +311,8 @@ class AdbWrapper(object):
"""
return self._RunAdbCmd(args, timeout=timeout, retries=retries,
device_serial=self._device_serial,
- check_error=check_error)
+ check_error=check_error,
+ ensure_logs_on_timeout=ensure_logs_on_timeout)
def _IterRunDeviceAdbCmd(self, args, iter_timeout, timeout):
"""Runs an adb command and returns an iterator over its output lines.
@@ -497,14 +507,17 @@ class AdbWrapper(object):
return cmd_helper.StartCmd(
self._BuildAdbCmd(['shell'] + cmd, self._device_serial))
- def Shell(self, command, expect_status=0, timeout=DEFAULT_TIMEOUT,
- retries=DEFAULT_RETRIES):
+ def Shell(self, command, expect_status=0, ensure_logs_on_timeout=False,
+ timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
"""Runs a shell command on the device.
Args:
command: A string with the shell command to run.
expect_status: (optional) Check that the command's exit status matches
this value. Default is 0. If set to None the test is skipped.
+ ensure_logs_on_timeout: If True, will use a timeout that is 5% smaller
+ than the remaining time on the thread watchdog for the internal adb
+ command, which allows to retrive logs on timeout.
timeout: (optional) Timeout per try in seconds.
retries: (optional) Number of retries to attempt.
@@ -519,7 +532,9 @@ class AdbWrapper(object):
args = ['shell', command]
else:
args = ['shell', '( %s );echo %%$?' % command.rstrip()]
- output = self._RunDeviceAdbCmd(args, timeout, retries, check_error=False)
+ output = self._RunDeviceAdbCmd(
+ args, timeout, retries, check_error=False,
+ ensure_logs_on_timeout=ensure_logs_on_timeout)
if expect_status is not None:
output_end = output.rfind('%')
if output_end < 0:
diff --git a/catapult/devil/devil/android/sdk/shared_prefs.py b/catapult/devil/devil/android/sdk/shared_prefs.py
index c985cacc..c8c82b4e 100644
--- a/catapult/devil/devil/android/sdk/shared_prefs.py
+++ b/catapult/devil/devil/android/sdk/shared_prefs.py
@@ -278,12 +278,17 @@ class SharedPrefs(object):
self._xml = None
self._changed = True
- def Commit(self):
+ def Commit(self, force_commit=False):
"""Save the current set of preferences to the device.
- Only actually saves if some preferences have been modified.
+ Only actually saves if some preferences have been modified or force_commit
+ is set to True.
+
+ Args:
+ force_commit: Commit even if no changes have been made to the SharedPrefs
+ instance.
"""
- if not self.changed:
+ if not (self.changed or force_commit):
return
self._device.RunShellCommand(
['mkdir', '-p', posixpath.dirname(self.path)],
diff --git a/catapult/devil/devil/android/sdk/shared_prefs_test.py b/catapult/devil/devil/android/sdk/shared_prefs_test.py
index 49587c89..08bbb467 100755
--- a/catapult/devil/devil/android/sdk/shared_prefs_test.py
+++ b/catapult/devil/devil/android/sdk/shared_prefs_test.py
@@ -19,6 +19,14 @@ with devil_env.SysPath(devil_env.PYMOCK_PATH):
import mock # pylint: disable=import-error
+INITIAL_XML = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ '<map>\n'
+ ' <int name="databaseVersion" value="107" />\n'
+ ' <boolean name="featureEnabled" value="false" />\n'
+ ' <string name="someHashValue">249b3e5af13d4db2</string>\n'
+ '</map>')
+
+
def MockDeviceWithFiles(files=None):
if files is None:
files = {}
@@ -43,13 +51,7 @@ class SharedPrefsTest(unittest.TestCase):
def setUp(self):
self.device = MockDeviceWithFiles({
- '/data/data/com.some.package/shared_prefs/prefs.xml':
- "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
- '<map>\n'
- ' <int name="databaseVersion" value="107" />\n'
- ' <boolean name="featureEnabled" value="false" />\n'
- ' <string name="someHashValue">249b3e5af13d4db2</string>\n'
- '</map>'})
+ '/data/data/com.some.package/shared_prefs/prefs.xml': INITIAL_XML})
self.expected_data = {'databaseVersion': 107,
'featureEnabled': False,
'someHashValue': '249b3e5af13d4db2'}
@@ -127,6 +129,22 @@ class SharedPrefsTest(unittest.TestCase):
'bigNumner': 6000000000,
'apps': ['gmail', 'chrome', 'music']}) # data survived roundtrip
+ def testForceCommit(self):
+ prefs = shared_prefs.SharedPrefs(
+ self.device, 'com.some.package', 'prefs.xml')
+ prefs.Load()
+ new_xml = 'Not valid XML'
+ self.device.WriteFile('/data/data/com.some.package/shared_prefs/prefs.xml',
+ new_xml)
+ prefs.Commit()
+ # Since we didn't change anything, Commit() should be a no-op.
+ self.assertEquals(self.device.ReadFile(
+ '/data/data/com.some.package/shared_prefs/prefs.xml'), new_xml)
+ prefs.Commit(force_commit=True)
+ # Forcing the commit should restore the originally read XML.
+ self.assertEquals(self.device.ReadFile(
+ '/data/data/com.some.package/shared_prefs/prefs.xml'), INITIAL_XML)
+
def testAsContextManager_onlyReads(self):
with shared_prefs.SharedPrefs(
self.device, 'com.some.package', 'prefs.xml') as prefs:
diff --git a/catapult/devil/devil/android/sdk/version_codes.py b/catapult/devil/devil/android/sdk/version_codes.py
index 1750f00d..29c7285e 100644
--- a/catapult/devil/devil/android/sdk/version_codes.py
+++ b/catapult/devil/devil/android/sdk/version_codes.py
@@ -19,3 +19,4 @@ NOUGAT = 24
NOUGAT_MR1 = 25
OREO = 26
OREO_MR1 = 27
+PIE = 28
diff --git a/catapult/devil/devil/android/tools/provision_devices.py b/catapult/devil/devil/android/tools/provision_devices.py
index 3a726e59..47b1dc3f 100755
--- a/catapult/devil/devil/android/tools/provision_devices.py
+++ b/catapult/devil/devil/android/tools/provision_devices.py
@@ -39,6 +39,7 @@ from devil.android import settings
from devil.android.sdk import adb_wrapper
from devil.android.sdk import intent
from devil.android.sdk import keyevent
+from devil.android.sdk import shared_prefs
from devil.android.sdk import version_codes
from devil.android.tools import script_common
from devil.constants import exit_codes
@@ -51,6 +52,9 @@ _SYSTEM_APP_DIRECTORIES = ['/system/app/', '/system/priv-app/']
_SYSTEM_WEBVIEW_NAMES = ['webview', 'WebViewGoogle']
_CHROME_PACKAGE_REGEX = re.compile('.*chrom.*')
_TOMBSTONE_REGEX = re.compile('tombstone.*')
+_STANDALONE_VR_DEVICES = [
+ 'vega', # Lenovo Mirage Solo
+]
class _DEFAULT_TIMEOUTS(object):
@@ -134,6 +138,7 @@ def ProvisionDevices(
steps.append(ProvisionStep(SetDate))
steps.append(ProvisionStep(CheckExternalStorage))
+ steps.append(ProvisionStep(StandaloneVrDeviceSetup))
parallel_devices.pMap(ProvisionDevice, steps, blacklist, reboot_timeout)
@@ -531,6 +536,30 @@ def CheckExternalStorage(device):
device.WriteFile(f.name, 'test')
+def StandaloneVrDeviceSetup(device):
+ """Performs any additional setup necessary for standalone Android VR devices.
+
+ Arguments:
+ device: The device to check.
+ """
+ if device.product_name not in _STANDALONE_VR_DEVICES:
+ return
+
+ # Modify VrCore's settings so that any first time setup, etc. is skipped.
+ shared_pref = shared_prefs.SharedPrefs(device, 'com.google.vr.vrcore',
+ 'VrCoreSettings.xml', use_encrypted_path=True)
+ shared_pref.Load()
+ # Skip first time setup.
+ shared_pref.SetBoolean('DaydreamSetupComplete', True)
+ # Disable the automatic prompt that shows anytime the device detects that a
+ # controller isn't connected.
+ shared_pref.SetBoolean('gConfigFlags:controller_recovery_enabled', False)
+ # Use an automated controller instead of a real one so we get past the
+ # controller pairing screen that's shown on startup.
+ shared_pref.SetBoolean('UseAutomatedController', True)
+ shared_pref.Commit()
+
+
def main(raw_args):
# Recommended options on perf bots:
# --disable-network
diff --git a/catapult/devil/devil/android/tools/system_app.py b/catapult/devil/devil/android/tools/system_app.py
index 00ea312a..4fe35e57 100755
--- a/catapult/devil/devil/android/tools/system_app.py
+++ b/catapult/devil/devil/android/tools/system_app.py
@@ -138,11 +138,11 @@ def _RelocateApp(device, package_name, relocate_to):
@contextlib.contextmanager
def _TemporarilyInstallApp(device, apk):
"""A context manager that installs an app while in scope."""
- device.adb.Install(apk, reinstall=True)
+ device.Install(apk, reinstall=True)
try:
yield
finally:
- device.adb.Uninstall(apk_helper.GetPackageName(apk))
+ device.Uninstall(apk_helper.GetPackageName(apk))
def _MoveApp(device, relocation_map):
diff --git a/catapult/devil/devil/android/tools/system_app_test.py b/catapult/devil/devil/android/tools/system_app_test.py
index f72aa166..1400d7eb 100644
--- a/catapult/devil/devil/android/tools/system_app_test.py
+++ b/catapult/devil/devil/android/tools/system_app_test.py
@@ -47,7 +47,7 @@ class SystemAppTest(unittest.TestCase):
mock_device.GetProp.side_effect = dict_getprop
with system_app.EnableSystemAppModification(mock_device):
- mock_device.EnableRoot.assert_called_once()
+ mock_device.EnableRoot.assert_called_once_with()
mock_device.GetProp.assert_called_once_with(
system_app._ENABLE_MODIFICATION_PROP)
mock_device.SetProp.assert_called_once_with(
@@ -55,10 +55,10 @@ class SystemAppTest(unittest.TestCase):
mock_device.reset_mock()
with system_app.EnableSystemAppModification(mock_device):
- mock_device.EnableRoot.assert_not_called()
+ self.assertFalse(mock_device.EnableRoot.mock_calls) # assert not called
mock_device.GetProp.assert_called_once_with(
system_app._ENABLE_MODIFICATION_PROP)
- mock_device.SetProp.assert_not_called()
+ self.assertFalse(mock_device.SetProp.mock_calls) # assert not called
mock_device.reset_mock()
mock_device.SetProp.assert_called_once_with(
diff --git a/catapult/devil/devil/android/tools/unlock_bootloader.py b/catapult/devil/devil/android/tools/unlock_bootloader.py
index 46fec9df..b38f6690 100644
--- a/catapult/devil/devil/android/tools/unlock_bootloader.py
+++ b/catapult/devil/devil/android/tools/unlock_bootloader.py
@@ -106,8 +106,10 @@ def unlock_bootloader(d):
logging.info('Device %s already unlocked.', d)
elif 'unlock is not allowed' in out:
logging.error("Device %s is oem locked. Can't unlock bootloader.", d)
+ return 1
else:
logging.error('Device %s in unknown state: "%s"', d, out)
+ return 1
break
if leftover_pids:
diff --git a/catapult/devil/devil/devil_dependencies.json b/catapult/devil/devil/devil_dependencies.json
index 6884a36b..8a7943e2 100644
--- a/catapult/devil/devil/devil_dependencies.json
+++ b/catapult/devil/devil/devil_dependencies.json
@@ -58,6 +58,10 @@
"android_armeabi-v7a": {
"cloud_storage_hash": "220ff3ba1a6c3c81877997e32784ffd008f293a5",
"download_path": "../bin/deps/android/armeabi-v7a/apks/EmptySystemWebView.apk"
+ },
+ "android_arm64-v8a": {
+ "cloud_storage_hash": "34e583c631a495afbba82ce8a1d4f9b5118a4411",
+ "download_path": "../bin/deps/android/arm64-v8a/apks/EmptySystemWebView.apk"
}
}
},
@@ -134,4 +138,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/catapult/devil/devil/utils/cmd_helper.py b/catapult/devil/devil/utils/cmd_helper.py
index 5ea85d85..b7b2f0dc 100644
--- a/catapult/devil/devil/utils/cmd_helper.py
+++ b/catapult/devil/devil/utils/cmd_helper.py
@@ -152,12 +152,12 @@ def _ValidateAndLogCommand(args, cwd, shell):
else:
if shell:
raise Exception('array args must be run with shell=False')
- args = ' '.join(SingleQuote(c) for c in args)
+ args = ' '.join(SingleQuote(str(c)) for c in args)
if cwd is None:
cwd = ''
else:
cwd = ':' + cwd
- logger.info('[host]%s> %s', cwd, args)
+ logger.debug('[host]%s> %s', cwd, args)
return args
diff --git a/catapult/devil/devil/utils/lazy/weak_constant_test.py b/catapult/devil/devil/utils/lazy/weak_constant_test.py
index 95191501..643351d8 100644
--- a/catapult/devil/devil/utils/lazy/weak_constant_test.py
+++ b/catapult/devil/devil/utils/lazy/weak_constant_test.py
@@ -38,7 +38,7 @@ class WeakConstantTest(unittest.TestCase):
self.assertEquals(
'initializer called',
test_constant.read())
- initializer.assert_called_once()
+ initializer.assert_called_once_with()
def testInitialized(self):
"""Ensure that reading doesn't reinitialize the value."""
@@ -49,7 +49,7 @@ class WeakConstantTest(unittest.TestCase):
self.assertEquals(
'initializer not called',
test_constant.read())
- initializer.assert_not_called()
+ self.assertFalse(initializer.mock_calls) # assert not called
def testFirstCallHangs(self):
"""Ensure that reading works even if the first initializer call hangs."""