blob: 5e157df57affa1db638f3b1032180ec321d98565 [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 Lewandowski11f8aed2016-06-29 15:44:40 -0700134# Directory where Brillo stores crash logs for native (non-Java) crashes.
135BRILLO_NATIVE_CRASH_LOG_DIR = '/data/misc/crash_reporter/crash'
136
Dan Shia2872172015-10-31 01:16:51 -0700137class AndroidInstallError(error.InstallError):
138 """Generic error for Android installation related exceptions."""
139
140
Simran Basi724b8a52013-09-30 11:19:31 -0700141class ADBHost(abstract_ssh.AbstractSSHHost):
Simran Basi431010f2013-09-04 10:42:41 -0700142 """This class represents a host running an ADB server."""
143
Simran Basi5ace6f22016-01-06 17:30:44 -0800144 VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700145 _LABEL_FUNCTIONS = []
146 _DETECTABLE_LABELS = []
147 label_decorator = functools.partial(utils.add_label_detector,
148 _LABEL_FUNCTIONS,
149 _DETECTABLE_LABELS)
150
Dan Shi225b9042015-11-18 10:25:21 -0800151 _parser = autoserv_parser.autoserv_parser
Simran Basi431010f2013-09-04 10:42:41 -0700152
Dan Shi6450e142016-03-11 11:52:20 -0800153 # Minimum build id that supports server side packaging. Older builds may
154 # not have server side package built or with Autotest code change to support
155 # server-side packaging.
156 MIN_VERSION_SUPPORT_SSP = CONFIG.get_config_value(
157 'AUTOSERV', 'min_launch_control_build_id_support_ssp', type=int)
158
beeps46dadc92013-11-07 14:07:10 -0800159 @staticmethod
160 def check_host(host, timeout=10):
161 """
162 Check if the given host is an adb host.
163
Simran Basi14622bb2015-11-25 13:23:40 -0800164 If SSH connectivity can't be established, check_host will try to use
165 user 'adb' as well. If SSH connectivity still can't be established
166 then the original SSH user is restored.
167
beeps46dadc92013-11-07 14:07:10 -0800168 @param host: An ssh host representing a device.
169 @param timeout: The timeout for the run command.
170
171
172 @return: True if the host device has adb.
173
174 @raises AutoservRunError: If the command failed.
175 @raises AutoservSSHTimeout: Ssh connection has timed out.
176 """
Dan Shi64e130f2015-12-16 14:45:44 -0800177 # host object may not have user attribute if it's a LocalHost object.
178 current_user = host.user if hasattr(host, 'user') else None
beeps46dadc92013-11-07 14:07:10 -0800179 try:
Simran Basi14622bb2015-11-25 13:23:40 -0800180 if not (host.hostname == 'localhost' or
181 host.verify_ssh_user_access()):
Simran Basi1621c632015-10-14 12:22:23 -0700182 host.user = 'adb'
Simran Basi933c8af2015-04-29 14:05:07 -0700183 result = host.run(
Dan Shia2872172015-10-31 01:16:51 -0700184 'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
Simran Basi933c8af2015-04-29 14:05:07 -0700185 timeout=timeout)
beeps46dadc92013-11-07 14:07:10 -0800186 except (error.AutoservRunError, error.AutoservSSHTimeout):
Dan Shi64e130f2015-12-16 14:45:44 -0800187 if current_user is not None:
188 host.user = current_user
beeps46dadc92013-11-07 14:07:10 -0800189 return False
190 return result.exit_status == 0
191
192
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700193 # TODO(garnold) Remove the 'serials' argument once all clients are made to
194 # not use it.
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700195 def _initialize(self, hostname='localhost', serials=None,
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700196 adb_serial=None, fastboot_serial=None,
Simran Basi9228a6f2016-03-29 12:03:37 -0700197 teststation=None, *args, **dargs):
Simran Basi431010f2013-09-04 10:42:41 -0700198 """Initialize an ADB Host.
199
200 This will create an ADB Host. Hostname should always refer to the
Kevin Chengd19e6c62015-10-28 16:39:39 -0700201 test station connected to an Android DUT. This will be the DUT
202 to test with. If there are multiple, serial must be specified or an
Simran Basi9228a6f2016-03-29 12:03:37 -0700203 exception will be raised.
Simran Basi431010f2013-09-04 10:42:41 -0700204
205 @param hostname: Hostname of the machine running ADB.
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700206 @param serials: DEPRECATED (to be removed)
207 @param adb_serial: An ADB device serial. If None, assume a single
208 device is attached (and fail otherwise).
209 @param fastboot_serial: A fastboot device serial. If None, defaults to
210 the ADB serial (or assumes a single device if
211 the latter is None).
Kevin Cheng549beb42015-11-18 11:42:25 -0800212 @param teststation: The teststation object ADBHost should use.
Simran Basi431010f2013-09-04 10:42:41 -0700213 """
Simran Basi1bf60eb2015-12-01 16:39:29 -0800214 # Sets up the is_client_install_supported field.
215 super(ADBHost, self)._initialize(hostname=hostname,
216 is_client_install_supported=False,
217 *args, **dargs)
Kevin Cheng85e864a2015-11-30 11:49:34 -0800218
Kevin Chengd19e6c62015-10-28 16:39:39 -0700219 self.tmp_dirs = []
Kevin Chengc6a645a2015-12-18 11:15:10 -0800220 self.labels = base_label.LabelRetriever(adb_label.ADB_LABELS)
Simran Basi1bf60eb2015-12-01 16:39:29 -0800221 # TODO (sbasi/kevcheng): Once the teststation host is committed,
222 # refactor the serial retrieval.
223 adb_serial = adb_serial or self.host_attributes.get('serials', None)
Simran Basi973bf712016-05-26 13:41:34 -0700224 fastboot_serial = fastboot_serial or self.host_attributes.get(
225 'fastboot_serial', None)
Dan Shi50a412a2016-01-05 10:52:40 -0800226 self.adb_serial = adb_serial
Dan Shi3a011ed2016-04-26 12:26:53 -0700227 if adb_serial:
228 adb_prefix = any(adb_serial.startswith(p)
229 for p in ADB_DEVICE_PREFIXES)
230 self.fastboot_serial = (fastboot_serial or
231 ('tcp:%s' % adb_serial.split(':')[0] if
232 ':' in adb_serial and not adb_prefix else adb_serial))
233 self._use_tcpip = ':' in adb_serial and not adb_prefix
234 else:
235 self.fastboot_serial = fastboot_serial or adb_serial
236 self._use_tcpip = False
Kevin Cheng85e864a2015-11-30 11:49:34 -0800237 self.teststation = (teststation if teststation
238 else teststation_host.create_teststationhost(hostname=hostname))
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700239
240 msg ='Initializing ADB device on host: %s' % hostname
Dan Shi50a412a2016-01-05 10:52:40 -0800241 if self.adb_serial:
242 msg += ', ADB serial: %s' % self.adb_serial
243 if self.fastboot_serial:
244 msg += ', fastboot serial: %s' % self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700245 logging.debug(msg)
246
Simran Basibeb2bb22016-02-03 15:25:48 -0800247 # Try resetting the ADB daemon on the device, however if we are
248 # creating the host to do a repair job, the device maybe inaccesible
249 # via ADB.
250 try:
251 self._reset_adbd_connection()
252 except (error.AutotestHostRunError, error.AutoservRunError) as e:
253 logging.error('Unable to reset the device adb daemon connection: '
254 '%s.', e)
Dan Shiab999722015-12-04 14:27:08 -0800255 self._os_type = None
256
Simran Basi431010f2013-09-04 10:42:41 -0700257
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700258 def _connect_over_tcpip_as_needed(self):
259 """Connect to the ADB device over TCP/IP if so configured."""
Simran Basi9228a6f2016-03-29 12:03:37 -0700260 if not self._use_tcpip:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700261 return
262 logging.debug('Connecting to device over TCP/IP')
Simran Basi9228a6f2016-03-29 12:03:37 -0700263 self.adb_run('connect %s' % self.adb_serial)
Simran Basi431010f2013-09-04 10:42:41 -0700264
265
Roshan Pius4d7540c2015-12-16 13:30:32 -0800266 def _restart_adbd_with_root_permissions(self):
267 """Restarts the adb daemon with root permissions."""
Dan Shi922de302016-04-22 15:19:18 -0700268 @retry.retry(error.AutoservRunError, timeout_min=20/60.0, delay_sec=1)
269 def run_adb_root():
270 """Run command `adb root`."""
271 self.adb_run('root')
272
273 # adb command may flake with error "device not found". Retry the root
274 # command to reduce the chance of flake.
275 run_adb_root()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800276 # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
277 time.sleep(1)
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300278 self._connect_over_tcpip_as_needed()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800279 self.adb_run('wait-for-device')
280
281
Simran Basi9228a6f2016-03-29 12:03:37 -0700282 def _set_tcp_port(self):
283 """Ensure the device remains in tcp/ip mode after a reboot."""
284 if not self._use_tcpip:
285 return
286 port = self.adb_serial.split(':')[-1]
287 self.run('setprop persist.adb.tcp.port %s' % port)
288
289
Roshan Pius4d7540c2015-12-16 13:30:32 -0800290 def _reset_adbd_connection(self):
291 """Resets adbd connection to the device after a reboot/initialization"""
Roshan Pius4d7540c2015-12-16 13:30:32 -0800292 self._connect_over_tcpip_as_needed()
Simran Basi9228a6f2016-03-29 12:03:37 -0700293 self._restart_adbd_with_root_permissions()
294 self._set_tcp_port()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800295
296
Kevin Cheng85e864a2015-11-30 11:49:34 -0800297 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800298 def adb_run(self, command, **kwargs):
Simran Basi431010f2013-09-04 10:42:41 -0700299 """Runs an adb command.
300
Kevin Chengd19e6c62015-10-28 16:39:39 -0700301 This command will launch on the test station.
Simran Basi431010f2013-09-04 10:42:41 -0700302
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700303 Refer to _device_run method for docstring for parameters.
304 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800305 return self._device_run(ADB_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700306
307
Kevin Cheng85e864a2015-11-30 11:49:34 -0800308 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800309 def fastboot_run(self, command, **kwargs):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700310 """Runs an fastboot command.
311
Kevin Chengd19e6c62015-10-28 16:39:39 -0700312 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700313
314 Refer to _device_run method for docstring for parameters.
315 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800316 return self._device_run(FASTBOOT_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700317
318
Dan Shi12a4f662016-05-10 14:49:42 -0700319 # pylint: disable=missing-docstring
320 @retry.retry(error.AutoservRunError,
321 timeout_min=DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN)
322 def _fastboot_run_with_retry(self, command, **kwargs):
323 """Runs an fastboot command with retry.
324
325 This command will launch on the test station.
326
327 Refer to _device_run method for docstring for parameters.
328 """
329 return self.fastboot_run(command, **kwargs)
330
331
Simran Basie6c4f142016-06-23 17:10:04 -0700332 def _log_adb_pid(self):
333 """Log the pid of adb server.
334
335 adb's server is known to have bugs and randomly restart. BY logging
336 the server's pid it will allow us to better debug random adb failures.
337 """
338 adb_pid = self.teststation.run('pgrep -f "adb.*server"')
339 logging.debug('ADB Server PID: %s', adb_pid.stdout)
340
341
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700342 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700343 timeout=3600, ignore_status=False, ignore_timeout=False,
344 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
345 connect_timeout=30, options='', stdin=None, verbose=True,
346 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700347 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700348
Kevin Chengd19e6c62015-10-28 16:39:39 -0700349 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700350
Simran Basi431010f2013-09-04 10:42:41 -0700351 @param command: Command to run.
352 @param shell: If true the command runs in the adb shell otherwise if
353 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700354 reboot with shell=False will call 'adb reboot'. This
355 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700356 @param timeout: Time limit in seconds before attempting to
357 kill the running process. The run() function
358 will take a few seconds longer than 'timeout'
359 to complete if it has to kill the process.
360 @param ignore_status: Do not raise an exception, no matter
361 what the exit code of the command is.
362 @param ignore_timeout: Bool True if command timeouts should be
363 ignored. Will return None on command timeout.
364 @param stdout: Redirect stdout.
365 @param stderr: Redirect stderr.
366 @param connect_timeout: Connection timeout (in seconds)
367 @param options: String with additional ssh command options
368 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700369 @param require_sudo: True to require sudo to run the command. Default is
370 False.
Simran Basi431010f2013-09-04 10:42:41 -0700371 @param args: Sequence of strings to pass as arguments to command by
372 quoting them in " and escaping their contents if
373 necessary.
374
375 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700376 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700377 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800378 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700379 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800380 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700381 else:
382 raise NotImplementedError('Mode %s is not supported' % function)
383
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700384 if function != ADB_CMD and shell:
385 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700386
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700387 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700388
389 if serial:
390 cmd += '-s %s ' % serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700391
Simran Basi431010f2013-09-04 10:42:41 -0700392 if shell:
393 cmd += '%s ' % SHELL_CMD
394 cmd += command
395
Simran Basie6c4f142016-06-23 17:10:04 -0700396 self._log_adb_pid()
397
Roshan Pius58e5dd32015-10-16 15:16:42 -0700398 if verbose:
399 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700400
Kevin Cheng85e864a2015-11-30 11:49:34 -0800401 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400402 ignore_status=ignore_status,
403 ignore_timeout=ignore_timeout, stdout_tee=stdout,
404 stderr_tee=stderr, options=options, stdin=stdin,
405 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700406
407
Dan Shi8c51bda2016-05-26 12:21:02 -0700408 def _run_output_with_retry(self, cmd):
409 """Call run_output method for the given command with retry.
410
Dan Shi68094122016-06-10 14:29:06 -0700411 adb command can be flaky some time, and the command may fail or return
412 empty string. It may take several retries until a value can be returned.
Dan Shi8c51bda2016-05-26 12:21:02 -0700413
414 @param cmd: The command to run.
415
416 @return: Return value from the command after retry.
417 """
418 try:
419 return client_utils.poll_for_condition(
Dan Shi68094122016-06-10 14:29:06 -0700420 lambda: self.run_output(cmd, ignore_status=True),
Dan Shi8c51bda2016-05-26 12:21:02 -0700421 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
422 sleep_interval=0.5,
423 desc='Get return value for command `%s`' % cmd)
424 except client_utils.TimeoutError:
425 return ''
426
427
Dan Shie234dea2016-01-20 17:15:17 -0800428 def get_board_name(self):
429 """Get the name of the board, e.g., shamu, dragonboard etc.
430 """
Simran Basi9c5d3982016-04-01 18:49:44 -0700431 product = self.run_output('getprop %s' % BOARD_FILE)
432 return PRODUCT_TARGET_MAP.get(product, product)
Dan Shie234dea2016-01-20 17:15:17 -0800433
434
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700435 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700436 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700437 """Determine the correct board label for the device.
438
439 @returns a string representing this device's board.
440 """
Dan Shie234dea2016-01-20 17:15:17 -0800441 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700442 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800443 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700444
445
Christopher Wiley08849d52013-11-22 08:57:58 -0800446 def job_start(self):
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700447 """Overload of parent which intentionally doesn't log certain files.
Dan Shi2d279cf2016-05-27 22:06:10 +0000448
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700449 The parent implementation attempts to log certain Linux files, such as
450 /var/log, which do not exist on Android, thus there is no call to the
451 parent's job_start(). The sync call is made so that logcat logs can be
452 approximately matched to server logs.
Dan Shi2d279cf2016-05-27 22:06:10 +0000453 """
Simran Basid6b49792016-06-07 17:22:03 -0700454 if self.is_up():
455 self._sync_time()
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700456 self._enable_native_crash_logging()
Christopher Wiley08849d52013-11-22 08:57:58 -0800457
458
Simran Basi431010f2013-09-04 10:42:41 -0700459 def run(self, command, timeout=3600, ignore_status=False,
460 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
461 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700462 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700463 """Run a command on the adb device.
464
465 The command given will be ran directly on the adb device; for example
466 'ls' will be ran as: 'abd shell ls'
467
468 @param command: The command line string.
469 @param timeout: Time limit in seconds before attempting to
470 kill the running process. The run() function
471 will take a few seconds longer than 'timeout'
472 to complete if it has to kill the process.
473 @param ignore_status: Do not raise an exception, no matter
474 what the exit code of the command is.
475 @param ignore_timeout: Bool True if command timeouts should be
476 ignored. Will return None on command timeout.
477 @param stdout_tee: Redirect stdout.
478 @param stderr_tee: Redirect stderr.
479 @param connect_timeout: Connection timeout (in seconds).
480 @param options: String with additional ssh command options.
481 @param stdin: Stdin to pass (a string) to the executed command
482 @param args: Sequence of strings to pass as arguments to command by
483 quoting them in " and escaping their contents if
484 necessary.
485
486 @returns A CMDResult object or None if the call timed out and
487 ignore_timeout is True.
488
489 @raises AutoservRunError: If the command failed.
490 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700491 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700492 command = ('"%s; echo %s:\$?"' %
493 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700494 result = self.adb_run(
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700495 command, shell=True, timeout=timeout,
Simran Basi431010f2013-09-04 10:42:41 -0700496 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
497 stdout=stdout_tee, stderr=stderr_tee,
498 connect_timeout=connect_timeout, options=options, stdin=stdin,
Roshan Pius58e5dd32015-10-16 15:16:42 -0700499 verbose=verbose, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700500 if not result:
501 # In case of timeouts.
502 return None
503
504 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
Roshan Pius5ba5d182015-10-28 09:19:41 -0700505 if not parse_output and not ignore_status:
Simran Basi431010f2013-09-04 10:42:41 -0700506 raise error.AutoservRunError(
Roshan Pius5ba5d182015-10-28 09:19:41 -0700507 'Failed to parse the exit code for command: %s' %
508 command, result)
509 elif parse_output:
510 result.stdout = parse_output.group('OUTPUT')
511 result.exit_status = int(parse_output.group('EXIT_CODE'))
512 if result.exit_status != 0 and not ignore_status:
513 raise error.AutoservRunError(command, result)
Simran Basi431010f2013-09-04 10:42:41 -0700514 return result
515
516
Dan Shicf7d2562016-06-16 14:08:23 -0700517 def check_boot_to_adb_complete(self, exception_type=error.TimeoutException):
518 """Check if the device has finished booting and accessible by adb.
519
520 @param exception_type: Type of exception to raise. Default is set to
521 error.TimeoutException for retry.
522
523 @raise exception_type: If the device has not finished booting yet, raise
524 an exception of type `exception_type`.
525 """
526 bootcomplete = self._run_output_with_retry('getprop dev.bootcomplete')
527 if bootcomplete != PROPERTY_VALUE_TRUE:
528 raise exception_type('dev.bootcomplete is %s.' % bootcomplete)
529 if self.get_os_type() == OS_TYPE_ANDROID:
530 boot_completed = self._run_output_with_retry(
531 'getprop sys.boot_completed')
532 if boot_completed != PROPERTY_VALUE_TRUE:
533 raise exception_type('sys.boot_completed is %s.' %
534 boot_completed)
535
536
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700537 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
538 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700539
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700540 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700541
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700542 @param timeout: Time limit in seconds before returning even if the host
543 is not up.
544 @param command: The command used to test if a device is up, i.e.,
545 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700546
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700547 @returns True if the host was found to be up before the timeout expires,
548 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700549 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700550 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
551 delay_sec=1)
552 def _wait_up():
553 if not self.is_up(command=command):
554 raise error.TimeoutException('Device is still down.')
Dan Shicf7d2562016-06-16 14:08:23 -0700555 if command == ADB_CMD:
556 self.check_boot_to_adb_complete()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700557 return True
558
559 try:
560 _wait_up()
561 logging.debug('Host %s is now up, and can be accessed by %s.',
562 self.hostname, command)
563 return True
564 except error.TimeoutException:
565 logging.debug('Host %s is still down after waiting %d seconds',
566 self.hostname, timeout)
567 return False
Simran Basi431010f2013-09-04 10:42:41 -0700568
569
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700570 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
571 warning_timer=None, old_boot_id=None, command=ADB_CMD):
572 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700573
574 Overrides wait_down from AbstractSSHHost.
575
576 @param timeout: Time in seconds to wait for the host to go down.
577 @param warning_timer: Time limit in seconds that will generate
578 a warning if the host is not down yet.
579 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700580 @param old_boot_id: Not applicable for adb_host.
581 @param command: `adb`, test if the device can be accessed by adb
582 command, or `fastboot`, test if the device can be accessed by
583 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700584
585 @returns True if the device goes down before the timeout, False
586 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700587 """
588 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
589 delay_sec=1)
590 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700591 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700592 raise error.TimeoutException('Device is still up.')
593 return True
594
595 try:
596 _wait_down()
597 logging.debug('Host %s is now down', self.hostname)
598 return True
599 except error.TimeoutException:
600 logging.debug('Host %s is still up after waiting %d seconds',
601 self.hostname, timeout)
602 return False
603
604
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700605 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700606 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700607
608 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700609 """
610 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700611 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700612 self.adb_run('reboot', timeout=10, ignore_timeout=True)
613 if not self.wait_down():
614 raise error.AutoservRebootError(
615 'ADB Device is still up after reboot')
616 if not self.wait_up():
617 raise error.AutoservRebootError(
618 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800619 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800620
621
Alexandru Branciog969ff7c2016-03-30 14:07:15 +0300622 def fastboot_reboot(self):
623 """Do a fastboot reboot to go back to adb.
624
625 @raises AutoservRebootError if reboot failed.
626 """
627 self.fastboot_run('reboot')
628 if not self.wait_down(command=FASTBOOT_CMD):
629 raise error.AutoservRebootError(
630 'Device is still in fastboot mode after reboot')
631 if not self.wait_up():
632 raise error.AutoservRebootError(
633 'Device failed to boot to adb after fastboot reboot.')
634 self._reset_adbd_connection()
635
636
Ralph Nathanb45eb672015-11-18 20:04:39 -0800637 def remount(self):
638 """Remounts paritions on the device read-write.
639
640 Specifically, the /system, /vendor (if present) and /oem (if present)
641 partitions on the device are remounted read-write.
642 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800643 self.adb_run('remount')
644
645
Kevin Cheng549beb42015-11-18 11:42:25 -0800646 @staticmethod
647 def parse_device_serials(devices_output):
648 """Return a list of parsed serials from the output.
649
650 @param devices_output: Output from either an adb or fastboot command.
651
652 @returns List of device serials
653 """
654 devices = []
655 for line in devices_output.splitlines():
656 match = re.search(DEVICE_FINDER_REGEX, line)
657 if match:
658 serial = match.group('SERIAL')
659 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
660 serial = DEVICE_NO_SERIAL_TAG
661 logging.debug('Found Device: %s', serial)
662 devices.append(serial)
663 return devices
664
665
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700666 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700667 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700668
669 @params use_adb: True to get adb accessible devices. Set to False to
670 get fastboot accessible devices.
671
Kevin Chengd19e6c62015-10-28 16:39:39 -0700672 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700673 """
674 if use_adb:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300675 result = self.adb_run('devices').stdout
676 if self.adb_serial and self.adb_serial not in result:
677 self._connect_over_tcpip_as_needed()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700678 else:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300679 result = self.fastboot_run('devices').stdout
680 if (self.fastboot_serial and
681 self.fastboot_serial not in result):
682 # fastboot devices won't list the devices using TCP
683 try:
684 if 'product' in self.fastboot_run('getvar product',
685 timeout=2).stderr:
686 result += '\n%s\tfastboot' % self.fastboot_serial
Kevin Chengcfcb2cf2016-04-13 10:04:36 -0700687 # The main reason we do a general Exception catch here instead
688 # of setting ignore_timeout/status to True is because even when
689 # the fastboot process has been nuked, it still stays around and
690 # so bgjob wants to warn us of this and tries to read the
691 # /proc/<pid>/stack file which then promptly returns an
692 # 'Operation not permitted' error since we're running as moblab
693 # and we don't have permission to read those files.
694 except Exception:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300695 pass
696 return self.parse_device_serials(result)
Simran Basi431010f2013-09-04 10:42:41 -0700697
698
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700699 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700700 """Get a list of devices currently attached to the test station and
701 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700702 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800703 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700704 raise error.AutoservError(
705 'Not given ADB serial but multiple devices detected')
706 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700707
708
709 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700710 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700711 accessible by fastboot command.
712 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700713 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800714 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700715 raise error.AutoservError(
716 'Not given fastboot serial but multiple devices detected')
717 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700718
719
720 def is_up(self, timeout=0, command=ADB_CMD):
721 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700722
723 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700724 @param command: `adb`, the device can be accessed by adb command,
725 or `fastboot`, the device can be accessed by fastboot command.
726 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700727
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700728 @returns True if the device is detectable by given command, False
729 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700730
731 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700732 if command == ADB_CMD:
733 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800734 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800735 # ADB has a device state, if the device is not online, no
736 # subsequent ADB command will complete.
Dan Shi6450e142016-03-11 11:52:20 -0800737 # DUT with single device connected may not have adb_serial set.
738 # Therefore, skip checking if serial is in the list of adb devices
739 # if self.adb_serial is not set.
740 if (serial and serial not in devices) or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800741 logging.debug('Waiting for device to enter the ready state.')
742 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700743 elif command == FASTBOOT_CMD:
744 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800745 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700746 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700747 raise NotImplementedError('Mode %s is not supported' % command)
748
749 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700750
751
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700752 def stop_loggers(self):
753 """Inherited stop_loggers function.
754
755 Calls parent function and captures logcat, since the end of the run
756 is logically the end/stop of the logcat log.
757 """
758 super(ADBHost, self).stop_loggers()
759 # Record logcat log to a temporary file on the teststation.
760 tmp_dir = self.teststation.get_tmp_dir()
Simran Basi242f8de2016-06-08 14:23:43 -0700761 logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
762 teststation_filename = os.path.join(tmp_dir, logcat_filename)
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700763 try:
764 self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
765 timeout=20)
Simran Basid6b49792016-06-07 17:22:03 -0700766 except (error.AutotestHostRunError, error.AutoservRunError,
767 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700768 return
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700769 # Copy-back the log to the drone's results directory.
Simran Basi242f8de2016-06-08 14:23:43 -0700770 results_logcat_filename = os.path.join(self.job.resultdir,
771 logcat_filename)
772 self.teststation.get_file(teststation_filename,
773 results_logcat_filename)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700774 try:
775 self.teststation.run('rm -rf %s' % tmp_dir)
776 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
777 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
778
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700779 self._collect_crash_logs()
780
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700781
Simran Basi431010f2013-09-04 10:42:41 -0700782 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700783 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700784
785 Called as the test ends. Will return the device to USB mode and kill
786 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700787 """
Christopher Wiley08849d52013-11-22 08:57:58 -0800788 # TODO(sbasi) Originally, we would kill the server after each test to
789 # reduce the opportunity for bad server state to hang around.
790 # Unfortunately, there is a period of time after each kill during which
791 # the Android device becomes unusable, and if we start the next test
792 # too quickly, we'll get an error complaining about no ADB device
793 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700794 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800795 # |close| the associated teststation as well.
796 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700797 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700798
799
800 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700801 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700802
803 @param message String message to log into syslog
804 @param tag String tag prefix for syslog
805
806 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700807 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700808
809
810 def get_autodir(self):
811 """Return the directory to install autotest for client side tests."""
812 return '/data/autotest'
813
Kevin Cheng018db352015-09-20 02:22:08 -0700814
Kris Rambishde8f9d12015-12-16 12:42:41 -0800815 def is_device_ready(self):
816 """Return the if the device is ready for ADB commands."""
Dan Shi7075f552016-04-21 15:42:41 -0700817 try:
818 # Retry to avoid possible flakes.
819 is_ready = client_utils.poll_for_condition(
820 lambda: self.adb_run('get-state').stdout.strip() == 'device',
821 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
822 desc='Waiting for device state to be `device`')
823 except client_utils.TimeoutError:
824 is_ready = False
825
826 logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
827 return is_ready
Kris Rambishde8f9d12015-12-16 12:42:41 -0800828
829
Kevin Chengd19e6c62015-10-28 16:39:39 -0700830 def verify_connectivity(self):
831 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800832 if not self.is_device_ready():
833 raise error.AutoservHostError('device state is not in the '
834 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700835
836
Simran Basid3ba3fb2015-09-11 14:35:07 -0700837 def verify_software(self):
838 """Verify working software on an adb_host.
839
Simran Basi38f7ddf2015-09-18 12:25:03 -0700840 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700841 """
Dan Shiab999722015-12-04 14:27:08 -0800842 # Check if adb and fastboot are present.
843 self.teststation.run('which adb')
844 self.teststation.run('which fastboot')
845 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700846
Dan Shi626d5412016-05-16 16:05:13 -0700847 # Apply checks only for Android device.
Dan Shi1e2a98a2016-05-18 12:08:08 -0700848 if self.get_os_type() == OS_TYPE_ANDROID:
Dan Shi626d5412016-05-16 16:05:13 -0700849 # Make sure ro.boot.hardware and ro.build.product match.
Dan Shi8c51bda2016-05-26 12:21:02 -0700850 hardware = self._run_output_with_retry('getprop ro.boot.hardware')
851 product = self._run_output_with_retry('getprop ro.build.product')
Dan Shi1e2a98a2016-05-18 12:08:08 -0700852 if hardware != product:
853 raise error.AutoservHostError('ro.boot.hardware: %s does not '
854 'match to ro.build.product: %s' %
855 (hardware, product))
856
Kevin Cheng018db352015-09-20 02:22:08 -0700857
Simran Basid3ba3fb2015-09-11 14:35:07 -0700858 def verify_job_repo_url(self, tag=''):
859 """Make sure job_repo_url of this host is valid.
860
Simran Basi38f7ddf2015-09-18 12:25:03 -0700861 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700862
863 @param tag: The tag from the server job, in the format
864 <job_id>-<user>/<hostname>, or <hostless> for a server job.
865 """
866 return
Kevin Cheng018db352015-09-20 02:22:08 -0700867
868
Simran Basibeb2bb22016-02-03 15:25:48 -0800869 def repair(self):
870 """Attempt to get the DUT to pass `self.verify()`."""
871 try:
872 self.ensure_adb_mode(timeout=30)
873 return
874 except error.AutoservError as e:
875 logging.error(e)
876 logging.debug('Verifying the device is accessible via fastboot.')
877 self.ensure_bootloader_mode()
878 if not self.job.run_test(
879 'provision_AndroidUpdate', host=self, value=None,
880 force=True, repair=True):
881 raise error.AutoservRepairTotalFailure(
882 'Unable to repair the device.')
883
884
Simran Basi1b023762015-09-25 12:12:20 -0700885 def send_file(self, source, dest, delete_dest=False,
886 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700887 """Copy files from the drone to the device.
888
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400889 Just a note, there is the possibility the test station is localhost
890 which makes some of these steps redundant (e.g. creating tmp dir) but
891 that scenario will undoubtedly be a development scenario (test station
892 is also the moblab) and not the typical live test running scenario so
893 the redundancy I think is harmless.
894
Kevin Cheng018db352015-09-20 02:22:08 -0700895 @param source: The file/directory on the drone to send to the device.
896 @param dest: The destination path on the device to copy to.
897 @param delete_dest: A flag set to choose whether or not to delete
898 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700899 @param preserve_symlinks: Controls if symlinks on the source will be
900 copied as such on the destination or
901 transformed into the referenced
902 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700903 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700904 # If we need to preserve symlinks, let's check if the source is a
905 # symlink itself and if so, just create it on the device.
906 if preserve_symlinks:
907 symlink_target = None
908 try:
909 symlink_target = os.readlink(source)
910 except OSError:
911 # Guess it's not a symlink.
912 pass
913
914 if symlink_target is not None:
915 # Once we create the symlink, let's get out of here.
916 self.run('ln -s %s %s' % (symlink_target, dest))
917 return
918
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400919 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700920 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400921 src_path = os.path.join(tmp_dir, os.path.basename(dest))
922 # Now copy the file over to the test station so you can reference the
923 # file in the push command.
924 self.teststation.send_file(source, src_path,
925 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700926
927 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400928 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700929
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700930 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700931
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400932 # Cleanup the test station.
933 try:
934 self.teststation.run('rm -rf %s' % tmp_dir)
935 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
936 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700937
938
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700939 def _get_file_info(self, dest):
940 """Get permission and possible symlink info about file on the device.
941
942 These files are on the device so we only have shell commands (via adb)
943 to get the info we want. We'll use 'ls' to get it all.
944
945 @param dest: File to get info about.
946
947 @returns a dict of the file permissions and symlink.
948 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800949 # Grab file info.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700950 file_info = self.run_output('ls -ld %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700951 symlink = None
952 perms = 0
953 match = re.match(FILE_INFO_REGEX, file_info)
954 if match:
955 # Check if it's a symlink and grab the linked dest if it is.
956 if match.group('TYPE') == 'l':
957 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
958 if symlink_match:
959 symlink = symlink_match.group('SYMLINK')
960
961 # Set the perms.
962 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
963 if perm != '-':
964 perms |= perm_flag
965
966 return {'perms': perms,
967 'symlink': symlink}
968
969
Simran Basi1b023762015-09-25 12:12:20 -0700970 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
971 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700972 """Copy files from the device to the drone.
973
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400974 Just a note, there is the possibility the test station is localhost
975 which makes some of these steps redundant (e.g. creating tmp dir) but
976 that scenario will undoubtedly be a development scenario (test station
977 is also the moblab) and not the typical live test running scenario so
978 the redundancy I think is harmless.
979
Kevin Cheng018db352015-09-20 02:22:08 -0700980 @param source: The file/directory on the device to copy back to the
981 drone.
982 @param dest: The destination path on the drone to copy to.
983 @param delete_dest: A flag set to choose whether or not to delete
984 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700985 @param preserve_perm: Tells get_file() to try to preserve the sources
986 permissions on files and dirs.
987 @param preserve_symlinks: Try to preserve symlinks instead of
988 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -0700989 """
David Purselle01548b2016-05-11 10:00:42 -0700990 # Stage the files on the test station under teststation_temp_dir.
991 teststation_temp_dir = self.teststation.get_tmp_dir()
992 teststation_dest = os.path.join(teststation_temp_dir,
993 os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -0700994
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700995 source_info = {}
996 if preserve_symlinks or preserve_perm:
997 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -0700998
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700999 # If we want to preserve symlinks, just create it here, otherwise pull
1000 # the file off the device.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001001 #
1002 # TODO(sadmac): Directories containing symlinks won't behave as
1003 # expected.
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001004 if preserve_symlinks and source_info['symlink']:
1005 os.symlink(source_info['symlink'], dest)
1006 else:
David Purselle01548b2016-05-11 10:00:42 -07001007 self.adb_run('pull %s %s' % (source, teststation_temp_dir))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001008
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001009 # Copy over the file from the test station and clean up.
David Purselle01548b2016-05-11 10:00:42 -07001010 self.teststation.get_file(teststation_dest, dest,
1011 delete_dest=delete_dest)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001012 try:
David Purselle01548b2016-05-11 10:00:42 -07001013 self.teststation.run('rm -rf %s' % teststation_temp_dir)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001014 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
David Purselle01548b2016-05-11 10:00:42 -07001015 logging.warn('failed to remove dir %s: %s',
1016 teststation_temp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001017
David Pursell788b1b52016-05-19 09:03:31 -07001018 # Source will be copied under dest if either:
1019 # 1. Source is a directory and doesn't end with /.
1020 # 2. Source is a file and dest is a directory.
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001021 command = '[ -d %s ]' % source
1022 source_is_dir = self.run(command,
David Pursell788b1b52016-05-19 09:03:31 -07001023 ignore_status=True).exit_status == 0
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001024
David Pursell788b1b52016-05-19 09:03:31 -07001025 if ((source_is_dir and not source.endswith(os.sep)) or
1026 (not source_is_dir and os.path.isdir(dest))):
1027 receive_path = os.path.join(dest, os.path.basename(source))
1028 else:
1029 receive_path = dest
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001030
David Pursell788b1b52016-05-19 09:03:31 -07001031 # Set the permissions of the received file/dirs.
1032 if os.path.isdir(receive_path):
1033 for root, _dirs, files in os.walk(receive_path):
1034 def process(rel_path, default_perm):
1035 info = self._get_file_info(os.path.join(source,
1036 rel_path))
1037 if info['perms'] != 0:
1038 target = os.path.join(receive_path, rel_path)
1039 if preserve_perm:
1040 os.chmod(target, info['perms'])
1041 else:
1042 os.chmod(target, default_perm)
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001043
David Pursell788b1b52016-05-19 09:03:31 -07001044 rel_root = os.path.relpath(root, receive_path)
1045 process(rel_root, _DEFAULT_DIR_PERMS)
1046 for f in files:
1047 process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
1048 elif preserve_perm:
1049 os.chmod(receive_path, source_info['perms'])
1050 else:
1051 os.chmod(receive_path, _DEFAULT_FILE_PERMS)
Kevin Cheng018db352015-09-20 02:22:08 -07001052
1053
1054 def get_release_version(self):
1055 """Get the release version from the RELEASE_FILE on the device.
1056
1057 @returns The release string in the RELEASE_FILE.
1058
1059 """
1060 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -07001061
1062
1063 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001064 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001065
Kevin Chengd19e6c62015-10-28 16:39:39 -07001066 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001067
1068 @param parent: Parent directory of the returned tmp dir.
1069
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07001070 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001071 """
Kevin Chengd19e6c62015-10-28 16:39:39 -07001072 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
1073 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001074 if not parent.startswith(TMP_DIR):
1075 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -07001076 self.run('mkdir -p %s' % parent)
1077 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
1078 self.tmp_dirs.append(tmp_dir)
1079 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -07001080
1081
1082 def get_platform(self):
1083 """Determine the correct platform label for this host.
1084
1085 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -07001086 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -07001087
1088 @returns a string representing this host's platform.
1089 """
1090 return 'adb'
1091
1092
Gilad Arnolda76bef02015-09-29 13:55:15 -07001093 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -08001094 """Get the OS type of the DUT, e.g., android or brillo.
1095 """
1096 if not self._os_type:
1097 if self.run_output('getprop ro.product.brand') == 'Brillo':
1098 self._os_type = OS_TYPE_BRILLO
1099 else:
1100 self._os_type = OS_TYPE_ANDROID
1101
1102 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001103
1104
1105 def _forward(self, reverse, args):
1106 """Execute a forwarding command.
1107
1108 @param reverse: Whether this is reverse forwarding (Boolean).
1109 @param args: List of command arguments.
1110 """
1111 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001112 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001113
1114
1115 def add_forwarding(self, src, dst, reverse=False, rebind=True):
1116 """Forward a port between the ADB host and device.
1117
1118 Port specifications are any strings accepted as such by ADB, for
1119 example 'tcp:8080'.
1120
1121 @param src: Port specification to forward from.
1122 @param dst: Port specification to forward to.
1123 @param reverse: Do reverse forwarding from device to host (Boolean).
1124 @param rebind: Allow rebinding an already bound port (Boolean).
1125 """
1126 args = []
1127 if not rebind:
1128 args.append('--no-rebind')
1129 args += [src, dst]
1130 self._forward(reverse, args)
1131
1132
1133 def remove_forwarding(self, src=None, reverse=False):
1134 """Removes forwarding on port.
1135
1136 @param src: Port specification, or None to remove all forwarding.
1137 @param reverse: Whether this is reverse forwarding (Boolean).
1138 """
1139 args = []
1140 if src is None:
1141 args.append('--remove-all')
1142 else:
1143 args += ['--remove', src]
1144 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001145
1146
xixuan6cf6d2f2016-01-29 15:29:00 -08001147 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001148 """
1149 Forwards a port securely through a tunnel process from the server
1150 to the DUT for RPC server connection.
1151 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
1152 to the DUT.
1153
1154 @param port: remote port on the DUT.
1155 @param local_port: local forwarding port.
1156
1157 @return: the tunnel process.
1158 """
1159 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001160 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001161
1162
xixuan6cf6d2f2016-01-29 15:29:00 -08001163 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001164 """
1165 Disconnects a previously forwarded port from the server to the DUT for
1166 RPC server connection.
1167 Remove the previously added 'ADB forward' rule to forward the RPC
1168 packets from the AdbHost to the DUT.
1169
1170 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -08001171 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -07001172 @param port: remote port on the DUT.
1173
1174 """
1175 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001176 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001177
1178
1179 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001180 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001181
1182 @raise: error.AutoservError if the device failed to reboot into
1183 bootloader mode.
1184 """
1185 if self.is_up(command=FASTBOOT_CMD):
1186 return
1187 self.adb_run('reboot bootloader')
1188 if not self.wait_up(command=FASTBOOT_CMD):
1189 raise error.AutoservError(
1190 'The device failed to reboot into bootloader mode.')
1191
1192
Dan Shie4e807b2015-12-10 09:04:03 -08001193 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001194 """Ensure the device is up and can be accessed by adb command.
1195
Dan Shie4e807b2015-12-10 09:04:03 -08001196 @param timeout: Time limit in seconds before returning even if the host
1197 is not up.
1198
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001199 @raise: error.AutoservError if the device failed to reboot into
1200 adb mode.
1201 """
1202 if self.is_up():
1203 return
Dan Shi04980372016-03-22 10:57:47 -07001204 # Ignore timeout error to allow `fastboot reboot` to fail quietly and
1205 # check if the device is in adb mode.
1206 self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
Dan Shie4e807b2015-12-10 09:04:03 -08001207 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001208 raise error.AutoservError(
1209 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -08001210 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -07001211
1212
1213 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -08001214 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001215 """Get the Android build information from the build url.
1216
1217 @param build_url: The url to use for downloading Android artifacts.
1218 pattern: http://$devserver:###/static/branch/target/build_id
1219
Dan Shi6450e142016-03-11 11:52:20 -08001220 @return: A dictionary of build information, including keys:
1221 build_target, branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -08001222 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -07001223 """
Dan Shiab999722015-12-04 14:27:08 -08001224 if not build_url:
1225 raise AndroidInstallError('Need build_url to download image files.')
1226
1227 try:
1228 match = re.match(DEVSERVER_URL_REGEX, build_url)
Dan Shi6450e142016-03-11 11:52:20 -08001229 return {'build_target': match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001230 'branch': match.group('BRANCH'),
Dan Shi6450e142016-03-11 11:52:20 -08001231 'target': ('%s-%s' % (match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001232 match.group('BUILD_TYPE'))),
1233 'build_id': match.group('BUILD_ID')}
1234 except (AttributeError, IndexError, ValueError) as e:
1235 raise AndroidInstallError(
1236 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001237
1238
Dan Shia2872172015-10-31 01:16:51 -07001239 @retry.retry(error.AutoservRunError, timeout_min=10)
Simran Basi7756a0b2016-03-16 13:10:07 -07001240 def download_file(self, build_url, file, dest_dir, unzip=False,
1241 unzip_dest=None):
Dan Shia2872172015-10-31 01:16:51 -07001242 """Download the given file from the build url.
1243
1244 @param build_url: The url to use for downloading Android artifacts.
1245 pattern: http://$devserver:###/static/branch/target/build_id
1246 @param file: Name of the file to be downloaded, e.g., boot.img.
1247 @param dest_dir: Destination folder for the file to be downloaded to.
Simran Basi7756a0b2016-03-16 13:10:07 -07001248 @param unzip: If True, unzip the downloaded file.
1249 @param unzip_dest: Location to unzip the downloaded file to. If not
1250 provided, dest_dir is used.
Dan Shia2872172015-10-31 01:16:51 -07001251 """
Dan Shidb0366c2016-02-19 10:36:18 -08001252 # Append the file name to the url if build_url is linked to the folder
1253 # containing the file.
1254 if not build_url.endswith('/%s' % file):
1255 src_url = os.path.join(build_url, file)
1256 else:
1257 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001258 dest_file = os.path.join(dest_dir, file)
1259 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001260 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Simran Basi7756a0b2016-03-16 13:10:07 -07001261 if unzip:
1262 unzip_dest = unzip_dest or dest_dir
1263 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1264 (dest_dir, file, unzip_dest))
Dan Shia2872172015-10-31 01:16:51 -07001265 except:
1266 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001267 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001268 raise
1269
1270
Dan Shiab999722015-12-04 14:27:08 -08001271 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001272 """Download required image files from the given build_url to a local
1273 directory in the machine runs fastboot command.
1274
1275 @param build_url: The url to use for downloading Android artifacts.
1276 pattern: http://$devserver:###/static/branch/target/build_id
1277
1278 @return: Path to the directory contains image files.
1279 """
Dan Shi08ff1282016-02-18 19:51:16 -08001280 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001281
1282 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001283 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001284
1285 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001286 self.download_file(build_url, zipped_image_file, image_dir,
1287 unzip=True)
Dan Shi49d451f2016-04-19 09:25:01 -07001288 images = android_utils.AndroidImageFiles.get_standalone_images(
1289 build_info['build_target'])
1290 for image_file in images:
Dan Shidb0366c2016-02-19 10:36:18 -08001291 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001292
Dan Shia2872172015-10-31 01:16:51 -07001293 return image_dir
1294 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001295 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001296 raise
1297
1298
Dan Shiab999722015-12-04 14:27:08 -08001299 def stage_brillo_image_files(self, build_url):
1300 """Download required brillo image files from the given build_url to a
1301 local directory in the machine runs fastboot command.
1302
1303 @param build_url: The url to use for downloading Android artifacts.
1304 pattern: http://$devserver:###/static/branch/target/build_id
1305
1306 @return: Path to the directory contains image files.
1307 """
Dan Shi08ff1282016-02-18 19:51:16 -08001308 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001309
1310 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1311 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1312 image_dir = self.teststation.get_tmp_dir()
Dan Shiab999722015-12-04 14:27:08 -08001313
1314 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001315 self.download_file(build_url, zipped_image_file, image_dir,
1316 unzip=True)
1317 self.download_file(build_url, vendor_partitions_file, image_dir,
1318 unzip=True,
1319 unzip_dest=os.path.join(image_dir, 'vendor'))
Dan Shiab999722015-12-04 14:27:08 -08001320 return image_dir
1321 except:
1322 self.teststation.run('rm -rf %s' % image_dir)
1323 raise
1324
1325
Simran Basibeb2bb22016-02-03 15:25:48 -08001326 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001327 """Stage a build on a devserver and return the build_url and devserver.
1328
1329 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001330
Dan Shi225b9042015-11-18 10:25:21 -08001331 @returns a tuple with an update URL like:
1332 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1333 and the devserver instance.
1334 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001335 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001336 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001337 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1338 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001339 build_name = devserver.translate(build_name)
Dan Shi6450e142016-03-11 11:52:20 -08001340 branch, target, build_id = utils.parse_launch_control_build(build_name)
Simran Basibeb2bb22016-02-03 15:25:48 -08001341 is_brillo = os_type == OS_TYPE_BRILLO
Dan Shi08ff1282016-02-18 19:51:16 -08001342 devserver.trigger_download(target, build_id, branch,
1343 is_brillo=is_brillo, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001344 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001345
1346
Dan Shie4e807b2015-12-10 09:04:03 -08001347 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001348 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001349 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001350
1351 Following are the steps used here to provision an android device:
1352 1. If build_local_path is not set, download the image zip file, e.g.,
1353 shamu-img-2284311.zip, unzip it.
1354 2. Run fastboot to install following artifacts:
1355 bootloader, radio, boot, system, vendor(only if exists)
1356
1357 Repair is not supported for Android devices yet.
1358
1359 @param build_url: The url to use for downloading Android artifacts.
1360 pattern: http://$devserver:###/static/$build
1361 @param build_local_path: The path to a local folder that contains the
1362 image files needed to provision the device. Note that the folder
1363 is in the machine running adb command, rather than the drone.
1364 @param wipe: If true, userdata will be wiped before flashing.
1365 @param flash_all: If True, all img files found in img_path will be
1366 flashed. Otherwise, only boot and system are flashed.
1367
1368 @raises AndroidInstallError if any error occurs.
1369 """
Dan Shia2872172015-10-31 01:16:51 -07001370 # If the build is not staged in local server yet, clean up the temp
1371 # folder used to store image files after the provision is completed.
1372 delete_build_folder = bool(not build_local_path)
1373
1374 try:
1375 # Download image files needed for provision to a local directory.
1376 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001377 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001378
1379 # Device needs to be in bootloader mode for flashing.
1380 self.ensure_bootloader_mode()
1381
1382 if wipe:
Dan Shi12a4f662016-05-10 14:49:42 -07001383 self._fastboot_run_with_retry('-w')
Dan Shia2872172015-10-31 01:16:51 -07001384
1385 # Get all *.img file in the build_local_path.
1386 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001387 image_files = self.teststation.run(
1388 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001389 images = dict([(os.path.basename(f), f) for f in image_files])
Dan Shi49d451f2016-04-19 09:25:01 -07001390 build_info = self.get_build_info_from_build_url(build_url)
1391 board = build_info['build_target']
1392 all_images = (
1393 android_utils.AndroidImageFiles.get_standalone_images(board)
1394 + android_utils.AndroidImageFiles.get_zipped_images(board))
1395
1396 # Sort images to be flashed, bootloader needs to be the first one.
1397 bootloader = android_utils.AndroidImageFiles.BOOTLOADER
1398 sorted_images = sorted(
1399 images.items(),
1400 key=lambda pair: 0 if pair[0] == bootloader else 1)
1401 for image, image_file in sorted_images:
1402 if image not in all_images:
Dan Shia2872172015-10-31 01:16:51 -07001403 continue
1404 logging.info('Flashing %s...', image_file)
Dan Shi12a4f662016-05-10 14:49:42 -07001405 self._fastboot_run_with_retry('-S 256M flash %s %s' %
1406 (image[:-4], image_file))
Dan Shi49d451f2016-04-19 09:25:01 -07001407 if image == android_utils.AndroidImageFiles.BOOTLOADER:
Dan Shia2872172015-10-31 01:16:51 -07001408 self.fastboot_run('reboot-bootloader')
1409 self.wait_up(command=FASTBOOT_CMD)
1410 except Exception as e:
1411 logging.error('Install Android build failed with error: %s', e)
1412 # Re-raise the exception with type of AndroidInstallError.
1413 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1414 finally:
1415 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001416 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001417 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1418 DEFAULT_WAIT_UP_TIME_SECONDS)
1419 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001420 logging.info('Successfully installed Android build staged at %s.',
1421 build_url)
1422
1423
Dan Shiab999722015-12-04 14:27:08 -08001424 def install_brillo(self, build_url, build_local_path=None):
1425 """Install the Brillo DUT.
1426
1427 Following are the steps used here to provision an android device:
1428 1. If build_local_path is not set, download the image zip file, e.g.,
1429 dragonboard-img-123456.zip, unzip it. And download the vendor
1430 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1431 unzip it to vendor folder.
1432 2. Run provision_device script to install OS images and vendor
1433 partitions.
1434
1435 @param build_url: The url to use for downloading Android artifacts.
1436 pattern: http://$devserver:###/static/$build
1437 @param build_local_path: The path to a local folder that contains the
1438 image files needed to provision the device. Note that the folder
1439 is in the machine running adb command, rather than the drone.
1440
1441 @raises AndroidInstallError if any error occurs.
1442 """
1443 # If the build is not staged in local server yet, clean up the temp
1444 # folder used to store image files after the provision is completed.
1445 delete_build_folder = bool(not build_local_path)
1446
Dan Shiab999722015-12-04 14:27:08 -08001447 try:
1448 # Download image files needed for provision to a local directory.
1449 if not build_local_path:
1450 build_local_path = self.stage_brillo_image_files(build_url)
1451
1452 # Device needs to be in bootloader mode for flashing.
1453 self.ensure_bootloader_mode()
1454
1455 # Run provision_device command to install image files and vendor
1456 # partitions.
1457 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1458 cmd = (BRILLO_PROVISION_CMD %
1459 {'os_image_dir': build_local_path,
1460 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001461 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001462 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001463 self.teststation.run(cmd)
1464 except Exception as e:
1465 logging.error('Install Brillo build failed with error: %s', e)
1466 # Re-raise the exception with type of AndroidInstallError.
1467 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1468 finally:
1469 if delete_build_folder:
1470 self.teststation.run('rm -rf %s' % build_local_path)
1471 self.ensure_adb_mode()
1472 logging.info('Successfully installed Android build staged at %s.',
1473 build_url)
1474
1475
Dan Shibe3636a2016-02-14 22:48:01 -08001476 @property
1477 def job_repo_url_attribute(self):
1478 """Get the host attribute name for job_repo_url, which should append the
1479 adb serial.
1480 """
1481 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1482
1483
Dan Shie4e807b2015-12-10 09:04:03 -08001484 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001485 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001486 """Install the DUT.
1487
1488 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001489 pattern: http://$devserver:###/static/$build. If build_url is
1490 set to None, the code may try _parser.options.image to do the
1491 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001492 @param build_local_path: The path to a local directory that contains the
1493 image files needed to provision the device.
1494 @param wipe: If true, userdata will be wiped before flashing.
1495 @param flash_all: If True, all img files found in img_path will be
1496 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001497
Dan Shibe3636a2016-02-14 22:48:01 -08001498 @returns A tuple of (image_name, host_attributes).
1499 image_name is the name of image installed, e.g.,
1500 git_mnc-release/shamu-userdebug/1234
1501 host_attributes is a dictionary of (attribute, value), which
1502 can be saved to afe_host_attributes table in database. This
1503 method returns a dictionary with a single entry of
1504 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1505 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001506 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001507 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001508 if not build_url and self._parser.options.image:
1509 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001510 self._parser.options.image, os_type=os_type)
1511 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001512 self.install_android(
1513 build_url=build_url, build_local_path=build_local_path,
1514 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001515 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001516 self.install_brillo(
1517 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001518 else:
1519 raise error.InstallError(
1520 'Installation of os type %s is not supported.' %
1521 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001522 return (build_url.split('static/')[-1],
1523 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001524
1525
1526 def list_files_glob(self, path_glob):
1527 """Get a list of files on the device given glob pattern path.
1528
1529 @param path_glob: The path glob that we want to return the list of
1530 files that match the glob. Relative paths will not work as
1531 expected. Supply an absolute path to get the list of files
1532 you're hoping for.
1533
1534 @returns List of files that match the path_glob.
1535 """
1536 # This is just in case path_glob has no path separator.
1537 base_path = os.path.dirname(path_glob) or '.'
1538 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001539 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001540 if result.exit_status != 0:
1541 return []
1542 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001543
1544
Dan Shic716ac62016-05-24 16:47:57 -07001545 @retry.retry(error.AutoservRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
Dan Shida995002016-04-25 23:12:58 -07001546 def install_apk(self, apk, force_reinstall=True):
Kevin Cheng31355942016-01-05 14:23:35 -08001547 """Install the specified apk.
1548
1549 This will install the apk and override it if it's already installed and
1550 will also allow for downgraded apks.
1551
1552 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001553 @param force_reinstall: True to reinstall the apk even if it's already
Dan Shida995002016-04-25 23:12:58 -07001554 installed. Default is set to True.
Dan Shidb0366c2016-02-19 10:36:18 -08001555
1556 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001557 """
Dan Shic716ac62016-05-24 16:47:57 -07001558 try:
1559 client_utils.poll_for_condition(
1560 lambda: self.run('pm list packages',
1561 ignore_status=True).exit_status == 0,
1562 timeout=120)
1563 client_utils.poll_for_condition(
1564 lambda: self.run('service list | grep mount',
1565 ignore_status=True).exit_status == 0,
1566 timeout=120)
1567 return self.adb_run('install %s -d %s' %
1568 ('-r' if force_reinstall else '', apk))
1569 except error.AutoservRunError:
1570 self.reboot()
1571 raise
Dan Shidb0366c2016-02-19 10:36:18 -08001572
1573
1574 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1575 def _confirm_apk_installed(self, package_name):
1576 """Confirm if apk is already installed with the given name.
1577
1578 `pm list packages` command is not reliable some time. The retry helps to
1579 reduce the chance of false negative.
1580
1581 @param package_name: Name of the package, e.g., com.android.phone.
1582
1583 @raise AutoservRunError: If the package is not found or pm list command
1584 failed for any reason.
1585 """
1586 name = 'package:%s' % package_name
1587 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1588
1589
1590 def is_apk_installed(self, package_name):
1591 """Check if apk is already installed with the given name.
1592
1593 @param package_name: Name of the package, e.g., com.android.phone.
1594
1595 @return: True if package is installed. False otherwise.
1596 """
1597 try:
1598 self._confirm_apk_installed(package_name)
1599 return True
1600 except:
1601 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001602
1603
1604 def get_attributes_to_clear_before_provision(self):
1605 """Get a list of attributes to be cleared before machine_install starts.
1606 """
1607 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001608
1609
1610 def get_labels(self):
1611 """Return a list of the labels gathered from the devices connected.
1612
1613 @return: A list of strings that denote the labels from all the devices
1614 connected.
1615 """
1616 return self.labels.get_labels(self)
1617
1618
1619 def update_labels(self):
1620 """Update the labels for this testbed."""
1621 self.labels.update_labels(self)
Dan Shi6450e142016-03-11 11:52:20 -08001622
1623
1624 def stage_server_side_package(self, image=None):
1625 """Stage autotest server-side package on devserver.
1626
1627 @param image: A build name, e.g., git_mnc_dev/shamu-eng/123
1628
1629 @return: A url to the autotest server-side package. Return None if
1630 server-side package is not supported.
1631 @raise: error.AutoservError if fail to locate the build to test with.
1632 """
Dan Shid37736b2016-07-06 15:10:29 -07001633 # If enable_drone_in_restricted_subnet is False, do not set hostname
1634 # in devserver.resolve call, so a devserver in non-restricted subnet
1635 # is picked to stage autotest server package for drone to download.
1636 hostname = self.hostname
1637 if not utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1638 hostname = None
Dan Shi6450e142016-03-11 11:52:20 -08001639 if image:
Dan Shid37736b2016-07-06 15:10:29 -07001640 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001641 else:
1642 job_repo_url = afe_utils.get_host_attribute(
1643 self, self.job_repo_url_attribute)
1644 if job_repo_url:
1645 devserver_url, image = (
1646 tools.get_devserver_build_from_package_url(
1647 job_repo_url, True))
Dan Shid37736b2016-07-06 15:10:29 -07001648 # If enable_drone_in_restricted_subnet is True, use the
1649 # existing devserver. Otherwise, resolve a new one in
1650 # non-restricted subnet.
1651 if utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1652 ds = dev_server.AndroidBuildServer(devserver_url)
1653 else:
1654 ds = dev_server.AndroidBuildServer.resolve(image)
Dan Shi6450e142016-03-11 11:52:20 -08001655 else:
1656 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
1657 if not labels:
1658 raise error.AutoservError(
1659 'Failed to stage server-side package. The host has '
1660 'no job_report_url attribute or version label.')
1661 image = labels[0].name[len(self.VERSION_PREFIX)+1:]
Dan Shid37736b2016-07-06 15:10:29 -07001662 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001663
1664 branch, target, build_id = utils.parse_launch_control_build(image)
1665 build_target, _ = utils.parse_launch_control_target(target)
1666
1667 # For any build older than MIN_VERSION_SUPPORT_SSP, server side
1668 # packaging is not supported.
1669 try:
1670 if int(build_id) < self.MIN_VERSION_SUPPORT_SSP:
1671 logging.warn('Build %s is older than %s. Server side packaging '
1672 'is disabled.', image,
1673 self.MIN_VERSION_SUPPORT_SSP)
1674 return None
1675 except ValueError:
1676 logging.warn('Failed to compare build id in %s with the minimum '
1677 'version that supports server side packaging. Server '
1678 'side packaging is disabled.', image)
1679 return None
1680
1681 ds.stage_artifacts(target, build_id, branch,
1682 artifacts=['autotest_server_package'])
1683 autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
1684 {'build_target': build_target,
1685 'build_id': build_id})
1686 return '%s/static/%s/%s' % (ds.url(), image,
1687 autotest_server_package_name)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07001688
1689
1690 def _sync_time(self):
1691 """Approximate synchronization of time between host and ADB device.
1692
1693 This sets the ADB/Android device's clock to approximately the same
1694 time as the Autotest host for the purposes of comparing Android system
1695 logs such as logcat to logs from the Autotest host system.
1696 """
1697 command = 'date '
1698 sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
1699 if sdk_version < 23:
1700 # Android L and earlier use this format: date -s (format).
1701 command += ('-s %s' %
1702 datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
1703 else:
1704 # Android M and later use this format: date (format).
1705 command += datetime.datetime.now().strftime('%m%d%H%M%Y.%S')
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -07001706 self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1707 ignore_timeout=True)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001708
1709
1710 def _enable_native_crash_logging(self):
1711 """Enable native (non-Java) crash logging.
1712
1713 Currently only supported on Brillo devices.
1714 """
1715 if self._os_type != OS_TYPE_BRILLO:
1716 return
1717
1718 self.run('touch /data/misc/metrics/enabled',
1719 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1720 ignore_timeout=True)
1721 # If running, crash_sender will delete crash files every hour.
1722 self.run('stop crash_sender',
1723 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1724 ignore_timeout=True)
1725
1726
1727 def _collect_crash_logs(self):
1728 """Copies crash log files from the DUT to the drone.
1729
1730 Currently only supported on Brillo devices.
1731 """
1732 if self.get_os_type() != OS_TYPE_BRILLO:
1733 return
1734
1735 files = None
1736 try:
1737 result = self.run('ls %s' % BRILLO_NATIVE_CRASH_LOG_DIR,
1738 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS)
1739 files = result.stdout.strip().split()
1740 except (error.AutotestHostRunError, error.AutoservRunError,
1741 error.AutoservSSHTimeout, error.CmdTimeoutError):
1742 logging.debug('Unable to ls %s, unable to find crash logs',
1743 BRILLO_NATIVE_CRASH_LOG_DIR)
1744 if not files:
1745 logging.debug('There are no Brillo crash logs.')
1746 return
1747
1748 crash_dir = os.path.join(self.job.resultdir, 'crash')
1749 try:
1750 os.mkdir(crash_dir)
1751 except OSError as e:
1752 if e.errno != errno.EEXIST:
1753 raise e
1754
1755 for f in files:
1756 logging.debug('Brillo native crash file produced: %s', f)
1757 source = os.path.join(BRILLO_NATIVE_CRASH_LOG_DIR, f)
1758 dest = os.path.join(crash_dir, f)
1759 self.get_file(source=source, dest=dest)