blob: 90d126ecfd130b901a4e8061ce57f3b191f83805 [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.
82DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS = 10
83
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
Simran Basi724b8a52013-09-30 11:19:31 -0700143class ADBHost(abstract_ssh.AbstractSSHHost):
Simran Basi431010f2013-09-04 10:42:41 -0700144 """This class represents a host running an ADB server."""
145
Simran Basi5ace6f22016-01-06 17:30:44 -0800146 VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700147 _LABEL_FUNCTIONS = []
148 _DETECTABLE_LABELS = []
149 label_decorator = functools.partial(utils.add_label_detector,
150 _LABEL_FUNCTIONS,
151 _DETECTABLE_LABELS)
152
Dan Shi225b9042015-11-18 10:25:21 -0800153 _parser = autoserv_parser.autoserv_parser
Simran Basi431010f2013-09-04 10:42:41 -0700154
Dan Shi6450e142016-03-11 11:52:20 -0800155 # Minimum build id that supports server side packaging. Older builds may
156 # not have server side package built or with Autotest code change to support
157 # server-side packaging.
158 MIN_VERSION_SUPPORT_SSP = CONFIG.get_config_value(
159 'AUTOSERV', 'min_launch_control_build_id_support_ssp', type=int)
160
beeps46dadc92013-11-07 14:07:10 -0800161 @staticmethod
162 def check_host(host, timeout=10):
163 """
164 Check if the given host is an adb host.
165
Simran Basi14622bb2015-11-25 13:23:40 -0800166 If SSH connectivity can't be established, check_host will try to use
167 user 'adb' as well. If SSH connectivity still can't be established
168 then the original SSH user is restored.
169
beeps46dadc92013-11-07 14:07:10 -0800170 @param host: An ssh host representing a device.
171 @param timeout: The timeout for the run command.
172
173
174 @return: True if the host device has adb.
175
176 @raises AutoservRunError: If the command failed.
177 @raises AutoservSSHTimeout: Ssh connection has timed out.
178 """
Dan Shi64e130f2015-12-16 14:45:44 -0800179 # host object may not have user attribute if it's a LocalHost object.
180 current_user = host.user if hasattr(host, 'user') else None
beeps46dadc92013-11-07 14:07:10 -0800181 try:
Simran Basi14622bb2015-11-25 13:23:40 -0800182 if not (host.hostname == 'localhost' or
183 host.verify_ssh_user_access()):
Simran Basi1621c632015-10-14 12:22:23 -0700184 host.user = 'adb'
Simran Basi933c8af2015-04-29 14:05:07 -0700185 result = host.run(
Dan Shia2872172015-10-31 01:16:51 -0700186 'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
Simran Basi933c8af2015-04-29 14:05:07 -0700187 timeout=timeout)
beeps46dadc92013-11-07 14:07:10 -0800188 except (error.AutoservRunError, error.AutoservSSHTimeout):
Dan Shi64e130f2015-12-16 14:45:44 -0800189 if current_user is not None:
190 host.user = current_user
beeps46dadc92013-11-07 14:07:10 -0800191 return False
192 return result.exit_status == 0
193
194
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700195 # TODO(garnold) Remove the 'serials' argument once all clients are made to
196 # not use it.
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700197 def _initialize(self, hostname='localhost', serials=None,
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700198 adb_serial=None, fastboot_serial=None,
Simran Basi9228a6f2016-03-29 12:03:37 -0700199 teststation=None, *args, **dargs):
Simran Basi431010f2013-09-04 10:42:41 -0700200 """Initialize an ADB Host.
201
202 This will create an ADB Host. Hostname should always refer to the
Kevin Chengd19e6c62015-10-28 16:39:39 -0700203 test station connected to an Android DUT. This will be the DUT
204 to test with. If there are multiple, serial must be specified or an
Simran Basi9228a6f2016-03-29 12:03:37 -0700205 exception will be raised.
Simran Basi431010f2013-09-04 10:42:41 -0700206
207 @param hostname: Hostname of the machine running ADB.
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700208 @param serials: DEPRECATED (to be removed)
209 @param adb_serial: An ADB device serial. If None, assume a single
210 device is attached (and fail otherwise).
211 @param fastboot_serial: A fastboot device serial. If None, defaults to
212 the ADB serial (or assumes a single device if
213 the latter is None).
Kevin Cheng549beb42015-11-18 11:42:25 -0800214 @param teststation: The teststation object ADBHost should use.
Simran Basi431010f2013-09-04 10:42:41 -0700215 """
Simran Basi1bf60eb2015-12-01 16:39:29 -0800216 # Sets up the is_client_install_supported field.
217 super(ADBHost, self)._initialize(hostname=hostname,
218 is_client_install_supported=False,
219 *args, **dargs)
Kevin Cheng85e864a2015-11-30 11:49:34 -0800220
Kevin Chengd19e6c62015-10-28 16:39:39 -0700221 self.tmp_dirs = []
Kevin Chengc6a645a2015-12-18 11:15:10 -0800222 self.labels = base_label.LabelRetriever(adb_label.ADB_LABELS)
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700223 adb_serial = adb_serial or self._afe_host.attributes.get('serials')
224 fastboot_serial = (fastboot_serial or
225 self._afe_host.attributes.get('fastboot_serial'))
226
Dan Shi50a412a2016-01-05 10:52:40 -0800227 self.adb_serial = adb_serial
Dan Shi3a011ed2016-04-26 12:26:53 -0700228 if adb_serial:
229 adb_prefix = any(adb_serial.startswith(p)
230 for p in ADB_DEVICE_PREFIXES)
231 self.fastboot_serial = (fastboot_serial or
232 ('tcp:%s' % adb_serial.split(':')[0] if
233 ':' in adb_serial and not adb_prefix else adb_serial))
234 self._use_tcpip = ':' in adb_serial and not adb_prefix
235 else:
236 self.fastboot_serial = fastboot_serial or adb_serial
237 self._use_tcpip = False
Kevin Cheng85e864a2015-11-30 11:49:34 -0800238 self.teststation = (teststation if teststation
239 else teststation_host.create_teststationhost(hostname=hostname))
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700240
241 msg ='Initializing ADB device on host: %s' % hostname
Dan Shi50a412a2016-01-05 10:52:40 -0800242 if self.adb_serial:
243 msg += ', ADB serial: %s' % self.adb_serial
244 if self.fastboot_serial:
245 msg += ', fastboot serial: %s' % self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700246 logging.debug(msg)
247
Simran Basibeb2bb22016-02-03 15:25:48 -0800248 # Try resetting the ADB daemon on the device, however if we are
249 # creating the host to do a repair job, the device maybe inaccesible
250 # via ADB.
251 try:
252 self._reset_adbd_connection()
253 except (error.AutotestHostRunError, error.AutoservRunError) as e:
254 logging.error('Unable to reset the device adb daemon connection: '
255 '%s.', e)
Dan Shiab999722015-12-04 14:27:08 -0800256 self._os_type = None
257
Simran Basi431010f2013-09-04 10:42:41 -0700258
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700259 def _connect_over_tcpip_as_needed(self):
260 """Connect to the ADB device over TCP/IP if so configured."""
Simran Basi9228a6f2016-03-29 12:03:37 -0700261 if not self._use_tcpip:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700262 return
263 logging.debug('Connecting to device over TCP/IP')
Simran Basi9228a6f2016-03-29 12:03:37 -0700264 self.adb_run('connect %s' % self.adb_serial)
Simran Basi431010f2013-09-04 10:42:41 -0700265
266
Roshan Pius4d7540c2015-12-16 13:30:32 -0800267 def _restart_adbd_with_root_permissions(self):
268 """Restarts the adb daemon with root permissions."""
Dan Shi922de302016-04-22 15:19:18 -0700269 @retry.retry(error.AutoservRunError, timeout_min=20/60.0, delay_sec=1)
270 def run_adb_root():
271 """Run command `adb root`."""
272 self.adb_run('root')
273
274 # adb command may flake with error "device not found". Retry the root
275 # command to reduce the chance of flake.
276 run_adb_root()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800277 # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
278 time.sleep(1)
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300279 self._connect_over_tcpip_as_needed()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800280 self.adb_run('wait-for-device')
281
282
Simran Basi9228a6f2016-03-29 12:03:37 -0700283 def _set_tcp_port(self):
284 """Ensure the device remains in tcp/ip mode after a reboot."""
285 if not self._use_tcpip:
286 return
287 port = self.adb_serial.split(':')[-1]
288 self.run('setprop persist.adb.tcp.port %s' % port)
289
290
Roshan Pius4d7540c2015-12-16 13:30:32 -0800291 def _reset_adbd_connection(self):
292 """Resets adbd connection to the device after a reboot/initialization"""
Roshan Pius4d7540c2015-12-16 13:30:32 -0800293 self._connect_over_tcpip_as_needed()
Simran Basi9228a6f2016-03-29 12:03:37 -0700294 self._restart_adbd_with_root_permissions()
295 self._set_tcp_port()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800296
297
Kevin Cheng85e864a2015-11-30 11:49:34 -0800298 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800299 def adb_run(self, command, **kwargs):
Simran Basi431010f2013-09-04 10:42:41 -0700300 """Runs an adb command.
301
Kevin Chengd19e6c62015-10-28 16:39:39 -0700302 This command will launch on the test station.
Simran Basi431010f2013-09-04 10:42:41 -0700303
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700304 Refer to _device_run method for docstring for parameters.
305 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800306 return self._device_run(ADB_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700307
308
Kevin Cheng85e864a2015-11-30 11:49:34 -0800309 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800310 def fastboot_run(self, command, **kwargs):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700311 """Runs an fastboot command.
312
Kevin Chengd19e6c62015-10-28 16:39:39 -0700313 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700314
315 Refer to _device_run method for docstring for parameters.
316 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800317 return self._device_run(FASTBOOT_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700318
319
Dan Shi12a4f662016-05-10 14:49:42 -0700320 # pylint: disable=missing-docstring
321 @retry.retry(error.AutoservRunError,
322 timeout_min=DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN)
323 def _fastboot_run_with_retry(self, command, **kwargs):
324 """Runs an fastboot command with retry.
325
326 This command will launch on the test station.
327
328 Refer to _device_run method for docstring for parameters.
329 """
330 return self.fastboot_run(command, **kwargs)
331
332
Simran Basie6c4f142016-06-23 17:10:04 -0700333 def _log_adb_pid(self):
334 """Log the pid of adb server.
335
336 adb's server is known to have bugs and randomly restart. BY logging
337 the server's pid it will allow us to better debug random adb failures.
338 """
339 adb_pid = self.teststation.run('pgrep -f "adb.*server"')
340 logging.debug('ADB Server PID: %s', adb_pid.stdout)
341
342
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700343 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700344 timeout=3600, ignore_status=False, ignore_timeout=False,
345 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
346 connect_timeout=30, options='', stdin=None, verbose=True,
347 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700348 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700349
Kevin Chengd19e6c62015-10-28 16:39:39 -0700350 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700351
Simran Basi431010f2013-09-04 10:42:41 -0700352 @param command: Command to run.
353 @param shell: If true the command runs in the adb shell otherwise if
354 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700355 reboot with shell=False will call 'adb reboot'. This
356 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700357 @param timeout: Time limit in seconds before attempting to
358 kill the running process. The run() function
359 will take a few seconds longer than 'timeout'
360 to complete if it has to kill the process.
361 @param ignore_status: Do not raise an exception, no matter
362 what the exit code of the command is.
363 @param ignore_timeout: Bool True if command timeouts should be
364 ignored. Will return None on command timeout.
365 @param stdout: Redirect stdout.
366 @param stderr: Redirect stderr.
367 @param connect_timeout: Connection timeout (in seconds)
368 @param options: String with additional ssh command options
369 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700370 @param require_sudo: True to require sudo to run the command. Default is
371 False.
Simran Basi431010f2013-09-04 10:42:41 -0700372 @param args: Sequence of strings to pass as arguments to command by
373 quoting them in " and escaping their contents if
374 necessary.
375
376 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700377 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700378 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800379 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700380 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800381 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700382 else:
383 raise NotImplementedError('Mode %s is not supported' % function)
384
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700385 if function != ADB_CMD and shell:
386 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700387
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700388 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700389
390 if serial:
391 cmd += '-s %s ' % serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700392
Simran Basi431010f2013-09-04 10:42:41 -0700393 if shell:
394 cmd += '%s ' % SHELL_CMD
395 cmd += command
396
Simran Basie6c4f142016-06-23 17:10:04 -0700397 self._log_adb_pid()
398
Roshan Pius58e5dd32015-10-16 15:16:42 -0700399 if verbose:
400 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700401
Kevin Cheng85e864a2015-11-30 11:49:34 -0800402 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400403 ignore_status=ignore_status,
404 ignore_timeout=ignore_timeout, stdout_tee=stdout,
405 stderr_tee=stderr, options=options, stdin=stdin,
406 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700407
408
Dan Shi8c51bda2016-05-26 12:21:02 -0700409 def _run_output_with_retry(self, cmd):
410 """Call run_output method for the given command with retry.
411
Dan Shi68094122016-06-10 14:29:06 -0700412 adb command can be flaky some time, and the command may fail or return
413 empty string. It may take several retries until a value can be returned.
Dan Shi8c51bda2016-05-26 12:21:02 -0700414
415 @param cmd: The command to run.
416
417 @return: Return value from the command after retry.
418 """
419 try:
420 return client_utils.poll_for_condition(
Dan Shi68094122016-06-10 14:29:06 -0700421 lambda: self.run_output(cmd, ignore_status=True),
Dan Shi8c51bda2016-05-26 12:21:02 -0700422 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
423 sleep_interval=0.5,
424 desc='Get return value for command `%s`' % cmd)
425 except client_utils.TimeoutError:
426 return ''
427
428
Dan Shie234dea2016-01-20 17:15:17 -0800429 def get_board_name(self):
430 """Get the name of the board, e.g., shamu, dragonboard etc.
431 """
Simran Basi9c5d3982016-04-01 18:49:44 -0700432 product = self.run_output('getprop %s' % BOARD_FILE)
433 return PRODUCT_TARGET_MAP.get(product, product)
Dan Shie234dea2016-01-20 17:15:17 -0800434
435
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700436 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700437 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700438 """Determine the correct board label for the device.
439
440 @returns a string representing this device's board.
441 """
Dan Shie234dea2016-01-20 17:15:17 -0800442 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700443 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800444 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700445
446
Christopher Wiley08849d52013-11-22 08:57:58 -0800447 def job_start(self):
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700448 """Overload of parent which intentionally doesn't log certain files.
Dan Shi2d279cf2016-05-27 22:06:10 +0000449
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700450 The parent implementation attempts to log certain Linux files, such as
451 /var/log, which do not exist on Android, thus there is no call to the
452 parent's job_start(). The sync call is made so that logcat logs can be
453 approximately matched to server logs.
Dan Shi2d279cf2016-05-27 22:06:10 +0000454 """
Simran Basid6b49792016-06-07 17:22:03 -0700455 if self.is_up():
456 self._sync_time()
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700457 self._enable_native_crash_logging()
Christopher Wiley08849d52013-11-22 08:57:58 -0800458
459
Simran Basi431010f2013-09-04 10:42:41 -0700460 def run(self, command, timeout=3600, ignore_status=False,
461 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
462 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700463 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700464 """Run a command on the adb device.
465
466 The command given will be ran directly on the adb device; for example
467 'ls' will be ran as: 'abd shell ls'
468
469 @param command: The command line string.
470 @param timeout: Time limit in seconds before attempting to
471 kill the running process. The run() function
472 will take a few seconds longer than 'timeout'
473 to complete if it has to kill the process.
474 @param ignore_status: Do not raise an exception, no matter
475 what the exit code of the command is.
476 @param ignore_timeout: Bool True if command timeouts should be
477 ignored. Will return None on command timeout.
478 @param stdout_tee: Redirect stdout.
479 @param stderr_tee: Redirect stderr.
480 @param connect_timeout: Connection timeout (in seconds).
481 @param options: String with additional ssh command options.
482 @param stdin: Stdin to pass (a string) to the executed command
483 @param args: Sequence of strings to pass as arguments to command by
484 quoting them in " and escaping their contents if
485 necessary.
486
487 @returns A CMDResult object or None if the call timed out and
488 ignore_timeout is True.
489
490 @raises AutoservRunError: If the command failed.
491 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700492 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700493 command = ('"%s; echo %s:\$?"' %
494 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700495 result = self.adb_run(
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700496 command, shell=True, timeout=timeout,
Simran Basi431010f2013-09-04 10:42:41 -0700497 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
498 stdout=stdout_tee, stderr=stderr_tee,
499 connect_timeout=connect_timeout, options=options, stdin=stdin,
Roshan Pius58e5dd32015-10-16 15:16:42 -0700500 verbose=verbose, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700501 if not result:
502 # In case of timeouts.
503 return None
504
505 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
Roshan Pius5ba5d182015-10-28 09:19:41 -0700506 if not parse_output and not ignore_status:
Simran Basi431010f2013-09-04 10:42:41 -0700507 raise error.AutoservRunError(
Roshan Pius5ba5d182015-10-28 09:19:41 -0700508 'Failed to parse the exit code for command: %s' %
509 command, result)
510 elif parse_output:
511 result.stdout = parse_output.group('OUTPUT')
512 result.exit_status = int(parse_output.group('EXIT_CODE'))
513 if result.exit_status != 0 and not ignore_status:
514 raise error.AutoservRunError(command, result)
Simran Basi431010f2013-09-04 10:42:41 -0700515 return result
516
517
Dan Shicf7d2562016-06-16 14:08:23 -0700518 def check_boot_to_adb_complete(self, exception_type=error.TimeoutException):
519 """Check if the device has finished booting and accessible by adb.
520
521 @param exception_type: Type of exception to raise. Default is set to
522 error.TimeoutException for retry.
523
524 @raise exception_type: If the device has not finished booting yet, raise
525 an exception of type `exception_type`.
526 """
527 bootcomplete = self._run_output_with_retry('getprop dev.bootcomplete')
528 if bootcomplete != PROPERTY_VALUE_TRUE:
529 raise exception_type('dev.bootcomplete is %s.' % bootcomplete)
530 if self.get_os_type() == OS_TYPE_ANDROID:
531 boot_completed = self._run_output_with_retry(
532 'getprop sys.boot_completed')
533 if boot_completed != PROPERTY_VALUE_TRUE:
534 raise exception_type('sys.boot_completed is %s.' %
535 boot_completed)
536
537
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700538 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
539 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700540
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700541 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700542
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700543 @param timeout: Time limit in seconds before returning even if the host
544 is not up.
545 @param command: The command used to test if a device is up, i.e.,
546 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700547
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700548 @returns True if the host was found to be up before the timeout expires,
549 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700550 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700551 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
552 delay_sec=1)
553 def _wait_up():
554 if not self.is_up(command=command):
555 raise error.TimeoutException('Device is still down.')
Dan Shicf7d2562016-06-16 14:08:23 -0700556 if command == ADB_CMD:
557 self.check_boot_to_adb_complete()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700558 return True
559
560 try:
561 _wait_up()
562 logging.debug('Host %s is now up, and can be accessed by %s.',
563 self.hostname, command)
564 return True
565 except error.TimeoutException:
566 logging.debug('Host %s is still down after waiting %d seconds',
567 self.hostname, timeout)
568 return False
Simran Basi431010f2013-09-04 10:42:41 -0700569
570
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700571 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
572 warning_timer=None, old_boot_id=None, command=ADB_CMD):
573 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700574
575 Overrides wait_down from AbstractSSHHost.
576
577 @param timeout: Time in seconds to wait for the host to go down.
578 @param warning_timer: Time limit in seconds that will generate
579 a warning if the host is not down yet.
580 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700581 @param old_boot_id: Not applicable for adb_host.
582 @param command: `adb`, test if the device can be accessed by adb
583 command, or `fastboot`, test if the device can be accessed by
584 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700585
586 @returns True if the device goes down before the timeout, False
587 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700588 """
589 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
590 delay_sec=1)
591 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700592 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700593 raise error.TimeoutException('Device is still up.')
594 return True
595
596 try:
597 _wait_down()
598 logging.debug('Host %s is now down', self.hostname)
599 return True
600 except error.TimeoutException:
601 logging.debug('Host %s is still up after waiting %d seconds',
602 self.hostname, timeout)
603 return False
604
605
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700606 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700607 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700608
609 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700610 """
611 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700612 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700613 self.adb_run('reboot', timeout=10, ignore_timeout=True)
614 if not self.wait_down():
615 raise error.AutoservRebootError(
616 'ADB Device is still up after reboot')
617 if not self.wait_up():
618 raise error.AutoservRebootError(
619 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800620 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800621
622
Alexandru Branciog969ff7c2016-03-30 14:07:15 +0300623 def fastboot_reboot(self):
624 """Do a fastboot reboot to go back to adb.
625
626 @raises AutoservRebootError if reboot failed.
627 """
628 self.fastboot_run('reboot')
629 if not self.wait_down(command=FASTBOOT_CMD):
630 raise error.AutoservRebootError(
631 'Device is still in fastboot mode after reboot')
632 if not self.wait_up():
633 raise error.AutoservRebootError(
634 'Device failed to boot to adb after fastboot reboot.')
635 self._reset_adbd_connection()
636
637
Ralph Nathanb45eb672015-11-18 20:04:39 -0800638 def remount(self):
639 """Remounts paritions on the device read-write.
640
641 Specifically, the /system, /vendor (if present) and /oem (if present)
642 partitions on the device are remounted read-write.
643 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800644 self.adb_run('remount')
645
646
Kevin Cheng549beb42015-11-18 11:42:25 -0800647 @staticmethod
648 def parse_device_serials(devices_output):
649 """Return a list of parsed serials from the output.
650
651 @param devices_output: Output from either an adb or fastboot command.
652
653 @returns List of device serials
654 """
655 devices = []
656 for line in devices_output.splitlines():
657 match = re.search(DEVICE_FINDER_REGEX, line)
658 if match:
659 serial = match.group('SERIAL')
660 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
661 serial = DEVICE_NO_SERIAL_TAG
662 logging.debug('Found Device: %s', serial)
663 devices.append(serial)
664 return devices
665
666
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700667 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700668 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700669
670 @params use_adb: True to get adb accessible devices. Set to False to
671 get fastboot accessible devices.
672
Kevin Chengd19e6c62015-10-28 16:39:39 -0700673 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700674 """
675 if use_adb:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300676 result = self.adb_run('devices').stdout
677 if self.adb_serial and self.adb_serial not in result:
678 self._connect_over_tcpip_as_needed()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700679 else:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300680 result = self.fastboot_run('devices').stdout
681 if (self.fastboot_serial and
682 self.fastboot_serial not in result):
683 # fastboot devices won't list the devices using TCP
684 try:
685 if 'product' in self.fastboot_run('getvar product',
686 timeout=2).stderr:
687 result += '\n%s\tfastboot' % self.fastboot_serial
Kevin Chengcfcb2cf2016-04-13 10:04:36 -0700688 # The main reason we do a general Exception catch here instead
689 # of setting ignore_timeout/status to True is because even when
690 # the fastboot process has been nuked, it still stays around and
691 # so bgjob wants to warn us of this and tries to read the
692 # /proc/<pid>/stack file which then promptly returns an
693 # 'Operation not permitted' error since we're running as moblab
694 # and we don't have permission to read those files.
695 except Exception:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300696 pass
697 return self.parse_device_serials(result)
Simran Basi431010f2013-09-04 10:42:41 -0700698
699
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700700 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700701 """Get a list of devices currently attached to the test station and
702 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700703 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800704 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700705 raise error.AutoservError(
706 'Not given ADB serial but multiple devices detected')
707 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700708
709
710 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700711 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700712 accessible by fastboot command.
713 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700714 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800715 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700716 raise error.AutoservError(
717 'Not given fastboot serial but multiple devices detected')
718 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700719
720
721 def is_up(self, timeout=0, command=ADB_CMD):
722 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700723
724 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700725 @param command: `adb`, the device can be accessed by adb command,
726 or `fastboot`, the device can be accessed by fastboot command.
727 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700728
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700729 @returns True if the device is detectable by given command, False
730 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700731
732 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700733 if command == ADB_CMD:
734 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800735 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800736 # ADB has a device state, if the device is not online, no
737 # subsequent ADB command will complete.
Dan Shi6450e142016-03-11 11:52:20 -0800738 # DUT with single device connected may not have adb_serial set.
739 # Therefore, skip checking if serial is in the list of adb devices
740 # if self.adb_serial is not set.
741 if (serial and serial not in devices) or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800742 logging.debug('Waiting for device to enter the ready state.')
743 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700744 elif command == FASTBOOT_CMD:
745 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800746 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700747 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700748 raise NotImplementedError('Mode %s is not supported' % command)
749
750 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700751
752
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700753 def stop_loggers(self):
754 """Inherited stop_loggers function.
755
756 Calls parent function and captures logcat, since the end of the run
757 is logically the end/stop of the logcat log.
758 """
759 super(ADBHost, self).stop_loggers()
760 # Record logcat log to a temporary file on the teststation.
761 tmp_dir = self.teststation.get_tmp_dir()
Simran Basi242f8de2016-06-08 14:23:43 -0700762 logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
763 teststation_filename = os.path.join(tmp_dir, logcat_filename)
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700764 try:
765 self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
766 timeout=20)
Simran Basid6b49792016-06-07 17:22:03 -0700767 except (error.AutotestHostRunError, error.AutoservRunError,
768 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700769 return
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700770 # Copy-back the log to the drone's results directory.
Simran Basi242f8de2016-06-08 14:23:43 -0700771 results_logcat_filename = os.path.join(self.job.resultdir,
772 logcat_filename)
773 self.teststation.get_file(teststation_filename,
774 results_logcat_filename)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700775 try:
776 self.teststation.run('rm -rf %s' % tmp_dir)
777 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
778 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
779
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700780 self._collect_crash_logs()
781
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700782
Simran Basi431010f2013-09-04 10:42:41 -0700783 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700784 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700785
786 Called as the test ends. Will return the device to USB mode and kill
787 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700788 """
Christopher Wiley08849d52013-11-22 08:57:58 -0800789 # TODO(sbasi) Originally, we would kill the server after each test to
790 # reduce the opportunity for bad server state to hang around.
791 # Unfortunately, there is a period of time after each kill during which
792 # the Android device becomes unusable, and if we start the next test
793 # too quickly, we'll get an error complaining about no ADB device
794 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700795 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800796 # |close| the associated teststation as well.
797 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700798 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700799
800
801 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700802 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700803
804 @param message String message to log into syslog
805 @param tag String tag prefix for syslog
806
807 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700808 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700809
810
811 def get_autodir(self):
812 """Return the directory to install autotest for client side tests."""
813 return '/data/autotest'
814
Kevin Cheng018db352015-09-20 02:22:08 -0700815
Kris Rambishde8f9d12015-12-16 12:42:41 -0800816 def is_device_ready(self):
817 """Return the if the device is ready for ADB commands."""
Dan Shi7075f552016-04-21 15:42:41 -0700818 try:
819 # Retry to avoid possible flakes.
820 is_ready = client_utils.poll_for_condition(
821 lambda: self.adb_run('get-state').stdout.strip() == 'device',
822 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
823 desc='Waiting for device state to be `device`')
824 except client_utils.TimeoutError:
825 is_ready = False
826
827 logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
828 return is_ready
Kris Rambishde8f9d12015-12-16 12:42:41 -0800829
830
Kevin Chengd19e6c62015-10-28 16:39:39 -0700831 def verify_connectivity(self):
832 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800833 if not self.is_device_ready():
834 raise error.AutoservHostError('device state is not in the '
835 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700836
837
Simran Basid3ba3fb2015-09-11 14:35:07 -0700838 def verify_software(self):
839 """Verify working software on an adb_host.
840
Simran Basi38f7ddf2015-09-18 12:25:03 -0700841 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700842 """
Dan Shiab999722015-12-04 14:27:08 -0800843 # Check if adb and fastboot are present.
844 self.teststation.run('which adb')
845 self.teststation.run('which fastboot')
846 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700847
Dan Shi626d5412016-05-16 16:05:13 -0700848 # Apply checks only for Android device.
Dan Shi1e2a98a2016-05-18 12:08:08 -0700849 if self.get_os_type() == OS_TYPE_ANDROID:
Dan Shi626d5412016-05-16 16:05:13 -0700850 # Make sure ro.boot.hardware and ro.build.product match.
Dan Shi8c51bda2016-05-26 12:21:02 -0700851 hardware = self._run_output_with_retry('getprop ro.boot.hardware')
852 product = self._run_output_with_retry('getprop ro.build.product')
Dan Shi1e2a98a2016-05-18 12:08:08 -0700853 if hardware != product:
854 raise error.AutoservHostError('ro.boot.hardware: %s does not '
855 'match to ro.build.product: %s' %
856 (hardware, product))
857
Kevin Cheng018db352015-09-20 02:22:08 -0700858
Simran Basid3ba3fb2015-09-11 14:35:07 -0700859 def verify_job_repo_url(self, tag=''):
860 """Make sure job_repo_url of this host is valid.
861
Simran Basi38f7ddf2015-09-18 12:25:03 -0700862 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700863
864 @param tag: The tag from the server job, in the format
865 <job_id>-<user>/<hostname>, or <hostless> for a server job.
866 """
867 return
Kevin Cheng018db352015-09-20 02:22:08 -0700868
869
Simran Basibeb2bb22016-02-03 15:25:48 -0800870 def repair(self):
871 """Attempt to get the DUT to pass `self.verify()`."""
872 try:
873 self.ensure_adb_mode(timeout=30)
874 return
875 except error.AutoservError as e:
876 logging.error(e)
877 logging.debug('Verifying the device is accessible via fastboot.')
878 self.ensure_bootloader_mode()
879 if not self.job.run_test(
880 'provision_AndroidUpdate', host=self, value=None,
881 force=True, repair=True):
882 raise error.AutoservRepairTotalFailure(
883 'Unable to repair the device.')
884
885
Simran Basi1b023762015-09-25 12:12:20 -0700886 def send_file(self, source, dest, delete_dest=False,
887 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700888 """Copy files from the drone to the device.
889
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400890 Just a note, there is the possibility the test station is localhost
891 which makes some of these steps redundant (e.g. creating tmp dir) but
892 that scenario will undoubtedly be a development scenario (test station
893 is also the moblab) and not the typical live test running scenario so
894 the redundancy I think is harmless.
895
Kevin Cheng018db352015-09-20 02:22:08 -0700896 @param source: The file/directory on the drone to send to the device.
897 @param dest: The destination path on the device to copy to.
898 @param delete_dest: A flag set to choose whether or not to delete
899 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700900 @param preserve_symlinks: Controls if symlinks on the source will be
901 copied as such on the destination or
902 transformed into the referenced
903 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700904 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700905 # If we need to preserve symlinks, let's check if the source is a
906 # symlink itself and if so, just create it on the device.
907 if preserve_symlinks:
908 symlink_target = None
909 try:
910 symlink_target = os.readlink(source)
911 except OSError:
912 # Guess it's not a symlink.
913 pass
914
915 if symlink_target is not None:
916 # Once we create the symlink, let's get out of here.
917 self.run('ln -s %s %s' % (symlink_target, dest))
918 return
919
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400920 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700921 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400922 src_path = os.path.join(tmp_dir, os.path.basename(dest))
923 # Now copy the file over to the test station so you can reference the
924 # file in the push command.
925 self.teststation.send_file(source, src_path,
926 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700927
928 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400929 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700930
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700931 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700932
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400933 # Cleanup the test station.
934 try:
935 self.teststation.run('rm -rf %s' % tmp_dir)
936 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
937 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700938
939
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700940 def _get_file_info(self, dest):
941 """Get permission and possible symlink info about file on the device.
942
943 These files are on the device so we only have shell commands (via adb)
944 to get the info we want. We'll use 'ls' to get it all.
945
946 @param dest: File to get info about.
947
948 @returns a dict of the file permissions and symlink.
949 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800950 # Grab file info.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700951 file_info = self.run_output('ls -ld %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700952 symlink = None
953 perms = 0
954 match = re.match(FILE_INFO_REGEX, file_info)
955 if match:
956 # Check if it's a symlink and grab the linked dest if it is.
957 if match.group('TYPE') == 'l':
958 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
959 if symlink_match:
960 symlink = symlink_match.group('SYMLINK')
961
962 # Set the perms.
963 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
964 if perm != '-':
965 perms |= perm_flag
966
967 return {'perms': perms,
968 'symlink': symlink}
969
970
Simran Basi1b023762015-09-25 12:12:20 -0700971 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
972 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700973 """Copy files from the device to the drone.
974
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400975 Just a note, there is the possibility the test station is localhost
976 which makes some of these steps redundant (e.g. creating tmp dir) but
977 that scenario will undoubtedly be a development scenario (test station
978 is also the moblab) and not the typical live test running scenario so
979 the redundancy I think is harmless.
980
Kevin Cheng018db352015-09-20 02:22:08 -0700981 @param source: The file/directory on the device to copy back to the
982 drone.
983 @param dest: The destination path on the drone to copy to.
984 @param delete_dest: A flag set to choose whether or not to delete
985 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700986 @param preserve_perm: Tells get_file() to try to preserve the sources
987 permissions on files and dirs.
988 @param preserve_symlinks: Try to preserve symlinks instead of
989 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -0700990 """
David Purselle01548b2016-05-11 10:00:42 -0700991 # Stage the files on the test station under teststation_temp_dir.
992 teststation_temp_dir = self.teststation.get_tmp_dir()
993 teststation_dest = os.path.join(teststation_temp_dir,
994 os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -0700995
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700996 source_info = {}
997 if preserve_symlinks or preserve_perm:
998 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -0700999
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001000 # If we want to preserve symlinks, just create it here, otherwise pull
1001 # the file off the device.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001002 #
1003 # TODO(sadmac): Directories containing symlinks won't behave as
1004 # expected.
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001005 if preserve_symlinks and source_info['symlink']:
1006 os.symlink(source_info['symlink'], dest)
1007 else:
David Purselle01548b2016-05-11 10:00:42 -07001008 self.adb_run('pull %s %s' % (source, teststation_temp_dir))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001009
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001010 # Copy over the file from the test station and clean up.
David Purselle01548b2016-05-11 10:00:42 -07001011 self.teststation.get_file(teststation_dest, dest,
1012 delete_dest=delete_dest)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001013 try:
David Purselle01548b2016-05-11 10:00:42 -07001014 self.teststation.run('rm -rf %s' % teststation_temp_dir)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001015 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
David Purselle01548b2016-05-11 10:00:42 -07001016 logging.warn('failed to remove dir %s: %s',
1017 teststation_temp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001018
David Pursell788b1b52016-05-19 09:03:31 -07001019 # Source will be copied under dest if either:
1020 # 1. Source is a directory and doesn't end with /.
1021 # 2. Source is a file and dest is a directory.
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001022 command = '[ -d %s ]' % source
1023 source_is_dir = self.run(command,
David Pursell788b1b52016-05-19 09:03:31 -07001024 ignore_status=True).exit_status == 0
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001025
David Pursell788b1b52016-05-19 09:03:31 -07001026 if ((source_is_dir and not source.endswith(os.sep)) or
1027 (not source_is_dir and os.path.isdir(dest))):
1028 receive_path = os.path.join(dest, os.path.basename(source))
1029 else:
1030 receive_path = dest
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001031
David Pursell788b1b52016-05-19 09:03:31 -07001032 # Set the permissions of the received file/dirs.
1033 if os.path.isdir(receive_path):
1034 for root, _dirs, files in os.walk(receive_path):
1035 def process(rel_path, default_perm):
1036 info = self._get_file_info(os.path.join(source,
1037 rel_path))
1038 if info['perms'] != 0:
1039 target = os.path.join(receive_path, rel_path)
1040 if preserve_perm:
1041 os.chmod(target, info['perms'])
1042 else:
1043 os.chmod(target, default_perm)
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001044
David Pursell788b1b52016-05-19 09:03:31 -07001045 rel_root = os.path.relpath(root, receive_path)
1046 process(rel_root, _DEFAULT_DIR_PERMS)
1047 for f in files:
1048 process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
1049 elif preserve_perm:
1050 os.chmod(receive_path, source_info['perms'])
1051 else:
1052 os.chmod(receive_path, _DEFAULT_FILE_PERMS)
Kevin Cheng018db352015-09-20 02:22:08 -07001053
1054
1055 def get_release_version(self):
1056 """Get the release version from the RELEASE_FILE on the device.
1057
1058 @returns The release string in the RELEASE_FILE.
1059
1060 """
1061 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -07001062
1063
1064 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001065 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001066
Kevin Chengd19e6c62015-10-28 16:39:39 -07001067 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001068
1069 @param parent: Parent directory of the returned tmp dir.
1070
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07001071 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001072 """
Kevin Chengd19e6c62015-10-28 16:39:39 -07001073 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
1074 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001075 if not parent.startswith(TMP_DIR):
1076 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -07001077 self.run('mkdir -p %s' % parent)
1078 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
1079 self.tmp_dirs.append(tmp_dir)
1080 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -07001081
1082
1083 def get_platform(self):
1084 """Determine the correct platform label for this host.
1085
1086 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -07001087 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -07001088
1089 @returns a string representing this host's platform.
1090 """
1091 return 'adb'
1092
1093
Gilad Arnolda76bef02015-09-29 13:55:15 -07001094 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -08001095 """Get the OS type of the DUT, e.g., android or brillo.
1096 """
1097 if not self._os_type:
1098 if self.run_output('getprop ro.product.brand') == 'Brillo':
1099 self._os_type = OS_TYPE_BRILLO
1100 else:
1101 self._os_type = OS_TYPE_ANDROID
1102
1103 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001104
1105
1106 def _forward(self, reverse, args):
1107 """Execute a forwarding command.
1108
1109 @param reverse: Whether this is reverse forwarding (Boolean).
1110 @param args: List of command arguments.
1111 """
1112 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001113 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001114
1115
1116 def add_forwarding(self, src, dst, reverse=False, rebind=True):
1117 """Forward a port between the ADB host and device.
1118
1119 Port specifications are any strings accepted as such by ADB, for
1120 example 'tcp:8080'.
1121
1122 @param src: Port specification to forward from.
1123 @param dst: Port specification to forward to.
1124 @param reverse: Do reverse forwarding from device to host (Boolean).
1125 @param rebind: Allow rebinding an already bound port (Boolean).
1126 """
1127 args = []
1128 if not rebind:
1129 args.append('--no-rebind')
1130 args += [src, dst]
1131 self._forward(reverse, args)
1132
1133
1134 def remove_forwarding(self, src=None, reverse=False):
1135 """Removes forwarding on port.
1136
1137 @param src: Port specification, or None to remove all forwarding.
1138 @param reverse: Whether this is reverse forwarding (Boolean).
1139 """
1140 args = []
1141 if src is None:
1142 args.append('--remove-all')
1143 else:
1144 args += ['--remove', src]
1145 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001146
1147
xixuan6cf6d2f2016-01-29 15:29:00 -08001148 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001149 """
1150 Forwards a port securely through a tunnel process from the server
1151 to the DUT for RPC server connection.
1152 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
1153 to the DUT.
1154
1155 @param port: remote port on the DUT.
1156 @param local_port: local forwarding port.
1157
1158 @return: the tunnel process.
1159 """
1160 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001161 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001162
1163
xixuan6cf6d2f2016-01-29 15:29:00 -08001164 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001165 """
1166 Disconnects a previously forwarded port from the server to the DUT for
1167 RPC server connection.
1168 Remove the previously added 'ADB forward' rule to forward the RPC
1169 packets from the AdbHost to the DUT.
1170
1171 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -08001172 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -07001173 @param port: remote port on the DUT.
1174
1175 """
1176 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001177 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001178
1179
1180 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001181 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001182
1183 @raise: error.AutoservError if the device failed to reboot into
1184 bootloader mode.
1185 """
1186 if self.is_up(command=FASTBOOT_CMD):
1187 return
1188 self.adb_run('reboot bootloader')
1189 if not self.wait_up(command=FASTBOOT_CMD):
1190 raise error.AutoservError(
1191 'The device failed to reboot into bootloader mode.')
1192
1193
Dan Shie4e807b2015-12-10 09:04:03 -08001194 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001195 """Ensure the device is up and can be accessed by adb command.
1196
Dan Shie4e807b2015-12-10 09:04:03 -08001197 @param timeout: Time limit in seconds before returning even if the host
1198 is not up.
1199
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001200 @raise: error.AutoservError if the device failed to reboot into
1201 adb mode.
1202 """
1203 if self.is_up():
1204 return
Dan Shi04980372016-03-22 10:57:47 -07001205 # Ignore timeout error to allow `fastboot reboot` to fail quietly and
1206 # check if the device is in adb mode.
1207 self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
Dan Shie4e807b2015-12-10 09:04:03 -08001208 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001209 raise error.AutoservError(
1210 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -08001211 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -07001212
1213
1214 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -08001215 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001216 """Get the Android build information from the build url.
1217
1218 @param build_url: The url to use for downloading Android artifacts.
1219 pattern: http://$devserver:###/static/branch/target/build_id
1220
Dan Shi6450e142016-03-11 11:52:20 -08001221 @return: A dictionary of build information, including keys:
1222 build_target, branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -08001223 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -07001224 """
Dan Shiab999722015-12-04 14:27:08 -08001225 if not build_url:
1226 raise AndroidInstallError('Need build_url to download image files.')
1227
1228 try:
1229 match = re.match(DEVSERVER_URL_REGEX, build_url)
Dan Shi6450e142016-03-11 11:52:20 -08001230 return {'build_target': match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001231 'branch': match.group('BRANCH'),
Dan Shi6450e142016-03-11 11:52:20 -08001232 'target': ('%s-%s' % (match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001233 match.group('BUILD_TYPE'))),
1234 'build_id': match.group('BUILD_ID')}
1235 except (AttributeError, IndexError, ValueError) as e:
1236 raise AndroidInstallError(
1237 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001238
1239
Dan Shia2872172015-10-31 01:16:51 -07001240 @retry.retry(error.AutoservRunError, timeout_min=10)
Simran Basi7756a0b2016-03-16 13:10:07 -07001241 def download_file(self, build_url, file, dest_dir, unzip=False,
1242 unzip_dest=None):
Dan Shia2872172015-10-31 01:16:51 -07001243 """Download the given file from the build url.
1244
1245 @param build_url: The url to use for downloading Android artifacts.
1246 pattern: http://$devserver:###/static/branch/target/build_id
1247 @param file: Name of the file to be downloaded, e.g., boot.img.
1248 @param dest_dir: Destination folder for the file to be downloaded to.
Simran Basi7756a0b2016-03-16 13:10:07 -07001249 @param unzip: If True, unzip the downloaded file.
1250 @param unzip_dest: Location to unzip the downloaded file to. If not
1251 provided, dest_dir is used.
Dan Shia2872172015-10-31 01:16:51 -07001252 """
Dan Shidb0366c2016-02-19 10:36:18 -08001253 # Append the file name to the url if build_url is linked to the folder
1254 # containing the file.
1255 if not build_url.endswith('/%s' % file):
1256 src_url = os.path.join(build_url, file)
1257 else:
1258 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001259 dest_file = os.path.join(dest_dir, file)
1260 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001261 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Simran Basi7756a0b2016-03-16 13:10:07 -07001262 if unzip:
1263 unzip_dest = unzip_dest or dest_dir
1264 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1265 (dest_dir, file, unzip_dest))
Dan Shia2872172015-10-31 01:16:51 -07001266 except:
1267 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001268 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001269 raise
1270
1271
Dan Shiab999722015-12-04 14:27:08 -08001272 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001273 """Download required image files from the given build_url to a local
1274 directory in the machine runs fastboot command.
1275
1276 @param build_url: The url to use for downloading Android artifacts.
1277 pattern: http://$devserver:###/static/branch/target/build_id
1278
1279 @return: Path to the directory contains image files.
1280 """
Dan Shi08ff1282016-02-18 19:51:16 -08001281 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001282
1283 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001284 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001285
1286 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001287 self.download_file(build_url, zipped_image_file, image_dir,
1288 unzip=True)
Dan Shi49d451f2016-04-19 09:25:01 -07001289 images = android_utils.AndroidImageFiles.get_standalone_images(
1290 build_info['build_target'])
1291 for image_file in images:
Dan Shidb0366c2016-02-19 10:36:18 -08001292 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001293
Dan Shia2872172015-10-31 01:16:51 -07001294 return image_dir
1295 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001296 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001297 raise
1298
1299
Dan Shiab999722015-12-04 14:27:08 -08001300 def stage_brillo_image_files(self, build_url):
1301 """Download required brillo image files from the given build_url to a
1302 local directory in the machine runs fastboot command.
1303
1304 @param build_url: The url to use for downloading Android artifacts.
1305 pattern: http://$devserver:###/static/branch/target/build_id
1306
1307 @return: Path to the directory contains image files.
1308 """
Dan Shi08ff1282016-02-18 19:51:16 -08001309 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001310
1311 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1312 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1313 image_dir = self.teststation.get_tmp_dir()
Dan Shiab999722015-12-04 14:27:08 -08001314
1315 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001316 self.download_file(build_url, zipped_image_file, image_dir,
1317 unzip=True)
1318 self.download_file(build_url, vendor_partitions_file, image_dir,
1319 unzip=True,
1320 unzip_dest=os.path.join(image_dir, 'vendor'))
Dan Shiab999722015-12-04 14:27:08 -08001321 return image_dir
1322 except:
1323 self.teststation.run('rm -rf %s' % image_dir)
1324 raise
1325
1326
Simran Basibeb2bb22016-02-03 15:25:48 -08001327 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001328 """Stage a build on a devserver and return the build_url and devserver.
1329
1330 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001331
Dan Shi225b9042015-11-18 10:25:21 -08001332 @returns a tuple with an update URL like:
1333 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1334 and the devserver instance.
1335 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001336 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001337 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001338 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1339 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001340 build_name = devserver.translate(build_name)
Dan Shi6450e142016-03-11 11:52:20 -08001341 branch, target, build_id = utils.parse_launch_control_build(build_name)
Simran Basibeb2bb22016-02-03 15:25:48 -08001342 is_brillo = os_type == OS_TYPE_BRILLO
Dan Shi08ff1282016-02-18 19:51:16 -08001343 devserver.trigger_download(target, build_id, branch,
1344 is_brillo=is_brillo, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001345 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001346
1347
Dan Shie4e807b2015-12-10 09:04:03 -08001348 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001349 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001350 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001351
1352 Following are the steps used here to provision an android device:
1353 1. If build_local_path is not set, download the image zip file, e.g.,
1354 shamu-img-2284311.zip, unzip it.
1355 2. Run fastboot to install following artifacts:
1356 bootloader, radio, boot, system, vendor(only if exists)
1357
1358 Repair is not supported for Android devices yet.
1359
1360 @param build_url: The url to use for downloading Android artifacts.
1361 pattern: http://$devserver:###/static/$build
1362 @param build_local_path: The path to a local folder that contains the
1363 image files needed to provision the device. Note that the folder
1364 is in the machine running adb command, rather than the drone.
1365 @param wipe: If true, userdata will be wiped before flashing.
1366 @param flash_all: If True, all img files found in img_path will be
1367 flashed. Otherwise, only boot and system are flashed.
1368
1369 @raises AndroidInstallError if any error occurs.
1370 """
Dan Shia2872172015-10-31 01:16:51 -07001371 # If the build is not staged in local server yet, clean up the temp
1372 # folder used to store image files after the provision is completed.
1373 delete_build_folder = bool(not build_local_path)
1374
1375 try:
1376 # Download image files needed for provision to a local directory.
1377 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001378 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001379
1380 # Device needs to be in bootloader mode for flashing.
1381 self.ensure_bootloader_mode()
1382
1383 if wipe:
Dan Shi12a4f662016-05-10 14:49:42 -07001384 self._fastboot_run_with_retry('-w')
Dan Shia2872172015-10-31 01:16:51 -07001385
1386 # Get all *.img file in the build_local_path.
1387 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001388 image_files = self.teststation.run(
1389 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001390 images = dict([(os.path.basename(f), f) for f in image_files])
Dan Shi49d451f2016-04-19 09:25:01 -07001391 build_info = self.get_build_info_from_build_url(build_url)
1392 board = build_info['build_target']
1393 all_images = (
1394 android_utils.AndroidImageFiles.get_standalone_images(board)
1395 + android_utils.AndroidImageFiles.get_zipped_images(board))
1396
1397 # Sort images to be flashed, bootloader needs to be the first one.
1398 bootloader = android_utils.AndroidImageFiles.BOOTLOADER
1399 sorted_images = sorted(
1400 images.items(),
1401 key=lambda pair: 0 if pair[0] == bootloader else 1)
1402 for image, image_file in sorted_images:
1403 if image not in all_images:
Dan Shia2872172015-10-31 01:16:51 -07001404 continue
1405 logging.info('Flashing %s...', image_file)
Dan Shi12a4f662016-05-10 14:49:42 -07001406 self._fastboot_run_with_retry('-S 256M flash %s %s' %
1407 (image[:-4], image_file))
Dan Shi49d451f2016-04-19 09:25:01 -07001408 if image == android_utils.AndroidImageFiles.BOOTLOADER:
Dan Shia2872172015-10-31 01:16:51 -07001409 self.fastboot_run('reboot-bootloader')
1410 self.wait_up(command=FASTBOOT_CMD)
1411 except Exception as e:
1412 logging.error('Install Android build failed with error: %s', e)
1413 # Re-raise the exception with type of AndroidInstallError.
1414 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1415 finally:
1416 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001417 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001418 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1419 DEFAULT_WAIT_UP_TIME_SECONDS)
1420 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001421 logging.info('Successfully installed Android build staged at %s.',
1422 build_url)
1423
1424
Dan Shiab999722015-12-04 14:27:08 -08001425 def install_brillo(self, build_url, build_local_path=None):
1426 """Install the Brillo DUT.
1427
1428 Following are the steps used here to provision an android device:
1429 1. If build_local_path is not set, download the image zip file, e.g.,
1430 dragonboard-img-123456.zip, unzip it. And download the vendor
1431 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1432 unzip it to vendor folder.
1433 2. Run provision_device script to install OS images and vendor
1434 partitions.
1435
1436 @param build_url: The url to use for downloading Android artifacts.
1437 pattern: http://$devserver:###/static/$build
1438 @param build_local_path: The path to a local folder that contains the
1439 image files needed to provision the device. Note that the folder
1440 is in the machine running adb command, rather than the drone.
1441
1442 @raises AndroidInstallError if any error occurs.
1443 """
1444 # If the build is not staged in local server yet, clean up the temp
1445 # folder used to store image files after the provision is completed.
1446 delete_build_folder = bool(not build_local_path)
1447
Dan Shiab999722015-12-04 14:27:08 -08001448 try:
1449 # Download image files needed for provision to a local directory.
1450 if not build_local_path:
1451 build_local_path = self.stage_brillo_image_files(build_url)
1452
1453 # Device needs to be in bootloader mode for flashing.
1454 self.ensure_bootloader_mode()
1455
1456 # Run provision_device command to install image files and vendor
1457 # partitions.
1458 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1459 cmd = (BRILLO_PROVISION_CMD %
1460 {'os_image_dir': build_local_path,
1461 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001462 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001463 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001464 self.teststation.run(cmd)
1465 except Exception as e:
1466 logging.error('Install Brillo build failed with error: %s', e)
1467 # Re-raise the exception with type of AndroidInstallError.
1468 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1469 finally:
1470 if delete_build_folder:
1471 self.teststation.run('rm -rf %s' % build_local_path)
1472 self.ensure_adb_mode()
1473 logging.info('Successfully installed Android build staged at %s.',
1474 build_url)
1475
1476
Dan Shibe3636a2016-02-14 22:48:01 -08001477 @property
1478 def job_repo_url_attribute(self):
1479 """Get the host attribute name for job_repo_url, which should append the
1480 adb serial.
1481 """
1482 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1483
1484
Dan Shie4e807b2015-12-10 09:04:03 -08001485 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001486 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001487 """Install the DUT.
1488
1489 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001490 pattern: http://$devserver:###/static/$build. If build_url is
1491 set to None, the code may try _parser.options.image to do the
1492 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001493 @param build_local_path: The path to a local directory that contains the
1494 image files needed to provision the device.
1495 @param wipe: If true, userdata will be wiped before flashing.
1496 @param flash_all: If True, all img files found in img_path will be
1497 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001498
Dan Shibe3636a2016-02-14 22:48:01 -08001499 @returns A tuple of (image_name, host_attributes).
1500 image_name is the name of image installed, e.g.,
1501 git_mnc-release/shamu-userdebug/1234
1502 host_attributes is a dictionary of (attribute, value), which
1503 can be saved to afe_host_attributes table in database. This
1504 method returns a dictionary with a single entry of
1505 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1506 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001507 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001508 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001509 if not build_url and self._parser.options.image:
1510 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001511 self._parser.options.image, os_type=os_type)
1512 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001513 self.install_android(
1514 build_url=build_url, build_local_path=build_local_path,
1515 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001516 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001517 self.install_brillo(
1518 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001519 else:
1520 raise error.InstallError(
1521 'Installation of os type %s is not supported.' %
1522 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001523 return (build_url.split('static/')[-1],
1524 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001525
1526
1527 def list_files_glob(self, path_glob):
1528 """Get a list of files on the device given glob pattern path.
1529
1530 @param path_glob: The path glob that we want to return the list of
1531 files that match the glob. Relative paths will not work as
1532 expected. Supply an absolute path to get the list of files
1533 you're hoping for.
1534
1535 @returns List of files that match the path_glob.
1536 """
1537 # This is just in case path_glob has no path separator.
1538 base_path = os.path.dirname(path_glob) or '.'
1539 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001540 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001541 if result.exit_status != 0:
1542 return []
1543 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001544
1545
Dan Shic716ac62016-05-24 16:47:57 -07001546 @retry.retry(error.AutoservRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
Dan Shida995002016-04-25 23:12:58 -07001547 def install_apk(self, apk, force_reinstall=True):
Kevin Cheng31355942016-01-05 14:23:35 -08001548 """Install the specified apk.
1549
1550 This will install the apk and override it if it's already installed and
1551 will also allow for downgraded apks.
1552
1553 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001554 @param force_reinstall: True to reinstall the apk even if it's already
Dan Shida995002016-04-25 23:12:58 -07001555 installed. Default is set to True.
Dan Shidb0366c2016-02-19 10:36:18 -08001556
1557 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001558 """
Dan Shic716ac62016-05-24 16:47:57 -07001559 try:
1560 client_utils.poll_for_condition(
1561 lambda: self.run('pm list packages',
1562 ignore_status=True).exit_status == 0,
1563 timeout=120)
1564 client_utils.poll_for_condition(
1565 lambda: self.run('service list | grep mount',
1566 ignore_status=True).exit_status == 0,
1567 timeout=120)
1568 return self.adb_run('install %s -d %s' %
1569 ('-r' if force_reinstall else '', apk))
1570 except error.AutoservRunError:
1571 self.reboot()
1572 raise
Dan Shidb0366c2016-02-19 10:36:18 -08001573
1574
1575 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1576 def _confirm_apk_installed(self, package_name):
1577 """Confirm if apk is already installed with the given name.
1578
1579 `pm list packages` command is not reliable some time. The retry helps to
1580 reduce the chance of false negative.
1581
1582 @param package_name: Name of the package, e.g., com.android.phone.
1583
1584 @raise AutoservRunError: If the package is not found or pm list command
1585 failed for any reason.
1586 """
1587 name = 'package:%s' % package_name
1588 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1589
1590
1591 def is_apk_installed(self, package_name):
1592 """Check if apk is already installed with the given name.
1593
1594 @param package_name: Name of the package, e.g., com.android.phone.
1595
1596 @return: True if package is installed. False otherwise.
1597 """
1598 try:
1599 self._confirm_apk_installed(package_name)
1600 return True
1601 except:
1602 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001603
1604
1605 def get_attributes_to_clear_before_provision(self):
1606 """Get a list of attributes to be cleared before machine_install starts.
1607 """
1608 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001609
1610
1611 def get_labels(self):
1612 """Return a list of the labels gathered from the devices connected.
1613
1614 @return: A list of strings that denote the labels from all the devices
1615 connected.
1616 """
1617 return self.labels.get_labels(self)
1618
1619
1620 def update_labels(self):
1621 """Update the labels for this testbed."""
1622 self.labels.update_labels(self)
Dan Shi6450e142016-03-11 11:52:20 -08001623
1624
1625 def stage_server_side_package(self, image=None):
1626 """Stage autotest server-side package on devserver.
1627
1628 @param image: A build name, e.g., git_mnc_dev/shamu-eng/123
1629
1630 @return: A url to the autotest server-side package. Return None if
1631 server-side package is not supported.
1632 @raise: error.AutoservError if fail to locate the build to test with.
1633 """
Dan Shid37736b2016-07-06 15:10:29 -07001634 # If enable_drone_in_restricted_subnet is False, do not set hostname
1635 # in devserver.resolve call, so a devserver in non-restricted subnet
1636 # is picked to stage autotest server package for drone to download.
1637 hostname = self.hostname
1638 if not utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1639 hostname = None
Dan Shi6450e142016-03-11 11:52:20 -08001640 if image:
Dan Shid37736b2016-07-06 15:10:29 -07001641 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001642 else:
1643 job_repo_url = afe_utils.get_host_attribute(
1644 self, self.job_repo_url_attribute)
1645 if job_repo_url:
1646 devserver_url, image = (
1647 tools.get_devserver_build_from_package_url(
1648 job_repo_url, True))
Dan Shid37736b2016-07-06 15:10:29 -07001649 # If enable_drone_in_restricted_subnet is True, use the
1650 # existing devserver. Otherwise, resolve a new one in
1651 # non-restricted subnet.
1652 if utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1653 ds = dev_server.AndroidBuildServer(devserver_url)
1654 else:
1655 ds = dev_server.AndroidBuildServer.resolve(image)
Dan Shi6450e142016-03-11 11:52:20 -08001656 else:
1657 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
1658 if not labels:
1659 raise error.AutoservError(
1660 'Failed to stage server-side package. The host has '
1661 'no job_report_url attribute or version label.')
1662 image = labels[0].name[len(self.VERSION_PREFIX)+1:]
Dan Shid37736b2016-07-06 15:10:29 -07001663 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001664
1665 branch, target, build_id = utils.parse_launch_control_build(image)
1666 build_target, _ = utils.parse_launch_control_target(target)
1667
1668 # For any build older than MIN_VERSION_SUPPORT_SSP, server side
1669 # packaging is not supported.
1670 try:
1671 if int(build_id) < self.MIN_VERSION_SUPPORT_SSP:
1672 logging.warn('Build %s is older than %s. Server side packaging '
1673 'is disabled.', image,
1674 self.MIN_VERSION_SUPPORT_SSP)
1675 return None
1676 except ValueError:
1677 logging.warn('Failed to compare build id in %s with the minimum '
1678 'version that supports server side packaging. Server '
1679 'side packaging is disabled.', image)
1680 return None
1681
1682 ds.stage_artifacts(target, build_id, branch,
1683 artifacts=['autotest_server_package'])
1684 autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
1685 {'build_target': build_target,
1686 'build_id': build_id})
1687 return '%s/static/%s/%s' % (ds.url(), image,
1688 autotest_server_package_name)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07001689
1690
1691 def _sync_time(self):
1692 """Approximate synchronization of time between host and ADB device.
1693
1694 This sets the ADB/Android device's clock to approximately the same
1695 time as the Autotest host for the purposes of comparing Android system
1696 logs such as logcat to logs from the Autotest host system.
1697 """
1698 command = 'date '
1699 sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
1700 if sdk_version < 23:
1701 # Android L and earlier use this format: date -s (format).
1702 command += ('-s %s' %
1703 datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
1704 else:
1705 # Android M and later use this format: date (format).
1706 command += datetime.datetime.now().strftime('%m%d%H%M%Y.%S')
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -07001707 self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1708 ignore_timeout=True)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001709
1710
1711 def _enable_native_crash_logging(self):
1712 """Enable native (non-Java) crash logging.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001713 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001714 if self.get_os_type() == OS_TYPE_BRILLO:
1715 self._enable_brillo_native_crash_logging()
1716 elif self.get_os_type() == OS_TYPE_ANDROID:
1717 self._enable_android_native_crash_logging()
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001718
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001719
1720 def _enable_brillo_native_crash_logging(self):
1721 """Enables native crash logging for a Brillo DUT.
1722 """
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001723 self.run('touch /data/misc/metrics/enabled',
1724 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1725 ignore_timeout=True)
1726 # If running, crash_sender will delete crash files every hour.
1727 self.run('stop crash_sender',
1728 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1729 ignore_timeout=True)
1730
1731
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001732 def _enable_android_native_crash_logging(self):
1733 """Enables native crash logging for an Android DUT.
1734 """
1735 # debuggerd should be enabled by default on Android.
1736 result = self.run('pgrep debuggerd',
1737 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1738 ignore_timeout=True, ignore_status=True)
1739 if not result or result.exit_status != 0:
1740 logging.debug('Unable to confirm that debuggerd is running.')
1741
1742
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001743 def _collect_crash_logs(self):
1744 """Copies crash log files from the DUT to the drone.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001745 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001746 if self.get_os_type() == OS_TYPE_BRILLO:
1747 self._collect_crash_logs_dut(BRILLO_NATIVE_CRASH_LOG_DIR)
1748 elif self.get_os_type() == OS_TYPE_ANDROID:
1749 self._collect_crash_logs_dut(ANDROID_TOMBSTONE_CRASH_LOG_DIR)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001750
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001751
1752 def _collect_crash_logs_dut(self, log_directory):
1753 """Copies native crash logs from the Android/Brillo DUT to the drone.
1754
1755 @param log_directory: absolute path of the directory on the DUT where
1756 log files are stored.
1757 """
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001758 files = None
1759 try:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001760 result = self.run('find %s -maxdepth 1 -type f' % log_directory,
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001761 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS)
1762 files = result.stdout.strip().split()
1763 except (error.AutotestHostRunError, error.AutoservRunError,
1764 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001765 logging.debug('Unable to call find %s, unable to find crash logs',
1766 log_directory)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001767 if not files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001768 logging.debug('There are no crash logs on the DUT.')
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001769 return
1770
1771 crash_dir = os.path.join(self.job.resultdir, 'crash')
1772 try:
1773 os.mkdir(crash_dir)
1774 except OSError as e:
1775 if e.errno != errno.EEXIST:
1776 raise e
1777
1778 for f in files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001779 logging.debug('DUT native crash file produced: %s', f)
1780 dest = os.path.join(crash_dir, os.path.basename(f))
1781 self.get_file(source=f, dest=dest)