blob: 8976f84fa1179a79d5153486eb4c6cd24e03dbf2 [file] [log] [blame]
Simran Basi431010f2013-09-04 10:42:41 -07001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07004
5import datetime
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07006import errno
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07007import functools
Simran Basi431010f2013-09-04 10:42:41 -07008import logging
Kevin Cheng018db352015-09-20 02:22:08 -07009import os
Simran Basi431010f2013-09-04 10:42:41 -070010import re
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070011import stat
Dan Shia2872172015-10-31 01:16:51 -070012import sys
Simran Basi431010f2013-09-04 10:42:41 -070013import time
14
15import common
16
Simran Basi9c5d3982016-04-01 18:49:44 -070017from autotest_lib.client.bin import utils as client_utils
Dan Shi49d451f2016-04-19 09:25:01 -070018from autotest_lib.client.common_lib import android_utils
Simran Basi431010f2013-09-04 10:42:41 -070019from autotest_lib.client.common_lib import error
Dan Shi6450e142016-03-11 11:52:20 -080020from autotest_lib.client.common_lib import global_config
Dan Shi225b9042015-11-18 10:25:21 -080021from autotest_lib.client.common_lib.cros import dev_server
Simran Basi431010f2013-09-04 10:42:41 -070022from autotest_lib.client.common_lib.cros import retry
Dan Shi6450e142016-03-11 11:52:20 -080023from autotest_lib.server import afe_utils
Dan Shi225b9042015-11-18 10:25:21 -080024from autotest_lib.server import autoserv_parser
Dan Shia2872172015-10-31 01:16:51 -070025from autotest_lib.server import constants as server_constants
Dan Shi225b9042015-11-18 10:25:21 -080026from autotest_lib.server import utils
Simran Basi5ace6f22016-01-06 17:30:44 -080027from autotest_lib.server.cros import provision
Dan Shi6450e142016-03-11 11:52:20 -080028from autotest_lib.server.cros.dynamic_suite import tools
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070029from autotest_lib.server.cros.dynamic_suite import constants
Simran Basi724b8a52013-09-30 11:19:31 -070030from autotest_lib.server.hosts import abstract_ssh
Kevin Chengc6a645a2015-12-18 11:15:10 -080031from autotest_lib.server.hosts import adb_label
32from autotest_lib.server.hosts import base_label
Kevin Cheng85e864a2015-11-30 11:49:34 -080033from autotest_lib.server.hosts import teststation_host
Simran Basi431010f2013-09-04 10:42:41 -070034
35
Dan Shi6450e142016-03-11 11:52:20 -080036CONFIG = global_config.global_config
37
Dan Shi6ea3e1c2015-10-28 15:19:04 -070038ADB_CMD = 'adb'
39FASTBOOT_CMD = 'fastboot'
Simran Basi431010f2013-09-04 10:42:41 -070040SHELL_CMD = 'shell'
Filipe Brandenburger34363392015-08-13 14:57:45 -070041# Some devices have no serial, then `adb serial` has output such as:
42# (no serial number) device
43# ?????????? device
44DEVICE_NO_SERIAL_MSG = '(no serial number)'
45DEVICE_NO_SERIAL_TAG = '<NO_SERIAL>'
Simran Basi431010f2013-09-04 10:42:41 -070046# Regex to find an adb device. Examples:
47# 0146B5580B01801B device
48# 018e0ecb20c97a62 device
49# 172.22.75.141:5555 device
Kevin Cheng224415e2016-04-22 11:32:10 -070050# localhost:22 device
Alexandru Branciogea380fb2016-04-01 16:01:34 +030051DEVICE_FINDER_REGEX = (r'^(?P<SERIAL>([\w-]+)|((tcp:)?' +
52 '\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}([:]5555)?)|' +
Kevin Cheng224415e2016-04-22 11:32:10 -070053 '((tcp:)?localhost([:]22)?)|' +
Filipe Brandenburger34363392015-08-13 14:57:45 -070054 re.escape(DEVICE_NO_SERIAL_MSG) +
Alexandru Branciogea380fb2016-04-01 16:01:34 +030055 r')[ \t]+(?:device|fastboot)')
Simran Basi431010f2013-09-04 10:42:41 -070056CMD_OUTPUT_PREFIX = 'ADB_CMD_OUTPUT'
57CMD_OUTPUT_REGEX = ('(?P<OUTPUT>[\s\S]*)%s:(?P<EXIT_CODE>\d{1,3})' %
58 CMD_OUTPUT_PREFIX)
Kevin Cheng018db352015-09-20 02:22:08 -070059RELEASE_FILE = 'ro.build.version.release'
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070060BOARD_FILE = 'ro.product.device'
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -070061SDK_FILE = 'ro.build.version.sdk'
Simran Basi242f8de2016-06-08 14:23:43 -070062LOGCAT_FILE_FMT = 'logcat_%s.log'
Simran Basi38f7ddf2015-09-18 12:25:03 -070063TMP_DIR = '/data/local/tmp'
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070064# Regex to pull out file type, perms and symlink. Example:
Kevin Chengaaabd0c2015-11-10 16:05:04 -080065# lrwxrwx--- 1 6 root system 2015-09-12 19:21 blah_link -> ./blah
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070066FILE_INFO_REGEX = '^(?P<TYPE>[dl-])(?P<PERMS>[rwx-]{9})'
67FILE_SYMLINK_REGEX = '^.*-> (?P<SYMLINK>.+)'
68# List of the perm stats indexed by the order they are listed in the example
69# supplied above.
70FILE_PERMS_FLAGS = [stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR,
71 stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP,
72 stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH]
Simran Basi431010f2013-09-04 10:42:41 -070073
Dan Shi6ea3e1c2015-10-28 15:19:04 -070074# Default maximum number of seconds to wait for a device to be down.
75DEFAULT_WAIT_DOWN_TIME_SECONDS = 10
76# Default maximum number of seconds to wait for a device to be up.
Dan Shie4e807b2015-12-10 09:04:03 -080077DEFAULT_WAIT_UP_TIME_SECONDS = 300
78# Maximum number of seconds to wait for a device to be up after it's wiped.
Dan Shi50a412a2016-01-05 10:52:40 -080079WAIT_UP_AFTER_WIPE_TIME_SECONDS = 1200
Simran Basi431010f2013-09-04 10:42:41 -070080
Dan Shi7075f552016-04-21 15:42:41 -070081# Default timeout for retrying adb/fastboot command.
Dan Shi1cbf3812016-07-18 23:06:38 +000082DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS = 10
Dan Shi7075f552016-04-21 15:42:41 -070083
Dan Shia2872172015-10-31 01:16:51 -070084OS_TYPE_ANDROID = 'android'
85OS_TYPE_BRILLO = 'brillo'
86
Dan Shie234dea2016-01-20 17:15:17 -080087# Regex to parse build name to get the detailed build information.
Dan Shi6450e142016-03-11 11:52:20 -080088BUILD_REGEX = ('(?P<BRANCH>([^/]+))/(?P<BUILD_TARGET>([^/]+))-'
Dan Shie234dea2016-01-20 17:15:17 -080089 '(?P<BUILD_TYPE>([^/]+))/(?P<BUILD_ID>([^/]+))')
Dan Shia2872172015-10-31 01:16:51 -070090# Regex to parse devserver url to get the detailed build information. Sample
91# url: http://$devserver:8080/static/branch/target/build_id
Dan Shie234dea2016-01-20 17:15:17 -080092DEVSERVER_URL_REGEX = '.*/%s/*' % BUILD_REGEX
Dan Shia2872172015-10-31 01:16:51 -070093
Dan Shi6450e142016-03-11 11:52:20 -080094ANDROID_IMAGE_FILE_FMT = '%(build_target)s-img-%(build_id)s.zip'
Dan Shi49d451f2016-04-19 09:25:01 -070095
Dan Shiab999722015-12-04 14:27:08 -080096BRILLO_VENDOR_PARTITIONS_FILE_FMT = (
Dan Shi6450e142016-03-11 11:52:20 -080097 '%(build_target)s-vendor_partitions-%(build_id)s.zip')
98AUTOTEST_SERVER_PACKAGE_FILE_FMT = (
99 '%(build_target)s-autotest_server_package-%(build_id)s.tar.bz2')
Simran Basi9228a6f2016-03-29 12:03:37 -0700100ADB_DEVICE_PREFIXES = ['product:', 'model:', 'device:']
Dan Shia2872172015-10-31 01:16:51 -0700101
Simran Basi9c5d3982016-04-01 18:49:44 -0700102# Map of product names to build target name.
103PRODUCT_TARGET_MAP = {'dragon' : 'ryu',
104 'flo' : 'razor',
105 'flo_lte' : 'razorg',
106 'gm4g_sprout' : 'seed_l8150',
107 'flounder' : 'volantis',
108 'flounder_lte' : 'volantisg'}
109
Dan Shiab999722015-12-04 14:27:08 -0800110# Command to provision a Brillo device.
111# os_image_dir: The full path of the directory that contains all the Android image
112# files (from the image zip file).
113# vendor_partition_dir: The full path of the directory that contains all the
114# Brillo vendor partitions, and provision-device script.
115BRILLO_PROVISION_CMD = (
Simran Basi7e52c622016-01-05 15:43:51 -0800116 'sudo ANDROID_PROVISION_OS_PARTITIONS=%(os_image_dir)s '
Dan Shiab999722015-12-04 14:27:08 -0800117 'ANDROID_PROVISION_VENDOR_PARTITIONS=%(vendor_partition_dir)s '
118 '%(vendor_partition_dir)s/provision-device')
Dan Shia2872172015-10-31 01:16:51 -0700119
Dan Shi12a4f662016-05-10 14:49:42 -0700120# Default timeout in minutes for fastboot commands.
121DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN = 10
122
David Purselle01548b2016-05-11 10:00:42 -0700123# Default permissions for files/dirs copied from the device.
124_DEFAULT_FILE_PERMS = 0o600
125_DEFAULT_DIR_PERMS = 0o700
126
Dan Shi626d5412016-05-16 16:05:13 -0700127# Constants for getprop return value for a given property.
128PROPERTY_VALUE_TRUE = '1'
129
Dan Shic716ac62016-05-24 16:47:57 -0700130# Timeout used for retrying installing apk. After reinstall apk failed, we try
131# to reboot the device and try again.
132APK_INSTALL_TIMEOUT_MIN = 5
133
Bryan Lewandowski68646b62016-07-12 10:24:57 -0700134# Directory where (non-Brillo) Android stores tombstone crash logs.
135ANDROID_TOMBSTONE_CRASH_LOG_DIR = '/data/tombstones'
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700136# Directory where Brillo stores crash logs for native (non-Java) crashes.
137BRILLO_NATIVE_CRASH_LOG_DIR = '/data/misc/crash_reporter/crash'
138
Dan Shia2872172015-10-31 01:16:51 -0700139class AndroidInstallError(error.InstallError):
140 """Generic error for Android installation related exceptions."""
141
142
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
Justin Giorgi5208eaa2016-07-02 20:12:12 -0700239 else teststation_host.create_teststationhost(
240 hostname=hostname,
241 user=self.user,
242 password=self.password,
243 port=self.port
244 ))
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700245
246 msg ='Initializing ADB device on host: %s' % hostname
Dan Shi50a412a2016-01-05 10:52:40 -0800247 if self.adb_serial:
248 msg += ', ADB serial: %s' % self.adb_serial
249 if self.fastboot_serial:
250 msg += ', fastboot serial: %s' % self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700251 logging.debug(msg)
252
Dan Shiab999722015-12-04 14:27:08 -0800253 self._os_type = None
254
Simran Basi431010f2013-09-04 10:42:41 -0700255
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700256 def _connect_over_tcpip_as_needed(self):
257 """Connect to the ADB device over TCP/IP if so configured."""
Simran Basi9228a6f2016-03-29 12:03:37 -0700258 if not self._use_tcpip:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700259 return
260 logging.debug('Connecting to device over TCP/IP')
Simran Basi9228a6f2016-03-29 12:03:37 -0700261 self.adb_run('connect %s' % self.adb_serial)
Simran Basi431010f2013-09-04 10:42:41 -0700262
263
Roshan Pius4d7540c2015-12-16 13:30:32 -0800264 def _restart_adbd_with_root_permissions(self):
265 """Restarts the adb daemon with root permissions."""
Dan Shi922de302016-04-22 15:19:18 -0700266 @retry.retry(error.AutoservRunError, timeout_min=20/60.0, delay_sec=1)
267 def run_adb_root():
268 """Run command `adb root`."""
269 self.adb_run('root')
270
271 # adb command may flake with error "device not found". Retry the root
272 # command to reduce the chance of flake.
273 run_adb_root()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800274 # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
275 time.sleep(1)
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300276 self._connect_over_tcpip_as_needed()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800277 self.adb_run('wait-for-device')
278
279
Simran Basi9228a6f2016-03-29 12:03:37 -0700280 def _set_tcp_port(self):
281 """Ensure the device remains in tcp/ip mode after a reboot."""
282 if not self._use_tcpip:
283 return
284 port = self.adb_serial.split(':')[-1]
285 self.run('setprop persist.adb.tcp.port %s' % port)
286
287
Roshan Pius4d7540c2015-12-16 13:30:32 -0800288 def _reset_adbd_connection(self):
289 """Resets adbd connection to the device after a reboot/initialization"""
Roshan Pius4d7540c2015-12-16 13:30:32 -0800290 self._connect_over_tcpip_as_needed()
Simran Basi9228a6f2016-03-29 12:03:37 -0700291 self._restart_adbd_with_root_permissions()
292 self._set_tcp_port()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800293
294
Kevin Cheng85e864a2015-11-30 11:49:34 -0800295 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800296 def adb_run(self, command, **kwargs):
Simran Basi431010f2013-09-04 10:42:41 -0700297 """Runs an adb command.
298
Kevin Chengd19e6c62015-10-28 16:39:39 -0700299 This command will launch on the test station.
Simran Basi431010f2013-09-04 10:42:41 -0700300
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700301 Refer to _device_run method for docstring for parameters.
302 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800303 return self._device_run(ADB_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700304
305
Kevin Cheng85e864a2015-11-30 11:49:34 -0800306 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800307 def fastboot_run(self, command, **kwargs):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700308 """Runs an fastboot command.
309
Kevin Chengd19e6c62015-10-28 16:39:39 -0700310 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700311
312 Refer to _device_run method for docstring for parameters.
313 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800314 return self._device_run(FASTBOOT_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700315
316
Dan Shi12a4f662016-05-10 14:49:42 -0700317 # pylint: disable=missing-docstring
318 @retry.retry(error.AutoservRunError,
319 timeout_min=DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN)
320 def _fastboot_run_with_retry(self, command, **kwargs):
321 """Runs an fastboot command with retry.
322
323 This command will launch on the test station.
324
325 Refer to _device_run method for docstring for parameters.
326 """
327 return self.fastboot_run(command, **kwargs)
328
329
Simran Basie6c4f142016-06-23 17:10:04 -0700330 def _log_adb_pid(self):
331 """Log the pid of adb server.
332
333 adb's server is known to have bugs and randomly restart. BY logging
334 the server's pid it will allow us to better debug random adb failures.
335 """
336 adb_pid = self.teststation.run('pgrep -f "adb.*server"')
337 logging.debug('ADB Server PID: %s', adb_pid.stdout)
338
339
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700340 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700341 timeout=3600, ignore_status=False, ignore_timeout=False,
342 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
343 connect_timeout=30, options='', stdin=None, verbose=True,
344 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700345 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700346
Kevin Chengd19e6c62015-10-28 16:39:39 -0700347 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700348
Simran Basi431010f2013-09-04 10:42:41 -0700349 @param command: Command to run.
350 @param shell: If true the command runs in the adb shell otherwise if
351 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700352 reboot with shell=False will call 'adb reboot'. This
353 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700354 @param timeout: Time limit in seconds before attempting to
355 kill the running process. The run() function
356 will take a few seconds longer than 'timeout'
357 to complete if it has to kill the process.
358 @param ignore_status: Do not raise an exception, no matter
359 what the exit code of the command is.
360 @param ignore_timeout: Bool True if command timeouts should be
361 ignored. Will return None on command timeout.
362 @param stdout: Redirect stdout.
363 @param stderr: Redirect stderr.
364 @param connect_timeout: Connection timeout (in seconds)
365 @param options: String with additional ssh command options
366 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700367 @param require_sudo: True to require sudo to run the command. Default is
368 False.
Simran Basi431010f2013-09-04 10:42:41 -0700369 @param args: Sequence of strings to pass as arguments to command by
370 quoting them in " and escaping their contents if
371 necessary.
372
373 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700374 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700375 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800376 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700377 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800378 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700379 else:
380 raise NotImplementedError('Mode %s is not supported' % function)
381
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700382 if function != ADB_CMD and shell:
383 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700384
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700385 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700386
387 if serial:
388 cmd += '-s %s ' % serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700389
Simran Basi431010f2013-09-04 10:42:41 -0700390 if shell:
391 cmd += '%s ' % SHELL_CMD
392 cmd += command
393
Simran Basie6c4f142016-06-23 17:10:04 -0700394 self._log_adb_pid()
395
Roshan Pius58e5dd32015-10-16 15:16:42 -0700396 if verbose:
397 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700398
Kevin Cheng85e864a2015-11-30 11:49:34 -0800399 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400400 ignore_status=ignore_status,
401 ignore_timeout=ignore_timeout, stdout_tee=stdout,
402 stderr_tee=stderr, options=options, stdin=stdin,
403 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700404
405
Dan Shi8c51bda2016-05-26 12:21:02 -0700406 def _run_output_with_retry(self, cmd):
407 """Call run_output method for the given command with retry.
408
Dan Shi68094122016-06-10 14:29:06 -0700409 adb command can be flaky some time, and the command may fail or return
410 empty string. It may take several retries until a value can be returned.
Dan Shi8c51bda2016-05-26 12:21:02 -0700411
412 @param cmd: The command to run.
413
414 @return: Return value from the command after retry.
415 """
416 try:
417 return client_utils.poll_for_condition(
Dan Shi68094122016-06-10 14:29:06 -0700418 lambda: self.run_output(cmd, ignore_status=True),
Dan Shi8c51bda2016-05-26 12:21:02 -0700419 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
420 sleep_interval=0.5,
421 desc='Get return value for command `%s`' % cmd)
422 except client_utils.TimeoutError:
423 return ''
424
425
Dan Shie234dea2016-01-20 17:15:17 -0800426 def get_board_name(self):
427 """Get the name of the board, e.g., shamu, dragonboard etc.
428 """
Simran Basi9c5d3982016-04-01 18:49:44 -0700429 product = self.run_output('getprop %s' % BOARD_FILE)
430 return PRODUCT_TARGET_MAP.get(product, product)
Dan Shie234dea2016-01-20 17:15:17 -0800431
432
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700433 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700434 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700435 """Determine the correct board label for the device.
436
437 @returns a string representing this device's board.
438 """
Dan Shie234dea2016-01-20 17:15:17 -0800439 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700440 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800441 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700442
443
Christopher Wiley08849d52013-11-22 08:57:58 -0800444 def job_start(self):
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700445 """Overload of parent which intentionally doesn't log certain files.
Dan Shi2d279cf2016-05-27 22:06:10 +0000446
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700447 The parent implementation attempts to log certain Linux files, such as
448 /var/log, which do not exist on Android, thus there is no call to the
449 parent's job_start(). The sync call is made so that logcat logs can be
450 approximately matched to server logs.
Dan Shi2d279cf2016-05-27 22:06:10 +0000451 """
Justin Giorgidd05a942016-07-05 20:53:12 -0700452 # Try resetting the ADB daemon on the device, however if we are
453 # creating the host to do a repair job, the device maybe inaccesible
454 # via ADB.
455 try:
456 self._reset_adbd_connection()
457 except (error.AutotestHostRunError, error.AutoservRunError) as e:
458 logging.error('Unable to reset the device adb daemon connection: '
459 '%s.', e)
460
Simran Basid6b49792016-06-07 17:22:03 -0700461 if self.is_up():
462 self._sync_time()
Bryan Lewandowski8c96bb22016-07-19 12:56:03 -0700463 self._enable_native_crash_logging()
Christopher Wiley08849d52013-11-22 08:57:58 -0800464
465
Simran Basi431010f2013-09-04 10:42:41 -0700466 def run(self, command, timeout=3600, ignore_status=False,
467 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
468 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700469 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700470 """Run a command on the adb device.
471
472 The command given will be ran directly on the adb device; for example
473 'ls' will be ran as: 'abd shell ls'
474
475 @param command: The command line string.
476 @param timeout: Time limit in seconds before attempting to
477 kill the running process. The run() function
478 will take a few seconds longer than 'timeout'
479 to complete if it has to kill the process.
480 @param ignore_status: Do not raise an exception, no matter
481 what the exit code of the command is.
482 @param ignore_timeout: Bool True if command timeouts should be
483 ignored. Will return None on command timeout.
484 @param stdout_tee: Redirect stdout.
485 @param stderr_tee: Redirect stderr.
486 @param connect_timeout: Connection timeout (in seconds).
487 @param options: String with additional ssh command options.
488 @param stdin: Stdin to pass (a string) to the executed command
489 @param args: Sequence of strings to pass as arguments to command by
490 quoting them in " and escaping their contents if
491 necessary.
492
493 @returns A CMDResult object or None if the call timed out and
494 ignore_timeout is True.
495
496 @raises AutoservRunError: If the command failed.
497 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700498 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700499 command = ('"%s; echo %s:\$?"' %
500 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700501 result = self.adb_run(
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700502 command, shell=True, timeout=timeout,
Simran Basi431010f2013-09-04 10:42:41 -0700503 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
504 stdout=stdout_tee, stderr=stderr_tee,
505 connect_timeout=connect_timeout, options=options, stdin=stdin,
Roshan Pius58e5dd32015-10-16 15:16:42 -0700506 verbose=verbose, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700507 if not result:
508 # In case of timeouts.
509 return None
510
511 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
Roshan Pius5ba5d182015-10-28 09:19:41 -0700512 if not parse_output and not ignore_status:
Dan Shi1cbf3812016-07-18 23:06:38 +0000513 raise error.AutoservRunError(
Roshan Pius5ba5d182015-10-28 09:19:41 -0700514 'Failed to parse the exit code for command: %s' %
515 command, result)
516 elif parse_output:
517 result.stdout = parse_output.group('OUTPUT')
518 result.exit_status = int(parse_output.group('EXIT_CODE'))
519 if result.exit_status != 0 and not ignore_status:
520 raise error.AutoservRunError(command, result)
Simran Basi431010f2013-09-04 10:42:41 -0700521 return result
522
523
Dan Shicf7d2562016-06-16 14:08:23 -0700524 def check_boot_to_adb_complete(self, exception_type=error.TimeoutException):
525 """Check if the device has finished booting and accessible by adb.
526
527 @param exception_type: Type of exception to raise. Default is set to
528 error.TimeoutException for retry.
529
530 @raise exception_type: If the device has not finished booting yet, raise
531 an exception of type `exception_type`.
532 """
533 bootcomplete = self._run_output_with_retry('getprop dev.bootcomplete')
534 if bootcomplete != PROPERTY_VALUE_TRUE:
535 raise exception_type('dev.bootcomplete is %s.' % bootcomplete)
536 if self.get_os_type() == OS_TYPE_ANDROID:
537 boot_completed = self._run_output_with_retry(
538 'getprop sys.boot_completed')
539 if boot_completed != PROPERTY_VALUE_TRUE:
540 raise exception_type('sys.boot_completed is %s.' %
541 boot_completed)
542
543
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700544 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
545 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700546
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700547 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700548
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700549 @param timeout: Time limit in seconds before returning even if the host
550 is not up.
551 @param command: The command used to test if a device is up, i.e.,
552 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700553
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700554 @returns True if the host was found to be up before the timeout expires,
555 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700556 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700557 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
558 delay_sec=1)
559 def _wait_up():
560 if not self.is_up(command=command):
561 raise error.TimeoutException('Device is still down.')
Dan Shicf7d2562016-06-16 14:08:23 -0700562 if command == ADB_CMD:
563 self.check_boot_to_adb_complete()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700564 return True
565
566 try:
567 _wait_up()
568 logging.debug('Host %s is now up, and can be accessed by %s.',
569 self.hostname, command)
570 return True
571 except error.TimeoutException:
572 logging.debug('Host %s is still down after waiting %d seconds',
573 self.hostname, timeout)
574 return False
Simran Basi431010f2013-09-04 10:42:41 -0700575
576
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700577 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
578 warning_timer=None, old_boot_id=None, command=ADB_CMD):
579 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700580
581 Overrides wait_down from AbstractSSHHost.
582
583 @param timeout: Time in seconds to wait for the host to go down.
584 @param warning_timer: Time limit in seconds that will generate
585 a warning if the host is not down yet.
586 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700587 @param old_boot_id: Not applicable for adb_host.
588 @param command: `adb`, test if the device can be accessed by adb
589 command, or `fastboot`, test if the device can be accessed by
590 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700591
592 @returns True if the device goes down before the timeout, False
593 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700594 """
595 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
596 delay_sec=1)
597 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700598 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700599 raise error.TimeoutException('Device is still up.')
600 return True
601
602 try:
603 _wait_down()
604 logging.debug('Host %s is now down', self.hostname)
605 return True
606 except error.TimeoutException:
607 logging.debug('Host %s is still up after waiting %d seconds',
608 self.hostname, timeout)
609 return False
610
611
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700612 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700613 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700614
615 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700616 """
617 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700618 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700619 self.adb_run('reboot', timeout=10, ignore_timeout=True)
620 if not self.wait_down():
621 raise error.AutoservRebootError(
622 'ADB Device is still up after reboot')
623 if not self.wait_up():
624 raise error.AutoservRebootError(
625 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800626 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800627
628
Alexandru Branciog969ff7c2016-03-30 14:07:15 +0300629 def fastboot_reboot(self):
630 """Do a fastboot reboot to go back to adb.
631
632 @raises AutoservRebootError if reboot failed.
633 """
634 self.fastboot_run('reboot')
635 if not self.wait_down(command=FASTBOOT_CMD):
636 raise error.AutoservRebootError(
637 'Device is still in fastboot mode after reboot')
638 if not self.wait_up():
639 raise error.AutoservRebootError(
640 'Device failed to boot to adb after fastboot reboot.')
641 self._reset_adbd_connection()
642
643
Ralph Nathanb45eb672015-11-18 20:04:39 -0800644 def remount(self):
645 """Remounts paritions on the device read-write.
646
647 Specifically, the /system, /vendor (if present) and /oem (if present)
648 partitions on the device are remounted read-write.
649 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800650 self.adb_run('remount')
651
652
Kevin Cheng549beb42015-11-18 11:42:25 -0800653 @staticmethod
654 def parse_device_serials(devices_output):
655 """Return a list of parsed serials from the output.
656
657 @param devices_output: Output from either an adb or fastboot command.
658
659 @returns List of device serials
660 """
661 devices = []
662 for line in devices_output.splitlines():
663 match = re.search(DEVICE_FINDER_REGEX, line)
664 if match:
665 serial = match.group('SERIAL')
666 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
667 serial = DEVICE_NO_SERIAL_TAG
668 logging.debug('Found Device: %s', serial)
669 devices.append(serial)
670 return devices
671
672
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700673 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700674 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700675
676 @params use_adb: True to get adb accessible devices. Set to False to
677 get fastboot accessible devices.
678
Kevin Chengd19e6c62015-10-28 16:39:39 -0700679 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700680 """
681 if use_adb:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300682 result = self.adb_run('devices').stdout
683 if self.adb_serial and self.adb_serial not in result:
684 self._connect_over_tcpip_as_needed()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700685 else:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300686 result = self.fastboot_run('devices').stdout
687 if (self.fastboot_serial and
688 self.fastboot_serial not in result):
689 # fastboot devices won't list the devices using TCP
690 try:
691 if 'product' in self.fastboot_run('getvar product',
692 timeout=2).stderr:
693 result += '\n%s\tfastboot' % self.fastboot_serial
Kevin Chengcfcb2cf2016-04-13 10:04:36 -0700694 # The main reason we do a general Exception catch here instead
695 # of setting ignore_timeout/status to True is because even when
696 # the fastboot process has been nuked, it still stays around and
697 # so bgjob wants to warn us of this and tries to read the
698 # /proc/<pid>/stack file which then promptly returns an
699 # 'Operation not permitted' error since we're running as moblab
700 # and we don't have permission to read those files.
701 except Exception:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300702 pass
703 return self.parse_device_serials(result)
Simran Basi431010f2013-09-04 10:42:41 -0700704
705
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700706 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700707 """Get a list of devices currently attached to the test station and
708 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700709 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800710 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700711 raise error.AutoservError(
712 'Not given ADB serial but multiple devices detected')
713 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700714
715
716 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700717 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700718 accessible by fastboot command.
719 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700720 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800721 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700722 raise error.AutoservError(
723 'Not given fastboot serial but multiple devices detected')
724 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700725
726
727 def is_up(self, timeout=0, command=ADB_CMD):
728 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700729
730 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700731 @param command: `adb`, the device can be accessed by adb command,
732 or `fastboot`, the device can be accessed by fastboot command.
733 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700734
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700735 @returns True if the device is detectable by given command, False
736 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700737
738 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700739 if command == ADB_CMD:
740 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800741 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800742 # ADB has a device state, if the device is not online, no
743 # subsequent ADB command will complete.
Dan Shi6450e142016-03-11 11:52:20 -0800744 # DUT with single device connected may not have adb_serial set.
745 # Therefore, skip checking if serial is in the list of adb devices
746 # if self.adb_serial is not set.
747 if (serial and serial not in devices) or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800748 logging.debug('Waiting for device to enter the ready state.')
749 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700750 elif command == FASTBOOT_CMD:
751 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800752 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700753 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700754 raise NotImplementedError('Mode %s is not supported' % command)
755
756 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700757
758
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700759 def stop_loggers(self):
760 """Inherited stop_loggers function.
761
762 Calls parent function and captures logcat, since the end of the run
763 is logically the end/stop of the logcat log.
764 """
765 super(ADBHost, self).stop_loggers()
766 # Record logcat log to a temporary file on the teststation.
767 tmp_dir = self.teststation.get_tmp_dir()
Simran Basi242f8de2016-06-08 14:23:43 -0700768 logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
769 teststation_filename = os.path.join(tmp_dir, logcat_filename)
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700770 try:
771 self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
772 timeout=20)
Simran Basid6b49792016-06-07 17:22:03 -0700773 except (error.AutotestHostRunError, error.AutoservRunError,
774 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700775 return
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700776 # Copy-back the log to the drone's results directory.
Simran Basi242f8de2016-06-08 14:23:43 -0700777 results_logcat_filename = os.path.join(self.job.resultdir,
778 logcat_filename)
779 self.teststation.get_file(teststation_filename,
780 results_logcat_filename)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700781 try:
782 self.teststation.run('rm -rf %s' % tmp_dir)
783 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
784 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
785
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700786 self._collect_crash_logs()
787
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700788
Simran Basi431010f2013-09-04 10:42:41 -0700789 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700790 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700791
792 Called as the test ends. Will return the device to USB mode and kill
793 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700794 """
Christopher Wiley08849d52013-11-22 08:57:58 -0800795 # TODO(sbasi) Originally, we would kill the server after each test to
796 # reduce the opportunity for bad server state to hang around.
797 # Unfortunately, there is a period of time after each kill during which
798 # the Android device becomes unusable, and if we start the next test
799 # too quickly, we'll get an error complaining about no ADB device
800 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700801 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800802 # |close| the associated teststation as well.
803 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700804 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700805
806
807 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700808 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700809
810 @param message String message to log into syslog
811 @param tag String tag prefix for syslog
812
813 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700814 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700815
816
817 def get_autodir(self):
818 """Return the directory to install autotest for client side tests."""
819 return '/data/autotest'
820
Kevin Cheng018db352015-09-20 02:22:08 -0700821
Kris Rambishde8f9d12015-12-16 12:42:41 -0800822 def is_device_ready(self):
823 """Return the if the device is ready for ADB commands."""
Dan Shi7075f552016-04-21 15:42:41 -0700824 try:
825 # Retry to avoid possible flakes.
826 is_ready = client_utils.poll_for_condition(
827 lambda: self.adb_run('get-state').stdout.strip() == 'device',
828 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
829 desc='Waiting for device state to be `device`')
830 except client_utils.TimeoutError:
831 is_ready = False
832
833 logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
834 return is_ready
Kris Rambishde8f9d12015-12-16 12:42:41 -0800835
836
Kevin Chengd19e6c62015-10-28 16:39:39 -0700837 def verify_connectivity(self):
838 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800839 if not self.is_device_ready():
840 raise error.AutoservHostError('device state is not in the '
841 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700842
843
Simran Basid3ba3fb2015-09-11 14:35:07 -0700844 def verify_software(self):
845 """Verify working software on an adb_host.
846
Simran Basi38f7ddf2015-09-18 12:25:03 -0700847 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700848 """
Dan Shiab999722015-12-04 14:27:08 -0800849 # Check if adb and fastboot are present.
850 self.teststation.run('which adb')
851 self.teststation.run('which fastboot')
852 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700853
Dan Shi626d5412016-05-16 16:05:13 -0700854 # Apply checks only for Android device.
Dan Shi1e2a98a2016-05-18 12:08:08 -0700855 if self.get_os_type() == OS_TYPE_ANDROID:
Dan Shi626d5412016-05-16 16:05:13 -0700856 # Make sure ro.boot.hardware and ro.build.product match.
Dan Shi8c51bda2016-05-26 12:21:02 -0700857 hardware = self._run_output_with_retry('getprop ro.boot.hardware')
858 product = self._run_output_with_retry('getprop ro.build.product')
Dan Shi1e2a98a2016-05-18 12:08:08 -0700859 if hardware != product:
860 raise error.AutoservHostError('ro.boot.hardware: %s does not '
861 'match to ro.build.product: %s' %
862 (hardware, product))
863
Kevin Cheng018db352015-09-20 02:22:08 -0700864
Simran Basid3ba3fb2015-09-11 14:35:07 -0700865 def verify_job_repo_url(self, tag=''):
866 """Make sure job_repo_url of this host is valid.
867
Simran Basi38f7ddf2015-09-18 12:25:03 -0700868 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700869
870 @param tag: The tag from the server job, in the format
871 <job_id>-<user>/<hostname>, or <hostless> for a server job.
872 """
873 return
Kevin Cheng018db352015-09-20 02:22:08 -0700874
875
Simran Basibeb2bb22016-02-03 15:25:48 -0800876 def repair(self):
877 """Attempt to get the DUT to pass `self.verify()`."""
878 try:
879 self.ensure_adb_mode(timeout=30)
880 return
881 except error.AutoservError as e:
882 logging.error(e)
883 logging.debug('Verifying the device is accessible via fastboot.')
884 self.ensure_bootloader_mode()
885 if not self.job.run_test(
886 'provision_AndroidUpdate', host=self, value=None,
887 force=True, repair=True):
888 raise error.AutoservRepairTotalFailure(
889 'Unable to repair the device.')
890
891
Simran Basi1b023762015-09-25 12:12:20 -0700892 def send_file(self, source, dest, delete_dest=False,
893 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700894 """Copy files from the drone to the device.
895
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400896 Just a note, there is the possibility the test station is localhost
897 which makes some of these steps redundant (e.g. creating tmp dir) but
898 that scenario will undoubtedly be a development scenario (test station
899 is also the moblab) and not the typical live test running scenario so
900 the redundancy I think is harmless.
901
Kevin Cheng018db352015-09-20 02:22:08 -0700902 @param source: The file/directory on the drone to send to the device.
903 @param dest: The destination path on the device to copy to.
904 @param delete_dest: A flag set to choose whether or not to delete
905 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700906 @param preserve_symlinks: Controls if symlinks on the source will be
907 copied as such on the destination or
908 transformed into the referenced
909 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700910 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700911 # If we need to preserve symlinks, let's check if the source is a
912 # symlink itself and if so, just create it on the device.
913 if preserve_symlinks:
914 symlink_target = None
915 try:
916 symlink_target = os.readlink(source)
917 except OSError:
918 # Guess it's not a symlink.
919 pass
920
921 if symlink_target is not None:
922 # Once we create the symlink, let's get out of here.
923 self.run('ln -s %s %s' % (symlink_target, dest))
924 return
925
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400926 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700927 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400928 src_path = os.path.join(tmp_dir, os.path.basename(dest))
929 # Now copy the file over to the test station so you can reference the
930 # file in the push command.
931 self.teststation.send_file(source, src_path,
932 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700933
934 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400935 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700936
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700937 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700938
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400939 # Cleanup the test station.
940 try:
941 self.teststation.run('rm -rf %s' % tmp_dir)
942 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
943 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700944
945
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700946 def _get_file_info(self, dest):
947 """Get permission and possible symlink info about file on the device.
948
949 These files are on the device so we only have shell commands (via adb)
950 to get the info we want. We'll use 'ls' to get it all.
951
952 @param dest: File to get info about.
953
954 @returns a dict of the file permissions and symlink.
955 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800956 # Grab file info.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700957 file_info = self.run_output('ls -ld %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700958 symlink = None
959 perms = 0
960 match = re.match(FILE_INFO_REGEX, file_info)
961 if match:
962 # Check if it's a symlink and grab the linked dest if it is.
963 if match.group('TYPE') == 'l':
964 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
965 if symlink_match:
966 symlink = symlink_match.group('SYMLINK')
967
968 # Set the perms.
969 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
970 if perm != '-':
971 perms |= perm_flag
972
973 return {'perms': perms,
974 'symlink': symlink}
975
976
Simran Basi1b023762015-09-25 12:12:20 -0700977 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
978 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700979 """Copy files from the device to the drone.
980
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400981 Just a note, there is the possibility the test station is localhost
982 which makes some of these steps redundant (e.g. creating tmp dir) but
983 that scenario will undoubtedly be a development scenario (test station
984 is also the moblab) and not the typical live test running scenario so
985 the redundancy I think is harmless.
986
Kevin Cheng018db352015-09-20 02:22:08 -0700987 @param source: The file/directory on the device to copy back to the
988 drone.
989 @param dest: The destination path on the drone to copy to.
990 @param delete_dest: A flag set to choose whether or not to delete
991 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700992 @param preserve_perm: Tells get_file() to try to preserve the sources
993 permissions on files and dirs.
994 @param preserve_symlinks: Try to preserve symlinks instead of
995 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -0700996 """
David Purselle01548b2016-05-11 10:00:42 -0700997 # Stage the files on the test station under teststation_temp_dir.
998 teststation_temp_dir = self.teststation.get_tmp_dir()
999 teststation_dest = os.path.join(teststation_temp_dir,
1000 os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -07001001
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001002 source_info = {}
1003 if preserve_symlinks or preserve_perm:
1004 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -07001005
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001006 # If we want to preserve symlinks, just create it here, otherwise pull
1007 # the file off the device.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001008 #
1009 # TODO(sadmac): Directories containing symlinks won't behave as
1010 # expected.
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001011 if preserve_symlinks and source_info['symlink']:
1012 os.symlink(source_info['symlink'], dest)
1013 else:
David Purselle01548b2016-05-11 10:00:42 -07001014 self.adb_run('pull %s %s' % (source, teststation_temp_dir))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001015
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001016 # Copy over the file from the test station and clean up.
David Purselle01548b2016-05-11 10:00:42 -07001017 self.teststation.get_file(teststation_dest, dest,
1018 delete_dest=delete_dest)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001019 try:
David Purselle01548b2016-05-11 10:00:42 -07001020 self.teststation.run('rm -rf %s' % teststation_temp_dir)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001021 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
David Purselle01548b2016-05-11 10:00:42 -07001022 logging.warn('failed to remove dir %s: %s',
1023 teststation_temp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001024
David Pursell788b1b52016-05-19 09:03:31 -07001025 # Source will be copied under dest if either:
1026 # 1. Source is a directory and doesn't end with /.
1027 # 2. Source is a file and dest is a directory.
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001028 command = '[ -d %s ]' % source
1029 source_is_dir = self.run(command,
David Pursell788b1b52016-05-19 09:03:31 -07001030 ignore_status=True).exit_status == 0
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001031
David Pursell788b1b52016-05-19 09:03:31 -07001032 if ((source_is_dir and not source.endswith(os.sep)) or
1033 (not source_is_dir and os.path.isdir(dest))):
1034 receive_path = os.path.join(dest, os.path.basename(source))
1035 else:
1036 receive_path = dest
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001037
David Pursell788b1b52016-05-19 09:03:31 -07001038 # Set the permissions of the received file/dirs.
1039 if os.path.isdir(receive_path):
1040 for root, _dirs, files in os.walk(receive_path):
1041 def process(rel_path, default_perm):
1042 info = self._get_file_info(os.path.join(source,
1043 rel_path))
1044 if info['perms'] != 0:
1045 target = os.path.join(receive_path, rel_path)
1046 if preserve_perm:
1047 os.chmod(target, info['perms'])
1048 else:
1049 os.chmod(target, default_perm)
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001050
David Pursell788b1b52016-05-19 09:03:31 -07001051 rel_root = os.path.relpath(root, receive_path)
1052 process(rel_root, _DEFAULT_DIR_PERMS)
1053 for f in files:
1054 process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
1055 elif preserve_perm:
1056 os.chmod(receive_path, source_info['perms'])
1057 else:
1058 os.chmod(receive_path, _DEFAULT_FILE_PERMS)
Kevin Cheng018db352015-09-20 02:22:08 -07001059
1060
1061 def get_release_version(self):
1062 """Get the release version from the RELEASE_FILE on the device.
1063
1064 @returns The release string in the RELEASE_FILE.
1065
1066 """
1067 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -07001068
1069
1070 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001071 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001072
Kevin Chengd19e6c62015-10-28 16:39:39 -07001073 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001074
1075 @param parent: Parent directory of the returned tmp dir.
1076
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07001077 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001078 """
Kevin Chengd19e6c62015-10-28 16:39:39 -07001079 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
1080 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001081 if not parent.startswith(TMP_DIR):
1082 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -07001083 self.run('mkdir -p %s' % parent)
1084 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
1085 self.tmp_dirs.append(tmp_dir)
1086 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -07001087
1088
1089 def get_platform(self):
1090 """Determine the correct platform label for this host.
1091
1092 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -07001093 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -07001094
1095 @returns a string representing this host's platform.
1096 """
1097 return 'adb'
1098
1099
Gilad Arnolda76bef02015-09-29 13:55:15 -07001100 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -08001101 """Get the OS type of the DUT, e.g., android or brillo.
1102 """
1103 if not self._os_type:
1104 if self.run_output('getprop ro.product.brand') == 'Brillo':
1105 self._os_type = OS_TYPE_BRILLO
1106 else:
1107 self._os_type = OS_TYPE_ANDROID
1108
1109 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001110
1111
1112 def _forward(self, reverse, args):
1113 """Execute a forwarding command.
1114
1115 @param reverse: Whether this is reverse forwarding (Boolean).
1116 @param args: List of command arguments.
1117 """
1118 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001119 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001120
1121
1122 def add_forwarding(self, src, dst, reverse=False, rebind=True):
1123 """Forward a port between the ADB host and device.
1124
1125 Port specifications are any strings accepted as such by ADB, for
1126 example 'tcp:8080'.
1127
1128 @param src: Port specification to forward from.
1129 @param dst: Port specification to forward to.
1130 @param reverse: Do reverse forwarding from device to host (Boolean).
1131 @param rebind: Allow rebinding an already bound port (Boolean).
1132 """
1133 args = []
1134 if not rebind:
1135 args.append('--no-rebind')
1136 args += [src, dst]
1137 self._forward(reverse, args)
1138
1139
1140 def remove_forwarding(self, src=None, reverse=False):
1141 """Removes forwarding on port.
1142
1143 @param src: Port specification, or None to remove all forwarding.
1144 @param reverse: Whether this is reverse forwarding (Boolean).
1145 """
1146 args = []
1147 if src is None:
1148 args.append('--remove-all')
1149 else:
1150 args += ['--remove', src]
1151 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001152
1153
xixuan6cf6d2f2016-01-29 15:29:00 -08001154 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001155 """
1156 Forwards a port securely through a tunnel process from the server
1157 to the DUT for RPC server connection.
1158 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
1159 to the DUT.
1160
1161 @param port: remote port on the DUT.
1162 @param local_port: local forwarding port.
1163
1164 @return: the tunnel process.
1165 """
1166 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001167 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001168
1169
xixuan6cf6d2f2016-01-29 15:29:00 -08001170 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001171 """
1172 Disconnects a previously forwarded port from the server to the DUT for
1173 RPC server connection.
1174 Remove the previously added 'ADB forward' rule to forward the RPC
1175 packets from the AdbHost to the DUT.
1176
1177 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -08001178 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -07001179 @param port: remote port on the DUT.
1180
1181 """
1182 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001183 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001184
1185
1186 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001187 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001188
1189 @raise: error.AutoservError if the device failed to reboot into
1190 bootloader mode.
1191 """
1192 if self.is_up(command=FASTBOOT_CMD):
1193 return
1194 self.adb_run('reboot bootloader')
1195 if not self.wait_up(command=FASTBOOT_CMD):
1196 raise error.AutoservError(
1197 'The device failed to reboot into bootloader mode.')
1198
1199
Dan Shie4e807b2015-12-10 09:04:03 -08001200 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001201 """Ensure the device is up and can be accessed by adb command.
1202
Dan Shie4e807b2015-12-10 09:04:03 -08001203 @param timeout: Time limit in seconds before returning even if the host
1204 is not up.
1205
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001206 @raise: error.AutoservError if the device failed to reboot into
1207 adb mode.
1208 """
1209 if self.is_up():
1210 return
Dan Shi04980372016-03-22 10:57:47 -07001211 # Ignore timeout error to allow `fastboot reboot` to fail quietly and
1212 # check if the device is in adb mode.
1213 self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
Dan Shie4e807b2015-12-10 09:04:03 -08001214 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001215 raise error.AutoservError(
1216 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -08001217 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -07001218
1219
1220 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -08001221 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001222 """Get the Android build information from the build url.
1223
1224 @param build_url: The url to use for downloading Android artifacts.
1225 pattern: http://$devserver:###/static/branch/target/build_id
1226
Dan Shi6450e142016-03-11 11:52:20 -08001227 @return: A dictionary of build information, including keys:
1228 build_target, branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -08001229 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -07001230 """
Dan Shiab999722015-12-04 14:27:08 -08001231 if not build_url:
1232 raise AndroidInstallError('Need build_url to download image files.')
1233
1234 try:
1235 match = re.match(DEVSERVER_URL_REGEX, build_url)
Dan Shi6450e142016-03-11 11:52:20 -08001236 return {'build_target': match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001237 'branch': match.group('BRANCH'),
Dan Shi6450e142016-03-11 11:52:20 -08001238 'target': ('%s-%s' % (match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001239 match.group('BUILD_TYPE'))),
1240 'build_id': match.group('BUILD_ID')}
1241 except (AttributeError, IndexError, ValueError) as e:
1242 raise AndroidInstallError(
1243 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001244
1245
Dan Shia2872172015-10-31 01:16:51 -07001246 @retry.retry(error.AutoservRunError, timeout_min=10)
Simran Basi7756a0b2016-03-16 13:10:07 -07001247 def download_file(self, build_url, file, dest_dir, unzip=False,
1248 unzip_dest=None):
Dan Shia2872172015-10-31 01:16:51 -07001249 """Download the given file from the build url.
1250
1251 @param build_url: The url to use for downloading Android artifacts.
1252 pattern: http://$devserver:###/static/branch/target/build_id
1253 @param file: Name of the file to be downloaded, e.g., boot.img.
1254 @param dest_dir: Destination folder for the file to be downloaded to.
Simran Basi7756a0b2016-03-16 13:10:07 -07001255 @param unzip: If True, unzip the downloaded file.
1256 @param unzip_dest: Location to unzip the downloaded file to. If not
1257 provided, dest_dir is used.
Dan Shia2872172015-10-31 01:16:51 -07001258 """
Dan Shidb0366c2016-02-19 10:36:18 -08001259 # Append the file name to the url if build_url is linked to the folder
1260 # containing the file.
1261 if not build_url.endswith('/%s' % file):
1262 src_url = os.path.join(build_url, file)
1263 else:
1264 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001265 dest_file = os.path.join(dest_dir, file)
1266 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001267 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Simran Basi7756a0b2016-03-16 13:10:07 -07001268 if unzip:
1269 unzip_dest = unzip_dest or dest_dir
1270 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1271 (dest_dir, file, unzip_dest))
Dan Shia2872172015-10-31 01:16:51 -07001272 except:
1273 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001274 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001275 raise
1276
1277
Dan Shiab999722015-12-04 14:27:08 -08001278 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001279 """Download required image files from the given build_url to a local
1280 directory in the machine runs fastboot command.
1281
1282 @param build_url: The url to use for downloading Android artifacts.
1283 pattern: http://$devserver:###/static/branch/target/build_id
1284
1285 @return: Path to the directory contains image files.
1286 """
Dan Shi08ff1282016-02-18 19:51:16 -08001287 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001288
1289 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001290 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001291
1292 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001293 self.download_file(build_url, zipped_image_file, image_dir,
1294 unzip=True)
Dan Shi49d451f2016-04-19 09:25:01 -07001295 images = android_utils.AndroidImageFiles.get_standalone_images(
1296 build_info['build_target'])
1297 for image_file in images:
Dan Shidb0366c2016-02-19 10:36:18 -08001298 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001299
Dan Shia2872172015-10-31 01:16:51 -07001300 return image_dir
1301 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001302 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001303 raise
1304
1305
Dan Shiab999722015-12-04 14:27:08 -08001306 def stage_brillo_image_files(self, build_url):
1307 """Download required brillo image files from the given build_url to a
1308 local directory in the machine runs fastboot command.
1309
1310 @param build_url: The url to use for downloading Android artifacts.
1311 pattern: http://$devserver:###/static/branch/target/build_id
1312
1313 @return: Path to the directory contains image files.
1314 """
Dan Shi08ff1282016-02-18 19:51:16 -08001315 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001316
1317 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1318 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1319 image_dir = self.teststation.get_tmp_dir()
Dan Shiab999722015-12-04 14:27:08 -08001320
1321 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001322 self.download_file(build_url, zipped_image_file, image_dir,
1323 unzip=True)
1324 self.download_file(build_url, vendor_partitions_file, image_dir,
1325 unzip=True,
1326 unzip_dest=os.path.join(image_dir, 'vendor'))
Dan Shiab999722015-12-04 14:27:08 -08001327 return image_dir
1328 except:
1329 self.teststation.run('rm -rf %s' % image_dir)
1330 raise
1331
1332
Simran Basibeb2bb22016-02-03 15:25:48 -08001333 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001334 """Stage a build on a devserver and return the build_url and devserver.
1335
1336 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001337
Dan Shi225b9042015-11-18 10:25:21 -08001338 @returns a tuple with an update URL like:
1339 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1340 and the devserver instance.
1341 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001342 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001343 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001344 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1345 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001346 build_name = devserver.translate(build_name)
Dan Shi6450e142016-03-11 11:52:20 -08001347 branch, target, build_id = utils.parse_launch_control_build(build_name)
Dan Shi08ff1282016-02-18 19:51:16 -08001348 devserver.trigger_download(target, build_id, branch,
Justin Giorgidd05a942016-07-05 20:53:12 -07001349 os=os_type, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001350 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001351
1352
Dan Shie4e807b2015-12-10 09:04:03 -08001353 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001354 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001355 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001356
1357 Following are the steps used here to provision an android device:
1358 1. If build_local_path is not set, download the image zip file, e.g.,
1359 shamu-img-2284311.zip, unzip it.
1360 2. Run fastboot to install following artifacts:
1361 bootloader, radio, boot, system, vendor(only if exists)
1362
1363 Repair is not supported for Android devices yet.
1364
1365 @param build_url: The url to use for downloading Android artifacts.
1366 pattern: http://$devserver:###/static/$build
1367 @param build_local_path: The path to a local folder that contains the
1368 image files needed to provision the device. Note that the folder
1369 is in the machine running adb command, rather than the drone.
1370 @param wipe: If true, userdata will be wiped before flashing.
1371 @param flash_all: If True, all img files found in img_path will be
1372 flashed. Otherwise, only boot and system are flashed.
1373
1374 @raises AndroidInstallError if any error occurs.
1375 """
Dan Shia2872172015-10-31 01:16:51 -07001376 # If the build is not staged in local server yet, clean up the temp
1377 # folder used to store image files after the provision is completed.
1378 delete_build_folder = bool(not build_local_path)
1379
1380 try:
1381 # Download image files needed for provision to a local directory.
1382 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001383 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001384
1385 # Device needs to be in bootloader mode for flashing.
1386 self.ensure_bootloader_mode()
1387
1388 if wipe:
Dan Shi12a4f662016-05-10 14:49:42 -07001389 self._fastboot_run_with_retry('-w')
Dan Shia2872172015-10-31 01:16:51 -07001390
1391 # Get all *.img file in the build_local_path.
1392 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001393 image_files = self.teststation.run(
1394 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001395 images = dict([(os.path.basename(f), f) for f in image_files])
Dan Shi49d451f2016-04-19 09:25:01 -07001396 build_info = self.get_build_info_from_build_url(build_url)
1397 board = build_info['build_target']
1398 all_images = (
1399 android_utils.AndroidImageFiles.get_standalone_images(board)
1400 + android_utils.AndroidImageFiles.get_zipped_images(board))
1401
1402 # Sort images to be flashed, bootloader needs to be the first one.
1403 bootloader = android_utils.AndroidImageFiles.BOOTLOADER
1404 sorted_images = sorted(
1405 images.items(),
1406 key=lambda pair: 0 if pair[0] == bootloader else 1)
1407 for image, image_file in sorted_images:
1408 if image not in all_images:
Dan Shia2872172015-10-31 01:16:51 -07001409 continue
1410 logging.info('Flashing %s...', image_file)
Dan Shi12a4f662016-05-10 14:49:42 -07001411 self._fastboot_run_with_retry('-S 256M flash %s %s' %
1412 (image[:-4], image_file))
Dan Shi49d451f2016-04-19 09:25:01 -07001413 if image == android_utils.AndroidImageFiles.BOOTLOADER:
Dan Shia2872172015-10-31 01:16:51 -07001414 self.fastboot_run('reboot-bootloader')
1415 self.wait_up(command=FASTBOOT_CMD)
1416 except Exception as e:
1417 logging.error('Install Android build failed with error: %s', e)
1418 # Re-raise the exception with type of AndroidInstallError.
1419 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1420 finally:
1421 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001422 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001423 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1424 DEFAULT_WAIT_UP_TIME_SECONDS)
1425 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001426 logging.info('Successfully installed Android build staged at %s.',
1427 build_url)
1428
1429
Dan Shiab999722015-12-04 14:27:08 -08001430 def install_brillo(self, build_url, build_local_path=None):
1431 """Install the Brillo DUT.
1432
1433 Following are the steps used here to provision an android device:
1434 1. If build_local_path is not set, download the image zip file, e.g.,
1435 dragonboard-img-123456.zip, unzip it. And download the vendor
1436 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1437 unzip it to vendor folder.
1438 2. Run provision_device script to install OS images and vendor
1439 partitions.
1440
1441 @param build_url: The url to use for downloading Android artifacts.
1442 pattern: http://$devserver:###/static/$build
1443 @param build_local_path: The path to a local folder that contains the
1444 image files needed to provision the device. Note that the folder
1445 is in the machine running adb command, rather than the drone.
1446
1447 @raises AndroidInstallError if any error occurs.
1448 """
1449 # If the build is not staged in local server yet, clean up the temp
1450 # folder used to store image files after the provision is completed.
1451 delete_build_folder = bool(not build_local_path)
1452
Dan Shiab999722015-12-04 14:27:08 -08001453 try:
1454 # Download image files needed for provision to a local directory.
1455 if not build_local_path:
1456 build_local_path = self.stage_brillo_image_files(build_url)
1457
1458 # Device needs to be in bootloader mode for flashing.
1459 self.ensure_bootloader_mode()
1460
1461 # Run provision_device command to install image files and vendor
1462 # partitions.
1463 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1464 cmd = (BRILLO_PROVISION_CMD %
1465 {'os_image_dir': build_local_path,
1466 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001467 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001468 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001469 self.teststation.run(cmd)
1470 except Exception as e:
1471 logging.error('Install Brillo build failed with error: %s', e)
1472 # Re-raise the exception with type of AndroidInstallError.
1473 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1474 finally:
1475 if delete_build_folder:
1476 self.teststation.run('rm -rf %s' % build_local_path)
1477 self.ensure_adb_mode()
1478 logging.info('Successfully installed Android build staged at %s.',
1479 build_url)
1480
1481
Dan Shibe3636a2016-02-14 22:48:01 -08001482 @property
1483 def job_repo_url_attribute(self):
1484 """Get the host attribute name for job_repo_url, which should append the
1485 adb serial.
1486 """
1487 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1488
1489
Dan Shie4e807b2015-12-10 09:04:03 -08001490 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001491 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001492 """Install the DUT.
1493
1494 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001495 pattern: http://$devserver:###/static/$build. If build_url is
1496 set to None, the code may try _parser.options.image to do the
1497 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001498 @param build_local_path: The path to a local directory that contains the
1499 image files needed to provision the device.
1500 @param wipe: If true, userdata will be wiped before flashing.
1501 @param flash_all: If True, all img files found in img_path will be
1502 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001503
Dan Shibe3636a2016-02-14 22:48:01 -08001504 @returns A tuple of (image_name, host_attributes).
1505 image_name is the name of image installed, e.g.,
1506 git_mnc-release/shamu-userdebug/1234
1507 host_attributes is a dictionary of (attribute, value), which
1508 can be saved to afe_host_attributes table in database. This
1509 method returns a dictionary with a single entry of
1510 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1511 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001512 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001513 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001514 if not build_url and self._parser.options.image:
1515 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001516 self._parser.options.image, os_type=os_type)
1517 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001518 self.install_android(
1519 build_url=build_url, build_local_path=build_local_path,
1520 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001521 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001522 self.install_brillo(
1523 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001524 else:
1525 raise error.InstallError(
1526 'Installation of os type %s is not supported.' %
1527 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001528 return (build_url.split('static/')[-1],
1529 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001530
1531
1532 def list_files_glob(self, path_glob):
1533 """Get a list of files on the device given glob pattern path.
1534
1535 @param path_glob: The path glob that we want to return the list of
1536 files that match the glob. Relative paths will not work as
1537 expected. Supply an absolute path to get the list of files
1538 you're hoping for.
1539
1540 @returns List of files that match the path_glob.
1541 """
1542 # This is just in case path_glob has no path separator.
1543 base_path = os.path.dirname(path_glob) or '.'
1544 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001545 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001546 if result.exit_status != 0:
1547 return []
1548 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001549
1550
Dan Shic716ac62016-05-24 16:47:57 -07001551 @retry.retry(error.AutoservRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
Dan Shida995002016-04-25 23:12:58 -07001552 def install_apk(self, apk, force_reinstall=True):
Kevin Cheng31355942016-01-05 14:23:35 -08001553 """Install the specified apk.
1554
1555 This will install the apk and override it if it's already installed and
1556 will also allow for downgraded apks.
1557
1558 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001559 @param force_reinstall: True to reinstall the apk even if it's already
Dan Shida995002016-04-25 23:12:58 -07001560 installed. Default is set to True.
Dan Shidb0366c2016-02-19 10:36:18 -08001561
1562 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001563 """
Dan Shic716ac62016-05-24 16:47:57 -07001564 try:
1565 client_utils.poll_for_condition(
1566 lambda: self.run('pm list packages',
1567 ignore_status=True).exit_status == 0,
1568 timeout=120)
1569 client_utils.poll_for_condition(
1570 lambda: self.run('service list | grep mount',
1571 ignore_status=True).exit_status == 0,
1572 timeout=120)
1573 return self.adb_run('install %s -d %s' %
1574 ('-r' if force_reinstall else '', apk))
1575 except error.AutoservRunError:
1576 self.reboot()
1577 raise
Dan Shidb0366c2016-02-19 10:36:18 -08001578
1579
1580 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1581 def _confirm_apk_installed(self, package_name):
1582 """Confirm if apk is already installed with the given name.
1583
1584 `pm list packages` command is not reliable some time. The retry helps to
1585 reduce the chance of false negative.
1586
1587 @param package_name: Name of the package, e.g., com.android.phone.
1588
1589 @raise AutoservRunError: If the package is not found or pm list command
1590 failed for any reason.
1591 """
1592 name = 'package:%s' % package_name
1593 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1594
1595
1596 def is_apk_installed(self, package_name):
1597 """Check if apk is already installed with the given name.
1598
1599 @param package_name: Name of the package, e.g., com.android.phone.
1600
1601 @return: True if package is installed. False otherwise.
1602 """
1603 try:
1604 self._confirm_apk_installed(package_name)
1605 return True
1606 except:
1607 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001608
1609
1610 def get_attributes_to_clear_before_provision(self):
1611 """Get a list of attributes to be cleared before machine_install starts.
1612 """
1613 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001614
1615
1616 def get_labels(self):
1617 """Return a list of the labels gathered from the devices connected.
1618
1619 @return: A list of strings that denote the labels from all the devices
1620 connected.
1621 """
1622 return self.labels.get_labels(self)
1623
1624
1625 def update_labels(self):
1626 """Update the labels for this testbed."""
1627 self.labels.update_labels(self)
Dan Shi6450e142016-03-11 11:52:20 -08001628
1629
1630 def stage_server_side_package(self, image=None):
1631 """Stage autotest server-side package on devserver.
1632
1633 @param image: A build name, e.g., git_mnc_dev/shamu-eng/123
1634
1635 @return: A url to the autotest server-side package. Return None if
1636 server-side package is not supported.
1637 @raise: error.AutoservError if fail to locate the build to test with.
1638 """
Dan Shid37736b2016-07-06 15:10:29 -07001639 # If enable_drone_in_restricted_subnet is False, do not set hostname
1640 # in devserver.resolve call, so a devserver in non-restricted subnet
1641 # is picked to stage autotest server package for drone to download.
1642 hostname = self.hostname
1643 if not utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1644 hostname = None
Dan Shi6450e142016-03-11 11:52:20 -08001645 if image:
Dan Shid37736b2016-07-06 15:10:29 -07001646 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001647 else:
1648 job_repo_url = afe_utils.get_host_attribute(
1649 self, self.job_repo_url_attribute)
1650 if job_repo_url:
1651 devserver_url, image = (
1652 tools.get_devserver_build_from_package_url(
1653 job_repo_url, True))
Dan Shid37736b2016-07-06 15:10:29 -07001654 # If enable_drone_in_restricted_subnet is True, use the
1655 # existing devserver. Otherwise, resolve a new one in
1656 # non-restricted subnet.
1657 if utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1658 ds = dev_server.AndroidBuildServer(devserver_url)
1659 else:
1660 ds = dev_server.AndroidBuildServer.resolve(image)
Dan Shi6450e142016-03-11 11:52:20 -08001661 else:
1662 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
1663 if not labels:
1664 raise error.AutoservError(
1665 'Failed to stage server-side package. The host has '
1666 'no job_report_url attribute or version label.')
Kevin Cheng84a71ba2016-07-14 11:03:57 -07001667 image = labels[0][len(self.VERSION_PREFIX + ':'):]
Dan Shid37736b2016-07-06 15:10:29 -07001668 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001669
1670 branch, target, build_id = utils.parse_launch_control_build(image)
1671 build_target, _ = utils.parse_launch_control_target(target)
1672
1673 # For any build older than MIN_VERSION_SUPPORT_SSP, server side
1674 # packaging is not supported.
1675 try:
1676 if int(build_id) < self.MIN_VERSION_SUPPORT_SSP:
1677 logging.warn('Build %s is older than %s. Server side packaging '
1678 'is disabled.', image,
1679 self.MIN_VERSION_SUPPORT_SSP)
1680 return None
1681 except ValueError:
1682 logging.warn('Failed to compare build id in %s with the minimum '
1683 'version that supports server side packaging. Server '
1684 'side packaging is disabled.', image)
1685 return None
1686
1687 ds.stage_artifacts(target, build_id, branch,
1688 artifacts=['autotest_server_package'])
1689 autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
1690 {'build_target': build_target,
1691 'build_id': build_id})
1692 return '%s/static/%s/%s' % (ds.url(), image,
1693 autotest_server_package_name)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07001694
1695
1696 def _sync_time(self):
1697 """Approximate synchronization of time between host and ADB device.
1698
1699 This sets the ADB/Android device's clock to approximately the same
1700 time as the Autotest host for the purposes of comparing Android system
1701 logs such as logcat to logs from the Autotest host system.
1702 """
1703 command = 'date '
1704 sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
1705 if sdk_version < 23:
1706 # Android L and earlier use this format: date -s (format).
1707 command += ('-s %s' %
1708 datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
1709 else:
1710 # Android M and later use this format: date (format).
1711 command += datetime.datetime.now().strftime('%m%d%H%M%Y.%S')
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -07001712 self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1713 ignore_timeout=True)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001714
1715
1716 def _enable_native_crash_logging(self):
1717 """Enable native (non-Java) crash logging.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001718 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001719 if self.get_os_type() == OS_TYPE_BRILLO:
1720 self._enable_brillo_native_crash_logging()
1721 elif self.get_os_type() == OS_TYPE_ANDROID:
1722 self._enable_android_native_crash_logging()
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001723
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001724
1725 def _enable_brillo_native_crash_logging(self):
1726 """Enables native crash logging for a Brillo DUT.
1727 """
Bryan Lewandowski8c96bb22016-07-19 12:56:03 -07001728 try:
1729 self.run('touch /data/misc/metrics/enabled',
1730 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1731 ignore_timeout=True)
1732 # If running, crash_sender will delete crash files every hour.
1733 self.run('stop crash_sender',
1734 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1735 ignore_timeout=True)
1736 except error.AutoservRunError as e:
1737 logging.warn(e)
1738 logging.warn('Failed to enable Brillo native crash logging.')
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001739
1740
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001741 def _enable_android_native_crash_logging(self):
1742 """Enables native crash logging for an Android DUT.
1743 """
1744 # debuggerd should be enabled by default on Android.
1745 result = self.run('pgrep debuggerd',
1746 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1747 ignore_timeout=True, ignore_status=True)
1748 if not result or result.exit_status != 0:
1749 logging.debug('Unable to confirm that debuggerd is running.')
1750
1751
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001752 def _collect_crash_logs(self):
1753 """Copies crash log files from the DUT to the drone.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001754 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001755 if self.get_os_type() == OS_TYPE_BRILLO:
1756 self._collect_crash_logs_dut(BRILLO_NATIVE_CRASH_LOG_DIR)
1757 elif self.get_os_type() == OS_TYPE_ANDROID:
1758 self._collect_crash_logs_dut(ANDROID_TOMBSTONE_CRASH_LOG_DIR)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001759
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001760
1761 def _collect_crash_logs_dut(self, log_directory):
1762 """Copies native crash logs from the Android/Brillo DUT to the drone.
1763
1764 @param log_directory: absolute path of the directory on the DUT where
1765 log files are stored.
1766 """
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001767 files = None
1768 try:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001769 result = self.run('find %s -maxdepth 1 -type f' % log_directory,
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001770 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS)
1771 files = result.stdout.strip().split()
1772 except (error.AutotestHostRunError, error.AutoservRunError,
1773 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001774 logging.debug('Unable to call find %s, unable to find crash logs',
1775 log_directory)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001776 if not files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001777 logging.debug('There are no crash logs on the DUT.')
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001778 return
1779
1780 crash_dir = os.path.join(self.job.resultdir, 'crash')
1781 try:
1782 os.mkdir(crash_dir)
1783 except OSError as e:
1784 if e.errno != errno.EEXIST:
1785 raise e
1786
1787 for f in files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001788 logging.debug('DUT native crash file produced: %s', f)
1789 dest = os.path.join(crash_dir, os.path.basename(f))
1790 self.get_file(source=f, dest=dest)