summaryrefslogtreecommitdiffstats
path: root/build/android
diff options
context:
space:
mode:
authorilevy@chromium.org <ilevy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-17 05:42:33 +0000
committerilevy@chromium.org <ilevy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-17 05:42:33 +0000
commit9244722045363b75d0eba8db56e158ff7877cc65 (patch)
treef12de2ba56a25679e92efbbeaa73ff617b7de10e /build/android
parent8638cf07c244e8f0c691adf8dae0f24bb554a880 (diff)
downloadchromium_src-9244722045363b75d0eba8db56e158ff7877cc65.zip
chromium_src-9244722045363b75d0eba8db56e158ff7877cc65.tar.gz
chromium_src-9244722045363b75d0eba8db56e158ff7877cc65.tar.bz2
Organize adb install cmds and reboot on failure
- Rewrote adb_install_content_shell to not call adb install directly - New function in android_commands 'ManagedInstall' which attempts to work around package manager freezes by restarting device BUG=141899 Review URL: https://chromiumcodereview.appspot.com/10824227 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152058 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'build/android')
-rwxr-xr-xbuild/android/adb_install_content_shell41
-rw-r--r--build/android/pylib/android_commands.py92
-rw-r--r--build/android/pylib/test_package_apk.py9
3 files changed, 90 insertions, 52 deletions
diff --git a/build/android/adb_install_content_shell b/build/android/adb_install_content_shell
index 3667998..a7cc218 100755
--- a/build/android/adb_install_content_shell
+++ b/build/android/adb_install_content_shell
@@ -1,26 +1,33 @@
-#!/bin/bash
+#!/usr/bin/env python
#
# Copyright (c) 2012 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.
-CONTENT_SHELL_APK=${CHROME_SRC}/out/Release/content_shell/ContentShell-debug.apk
+from multiprocessing import Process
+import os
-if [ ! -f "${CONTENT_SHELL_APK}" ]; then
- echo "Error: Could not find ${CONTENT_SHELL_APK} to install."
- exit 1
-fi
+from pylib import android_commands
-DEVS=$(adb devices | grep device | grep -v devices | awk '{ print $1 }')
-if [[ -z $DEVS ]]; then
- echo "Error: No connected devices. Device needed to run content shell test."
- exit 1
-fi
+def InstallContentShell(device):
+ apk_path = os.path.join(os.environ['CHROME_SRC'],
+ 'out/Release/content_shell/ContentShell-debug.apk')
+ result = android_commands.AndroidCommands(device=device).ManagedInstall(
+ apk_path, False, 'org.chromium.content_shell')
+ print '----- Installed on %s -----' % device
+ print result
-for DEV in ${DEVS}; do
- # Reinstall content shell. This will also kill existing content_shell procs.
- echo "Installing ${CONTENT_SHELL_APK} in ${DEV}"
- adb -s ${DEV} uninstall org.chromium.content_shell
- adb -s ${DEV} install -r ${CONTENT_SHELL_APK}
-done
+
+devices = android_commands.GetAttachedDevices()
+if not devices:
+ raise Exception('Error: no connected devices')
+
+procs = []
+for device in devices:
+ p = Process(target=InstallContentShell, args=(device,))
+ p.start()
+ procs += [p]
+
+for p in procs:
+ p.join()
diff --git a/build/android/pylib/android_commands.py b/build/android/pylib/android_commands.py
index c0863e0..f030424 100644
--- a/build/android/pylib/android_commands.py
+++ b/build/android/pylib/android_commands.py
@@ -9,11 +9,8 @@ Assumes adb binary is currently on system path.
import collections
import datetime
-import io_stats_parser
import logging
-import optparse
import os
-import pexpect
import re
import shlex
import subprocess
@@ -21,10 +18,12 @@ import sys
import tempfile
import time
+import pexpect
+import io_stats_parser
# adb_interface.py is under ../../../third_party/android_testrunner/
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..',
- '..', '..', 'third_party', 'android_testrunner'))
+ '..', '..', 'third_party', 'android_testrunner'))
import adb_interface
import cmd_helper
import errors # is under ../../../third_party/android_testrunner/errors.py
@@ -51,7 +50,7 @@ JAVA_ASSERT_PROPERTY = 'dalvik.vm.enableassertions'
BOOT_COMPLETE_RE = re.compile(
'android.intent.action.MEDIA_MOUNTED path: /\w+/sdcard\d?'
- + '|' + 'PowerManagerService(\(\s+\d+\))?: bootCompleted')
+ '|PowerManagerService(\(\s+\d+\))?: bootCompleted')
MEMORY_INFO_RE = re.compile('^(?P<key>\w+):\s+(?P<usage_kb>\d+) kB$')
NVIDIA_MEMORY_INFO_RE = re.compile('^\s*(?P<user>\S+)\s*(?P<name>\S+)\s*'
@@ -107,7 +106,7 @@ def GetAttachedDevices():
"""
re_device = re.compile('^([a-zA-Z0-9_:.-]+)\tdevice$', re.MULTILINE)
devices = re_device.findall(cmd_helper.GetCmdOutput(['adb', 'devices']))
- preferred_device = os.environ.get("ANDROID_SERIAL")
+ preferred_device = os.environ.get('ANDROID_SERIAL')
if preferred_device in devices:
devices.remove(preferred_device)
devices.insert(0, preferred_device)
@@ -196,7 +195,7 @@ def _GetFilesFromRecursiveLsOutput(path, ls_output, re_file, utc_offset=None):
utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]),
minutes=int(utc_offset[3:5]))
if utc_offset[0:1] == '-':
- utc_delta = -utc_delta;
+ utc_delta = -utc_delta
lastmod -= utc_delta
files[filename] = (int(file_match.group('size')), lastmod)
return files
@@ -244,7 +243,7 @@ class AndroidCommands(object):
return self._root_enabled
def GetDeviceYear(self):
- """Returns the year information of the date on device"""
+ """Returns the year information of the date on device."""
return self.RunShellCommand('date +%Y')[0]
def WaitForDevicePm(self):
@@ -264,7 +263,7 @@ class AndroidCommands(object):
return # Success
except errors.WaitForResponseTimedOutError as e:
last_err = e
- logging.warning('Restarting and retrying after timeout: %s' % str(e))
+ logging.warning('Restarting and retrying after timeout: %s', e)
retries -= 1
self.RestartShell()
raise last_err # Only reached after max retries, re-raise the last error.
@@ -289,12 +288,14 @@ class AndroidCommands(object):
if os.environ.get('USING_HIVE'):
logging.warning('Ignoring reboot request as we are on hive')
return
- if full_reboot:
+ if full_reboot or not self.IsRootEnabled():
self._adb.SendCommand('reboot')
+ timeout = 300
else:
self.RestartShell()
+ timeout = 120
self.WaitForDevicePm()
- self.StartMonitoringLogcat(timeout=120)
+ self.StartMonitoringLogcat(timeout=timeout)
self.WaitForLogMatch(BOOT_COMPLETE_RE, None)
def Uninstall(self, package):
@@ -311,24 +312,59 @@ class AndroidCommands(object):
logging.info('>>> $' + uninstall_command)
return self._adb.SendCommand(uninstall_command, timeout_time=60)
- def Install(self, package_file_path):
+ def Install(self, package_file_path, reinstall=False):
"""Installs the specified package to the device.
Args:
package_file_path: Path to .apk file to install.
+ reinstall: Whether to reinstall over existing package
Returns:
A status string returned by adb install
"""
assert os.path.isfile(package_file_path)
- install_command = 'install %s' % package_file_path
+ if reinstall:
+ install_cmd = 'install -r %s'
+ else:
+ install_cmd = 'install %s'
+
+ return self._adb.SendCommand(install_cmd % package_file_path,
+ timeout_time=2*60, retry_count=0)
+
+ def ManagedInstall(self, apk_path, keep_data, package_name=None,
+ reboots_on_failure=2):
+ """Installs specified package and reboots device on timeouts.
+
+ Args:
+ apk_path: Path to .apk file to install.
+ keep_data: Whether to keep data if package already exists
+ package_name: Package name (only needed if keep_data=False)
+ reboots_on_failure: number of time to reboot if package manager is frozen.
+
+ Returns:
+ A status string returned by adb install
+ """
+ reboots_left = reboots_on_failure
+ while True:
+ try:
+ if not keep_data:
+ self.Uninstall(package_name)
+ install_status = self.Install(apk_path, keep_data)
+ if 'Success' in install_status:
+ return install_status
+ except errors.WaitForResponseTimedOutError:
+ logging.info('Timout on installing %s' % apk_path)
- logging.info('>>> $' + install_command)
- return self._adb.SendCommand(install_command, timeout_time=2*60)
+ if reboots_left <= 0:
+ raise Exception('Install failure')
+
+ # Force a hard reboot on last attempt
+ self.Reboot(full_reboot=(reboots_left == 1))
+ reboots_left -= 1
def MakeSystemFolderWritable(self):
- """Remounts the /system folder rw. """
+ """Remounts the /system folder rw."""
out = self._adb.SendCommand('remount')
if out.strip() != 'remount succeeded':
raise errors.MsgException('Remount failed: %s' % out)
@@ -391,7 +427,7 @@ class AndroidCommands(object):
wait_period = 5
while not sdcard_ready and attempts * wait_period < timeout_time:
output = self.RunShellCommand('ls /sdcard/')
- if len(output) > 0:
+ if output:
sdcard_ready = True
else:
time.sleep(wait_period)
@@ -420,8 +456,10 @@ class AndroidCommands(object):
"""
logging.info('>>> $' + command)
if "'" in command: logging.warning(command + " contains ' quotes")
- result = self._adb.SendShellCommand("'%s'" % command,
- timeout_time).splitlines()
+ result = self._adb.SendShellCommand(
+ "'%s'" % command, timeout_time).splitlines()
+ if ['error: device not found'] == result:
+ raise errors.DeviceUnresponsiveError('device not found')
if log_result:
logging.info('\n>>> '.join(result))
return result
@@ -483,7 +521,6 @@ class AndroidCommands(object):
cmd += ' --start-profiler ' + trace_file_name
self.RunShellCommand(cmd)
-
def CloseApplication(self, package):
"""Attempt to close down the application, using increasing violence.
@@ -532,7 +569,7 @@ class AndroidCommands(object):
else:
is_equal = local_contents == device_contents
if is_equal:
- logging.info('%s is up-to-date. Skipping file push.' % device_path)
+ logging.info('%s is up-to-date. Skipping file push.', device_path)
return
# They don't match, so remove everything first and then create it.
@@ -648,7 +685,7 @@ class AndroidCommands(object):
self.RunShellCommand('echo 3 > ' + DROP_CACHES)
def StartMonitoringLogcat(self, clear=True, timeout=10, logfile=None,
- filters=[]):
+ filters=None):
"""Starts monitoring the output of logcat, for use with WaitForLogMatch.
Args:
@@ -759,7 +796,7 @@ class AndroidCommands(object):
# Cannot evaluate directly as 0 is a possible value.
# Better to read the self.logcat_process.stdout before killing it,
# Otherwise the communicate may return incomplete output due to pipe break.
- if self.logcat_process.poll() == None:
+ if self.logcat_process.poll() is None:
self.logcat_process.kill()
(output, _) = self.logcat_process.communicate()
self.logcat_process = None
@@ -898,7 +935,7 @@ class AndroidCommands(object):
"""Returns the memory usage for all processes whose name contains |pacakge|.
Args:
- name: A string holding process name to lookup pid list for.
+ package: A string holding process name to lookup pid list for.
Returns:
A tuple containg:
@@ -922,8 +959,7 @@ class AndroidCommands(object):
return usage_dict, smaps
def ProcessesUsingDevicePort(self, device_port):
- """Lists the processes using the specified device port on loopback
- interface.
+ """Lists processes using the specified device port on loopback interface.
Args:
device_port: Port on device we want to check.
@@ -932,7 +968,7 @@ class AndroidCommands(object):
A list of (pid, process_name) tuples using the specified port.
"""
tcp_results = self.RunShellCommand('cat /proc/net/tcp', log_result=False)
- tcp_address = "0100007F:%04X" % device_port
+ tcp_address = '0100007F:%04X' % device_port
pids = []
for single_connect in tcp_results:
connect_results = single_connect.split()
@@ -951,7 +987,7 @@ class AndroidCommands(object):
# Column 1 is the pid
# Column 8 is the Inode in use
if process_results[8] == socket_name:
- pids.append( (int(process_results[1]), process_results[0]) )
+ pids.append((int(process_results[1]), process_results[0]))
break
logging.info('PidsUsingDevicePort: %s', pids)
return pids
diff --git a/build/android/pylib/test_package_apk.py b/build/android/pylib/test_package_apk.py
index de6fdb7..c276825 100644
--- a/build/android/pylib/test_package_apk.py
+++ b/build/android/pylib/test_package_apk.py
@@ -97,13 +97,8 @@ class TestPackageApk(TestPackage):
def StripAndCopyExecutable(self):
# Always uninstall the previous one (by activity name); we don't
# know what was embedded in it.
- logging.info('Uninstalling any activity with the test name')
- self.adb.Adb().SendCommand('uninstall org.chromium.native_test',
- timeout_time=60*5)
- logging.info('Installing new apk')
- self.adb.Adb().SendCommand('install -r ' + self.test_suite_full,
- timeout_time=60*5)
- logging.info('Install has completed.')
+ self.adb.ManagedInstall(self.test_suite_full, False,
+ package_name='org.chromium.native_test')
def _GetTestSuiteBaseName(self):
"""Returns the base name of the test suite."""