blob: f3bbd13de70dc5068b73c447dc99aa9963768a1e [file] [log] [blame]
Simran Basi431010f2013-09-04 10:42:41 -07001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07004
5import datetime
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07006import errno
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07007import functools
Simran Basi431010f2013-09-04 10:42:41 -07008import logging
Kevin Cheng018db352015-09-20 02:22:08 -07009import os
Simran Basi431010f2013-09-04 10:42:41 -070010import re
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070011import stat
Dan Shia2872172015-10-31 01:16:51 -070012import sys
Simran Basi431010f2013-09-04 10:42:41 -070013import time
14
15import common
16
Simran Basi9c5d3982016-04-01 18:49:44 -070017from autotest_lib.client.bin import utils as client_utils
Dan Shi49d451f2016-04-19 09:25:01 -070018from autotest_lib.client.common_lib import android_utils
Simran Basi431010f2013-09-04 10:42:41 -070019from autotest_lib.client.common_lib import error
Dan Shi6450e142016-03-11 11:52:20 -080020from autotest_lib.client.common_lib import global_config
Dan Shi225b9042015-11-18 10:25:21 -080021from autotest_lib.client.common_lib.cros import dev_server
Simran Basi431010f2013-09-04 10:42:41 -070022from autotest_lib.client.common_lib.cros import retry
Dan Shi6450e142016-03-11 11:52:20 -080023from autotest_lib.server import afe_utils
Dan Shi225b9042015-11-18 10:25:21 -080024from autotest_lib.server import autoserv_parser
Dan Shia2872172015-10-31 01:16:51 -070025from autotest_lib.server import constants as server_constants
Dan Shi225b9042015-11-18 10:25:21 -080026from autotest_lib.server import utils
Simran Basi5ace6f22016-01-06 17:30:44 -080027from autotest_lib.server.cros import provision
Dan Shi6450e142016-03-11 11:52:20 -080028from autotest_lib.server.cros.dynamic_suite import tools
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070029from autotest_lib.server.cros.dynamic_suite import constants
Simran Basi724b8a52013-09-30 11:19:31 -070030from autotest_lib.server.hosts import abstract_ssh
Kevin Chengc6a645a2015-12-18 11:15:10 -080031from autotest_lib.server.hosts import adb_label
32from autotest_lib.server.hosts import base_label
Kevin Cheng85e864a2015-11-30 11:49:34 -080033from autotest_lib.server.hosts import teststation_host
Simran Basi431010f2013-09-04 10:42:41 -070034
35
Dan Shi6450e142016-03-11 11:52:20 -080036CONFIG = global_config.global_config
37
Dan Shi6ea3e1c2015-10-28 15:19:04 -070038ADB_CMD = 'adb'
39FASTBOOT_CMD = 'fastboot'
Simran Basi431010f2013-09-04 10:42:41 -070040SHELL_CMD = 'shell'
Filipe Brandenburger34363392015-08-13 14:57:45 -070041# Some devices have no serial, then `adb serial` has output such as:
42# (no serial number) device
43# ?????????? device
44DEVICE_NO_SERIAL_MSG = '(no serial number)'
45DEVICE_NO_SERIAL_TAG = '<NO_SERIAL>'
Simran Basi431010f2013-09-04 10:42:41 -070046# Regex to find an adb device. Examples:
47# 0146B5580B01801B device
48# 018e0ecb20c97a62 device
49# 172.22.75.141:5555 device
Kevin Cheng224415e2016-04-22 11:32:10 -070050# localhost:22 device
Alexandru Branciogea380fb2016-04-01 16:01:34 +030051DEVICE_FINDER_REGEX = (r'^(?P<SERIAL>([\w-]+)|((tcp:)?' +
52 '\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}([:]5555)?)|' +
Kevin Cheng224415e2016-04-22 11:32:10 -070053 '((tcp:)?localhost([:]22)?)|' +
Filipe Brandenburger34363392015-08-13 14:57:45 -070054 re.escape(DEVICE_NO_SERIAL_MSG) +
Alexandru Branciogea380fb2016-04-01 16:01:34 +030055 r')[ \t]+(?:device|fastboot)')
Simran Basi431010f2013-09-04 10:42:41 -070056CMD_OUTPUT_PREFIX = 'ADB_CMD_OUTPUT'
57CMD_OUTPUT_REGEX = ('(?P<OUTPUT>[\s\S]*)%s:(?P<EXIT_CODE>\d{1,3})' %
58 CMD_OUTPUT_PREFIX)
Kevin Cheng018db352015-09-20 02:22:08 -070059RELEASE_FILE = 'ro.build.version.release'
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070060BOARD_FILE = 'ro.product.device'
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -070061SDK_FILE = 'ro.build.version.sdk'
Simran Basi242f8de2016-06-08 14:23:43 -070062LOGCAT_FILE_FMT = 'logcat_%s.log'
Simran Basi38f7ddf2015-09-18 12:25:03 -070063TMP_DIR = '/data/local/tmp'
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070064# Regex to pull out file type, perms and symlink. Example:
Kevin Chengaaabd0c2015-11-10 16:05:04 -080065# lrwxrwx--- 1 6 root system 2015-09-12 19:21 blah_link -> ./blah
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070066FILE_INFO_REGEX = '^(?P<TYPE>[dl-])(?P<PERMS>[rwx-]{9})'
67FILE_SYMLINK_REGEX = '^.*-> (?P<SYMLINK>.+)'
68# List of the perm stats indexed by the order they are listed in the example
69# supplied above.
70FILE_PERMS_FLAGS = [stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR,
71 stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP,
72 stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH]
Simran Basi431010f2013-09-04 10:42:41 -070073
Dan Shi6ea3e1c2015-10-28 15:19:04 -070074# Default maximum number of seconds to wait for a device to be down.
75DEFAULT_WAIT_DOWN_TIME_SECONDS = 10
76# Default maximum number of seconds to wait for a device to be up.
Dan Shie4e807b2015-12-10 09:04:03 -080077DEFAULT_WAIT_UP_TIME_SECONDS = 300
78# Maximum number of seconds to wait for a device to be up after it's wiped.
Dan Shi50a412a2016-01-05 10:52:40 -080079WAIT_UP_AFTER_WIPE_TIME_SECONDS = 1200
Simran Basi431010f2013-09-04 10:42:41 -070080
Dan Shi7075f552016-04-21 15:42:41 -070081# Default timeout for retrying adb/fastboot command.
Dan Shifecac0c2016-07-15 16:05:03 -070082DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS = 20
Dan Shi7075f552016-04-21 15:42:41 -070083
Dan Shia2872172015-10-31 01:16:51 -070084OS_TYPE_ANDROID = 'android'
85OS_TYPE_BRILLO = 'brillo'
86
Dan Shie234dea2016-01-20 17:15:17 -080087# Regex to parse build name to get the detailed build information.
Dan Shi6450e142016-03-11 11:52:20 -080088BUILD_REGEX = ('(?P<BRANCH>([^/]+))/(?P<BUILD_TARGET>([^/]+))-'
Dan Shie234dea2016-01-20 17:15:17 -080089 '(?P<BUILD_TYPE>([^/]+))/(?P<BUILD_ID>([^/]+))')
Dan Shia2872172015-10-31 01:16:51 -070090# Regex to parse devserver url to get the detailed build information. Sample
91# url: http://$devserver:8080/static/branch/target/build_id
Dan Shie234dea2016-01-20 17:15:17 -080092DEVSERVER_URL_REGEX = '.*/%s/*' % BUILD_REGEX
Dan Shia2872172015-10-31 01:16:51 -070093
Dan Shi6450e142016-03-11 11:52:20 -080094ANDROID_IMAGE_FILE_FMT = '%(build_target)s-img-%(build_id)s.zip'
Dan Shi49d451f2016-04-19 09:25:01 -070095
Dan Shiab999722015-12-04 14:27:08 -080096BRILLO_VENDOR_PARTITIONS_FILE_FMT = (
Dan Shi6450e142016-03-11 11:52:20 -080097 '%(build_target)s-vendor_partitions-%(build_id)s.zip')
98AUTOTEST_SERVER_PACKAGE_FILE_FMT = (
99 '%(build_target)s-autotest_server_package-%(build_id)s.tar.bz2')
Simran Basi9228a6f2016-03-29 12:03:37 -0700100ADB_DEVICE_PREFIXES = ['product:', 'model:', 'device:']
Dan Shia2872172015-10-31 01:16:51 -0700101
Simran Basi9c5d3982016-04-01 18:49:44 -0700102# Map of product names to build target name.
103PRODUCT_TARGET_MAP = {'dragon' : 'ryu',
104 'flo' : 'razor',
105 'flo_lte' : 'razorg',
106 'gm4g_sprout' : 'seed_l8150',
107 'flounder' : 'volantis',
108 'flounder_lte' : 'volantisg'}
109
Dan Shiab999722015-12-04 14:27:08 -0800110# Command to provision a Brillo device.
111# os_image_dir: The full path of the directory that contains all the Android image
112# files (from the image zip file).
113# vendor_partition_dir: The full path of the directory that contains all the
114# Brillo vendor partitions, and provision-device script.
115BRILLO_PROVISION_CMD = (
Simran Basi7e52c622016-01-05 15:43:51 -0800116 'sudo ANDROID_PROVISION_OS_PARTITIONS=%(os_image_dir)s '
Dan Shiab999722015-12-04 14:27:08 -0800117 'ANDROID_PROVISION_VENDOR_PARTITIONS=%(vendor_partition_dir)s '
118 '%(vendor_partition_dir)s/provision-device')
Dan Shia2872172015-10-31 01:16:51 -0700119
Dan Shi12a4f662016-05-10 14:49:42 -0700120# Default timeout in minutes for fastboot commands.
121DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN = 10
122
David Purselle01548b2016-05-11 10:00:42 -0700123# Default permissions for files/dirs copied from the device.
124_DEFAULT_FILE_PERMS = 0o600
125_DEFAULT_DIR_PERMS = 0o700
126
Dan Shi626d5412016-05-16 16:05:13 -0700127# Constants for getprop return value for a given property.
128PROPERTY_VALUE_TRUE = '1'
129
Dan Shic716ac62016-05-24 16:47:57 -0700130# Timeout used for retrying installing apk. After reinstall apk failed, we try
131# to reboot the device and try again.
132APK_INSTALL_TIMEOUT_MIN = 5
133
Bryan Lewandowski68646b62016-07-12 10:24:57 -0700134# Directory where (non-Brillo) Android stores tombstone crash logs.
135ANDROID_TOMBSTONE_CRASH_LOG_DIR = '/data/tombstones'
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700136# Directory where Brillo stores crash logs for native (non-Java) crashes.
137BRILLO_NATIVE_CRASH_LOG_DIR = '/data/misc/crash_reporter/crash'
138
Dan Shia2872172015-10-31 01:16:51 -0700139class AndroidInstallError(error.InstallError):
140 """Generic error for Android installation related exceptions."""
141
142
Dan Shifecac0c2016-07-15 16:05:03 -0700143class AutoservRunParseError(error.AutoservRunError):
144 """Error when a command return successfully but the return value is failed
145 to be parsed.
146 """
147
148
Simran Basi724b8a52013-09-30 11:19:31 -0700149class ADBHost(abstract_ssh.AbstractSSHHost):
Simran Basi431010f2013-09-04 10:42:41 -0700150 """This class represents a host running an ADB server."""
151
Simran Basi5ace6f22016-01-06 17:30:44 -0800152 VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700153 _LABEL_FUNCTIONS = []
154 _DETECTABLE_LABELS = []
155 label_decorator = functools.partial(utils.add_label_detector,
156 _LABEL_FUNCTIONS,
157 _DETECTABLE_LABELS)
158
Dan Shi225b9042015-11-18 10:25:21 -0800159 _parser = autoserv_parser.autoserv_parser
Simran Basi431010f2013-09-04 10:42:41 -0700160
Dan Shi6450e142016-03-11 11:52:20 -0800161 # Minimum build id that supports server side packaging. Older builds may
162 # not have server side package built or with Autotest code change to support
163 # server-side packaging.
164 MIN_VERSION_SUPPORT_SSP = CONFIG.get_config_value(
165 'AUTOSERV', 'min_launch_control_build_id_support_ssp', type=int)
166
beeps46dadc92013-11-07 14:07:10 -0800167 @staticmethod
168 def check_host(host, timeout=10):
169 """
170 Check if the given host is an adb host.
171
Simran Basi14622bb2015-11-25 13:23:40 -0800172 If SSH connectivity can't be established, check_host will try to use
173 user 'adb' as well. If SSH connectivity still can't be established
174 then the original SSH user is restored.
175
beeps46dadc92013-11-07 14:07:10 -0800176 @param host: An ssh host representing a device.
177 @param timeout: The timeout for the run command.
178
179
180 @return: True if the host device has adb.
181
182 @raises AutoservRunError: If the command failed.
183 @raises AutoservSSHTimeout: Ssh connection has timed out.
184 """
Dan Shi64e130f2015-12-16 14:45:44 -0800185 # host object may not have user attribute if it's a LocalHost object.
186 current_user = host.user if hasattr(host, 'user') else None
beeps46dadc92013-11-07 14:07:10 -0800187 try:
Simran Basi14622bb2015-11-25 13:23:40 -0800188 if not (host.hostname == 'localhost' or
189 host.verify_ssh_user_access()):
Simran Basi1621c632015-10-14 12:22:23 -0700190 host.user = 'adb'
Simran Basi933c8af2015-04-29 14:05:07 -0700191 result = host.run(
Dan Shia2872172015-10-31 01:16:51 -0700192 'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
Simran Basi933c8af2015-04-29 14:05:07 -0700193 timeout=timeout)
beeps46dadc92013-11-07 14:07:10 -0800194 except (error.AutoservRunError, error.AutoservSSHTimeout):
Dan Shi64e130f2015-12-16 14:45:44 -0800195 if current_user is not None:
196 host.user = current_user
beeps46dadc92013-11-07 14:07:10 -0800197 return False
198 return result.exit_status == 0
199
200
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700201 # TODO(garnold) Remove the 'serials' argument once all clients are made to
202 # not use it.
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700203 def _initialize(self, hostname='localhost', serials=None,
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700204 adb_serial=None, fastboot_serial=None,
Simran Basi9228a6f2016-03-29 12:03:37 -0700205 teststation=None, *args, **dargs):
Simran Basi431010f2013-09-04 10:42:41 -0700206 """Initialize an ADB Host.
207
208 This will create an ADB Host. Hostname should always refer to the
Kevin Chengd19e6c62015-10-28 16:39:39 -0700209 test station connected to an Android DUT. This will be the DUT
210 to test with. If there are multiple, serial must be specified or an
Simran Basi9228a6f2016-03-29 12:03:37 -0700211 exception will be raised.
Simran Basi431010f2013-09-04 10:42:41 -0700212
213 @param hostname: Hostname of the machine running ADB.
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700214 @param serials: DEPRECATED (to be removed)
215 @param adb_serial: An ADB device serial. If None, assume a single
216 device is attached (and fail otherwise).
217 @param fastboot_serial: A fastboot device serial. If None, defaults to
218 the ADB serial (or assumes a single device if
219 the latter is None).
Kevin Cheng549beb42015-11-18 11:42:25 -0800220 @param teststation: The teststation object ADBHost should use.
Simran Basi431010f2013-09-04 10:42:41 -0700221 """
Simran Basi1bf60eb2015-12-01 16:39:29 -0800222 # Sets up the is_client_install_supported field.
223 super(ADBHost, self)._initialize(hostname=hostname,
224 is_client_install_supported=False,
225 *args, **dargs)
Kevin Cheng85e864a2015-11-30 11:49:34 -0800226
Kevin Chengd19e6c62015-10-28 16:39:39 -0700227 self.tmp_dirs = []
Kevin Chengc6a645a2015-12-18 11:15:10 -0800228 self.labels = base_label.LabelRetriever(adb_label.ADB_LABELS)
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700229 adb_serial = adb_serial or self._afe_host.attributes.get('serials')
230 fastboot_serial = (fastboot_serial or
231 self._afe_host.attributes.get('fastboot_serial'))
232
Dan Shi50a412a2016-01-05 10:52:40 -0800233 self.adb_serial = adb_serial
Dan Shi3a011ed2016-04-26 12:26:53 -0700234 if adb_serial:
235 adb_prefix = any(adb_serial.startswith(p)
236 for p in ADB_DEVICE_PREFIXES)
237 self.fastboot_serial = (fastboot_serial or
238 ('tcp:%s' % adb_serial.split(':')[0] if
239 ':' in adb_serial and not adb_prefix else adb_serial))
240 self._use_tcpip = ':' in adb_serial and not adb_prefix
241 else:
242 self.fastboot_serial = fastboot_serial or adb_serial
243 self._use_tcpip = False
Kevin Cheng85e864a2015-11-30 11:49:34 -0800244 self.teststation = (teststation if teststation
Justin Giorgi5208eaa2016-07-02 20:12:12 -0700245 else teststation_host.create_teststationhost(
246 hostname=hostname,
247 user=self.user,
248 password=self.password,
249 port=self.port
250 ))
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700251
252 msg ='Initializing ADB device on host: %s' % hostname
Dan Shi50a412a2016-01-05 10:52:40 -0800253 if self.adb_serial:
254 msg += ', ADB serial: %s' % self.adb_serial
255 if self.fastboot_serial:
256 msg += ', fastboot serial: %s' % self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700257 logging.debug(msg)
258
Simran Basibeb2bb22016-02-03 15:25:48 -0800259 # Try resetting the ADB daemon on the device, however if we are
260 # creating the host to do a repair job, the device maybe inaccesible
261 # via ADB.
262 try:
263 self._reset_adbd_connection()
264 except (error.AutotestHostRunError, error.AutoservRunError) as e:
265 logging.error('Unable to reset the device adb daemon connection: '
266 '%s.', e)
Dan Shiab999722015-12-04 14:27:08 -0800267 self._os_type = None
268
Simran Basi431010f2013-09-04 10:42:41 -0700269
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700270 def _connect_over_tcpip_as_needed(self):
271 """Connect to the ADB device over TCP/IP if so configured."""
Simran Basi9228a6f2016-03-29 12:03:37 -0700272 if not self._use_tcpip:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700273 return
274 logging.debug('Connecting to device over TCP/IP')
Simran Basi9228a6f2016-03-29 12:03:37 -0700275 self.adb_run('connect %s' % self.adb_serial)
Simran Basi431010f2013-09-04 10:42:41 -0700276
277
Roshan Pius4d7540c2015-12-16 13:30:32 -0800278 def _restart_adbd_with_root_permissions(self):
279 """Restarts the adb daemon with root permissions."""
Dan Shi922de302016-04-22 15:19:18 -0700280 @retry.retry(error.AutoservRunError, timeout_min=20/60.0, delay_sec=1)
281 def run_adb_root():
282 """Run command `adb root`."""
283 self.adb_run('root')
284
285 # adb command may flake with error "device not found". Retry the root
286 # command to reduce the chance of flake.
287 run_adb_root()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800288 # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
289 time.sleep(1)
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300290 self._connect_over_tcpip_as_needed()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800291 self.adb_run('wait-for-device')
292
293
Simran Basi9228a6f2016-03-29 12:03:37 -0700294 def _set_tcp_port(self):
295 """Ensure the device remains in tcp/ip mode after a reboot."""
296 if not self._use_tcpip:
297 return
298 port = self.adb_serial.split(':')[-1]
299 self.run('setprop persist.adb.tcp.port %s' % port)
300
301
Roshan Pius4d7540c2015-12-16 13:30:32 -0800302 def _reset_adbd_connection(self):
303 """Resets adbd connection to the device after a reboot/initialization"""
Roshan Pius4d7540c2015-12-16 13:30:32 -0800304 self._connect_over_tcpip_as_needed()
Simran Basi9228a6f2016-03-29 12:03:37 -0700305 self._restart_adbd_with_root_permissions()
306 self._set_tcp_port()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800307
308
Kevin Cheng85e864a2015-11-30 11:49:34 -0800309 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800310 def adb_run(self, command, **kwargs):
Simran Basi431010f2013-09-04 10:42:41 -0700311 """Runs an adb command.
312
Kevin Chengd19e6c62015-10-28 16:39:39 -0700313 This command will launch on the test station.
Simran Basi431010f2013-09-04 10:42:41 -0700314
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700315 Refer to _device_run method for docstring for parameters.
316 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800317 return self._device_run(ADB_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700318
319
Kevin Cheng85e864a2015-11-30 11:49:34 -0800320 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800321 def fastboot_run(self, command, **kwargs):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700322 """Runs an fastboot command.
323
Kevin Chengd19e6c62015-10-28 16:39:39 -0700324 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700325
326 Refer to _device_run method for docstring for parameters.
327 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800328 return self._device_run(FASTBOOT_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700329
330
Dan Shi12a4f662016-05-10 14:49:42 -0700331 # pylint: disable=missing-docstring
332 @retry.retry(error.AutoservRunError,
333 timeout_min=DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN)
334 def _fastboot_run_with_retry(self, command, **kwargs):
335 """Runs an fastboot command with retry.
336
337 This command will launch on the test station.
338
339 Refer to _device_run method for docstring for parameters.
340 """
341 return self.fastboot_run(command, **kwargs)
342
343
Simran Basie6c4f142016-06-23 17:10:04 -0700344 def _log_adb_pid(self):
345 """Log the pid of adb server.
346
347 adb's server is known to have bugs and randomly restart. BY logging
348 the server's pid it will allow us to better debug random adb failures.
349 """
350 adb_pid = self.teststation.run('pgrep -f "adb.*server"')
351 logging.debug('ADB Server PID: %s', adb_pid.stdout)
352
353
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700354 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700355 timeout=3600, ignore_status=False, ignore_timeout=False,
356 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
357 connect_timeout=30, options='', stdin=None, verbose=True,
358 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700359 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700360
Kevin Chengd19e6c62015-10-28 16:39:39 -0700361 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700362
Simran Basi431010f2013-09-04 10:42:41 -0700363 @param command: Command to run.
364 @param shell: If true the command runs in the adb shell otherwise if
365 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700366 reboot with shell=False will call 'adb reboot'. This
367 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700368 @param timeout: Time limit in seconds before attempting to
369 kill the running process. The run() function
370 will take a few seconds longer than 'timeout'
371 to complete if it has to kill the process.
372 @param ignore_status: Do not raise an exception, no matter
373 what the exit code of the command is.
374 @param ignore_timeout: Bool True if command timeouts should be
375 ignored. Will return None on command timeout.
376 @param stdout: Redirect stdout.
377 @param stderr: Redirect stderr.
378 @param connect_timeout: Connection timeout (in seconds)
379 @param options: String with additional ssh command options
380 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700381 @param require_sudo: True to require sudo to run the command. Default is
382 False.
Simran Basi431010f2013-09-04 10:42:41 -0700383 @param args: Sequence of strings to pass as arguments to command by
384 quoting them in " and escaping their contents if
385 necessary.
386
387 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700388 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700389 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800390 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700391 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800392 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700393 else:
394 raise NotImplementedError('Mode %s is not supported' % function)
395
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700396 if function != ADB_CMD and shell:
397 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700398
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700399 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700400
401 if serial:
402 cmd += '-s %s ' % serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700403
Simran Basi431010f2013-09-04 10:42:41 -0700404 if shell:
405 cmd += '%s ' % SHELL_CMD
406 cmd += command
407
Simran Basie6c4f142016-06-23 17:10:04 -0700408 self._log_adb_pid()
409
Roshan Pius58e5dd32015-10-16 15:16:42 -0700410 if verbose:
411 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700412
Kevin Cheng85e864a2015-11-30 11:49:34 -0800413 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400414 ignore_status=ignore_status,
415 ignore_timeout=ignore_timeout, stdout_tee=stdout,
416 stderr_tee=stderr, options=options, stdin=stdin,
417 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700418
419
Dan Shi8c51bda2016-05-26 12:21:02 -0700420 def _run_output_with_retry(self, cmd):
421 """Call run_output method for the given command with retry.
422
Dan Shi68094122016-06-10 14:29:06 -0700423 adb command can be flaky some time, and the command may fail or return
424 empty string. It may take several retries until a value can be returned.
Dan Shi8c51bda2016-05-26 12:21:02 -0700425
426 @param cmd: The command to run.
427
428 @return: Return value from the command after retry.
429 """
430 try:
431 return client_utils.poll_for_condition(
Dan Shi68094122016-06-10 14:29:06 -0700432 lambda: self.run_output(cmd, ignore_status=True),
Dan Shi8c51bda2016-05-26 12:21:02 -0700433 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
434 sleep_interval=0.5,
435 desc='Get return value for command `%s`' % cmd)
436 except client_utils.TimeoutError:
437 return ''
438
439
Dan Shie234dea2016-01-20 17:15:17 -0800440 def get_board_name(self):
441 """Get the name of the board, e.g., shamu, dragonboard etc.
442 """
Simran Basi9c5d3982016-04-01 18:49:44 -0700443 product = self.run_output('getprop %s' % BOARD_FILE)
444 return PRODUCT_TARGET_MAP.get(product, product)
Dan Shie234dea2016-01-20 17:15:17 -0800445
446
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700447 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700448 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700449 """Determine the correct board label for the device.
450
451 @returns a string representing this device's board.
452 """
Dan Shie234dea2016-01-20 17:15:17 -0800453 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700454 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800455 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700456
457
Christopher Wiley08849d52013-11-22 08:57:58 -0800458 def job_start(self):
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700459 """Overload of parent which intentionally doesn't log certain files.
Dan Shi2d279cf2016-05-27 22:06:10 +0000460
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700461 The parent implementation attempts to log certain Linux files, such as
462 /var/log, which do not exist on Android, thus there is no call to the
463 parent's job_start(). The sync call is made so that logcat logs can be
464 approximately matched to server logs.
Dan Shi2d279cf2016-05-27 22:06:10 +0000465 """
Simran Basid6b49792016-06-07 17:22:03 -0700466 if self.is_up():
467 self._sync_time()
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700468 self._enable_native_crash_logging()
Christopher Wiley08849d52013-11-22 08:57:58 -0800469
470
Dan Shifecac0c2016-07-15 16:05:03 -0700471 @retry.retry(AutoservRunParseError,
472 timeout_min=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS/60.0)
Simran Basi431010f2013-09-04 10:42:41 -0700473 def run(self, command, timeout=3600, ignore_status=False,
474 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
475 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700476 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700477 """Run a command on the adb device.
478
479 The command given will be ran directly on the adb device; for example
480 'ls' will be ran as: 'abd shell ls'
481
482 @param command: The command line string.
483 @param timeout: Time limit in seconds before attempting to
484 kill the running process. The run() function
485 will take a few seconds longer than 'timeout'
486 to complete if it has to kill the process.
487 @param ignore_status: Do not raise an exception, no matter
488 what the exit code of the command is.
489 @param ignore_timeout: Bool True if command timeouts should be
490 ignored. Will return None on command timeout.
491 @param stdout_tee: Redirect stdout.
492 @param stderr_tee: Redirect stderr.
493 @param connect_timeout: Connection timeout (in seconds).
494 @param options: String with additional ssh command options.
495 @param stdin: Stdin to pass (a string) to the executed command
496 @param args: Sequence of strings to pass as arguments to command by
497 quoting them in " and escaping their contents if
498 necessary.
499
500 @returns A CMDResult object or None if the call timed out and
501 ignore_timeout is True.
502
503 @raises AutoservRunError: If the command failed.
Dan Shifecac0c2016-07-15 16:05:03 -0700504 @raises AutoservRunParseError: If the command finished but failed to
505 pass the return value.
Simran Basi431010f2013-09-04 10:42:41 -0700506 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700507 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700508 command = ('"%s; echo %s:\$?"' %
509 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700510 result = self.adb_run(
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700511 command, shell=True, timeout=timeout,
Simran Basi431010f2013-09-04 10:42:41 -0700512 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
513 stdout=stdout_tee, stderr=stderr_tee,
514 connect_timeout=connect_timeout, options=options, stdin=stdin,
Roshan Pius58e5dd32015-10-16 15:16:42 -0700515 verbose=verbose, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700516 if not result:
517 # In case of timeouts.
518 return None
519
520 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
Roshan Pius5ba5d182015-10-28 09:19:41 -0700521 if not parse_output and not ignore_status:
Dan Shifecac0c2016-07-15 16:05:03 -0700522 raise AutoservRunParseError(
Roshan Pius5ba5d182015-10-28 09:19:41 -0700523 'Failed to parse the exit code for command: %s' %
524 command, result)
525 elif parse_output:
526 result.stdout = parse_output.group('OUTPUT')
527 result.exit_status = int(parse_output.group('EXIT_CODE'))
528 if result.exit_status != 0 and not ignore_status:
529 raise error.AutoservRunError(command, result)
Simran Basi431010f2013-09-04 10:42:41 -0700530 return result
531
532
Dan Shicf7d2562016-06-16 14:08:23 -0700533 def check_boot_to_adb_complete(self, exception_type=error.TimeoutException):
534 """Check if the device has finished booting and accessible by adb.
535
536 @param exception_type: Type of exception to raise. Default is set to
537 error.TimeoutException for retry.
538
539 @raise exception_type: If the device has not finished booting yet, raise
540 an exception of type `exception_type`.
541 """
542 bootcomplete = self._run_output_with_retry('getprop dev.bootcomplete')
543 if bootcomplete != PROPERTY_VALUE_TRUE:
544 raise exception_type('dev.bootcomplete is %s.' % bootcomplete)
545 if self.get_os_type() == OS_TYPE_ANDROID:
546 boot_completed = self._run_output_with_retry(
547 'getprop sys.boot_completed')
548 if boot_completed != PROPERTY_VALUE_TRUE:
549 raise exception_type('sys.boot_completed is %s.' %
550 boot_completed)
551
552
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700553 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
554 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700555
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700556 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700557
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700558 @param timeout: Time limit in seconds before returning even if the host
559 is not up.
560 @param command: The command used to test if a device is up, i.e.,
561 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700562
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700563 @returns True if the host was found to be up before the timeout expires,
564 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700565 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700566 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
567 delay_sec=1)
568 def _wait_up():
569 if not self.is_up(command=command):
570 raise error.TimeoutException('Device is still down.')
Dan Shicf7d2562016-06-16 14:08:23 -0700571 if command == ADB_CMD:
572 self.check_boot_to_adb_complete()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700573 return True
574
575 try:
576 _wait_up()
577 logging.debug('Host %s is now up, and can be accessed by %s.',
578 self.hostname, command)
579 return True
580 except error.TimeoutException:
581 logging.debug('Host %s is still down after waiting %d seconds',
582 self.hostname, timeout)
583 return False
Simran Basi431010f2013-09-04 10:42:41 -0700584
585
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700586 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
587 warning_timer=None, old_boot_id=None, command=ADB_CMD):
588 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700589
590 Overrides wait_down from AbstractSSHHost.
591
592 @param timeout: Time in seconds to wait for the host to go down.
593 @param warning_timer: Time limit in seconds that will generate
594 a warning if the host is not down yet.
595 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700596 @param old_boot_id: Not applicable for adb_host.
597 @param command: `adb`, test if the device can be accessed by adb
598 command, or `fastboot`, test if the device can be accessed by
599 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700600
601 @returns True if the device goes down before the timeout, False
602 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700603 """
604 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
605 delay_sec=1)
606 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700607 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700608 raise error.TimeoutException('Device is still up.')
609 return True
610
611 try:
612 _wait_down()
613 logging.debug('Host %s is now down', self.hostname)
614 return True
615 except error.TimeoutException:
616 logging.debug('Host %s is still up after waiting %d seconds',
617 self.hostname, timeout)
618 return False
619
620
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700621 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700622 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700623
624 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700625 """
626 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700627 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700628 self.adb_run('reboot', timeout=10, ignore_timeout=True)
629 if not self.wait_down():
630 raise error.AutoservRebootError(
631 'ADB Device is still up after reboot')
632 if not self.wait_up():
633 raise error.AutoservRebootError(
634 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800635 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800636
637
Alexandru Branciog969ff7c2016-03-30 14:07:15 +0300638 def fastboot_reboot(self):
639 """Do a fastboot reboot to go back to adb.
640
641 @raises AutoservRebootError if reboot failed.
642 """
643 self.fastboot_run('reboot')
644 if not self.wait_down(command=FASTBOOT_CMD):
645 raise error.AutoservRebootError(
646 'Device is still in fastboot mode after reboot')
647 if not self.wait_up():
648 raise error.AutoservRebootError(
649 'Device failed to boot to adb after fastboot reboot.')
650 self._reset_adbd_connection()
651
652
Ralph Nathanb45eb672015-11-18 20:04:39 -0800653 def remount(self):
654 """Remounts paritions on the device read-write.
655
656 Specifically, the /system, /vendor (if present) and /oem (if present)
657 partitions on the device are remounted read-write.
658 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800659 self.adb_run('remount')
660
661
Kevin Cheng549beb42015-11-18 11:42:25 -0800662 @staticmethod
663 def parse_device_serials(devices_output):
664 """Return a list of parsed serials from the output.
665
666 @param devices_output: Output from either an adb or fastboot command.
667
668 @returns List of device serials
669 """
670 devices = []
671 for line in devices_output.splitlines():
672 match = re.search(DEVICE_FINDER_REGEX, line)
673 if match:
674 serial = match.group('SERIAL')
675 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
676 serial = DEVICE_NO_SERIAL_TAG
677 logging.debug('Found Device: %s', serial)
678 devices.append(serial)
679 return devices
680
681
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700682 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700683 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700684
685 @params use_adb: True to get adb accessible devices. Set to False to
686 get fastboot accessible devices.
687
Kevin Chengd19e6c62015-10-28 16:39:39 -0700688 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700689 """
690 if use_adb:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300691 result = self.adb_run('devices').stdout
692 if self.adb_serial and self.adb_serial not in result:
693 self._connect_over_tcpip_as_needed()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700694 else:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300695 result = self.fastboot_run('devices').stdout
696 if (self.fastboot_serial and
697 self.fastboot_serial not in result):
698 # fastboot devices won't list the devices using TCP
699 try:
700 if 'product' in self.fastboot_run('getvar product',
701 timeout=2).stderr:
702 result += '\n%s\tfastboot' % self.fastboot_serial
Kevin Chengcfcb2cf2016-04-13 10:04:36 -0700703 # The main reason we do a general Exception catch here instead
704 # of setting ignore_timeout/status to True is because even when
705 # the fastboot process has been nuked, it still stays around and
706 # so bgjob wants to warn us of this and tries to read the
707 # /proc/<pid>/stack file which then promptly returns an
708 # 'Operation not permitted' error since we're running as moblab
709 # and we don't have permission to read those files.
710 except Exception:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300711 pass
712 return self.parse_device_serials(result)
Simran Basi431010f2013-09-04 10:42:41 -0700713
714
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700715 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700716 """Get a list of devices currently attached to the test station and
717 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700718 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800719 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700720 raise error.AutoservError(
721 'Not given ADB serial but multiple devices detected')
722 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700723
724
725 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700726 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700727 accessible by fastboot command.
728 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700729 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800730 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700731 raise error.AutoservError(
732 'Not given fastboot serial but multiple devices detected')
733 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700734
735
736 def is_up(self, timeout=0, command=ADB_CMD):
737 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700738
739 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700740 @param command: `adb`, the device can be accessed by adb command,
741 or `fastboot`, the device can be accessed by fastboot command.
742 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700743
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700744 @returns True if the device is detectable by given command, False
745 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700746
747 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700748 if command == ADB_CMD:
749 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800750 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800751 # ADB has a device state, if the device is not online, no
752 # subsequent ADB command will complete.
Dan Shi6450e142016-03-11 11:52:20 -0800753 # DUT with single device connected may not have adb_serial set.
754 # Therefore, skip checking if serial is in the list of adb devices
755 # if self.adb_serial is not set.
756 if (serial and serial not in devices) or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800757 logging.debug('Waiting for device to enter the ready state.')
758 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700759 elif command == FASTBOOT_CMD:
760 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800761 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700762 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700763 raise NotImplementedError('Mode %s is not supported' % command)
764
765 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700766
767
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700768 def stop_loggers(self):
769 """Inherited stop_loggers function.
770
771 Calls parent function and captures logcat, since the end of the run
772 is logically the end/stop of the logcat log.
773 """
774 super(ADBHost, self).stop_loggers()
775 # Record logcat log to a temporary file on the teststation.
776 tmp_dir = self.teststation.get_tmp_dir()
Simran Basi242f8de2016-06-08 14:23:43 -0700777 logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
778 teststation_filename = os.path.join(tmp_dir, logcat_filename)
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700779 try:
780 self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
781 timeout=20)
Simran Basid6b49792016-06-07 17:22:03 -0700782 except (error.AutotestHostRunError, error.AutoservRunError,
783 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700784 return
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700785 # Copy-back the log to the drone's results directory.
Simran Basi242f8de2016-06-08 14:23:43 -0700786 results_logcat_filename = os.path.join(self.job.resultdir,
787 logcat_filename)
788 self.teststation.get_file(teststation_filename,
789 results_logcat_filename)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700790 try:
791 self.teststation.run('rm -rf %s' % tmp_dir)
792 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
793 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
794
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700795 self._collect_crash_logs()
796
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700797
Simran Basi431010f2013-09-04 10:42:41 -0700798 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700799 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700800
801 Called as the test ends. Will return the device to USB mode and kill
802 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700803 """
Christopher Wiley08849d52013-11-22 08:57:58 -0800804 # TODO(sbasi) Originally, we would kill the server after each test to
805 # reduce the opportunity for bad server state to hang around.
806 # Unfortunately, there is a period of time after each kill during which
807 # the Android device becomes unusable, and if we start the next test
808 # too quickly, we'll get an error complaining about no ADB device
809 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700810 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800811 # |close| the associated teststation as well.
812 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700813 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700814
815
816 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700817 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700818
819 @param message String message to log into syslog
820 @param tag String tag prefix for syslog
821
822 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700823 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700824
825
826 def get_autodir(self):
827 """Return the directory to install autotest for client side tests."""
828 return '/data/autotest'
829
Kevin Cheng018db352015-09-20 02:22:08 -0700830
Kris Rambishde8f9d12015-12-16 12:42:41 -0800831 def is_device_ready(self):
832 """Return the if the device is ready for ADB commands."""
Dan Shi7075f552016-04-21 15:42:41 -0700833 try:
834 # Retry to avoid possible flakes.
835 is_ready = client_utils.poll_for_condition(
836 lambda: self.adb_run('get-state').stdout.strip() == 'device',
837 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
838 desc='Waiting for device state to be `device`')
839 except client_utils.TimeoutError:
840 is_ready = False
841
842 logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
843 return is_ready
Kris Rambishde8f9d12015-12-16 12:42:41 -0800844
845
Kevin Chengd19e6c62015-10-28 16:39:39 -0700846 def verify_connectivity(self):
847 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800848 if not self.is_device_ready():
849 raise error.AutoservHostError('device state is not in the '
850 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700851
852
Simran Basid3ba3fb2015-09-11 14:35:07 -0700853 def verify_software(self):
854 """Verify working software on an adb_host.
855
Simran Basi38f7ddf2015-09-18 12:25:03 -0700856 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700857 """
Dan Shiab999722015-12-04 14:27:08 -0800858 # Check if adb and fastboot are present.
859 self.teststation.run('which adb')
860 self.teststation.run('which fastboot')
861 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700862
Dan Shi626d5412016-05-16 16:05:13 -0700863 # Apply checks only for Android device.
Dan Shi1e2a98a2016-05-18 12:08:08 -0700864 if self.get_os_type() == OS_TYPE_ANDROID:
Dan Shi626d5412016-05-16 16:05:13 -0700865 # Make sure ro.boot.hardware and ro.build.product match.
Dan Shi8c51bda2016-05-26 12:21:02 -0700866 hardware = self._run_output_with_retry('getprop ro.boot.hardware')
867 product = self._run_output_with_retry('getprop ro.build.product')
Dan Shi1e2a98a2016-05-18 12:08:08 -0700868 if hardware != product:
869 raise error.AutoservHostError('ro.boot.hardware: %s does not '
870 'match to ro.build.product: %s' %
871 (hardware, product))
872
Kevin Cheng018db352015-09-20 02:22:08 -0700873
Simran Basid3ba3fb2015-09-11 14:35:07 -0700874 def verify_job_repo_url(self, tag=''):
875 """Make sure job_repo_url of this host is valid.
876
Simran Basi38f7ddf2015-09-18 12:25:03 -0700877 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700878
879 @param tag: The tag from the server job, in the format
880 <job_id>-<user>/<hostname>, or <hostless> for a server job.
881 """
882 return
Kevin Cheng018db352015-09-20 02:22:08 -0700883
884
Simran Basibeb2bb22016-02-03 15:25:48 -0800885 def repair(self):
886 """Attempt to get the DUT to pass `self.verify()`."""
887 try:
888 self.ensure_adb_mode(timeout=30)
889 return
890 except error.AutoservError as e:
891 logging.error(e)
892 logging.debug('Verifying the device is accessible via fastboot.')
893 self.ensure_bootloader_mode()
894 if not self.job.run_test(
895 'provision_AndroidUpdate', host=self, value=None,
896 force=True, repair=True):
897 raise error.AutoservRepairTotalFailure(
898 'Unable to repair the device.')
899
900
Simran Basi1b023762015-09-25 12:12:20 -0700901 def send_file(self, source, dest, delete_dest=False,
902 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700903 """Copy files from the drone to the device.
904
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400905 Just a note, there is the possibility the test station is localhost
906 which makes some of these steps redundant (e.g. creating tmp dir) but
907 that scenario will undoubtedly be a development scenario (test station
908 is also the moblab) and not the typical live test running scenario so
909 the redundancy I think is harmless.
910
Kevin Cheng018db352015-09-20 02:22:08 -0700911 @param source: The file/directory on the drone to send to the device.
912 @param dest: The destination path on the device to copy to.
913 @param delete_dest: A flag set to choose whether or not to delete
914 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700915 @param preserve_symlinks: Controls if symlinks on the source will be
916 copied as such on the destination or
917 transformed into the referenced
918 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700919 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700920 # If we need to preserve symlinks, let's check if the source is a
921 # symlink itself and if so, just create it on the device.
922 if preserve_symlinks:
923 symlink_target = None
924 try:
925 symlink_target = os.readlink(source)
926 except OSError:
927 # Guess it's not a symlink.
928 pass
929
930 if symlink_target is not None:
931 # Once we create the symlink, let's get out of here.
932 self.run('ln -s %s %s' % (symlink_target, dest))
933 return
934
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400935 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700936 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400937 src_path = os.path.join(tmp_dir, os.path.basename(dest))
938 # Now copy the file over to the test station so you can reference the
939 # file in the push command.
940 self.teststation.send_file(source, src_path,
941 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700942
943 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400944 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700945
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700946 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700947
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400948 # Cleanup the test station.
949 try:
950 self.teststation.run('rm -rf %s' % tmp_dir)
951 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
952 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700953
954
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700955 def _get_file_info(self, dest):
956 """Get permission and possible symlink info about file on the device.
957
958 These files are on the device so we only have shell commands (via adb)
959 to get the info we want. We'll use 'ls' to get it all.
960
961 @param dest: File to get info about.
962
963 @returns a dict of the file permissions and symlink.
964 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800965 # Grab file info.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700966 file_info = self.run_output('ls -ld %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700967 symlink = None
968 perms = 0
969 match = re.match(FILE_INFO_REGEX, file_info)
970 if match:
971 # Check if it's a symlink and grab the linked dest if it is.
972 if match.group('TYPE') == 'l':
973 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
974 if symlink_match:
975 symlink = symlink_match.group('SYMLINK')
976
977 # Set the perms.
978 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
979 if perm != '-':
980 perms |= perm_flag
981
982 return {'perms': perms,
983 'symlink': symlink}
984
985
Simran Basi1b023762015-09-25 12:12:20 -0700986 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
987 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700988 """Copy files from the device to the drone.
989
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400990 Just a note, there is the possibility the test station is localhost
991 which makes some of these steps redundant (e.g. creating tmp dir) but
992 that scenario will undoubtedly be a development scenario (test station
993 is also the moblab) and not the typical live test running scenario so
994 the redundancy I think is harmless.
995
Kevin Cheng018db352015-09-20 02:22:08 -0700996 @param source: The file/directory on the device to copy back to the
997 drone.
998 @param dest: The destination path on the drone to copy to.
999 @param delete_dest: A flag set to choose whether or not to delete
1000 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -07001001 @param preserve_perm: Tells get_file() to try to preserve the sources
1002 permissions on files and dirs.
1003 @param preserve_symlinks: Try to preserve symlinks instead of
1004 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -07001005 """
David Purselle01548b2016-05-11 10:00:42 -07001006 # Stage the files on the test station under teststation_temp_dir.
1007 teststation_temp_dir = self.teststation.get_tmp_dir()
1008 teststation_dest = os.path.join(teststation_temp_dir,
1009 os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -07001010
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001011 source_info = {}
1012 if preserve_symlinks or preserve_perm:
1013 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -07001014
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001015 # If we want to preserve symlinks, just create it here, otherwise pull
1016 # the file off the device.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001017 #
1018 # TODO(sadmac): Directories containing symlinks won't behave as
1019 # expected.
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001020 if preserve_symlinks and source_info['symlink']:
1021 os.symlink(source_info['symlink'], dest)
1022 else:
David Purselle01548b2016-05-11 10:00:42 -07001023 self.adb_run('pull %s %s' % (source, teststation_temp_dir))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001024
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001025 # Copy over the file from the test station and clean up.
David Purselle01548b2016-05-11 10:00:42 -07001026 self.teststation.get_file(teststation_dest, dest,
1027 delete_dest=delete_dest)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001028 try:
David Purselle01548b2016-05-11 10:00:42 -07001029 self.teststation.run('rm -rf %s' % teststation_temp_dir)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001030 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
David Purselle01548b2016-05-11 10:00:42 -07001031 logging.warn('failed to remove dir %s: %s',
1032 teststation_temp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001033
David Pursell788b1b52016-05-19 09:03:31 -07001034 # Source will be copied under dest if either:
1035 # 1. Source is a directory and doesn't end with /.
1036 # 2. Source is a file and dest is a directory.
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001037 command = '[ -d %s ]' % source
1038 source_is_dir = self.run(command,
David Pursell788b1b52016-05-19 09:03:31 -07001039 ignore_status=True).exit_status == 0
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001040
David Pursell788b1b52016-05-19 09:03:31 -07001041 if ((source_is_dir and not source.endswith(os.sep)) or
1042 (not source_is_dir and os.path.isdir(dest))):
1043 receive_path = os.path.join(dest, os.path.basename(source))
1044 else:
1045 receive_path = dest
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001046
David Pursell788b1b52016-05-19 09:03:31 -07001047 # Set the permissions of the received file/dirs.
1048 if os.path.isdir(receive_path):
1049 for root, _dirs, files in os.walk(receive_path):
1050 def process(rel_path, default_perm):
1051 info = self._get_file_info(os.path.join(source,
1052 rel_path))
1053 if info['perms'] != 0:
1054 target = os.path.join(receive_path, rel_path)
1055 if preserve_perm:
1056 os.chmod(target, info['perms'])
1057 else:
1058 os.chmod(target, default_perm)
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001059
David Pursell788b1b52016-05-19 09:03:31 -07001060 rel_root = os.path.relpath(root, receive_path)
1061 process(rel_root, _DEFAULT_DIR_PERMS)
1062 for f in files:
1063 process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
1064 elif preserve_perm:
1065 os.chmod(receive_path, source_info['perms'])
1066 else:
1067 os.chmod(receive_path, _DEFAULT_FILE_PERMS)
Kevin Cheng018db352015-09-20 02:22:08 -07001068
1069
1070 def get_release_version(self):
1071 """Get the release version from the RELEASE_FILE on the device.
1072
1073 @returns The release string in the RELEASE_FILE.
1074
1075 """
1076 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -07001077
1078
1079 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001080 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001081
Kevin Chengd19e6c62015-10-28 16:39:39 -07001082 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001083
1084 @param parent: Parent directory of the returned tmp dir.
1085
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07001086 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001087 """
Kevin Chengd19e6c62015-10-28 16:39:39 -07001088 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
1089 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001090 if not parent.startswith(TMP_DIR):
1091 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -07001092 self.run('mkdir -p %s' % parent)
1093 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
1094 self.tmp_dirs.append(tmp_dir)
1095 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -07001096
1097
1098 def get_platform(self):
1099 """Determine the correct platform label for this host.
1100
1101 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -07001102 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -07001103
1104 @returns a string representing this host's platform.
1105 """
1106 return 'adb'
1107
1108
Gilad Arnolda76bef02015-09-29 13:55:15 -07001109 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -08001110 """Get the OS type of the DUT, e.g., android or brillo.
1111 """
1112 if not self._os_type:
1113 if self.run_output('getprop ro.product.brand') == 'Brillo':
1114 self._os_type = OS_TYPE_BRILLO
1115 else:
1116 self._os_type = OS_TYPE_ANDROID
1117
1118 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001119
1120
1121 def _forward(self, reverse, args):
1122 """Execute a forwarding command.
1123
1124 @param reverse: Whether this is reverse forwarding (Boolean).
1125 @param args: List of command arguments.
1126 """
1127 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001128 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001129
1130
1131 def add_forwarding(self, src, dst, reverse=False, rebind=True):
1132 """Forward a port between the ADB host and device.
1133
1134 Port specifications are any strings accepted as such by ADB, for
1135 example 'tcp:8080'.
1136
1137 @param src: Port specification to forward from.
1138 @param dst: Port specification to forward to.
1139 @param reverse: Do reverse forwarding from device to host (Boolean).
1140 @param rebind: Allow rebinding an already bound port (Boolean).
1141 """
1142 args = []
1143 if not rebind:
1144 args.append('--no-rebind')
1145 args += [src, dst]
1146 self._forward(reverse, args)
1147
1148
1149 def remove_forwarding(self, src=None, reverse=False):
1150 """Removes forwarding on port.
1151
1152 @param src: Port specification, or None to remove all forwarding.
1153 @param reverse: Whether this is reverse forwarding (Boolean).
1154 """
1155 args = []
1156 if src is None:
1157 args.append('--remove-all')
1158 else:
1159 args += ['--remove', src]
1160 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001161
1162
xixuan6cf6d2f2016-01-29 15:29:00 -08001163 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001164 """
1165 Forwards a port securely through a tunnel process from the server
1166 to the DUT for RPC server connection.
1167 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
1168 to the DUT.
1169
1170 @param port: remote port on the DUT.
1171 @param local_port: local forwarding port.
1172
1173 @return: the tunnel process.
1174 """
1175 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001176 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001177
1178
xixuan6cf6d2f2016-01-29 15:29:00 -08001179 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001180 """
1181 Disconnects a previously forwarded port from the server to the DUT for
1182 RPC server connection.
1183 Remove the previously added 'ADB forward' rule to forward the RPC
1184 packets from the AdbHost to the DUT.
1185
1186 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -08001187 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -07001188 @param port: remote port on the DUT.
1189
1190 """
1191 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001192 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001193
1194
1195 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001196 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001197
1198 @raise: error.AutoservError if the device failed to reboot into
1199 bootloader mode.
1200 """
1201 if self.is_up(command=FASTBOOT_CMD):
1202 return
1203 self.adb_run('reboot bootloader')
1204 if not self.wait_up(command=FASTBOOT_CMD):
1205 raise error.AutoservError(
1206 'The device failed to reboot into bootloader mode.')
1207
1208
Dan Shie4e807b2015-12-10 09:04:03 -08001209 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001210 """Ensure the device is up and can be accessed by adb command.
1211
Dan Shie4e807b2015-12-10 09:04:03 -08001212 @param timeout: Time limit in seconds before returning even if the host
1213 is not up.
1214
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001215 @raise: error.AutoservError if the device failed to reboot into
1216 adb mode.
1217 """
1218 if self.is_up():
1219 return
Dan Shi04980372016-03-22 10:57:47 -07001220 # Ignore timeout error to allow `fastboot reboot` to fail quietly and
1221 # check if the device is in adb mode.
1222 self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
Dan Shie4e807b2015-12-10 09:04:03 -08001223 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001224 raise error.AutoservError(
1225 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -08001226 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -07001227
1228
1229 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -08001230 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001231 """Get the Android build information from the build url.
1232
1233 @param build_url: The url to use for downloading Android artifacts.
1234 pattern: http://$devserver:###/static/branch/target/build_id
1235
Dan Shi6450e142016-03-11 11:52:20 -08001236 @return: A dictionary of build information, including keys:
1237 build_target, branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -08001238 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -07001239 """
Dan Shiab999722015-12-04 14:27:08 -08001240 if not build_url:
1241 raise AndroidInstallError('Need build_url to download image files.')
1242
1243 try:
1244 match = re.match(DEVSERVER_URL_REGEX, build_url)
Dan Shi6450e142016-03-11 11:52:20 -08001245 return {'build_target': match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001246 'branch': match.group('BRANCH'),
Dan Shi6450e142016-03-11 11:52:20 -08001247 'target': ('%s-%s' % (match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001248 match.group('BUILD_TYPE'))),
1249 'build_id': match.group('BUILD_ID')}
1250 except (AttributeError, IndexError, ValueError) as e:
1251 raise AndroidInstallError(
1252 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001253
1254
Dan Shia2872172015-10-31 01:16:51 -07001255 @retry.retry(error.AutoservRunError, timeout_min=10)
Simran Basi7756a0b2016-03-16 13:10:07 -07001256 def download_file(self, build_url, file, dest_dir, unzip=False,
1257 unzip_dest=None):
Dan Shia2872172015-10-31 01:16:51 -07001258 """Download the given file from the build url.
1259
1260 @param build_url: The url to use for downloading Android artifacts.
1261 pattern: http://$devserver:###/static/branch/target/build_id
1262 @param file: Name of the file to be downloaded, e.g., boot.img.
1263 @param dest_dir: Destination folder for the file to be downloaded to.
Simran Basi7756a0b2016-03-16 13:10:07 -07001264 @param unzip: If True, unzip the downloaded file.
1265 @param unzip_dest: Location to unzip the downloaded file to. If not
1266 provided, dest_dir is used.
Dan Shia2872172015-10-31 01:16:51 -07001267 """
Dan Shidb0366c2016-02-19 10:36:18 -08001268 # Append the file name to the url if build_url is linked to the folder
1269 # containing the file.
1270 if not build_url.endswith('/%s' % file):
1271 src_url = os.path.join(build_url, file)
1272 else:
1273 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001274 dest_file = os.path.join(dest_dir, file)
1275 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001276 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Simran Basi7756a0b2016-03-16 13:10:07 -07001277 if unzip:
1278 unzip_dest = unzip_dest or dest_dir
1279 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1280 (dest_dir, file, unzip_dest))
Dan Shia2872172015-10-31 01:16:51 -07001281 except:
1282 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001283 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001284 raise
1285
1286
Dan Shiab999722015-12-04 14:27:08 -08001287 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001288 """Download required image files from the given build_url to a local
1289 directory in the machine runs fastboot command.
1290
1291 @param build_url: The url to use for downloading Android artifacts.
1292 pattern: http://$devserver:###/static/branch/target/build_id
1293
1294 @return: Path to the directory contains image files.
1295 """
Dan Shi08ff1282016-02-18 19:51:16 -08001296 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001297
1298 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001299 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001300
1301 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001302 self.download_file(build_url, zipped_image_file, image_dir,
1303 unzip=True)
Dan Shi49d451f2016-04-19 09:25:01 -07001304 images = android_utils.AndroidImageFiles.get_standalone_images(
1305 build_info['build_target'])
1306 for image_file in images:
Dan Shidb0366c2016-02-19 10:36:18 -08001307 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001308
Dan Shia2872172015-10-31 01:16:51 -07001309 return image_dir
1310 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001311 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001312 raise
1313
1314
Dan Shiab999722015-12-04 14:27:08 -08001315 def stage_brillo_image_files(self, build_url):
1316 """Download required brillo image files from the given build_url to a
1317 local directory in the machine runs fastboot command.
1318
1319 @param build_url: The url to use for downloading Android artifacts.
1320 pattern: http://$devserver:###/static/branch/target/build_id
1321
1322 @return: Path to the directory contains image files.
1323 """
Dan Shi08ff1282016-02-18 19:51:16 -08001324 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001325
1326 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1327 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1328 image_dir = self.teststation.get_tmp_dir()
Dan Shiab999722015-12-04 14:27:08 -08001329
1330 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001331 self.download_file(build_url, zipped_image_file, image_dir,
1332 unzip=True)
1333 self.download_file(build_url, vendor_partitions_file, image_dir,
1334 unzip=True,
1335 unzip_dest=os.path.join(image_dir, 'vendor'))
Dan Shiab999722015-12-04 14:27:08 -08001336 return image_dir
1337 except:
1338 self.teststation.run('rm -rf %s' % image_dir)
1339 raise
1340
1341
Simran Basibeb2bb22016-02-03 15:25:48 -08001342 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001343 """Stage a build on a devserver and return the build_url and devserver.
1344
1345 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001346
Dan Shi225b9042015-11-18 10:25:21 -08001347 @returns a tuple with an update URL like:
1348 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1349 and the devserver instance.
1350 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001351 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001352 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001353 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1354 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001355 build_name = devserver.translate(build_name)
Dan Shi6450e142016-03-11 11:52:20 -08001356 branch, target, build_id = utils.parse_launch_control_build(build_name)
Simran Basibeb2bb22016-02-03 15:25:48 -08001357 is_brillo = os_type == OS_TYPE_BRILLO
Dan Shi08ff1282016-02-18 19:51:16 -08001358 devserver.trigger_download(target, build_id, branch,
1359 is_brillo=is_brillo, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001360 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001361
1362
Dan Shie4e807b2015-12-10 09:04:03 -08001363 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001364 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001365 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001366
1367 Following are the steps used here to provision an android device:
1368 1. If build_local_path is not set, download the image zip file, e.g.,
1369 shamu-img-2284311.zip, unzip it.
1370 2. Run fastboot to install following artifacts:
1371 bootloader, radio, boot, system, vendor(only if exists)
1372
1373 Repair is not supported for Android devices yet.
1374
1375 @param build_url: The url to use for downloading Android artifacts.
1376 pattern: http://$devserver:###/static/$build
1377 @param build_local_path: The path to a local folder that contains the
1378 image files needed to provision the device. Note that the folder
1379 is in the machine running adb command, rather than the drone.
1380 @param wipe: If true, userdata will be wiped before flashing.
1381 @param flash_all: If True, all img files found in img_path will be
1382 flashed. Otherwise, only boot and system are flashed.
1383
1384 @raises AndroidInstallError if any error occurs.
1385 """
Dan Shia2872172015-10-31 01:16:51 -07001386 # If the build is not staged in local server yet, clean up the temp
1387 # folder used to store image files after the provision is completed.
1388 delete_build_folder = bool(not build_local_path)
1389
1390 try:
1391 # Download image files needed for provision to a local directory.
1392 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001393 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001394
1395 # Device needs to be in bootloader mode for flashing.
1396 self.ensure_bootloader_mode()
1397
1398 if wipe:
Dan Shi12a4f662016-05-10 14:49:42 -07001399 self._fastboot_run_with_retry('-w')
Dan Shia2872172015-10-31 01:16:51 -07001400
1401 # Get all *.img file in the build_local_path.
1402 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001403 image_files = self.teststation.run(
1404 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001405 images = dict([(os.path.basename(f), f) for f in image_files])
Dan Shi49d451f2016-04-19 09:25:01 -07001406 build_info = self.get_build_info_from_build_url(build_url)
1407 board = build_info['build_target']
1408 all_images = (
1409 android_utils.AndroidImageFiles.get_standalone_images(board)
1410 + android_utils.AndroidImageFiles.get_zipped_images(board))
1411
1412 # Sort images to be flashed, bootloader needs to be the first one.
1413 bootloader = android_utils.AndroidImageFiles.BOOTLOADER
1414 sorted_images = sorted(
1415 images.items(),
1416 key=lambda pair: 0 if pair[0] == bootloader else 1)
1417 for image, image_file in sorted_images:
1418 if image not in all_images:
Dan Shia2872172015-10-31 01:16:51 -07001419 continue
1420 logging.info('Flashing %s...', image_file)
Dan Shi12a4f662016-05-10 14:49:42 -07001421 self._fastboot_run_with_retry('-S 256M flash %s %s' %
1422 (image[:-4], image_file))
Dan Shi49d451f2016-04-19 09:25:01 -07001423 if image == android_utils.AndroidImageFiles.BOOTLOADER:
Dan Shia2872172015-10-31 01:16:51 -07001424 self.fastboot_run('reboot-bootloader')
1425 self.wait_up(command=FASTBOOT_CMD)
1426 except Exception as e:
1427 logging.error('Install Android build failed with error: %s', e)
1428 # Re-raise the exception with type of AndroidInstallError.
1429 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1430 finally:
1431 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001432 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001433 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1434 DEFAULT_WAIT_UP_TIME_SECONDS)
1435 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001436 logging.info('Successfully installed Android build staged at %s.',
1437 build_url)
1438
1439
Dan Shiab999722015-12-04 14:27:08 -08001440 def install_brillo(self, build_url, build_local_path=None):
1441 """Install the Brillo DUT.
1442
1443 Following are the steps used here to provision an android device:
1444 1. If build_local_path is not set, download the image zip file, e.g.,
1445 dragonboard-img-123456.zip, unzip it. And download the vendor
1446 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1447 unzip it to vendor folder.
1448 2. Run provision_device script to install OS images and vendor
1449 partitions.
1450
1451 @param build_url: The url to use for downloading Android artifacts.
1452 pattern: http://$devserver:###/static/$build
1453 @param build_local_path: The path to a local folder that contains the
1454 image files needed to provision the device. Note that the folder
1455 is in the machine running adb command, rather than the drone.
1456
1457 @raises AndroidInstallError if any error occurs.
1458 """
1459 # If the build is not staged in local server yet, clean up the temp
1460 # folder used to store image files after the provision is completed.
1461 delete_build_folder = bool(not build_local_path)
1462
Dan Shiab999722015-12-04 14:27:08 -08001463 try:
1464 # Download image files needed for provision to a local directory.
1465 if not build_local_path:
1466 build_local_path = self.stage_brillo_image_files(build_url)
1467
1468 # Device needs to be in bootloader mode for flashing.
1469 self.ensure_bootloader_mode()
1470
1471 # Run provision_device command to install image files and vendor
1472 # partitions.
1473 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1474 cmd = (BRILLO_PROVISION_CMD %
1475 {'os_image_dir': build_local_path,
1476 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001477 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001478 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001479 self.teststation.run(cmd)
1480 except Exception as e:
1481 logging.error('Install Brillo build failed with error: %s', e)
1482 # Re-raise the exception with type of AndroidInstallError.
1483 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1484 finally:
1485 if delete_build_folder:
1486 self.teststation.run('rm -rf %s' % build_local_path)
1487 self.ensure_adb_mode()
1488 logging.info('Successfully installed Android build staged at %s.',
1489 build_url)
1490
1491
Dan Shibe3636a2016-02-14 22:48:01 -08001492 @property
1493 def job_repo_url_attribute(self):
1494 """Get the host attribute name for job_repo_url, which should append the
1495 adb serial.
1496 """
1497 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1498
1499
Dan Shie4e807b2015-12-10 09:04:03 -08001500 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001501 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001502 """Install the DUT.
1503
1504 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001505 pattern: http://$devserver:###/static/$build. If build_url is
1506 set to None, the code may try _parser.options.image to do the
1507 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001508 @param build_local_path: The path to a local directory that contains the
1509 image files needed to provision the device.
1510 @param wipe: If true, userdata will be wiped before flashing.
1511 @param flash_all: If True, all img files found in img_path will be
1512 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001513
Dan Shibe3636a2016-02-14 22:48:01 -08001514 @returns A tuple of (image_name, host_attributes).
1515 image_name is the name of image installed, e.g.,
1516 git_mnc-release/shamu-userdebug/1234
1517 host_attributes is a dictionary of (attribute, value), which
1518 can be saved to afe_host_attributes table in database. This
1519 method returns a dictionary with a single entry of
1520 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1521 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001522 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001523 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001524 if not build_url and self._parser.options.image:
1525 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001526 self._parser.options.image, os_type=os_type)
1527 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001528 self.install_android(
1529 build_url=build_url, build_local_path=build_local_path,
1530 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001531 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001532 self.install_brillo(
1533 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001534 else:
1535 raise error.InstallError(
1536 'Installation of os type %s is not supported.' %
1537 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001538 return (build_url.split('static/')[-1],
1539 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001540
1541
1542 def list_files_glob(self, path_glob):
1543 """Get a list of files on the device given glob pattern path.
1544
1545 @param path_glob: The path glob that we want to return the list of
1546 files that match the glob. Relative paths will not work as
1547 expected. Supply an absolute path to get the list of files
1548 you're hoping for.
1549
1550 @returns List of files that match the path_glob.
1551 """
1552 # This is just in case path_glob has no path separator.
1553 base_path = os.path.dirname(path_glob) or '.'
1554 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001555 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001556 if result.exit_status != 0:
1557 return []
1558 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001559
1560
Dan Shic716ac62016-05-24 16:47:57 -07001561 @retry.retry(error.AutoservRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
Dan Shida995002016-04-25 23:12:58 -07001562 def install_apk(self, apk, force_reinstall=True):
Kevin Cheng31355942016-01-05 14:23:35 -08001563 """Install the specified apk.
1564
1565 This will install the apk and override it if it's already installed and
1566 will also allow for downgraded apks.
1567
1568 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001569 @param force_reinstall: True to reinstall the apk even if it's already
Dan Shida995002016-04-25 23:12:58 -07001570 installed. Default is set to True.
Dan Shidb0366c2016-02-19 10:36:18 -08001571
1572 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001573 """
Dan Shic716ac62016-05-24 16:47:57 -07001574 try:
1575 client_utils.poll_for_condition(
1576 lambda: self.run('pm list packages',
1577 ignore_status=True).exit_status == 0,
1578 timeout=120)
1579 client_utils.poll_for_condition(
1580 lambda: self.run('service list | grep mount',
1581 ignore_status=True).exit_status == 0,
1582 timeout=120)
1583 return self.adb_run('install %s -d %s' %
1584 ('-r' if force_reinstall else '', apk))
1585 except error.AutoservRunError:
1586 self.reboot()
1587 raise
Dan Shidb0366c2016-02-19 10:36:18 -08001588
1589
1590 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1591 def _confirm_apk_installed(self, package_name):
1592 """Confirm if apk is already installed with the given name.
1593
1594 `pm list packages` command is not reliable some time. The retry helps to
1595 reduce the chance of false negative.
1596
1597 @param package_name: Name of the package, e.g., com.android.phone.
1598
1599 @raise AutoservRunError: If the package is not found or pm list command
1600 failed for any reason.
1601 """
1602 name = 'package:%s' % package_name
1603 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1604
1605
1606 def is_apk_installed(self, package_name):
1607 """Check if apk is already installed with the given name.
1608
1609 @param package_name: Name of the package, e.g., com.android.phone.
1610
1611 @return: True if package is installed. False otherwise.
1612 """
1613 try:
1614 self._confirm_apk_installed(package_name)
1615 return True
1616 except:
1617 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001618
1619
1620 def get_attributes_to_clear_before_provision(self):
1621 """Get a list of attributes to be cleared before machine_install starts.
1622 """
1623 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001624
1625
1626 def get_labels(self):
1627 """Return a list of the labels gathered from the devices connected.
1628
1629 @return: A list of strings that denote the labels from all the devices
1630 connected.
1631 """
1632 return self.labels.get_labels(self)
1633
1634
1635 def update_labels(self):
1636 """Update the labels for this testbed."""
1637 self.labels.update_labels(self)
Dan Shi6450e142016-03-11 11:52:20 -08001638
1639
1640 def stage_server_side_package(self, image=None):
1641 """Stage autotest server-side package on devserver.
1642
1643 @param image: A build name, e.g., git_mnc_dev/shamu-eng/123
1644
1645 @return: A url to the autotest server-side package. Return None if
1646 server-side package is not supported.
1647 @raise: error.AutoservError if fail to locate the build to test with.
1648 """
Dan Shid37736b2016-07-06 15:10:29 -07001649 # If enable_drone_in_restricted_subnet is False, do not set hostname
1650 # in devserver.resolve call, so a devserver in non-restricted subnet
1651 # is picked to stage autotest server package for drone to download.
1652 hostname = self.hostname
1653 if not utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1654 hostname = None
Dan Shi6450e142016-03-11 11:52:20 -08001655 if image:
Dan Shid37736b2016-07-06 15:10:29 -07001656 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001657 else:
1658 job_repo_url = afe_utils.get_host_attribute(
1659 self, self.job_repo_url_attribute)
1660 if job_repo_url:
1661 devserver_url, image = (
1662 tools.get_devserver_build_from_package_url(
1663 job_repo_url, True))
Dan Shid37736b2016-07-06 15:10:29 -07001664 # If enable_drone_in_restricted_subnet is True, use the
1665 # existing devserver. Otherwise, resolve a new one in
1666 # non-restricted subnet.
1667 if utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1668 ds = dev_server.AndroidBuildServer(devserver_url)
1669 else:
1670 ds = dev_server.AndroidBuildServer.resolve(image)
Dan Shi6450e142016-03-11 11:52:20 -08001671 else:
1672 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
1673 if not labels:
1674 raise error.AutoservError(
1675 'Failed to stage server-side package. The host has '
1676 'no job_report_url attribute or version label.')
Kevin Cheng84a71ba2016-07-14 11:03:57 -07001677 image = labels[0][len(self.VERSION_PREFIX + ':'):]
Dan Shid37736b2016-07-06 15:10:29 -07001678 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001679
1680 branch, target, build_id = utils.parse_launch_control_build(image)
1681 build_target, _ = utils.parse_launch_control_target(target)
1682
1683 # For any build older than MIN_VERSION_SUPPORT_SSP, server side
1684 # packaging is not supported.
1685 try:
1686 if int(build_id) < self.MIN_VERSION_SUPPORT_SSP:
1687 logging.warn('Build %s is older than %s. Server side packaging '
1688 'is disabled.', image,
1689 self.MIN_VERSION_SUPPORT_SSP)
1690 return None
1691 except ValueError:
1692 logging.warn('Failed to compare build id in %s with the minimum '
1693 'version that supports server side packaging. Server '
1694 'side packaging is disabled.', image)
1695 return None
1696
1697 ds.stage_artifacts(target, build_id, branch,
1698 artifacts=['autotest_server_package'])
1699 autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
1700 {'build_target': build_target,
1701 'build_id': build_id})
1702 return '%s/static/%s/%s' % (ds.url(), image,
1703 autotest_server_package_name)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07001704
1705
1706 def _sync_time(self):
1707 """Approximate synchronization of time between host and ADB device.
1708
1709 This sets the ADB/Android device's clock to approximately the same
1710 time as the Autotest host for the purposes of comparing Android system
1711 logs such as logcat to logs from the Autotest host system.
1712 """
1713 command = 'date '
1714 sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
1715 if sdk_version < 23:
1716 # Android L and earlier use this format: date -s (format).
1717 command += ('-s %s' %
1718 datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
1719 else:
1720 # Android M and later use this format: date (format).
1721 command += datetime.datetime.now().strftime('%m%d%H%M%Y.%S')
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -07001722 self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1723 ignore_timeout=True)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001724
1725
1726 def _enable_native_crash_logging(self):
1727 """Enable native (non-Java) crash logging.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001728 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001729 if self.get_os_type() == OS_TYPE_BRILLO:
1730 self._enable_brillo_native_crash_logging()
1731 elif self.get_os_type() == OS_TYPE_ANDROID:
1732 self._enable_android_native_crash_logging()
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001733
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001734
1735 def _enable_brillo_native_crash_logging(self):
1736 """Enables native crash logging for a Brillo DUT.
1737 """
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001738 self.run('touch /data/misc/metrics/enabled',
1739 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1740 ignore_timeout=True)
1741 # If running, crash_sender will delete crash files every hour.
1742 self.run('stop crash_sender',
1743 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1744 ignore_timeout=True)
1745
1746
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001747 def _enable_android_native_crash_logging(self):
1748 """Enables native crash logging for an Android DUT.
1749 """
1750 # debuggerd should be enabled by default on Android.
1751 result = self.run('pgrep debuggerd',
1752 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1753 ignore_timeout=True, ignore_status=True)
1754 if not result or result.exit_status != 0:
1755 logging.debug('Unable to confirm that debuggerd is running.')
1756
1757
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001758 def _collect_crash_logs(self):
1759 """Copies crash log files from the DUT to the drone.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001760 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001761 if self.get_os_type() == OS_TYPE_BRILLO:
1762 self._collect_crash_logs_dut(BRILLO_NATIVE_CRASH_LOG_DIR)
1763 elif self.get_os_type() == OS_TYPE_ANDROID:
1764 self._collect_crash_logs_dut(ANDROID_TOMBSTONE_CRASH_LOG_DIR)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001765
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001766
1767 def _collect_crash_logs_dut(self, log_directory):
1768 """Copies native crash logs from the Android/Brillo DUT to the drone.
1769
1770 @param log_directory: absolute path of the directory on the DUT where
1771 log files are stored.
1772 """
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001773 files = None
1774 try:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001775 result = self.run('find %s -maxdepth 1 -type f' % log_directory,
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001776 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS)
1777 files = result.stdout.strip().split()
1778 except (error.AutotestHostRunError, error.AutoservRunError,
1779 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001780 logging.debug('Unable to call find %s, unable to find crash logs',
1781 log_directory)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001782 if not files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001783 logging.debug('There are no crash logs on the DUT.')
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001784 return
1785
1786 crash_dir = os.path.join(self.job.resultdir, 'crash')
1787 try:
1788 os.mkdir(crash_dir)
1789 except OSError as e:
1790 if e.errno != errno.EEXIST:
1791 raise e
1792
1793 for f in files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001794 logging.debug('DUT native crash file produced: %s', f)
1795 dest = os.path.join(crash_dir, os.path.basename(f))
1796 self.get_file(source=f, dest=dest)