blob: 56a79d12b87e5ac759dc064691d4c05a3b963975 [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 Shi35a39be2016-07-25 00:20:31 -0700139# A specific string value to return when a timeout has occurred.
140TIMEOUT_MSG = 'TIMEOUT_OCCURRED'
141
Dan Shia2872172015-10-31 01:16:51 -0700142class AndroidInstallError(error.InstallError):
143 """Generic error for Android installation related exceptions."""
144
145
Simran Basi724b8a52013-09-30 11:19:31 -0700146class ADBHost(abstract_ssh.AbstractSSHHost):
Simran Basi431010f2013-09-04 10:42:41 -0700147 """This class represents a host running an ADB server."""
148
Simran Basi5ace6f22016-01-06 17:30:44 -0800149 VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700150 _LABEL_FUNCTIONS = []
151 _DETECTABLE_LABELS = []
152 label_decorator = functools.partial(utils.add_label_detector,
153 _LABEL_FUNCTIONS,
154 _DETECTABLE_LABELS)
155
Dan Shi225b9042015-11-18 10:25:21 -0800156 _parser = autoserv_parser.autoserv_parser
Simran Basi431010f2013-09-04 10:42:41 -0700157
Dan Shi6450e142016-03-11 11:52:20 -0800158 # Minimum build id that supports server side packaging. Older builds may
159 # not have server side package built or with Autotest code change to support
160 # server-side packaging.
161 MIN_VERSION_SUPPORT_SSP = CONFIG.get_config_value(
162 'AUTOSERV', 'min_launch_control_build_id_support_ssp', type=int)
163
beeps46dadc92013-11-07 14:07:10 -0800164 @staticmethod
165 def check_host(host, timeout=10):
166 """
167 Check if the given host is an adb host.
168
Simran Basi14622bb2015-11-25 13:23:40 -0800169 If SSH connectivity can't be established, check_host will try to use
170 user 'adb' as well. If SSH connectivity still can't be established
171 then the original SSH user is restored.
172
beeps46dadc92013-11-07 14:07:10 -0800173 @param host: An ssh host representing a device.
174 @param timeout: The timeout for the run command.
175
176
177 @return: True if the host device has adb.
178
179 @raises AutoservRunError: If the command failed.
180 @raises AutoservSSHTimeout: Ssh connection has timed out.
181 """
Dan Shi64e130f2015-12-16 14:45:44 -0800182 # host object may not have user attribute if it's a LocalHost object.
183 current_user = host.user if hasattr(host, 'user') else None
beeps46dadc92013-11-07 14:07:10 -0800184 try:
Simran Basi14622bb2015-11-25 13:23:40 -0800185 if not (host.hostname == 'localhost' or
186 host.verify_ssh_user_access()):
Simran Basi1621c632015-10-14 12:22:23 -0700187 host.user = 'adb'
Simran Basi933c8af2015-04-29 14:05:07 -0700188 result = host.run(
Dan Shia2872172015-10-31 01:16:51 -0700189 'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
Simran Basi933c8af2015-04-29 14:05:07 -0700190 timeout=timeout)
beeps46dadc92013-11-07 14:07:10 -0800191 except (error.AutoservRunError, error.AutoservSSHTimeout):
Dan Shi64e130f2015-12-16 14:45:44 -0800192 if current_user is not None:
193 host.user = current_user
beeps46dadc92013-11-07 14:07:10 -0800194 return False
195 return result.exit_status == 0
196
197
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700198 # TODO(garnold) Remove the 'serials' argument once all clients are made to
199 # not use it.
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700200 def _initialize(self, hostname='localhost', serials=None,
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700201 adb_serial=None, fastboot_serial=None,
Simran Basi9228a6f2016-03-29 12:03:37 -0700202 teststation=None, *args, **dargs):
Simran Basi431010f2013-09-04 10:42:41 -0700203 """Initialize an ADB Host.
204
205 This will create an ADB Host. Hostname should always refer to the
Kevin Chengd19e6c62015-10-28 16:39:39 -0700206 test station connected to an Android DUT. This will be the DUT
207 to test with. If there are multiple, serial must be specified or an
Simran Basi9228a6f2016-03-29 12:03:37 -0700208 exception will be raised.
Simran Basi431010f2013-09-04 10:42:41 -0700209
210 @param hostname: Hostname of the machine running ADB.
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700211 @param serials: DEPRECATED (to be removed)
212 @param adb_serial: An ADB device serial. If None, assume a single
213 device is attached (and fail otherwise).
214 @param fastboot_serial: A fastboot device serial. If None, defaults to
215 the ADB serial (or assumes a single device if
216 the latter is None).
Kevin Cheng549beb42015-11-18 11:42:25 -0800217 @param teststation: The teststation object ADBHost should use.
Simran Basi431010f2013-09-04 10:42:41 -0700218 """
Simran Basi1bf60eb2015-12-01 16:39:29 -0800219 # Sets up the is_client_install_supported field.
220 super(ADBHost, self)._initialize(hostname=hostname,
221 is_client_install_supported=False,
222 *args, **dargs)
Kevin Cheng85e864a2015-11-30 11:49:34 -0800223
Kevin Chengd19e6c62015-10-28 16:39:39 -0700224 self.tmp_dirs = []
Kevin Chengc6a645a2015-12-18 11:15:10 -0800225 self.labels = base_label.LabelRetriever(adb_label.ADB_LABELS)
Kevin Cheng05ae2a42016-06-06 10:12:48 -0700226 adb_serial = adb_serial or self._afe_host.attributes.get('serials')
227 fastboot_serial = (fastboot_serial or
228 self._afe_host.attributes.get('fastboot_serial'))
229
Dan Shi50a412a2016-01-05 10:52:40 -0800230 self.adb_serial = adb_serial
Dan Shi3a011ed2016-04-26 12:26:53 -0700231 if adb_serial:
232 adb_prefix = any(adb_serial.startswith(p)
233 for p in ADB_DEVICE_PREFIXES)
234 self.fastboot_serial = (fastboot_serial or
235 ('tcp:%s' % adb_serial.split(':')[0] if
236 ':' in adb_serial and not adb_prefix else adb_serial))
237 self._use_tcpip = ':' in adb_serial and not adb_prefix
238 else:
239 self.fastboot_serial = fastboot_serial or adb_serial
240 self._use_tcpip = False
Kevin Cheng85e864a2015-11-30 11:49:34 -0800241 self.teststation = (teststation if teststation
Justin Giorgi5208eaa2016-07-02 20:12:12 -0700242 else teststation_host.create_teststationhost(
243 hostname=hostname,
244 user=self.user,
245 password=self.password,
246 port=self.port
247 ))
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700248
249 msg ='Initializing ADB device on host: %s' % hostname
Dan Shi50a412a2016-01-05 10:52:40 -0800250 if self.adb_serial:
251 msg += ', ADB serial: %s' % self.adb_serial
252 if self.fastboot_serial:
253 msg += ', fastboot serial: %s' % self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700254 logging.debug(msg)
255
Dan Shiab999722015-12-04 14:27:08 -0800256 self._os_type = None
257
Simran Basi431010f2013-09-04 10:42:41 -0700258
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700259 def _connect_over_tcpip_as_needed(self):
260 """Connect to the ADB device over TCP/IP if so configured."""
Simran Basi9228a6f2016-03-29 12:03:37 -0700261 if not self._use_tcpip:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700262 return
263 logging.debug('Connecting to device over TCP/IP')
Simran Basi9228a6f2016-03-29 12:03:37 -0700264 self.adb_run('connect %s' % self.adb_serial)
Simran Basi431010f2013-09-04 10:42:41 -0700265
266
Roshan Pius4d7540c2015-12-16 13:30:32 -0800267 def _restart_adbd_with_root_permissions(self):
268 """Restarts the adb daemon with root permissions."""
Dan Shi922de302016-04-22 15:19:18 -0700269 @retry.retry(error.AutoservRunError, timeout_min=20/60.0, delay_sec=1)
270 def run_adb_root():
271 """Run command `adb root`."""
272 self.adb_run('root')
273
274 # adb command may flake with error "device not found". Retry the root
275 # command to reduce the chance of flake.
276 run_adb_root()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800277 # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
278 time.sleep(1)
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300279 self._connect_over_tcpip_as_needed()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800280 self.adb_run('wait-for-device')
281
282
Simran Basi9228a6f2016-03-29 12:03:37 -0700283 def _set_tcp_port(self):
284 """Ensure the device remains in tcp/ip mode after a reboot."""
285 if not self._use_tcpip:
286 return
287 port = self.adb_serial.split(':')[-1]
288 self.run('setprop persist.adb.tcp.port %s' % port)
289
290
Roshan Pius4d7540c2015-12-16 13:30:32 -0800291 def _reset_adbd_connection(self):
292 """Resets adbd connection to the device after a reboot/initialization"""
Roshan Pius4d7540c2015-12-16 13:30:32 -0800293 self._connect_over_tcpip_as_needed()
Simran Basi9228a6f2016-03-29 12:03:37 -0700294 self._restart_adbd_with_root_permissions()
295 self._set_tcp_port()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800296
297
Kevin Cheng85e864a2015-11-30 11:49:34 -0800298 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800299 def adb_run(self, command, **kwargs):
Simran Basi431010f2013-09-04 10:42:41 -0700300 """Runs an adb command.
301
Kevin Chengd19e6c62015-10-28 16:39:39 -0700302 This command will launch on the test station.
Simran Basi431010f2013-09-04 10:42:41 -0700303
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700304 Refer to _device_run method for docstring for parameters.
305 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800306 return self._device_run(ADB_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700307
308
Kevin Cheng85e864a2015-11-30 11:49:34 -0800309 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800310 def fastboot_run(self, command, **kwargs):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700311 """Runs an fastboot command.
312
Kevin Chengd19e6c62015-10-28 16:39:39 -0700313 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700314
315 Refer to _device_run method for docstring for parameters.
316 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800317 return self._device_run(FASTBOOT_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700318
319
Dan Shi12a4f662016-05-10 14:49:42 -0700320 # pylint: disable=missing-docstring
321 @retry.retry(error.AutoservRunError,
322 timeout_min=DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN)
323 def _fastboot_run_with_retry(self, command, **kwargs):
324 """Runs an fastboot command with retry.
325
326 This command will launch on the test station.
327
328 Refer to _device_run method for docstring for parameters.
329 """
330 return self.fastboot_run(command, **kwargs)
331
332
Simran Basie6c4f142016-06-23 17:10:04 -0700333 def _log_adb_pid(self):
334 """Log the pid of adb server.
335
336 adb's server is known to have bugs and randomly restart. BY logging
337 the server's pid it will allow us to better debug random adb failures.
338 """
339 adb_pid = self.teststation.run('pgrep -f "adb.*server"')
340 logging.debug('ADB Server PID: %s', adb_pid.stdout)
341
342
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700343 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700344 timeout=3600, ignore_status=False, ignore_timeout=False,
345 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
346 connect_timeout=30, options='', stdin=None, verbose=True,
347 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700348 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700349
Kevin Chengd19e6c62015-10-28 16:39:39 -0700350 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700351
Simran Basi431010f2013-09-04 10:42:41 -0700352 @param command: Command to run.
353 @param shell: If true the command runs in the adb shell otherwise if
354 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700355 reboot with shell=False will call 'adb reboot'. This
356 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700357 @param timeout: Time limit in seconds before attempting to
358 kill the running process. The run() function
359 will take a few seconds longer than 'timeout'
360 to complete if it has to kill the process.
361 @param ignore_status: Do not raise an exception, no matter
362 what the exit code of the command is.
363 @param ignore_timeout: Bool True if command timeouts should be
364 ignored. Will return None on command timeout.
365 @param stdout: Redirect stdout.
366 @param stderr: Redirect stderr.
367 @param connect_timeout: Connection timeout (in seconds)
368 @param options: String with additional ssh command options
369 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700370 @param require_sudo: True to require sudo to run the command. Default is
371 False.
Simran Basi431010f2013-09-04 10:42:41 -0700372 @param args: Sequence of strings to pass as arguments to command by
373 quoting them in " and escaping their contents if
374 necessary.
375
376 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700377 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700378 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800379 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700380 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800381 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700382 else:
383 raise NotImplementedError('Mode %s is not supported' % function)
384
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700385 if function != ADB_CMD and shell:
386 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700387
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700388 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700389
390 if serial:
391 cmd += '-s %s ' % serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700392
Simran Basi431010f2013-09-04 10:42:41 -0700393 if shell:
394 cmd += '%s ' % SHELL_CMD
395 cmd += command
396
Simran Basie6c4f142016-06-23 17:10:04 -0700397 self._log_adb_pid()
398
Roshan Pius58e5dd32015-10-16 15:16:42 -0700399 if verbose:
400 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700401
Kevin Cheng85e864a2015-11-30 11:49:34 -0800402 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400403 ignore_status=ignore_status,
404 ignore_timeout=ignore_timeout, stdout_tee=stdout,
405 stderr_tee=stderr, options=options, stdin=stdin,
406 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700407
408
Dan Shi8c51bda2016-05-26 12:21:02 -0700409 def _run_output_with_retry(self, cmd):
410 """Call run_output method for the given command with retry.
411
Dan Shi68094122016-06-10 14:29:06 -0700412 adb command can be flaky some time, and the command may fail or return
413 empty string. It may take several retries until a value can be returned.
Dan Shi8c51bda2016-05-26 12:21:02 -0700414
415 @param cmd: The command to run.
416
417 @return: Return value from the command after retry.
418 """
419 try:
420 return client_utils.poll_for_condition(
Dan Shi68094122016-06-10 14:29:06 -0700421 lambda: self.run_output(cmd, ignore_status=True),
Dan Shi8c51bda2016-05-26 12:21:02 -0700422 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
423 sleep_interval=0.5,
424 desc='Get return value for command `%s`' % cmd)
425 except client_utils.TimeoutError:
426 return ''
427
428
Dan Shie234dea2016-01-20 17:15:17 -0800429 def get_board_name(self):
430 """Get the name of the board, e.g., shamu, dragonboard etc.
431 """
Simran Basi9c5d3982016-04-01 18:49:44 -0700432 product = self.run_output('getprop %s' % BOARD_FILE)
433 return PRODUCT_TARGET_MAP.get(product, product)
Dan Shie234dea2016-01-20 17:15:17 -0800434
435
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700436 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700437 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700438 """Determine the correct board label for the device.
439
440 @returns a string representing this device's board.
441 """
Dan Shie234dea2016-01-20 17:15:17 -0800442 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700443 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800444 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700445
446
Christopher Wiley08849d52013-11-22 08:57:58 -0800447 def job_start(self):
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700448 """Overload of parent which intentionally doesn't log certain files.
Dan Shi2d279cf2016-05-27 22:06:10 +0000449
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700450 The parent implementation attempts to log certain Linux files, such as
451 /var/log, which do not exist on Android, thus there is no call to the
452 parent's job_start(). The sync call is made so that logcat logs can be
453 approximately matched to server logs.
Dan Shi2d279cf2016-05-27 22:06:10 +0000454 """
Justin Giorgidd05a942016-07-05 20:53:12 -0700455 # Try resetting the ADB daemon on the device, however if we are
456 # creating the host to do a repair job, the device maybe inaccesible
457 # via ADB.
458 try:
459 self._reset_adbd_connection()
460 except (error.AutotestHostRunError, error.AutoservRunError) as e:
461 logging.error('Unable to reset the device adb daemon connection: '
462 '%s.', e)
463
Simran Basid6b49792016-06-07 17:22:03 -0700464 if self.is_up():
465 self._sync_time()
Bryan Lewandowski8c96bb22016-07-19 12:56:03 -0700466 self._enable_native_crash_logging()
Christopher Wiley08849d52013-11-22 08:57:58 -0800467
468
Simran Basi431010f2013-09-04 10:42:41 -0700469 def run(self, command, timeout=3600, ignore_status=False,
470 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
471 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700472 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700473 """Run a command on the adb device.
474
475 The command given will be ran directly on the adb device; for example
476 'ls' will be ran as: 'abd shell ls'
477
478 @param command: The command line string.
479 @param timeout: Time limit in seconds before attempting to
480 kill the running process. The run() function
481 will take a few seconds longer than 'timeout'
482 to complete if it has to kill the process.
483 @param ignore_status: Do not raise an exception, no matter
484 what the exit code of the command is.
485 @param ignore_timeout: Bool True if command timeouts should be
486 ignored. Will return None on command timeout.
487 @param stdout_tee: Redirect stdout.
488 @param stderr_tee: Redirect stderr.
489 @param connect_timeout: Connection timeout (in seconds).
490 @param options: String with additional ssh command options.
491 @param stdin: Stdin to pass (a string) to the executed command
492 @param args: Sequence of strings to pass as arguments to command by
493 quoting them in " and escaping their contents if
494 necessary.
495
496 @returns A CMDResult object or None if the call timed out and
497 ignore_timeout is True.
498
499 @raises AutoservRunError: If the command failed.
500 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700501 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700502 command = ('"%s; echo %s:\$?"' %
Dan Shi35a39be2016-07-25 00:20:31 -0700503 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Simran Basi431010f2013-09-04 10:42:41 -0700504
Dan Shi35a39be2016-07-25 00:20:31 -0700505 def _run():
506 """Run the command and try to parse the exit code.
507 """
508 result = self.adb_run(
509 command, shell=True, timeout=timeout,
510 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
511 stdout=stdout_tee, stderr=stderr_tee,
512 connect_timeout=connect_timeout, options=options,
513 stdin=stdin, verbose=verbose, args=args)
514 if not result:
515 # In case of timeouts. Set the return to a specific string
516 # value. That way the caller of poll_for_condition knows
517 # a timeout occurs and should return None. Return None here will
518 # lead to the command to be retried.
519 return TIMEOUT_MSG
520 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
521 if not parse_output and not ignore_status:
522 logging.error('Failed to parse the exit code for command: `%s`.'
523 ' result: `%s`', command, result.stdout)
524 return None
525 elif parse_output:
526 result.stdout = parse_output.group('OUTPUT')
527 result.exit_status = int(parse_output.group('EXIT_CODE'))
528 if result.exit_status != 0 and not ignore_status:
529 raise error.AutoservRunError(command, result)
530 return result
531
532 result = client_utils.poll_for_condition(
533 lambda: _run(),
534 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
535 sleep_interval=0.5,
536 desc='Run command `%s`' % command)
537 return None if result == TIMEOUT_MSG else result
Simran Basi431010f2013-09-04 10:42:41 -0700538
539
Dan Shicf7d2562016-06-16 14:08:23 -0700540 def check_boot_to_adb_complete(self, exception_type=error.TimeoutException):
541 """Check if the device has finished booting and accessible by adb.
542
543 @param exception_type: Type of exception to raise. Default is set to
544 error.TimeoutException for retry.
545
546 @raise exception_type: If the device has not finished booting yet, raise
547 an exception of type `exception_type`.
548 """
549 bootcomplete = self._run_output_with_retry('getprop dev.bootcomplete')
550 if bootcomplete != PROPERTY_VALUE_TRUE:
551 raise exception_type('dev.bootcomplete is %s.' % bootcomplete)
552 if self.get_os_type() == OS_TYPE_ANDROID:
553 boot_completed = self._run_output_with_retry(
554 'getprop sys.boot_completed')
555 if boot_completed != PROPERTY_VALUE_TRUE:
556 raise exception_type('sys.boot_completed is %s.' %
557 boot_completed)
558
559
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700560 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
561 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700562
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700563 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700564
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700565 @param timeout: Time limit in seconds before returning even if the host
566 is not up.
567 @param command: The command used to test if a device is up, i.e.,
568 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700569
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700570 @returns True if the host was found to be up before the timeout expires,
571 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700572 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700573 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
574 delay_sec=1)
575 def _wait_up():
576 if not self.is_up(command=command):
577 raise error.TimeoutException('Device is still down.')
Dan Shicf7d2562016-06-16 14:08:23 -0700578 if command == ADB_CMD:
579 self.check_boot_to_adb_complete()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700580 return True
581
582 try:
583 _wait_up()
584 logging.debug('Host %s is now up, and can be accessed by %s.',
585 self.hostname, command)
586 return True
587 except error.TimeoutException:
588 logging.debug('Host %s is still down after waiting %d seconds',
589 self.hostname, timeout)
590 return False
Simran Basi431010f2013-09-04 10:42:41 -0700591
592
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700593 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
594 warning_timer=None, old_boot_id=None, command=ADB_CMD):
595 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700596
597 Overrides wait_down from AbstractSSHHost.
598
599 @param timeout: Time in seconds to wait for the host to go down.
600 @param warning_timer: Time limit in seconds that will generate
601 a warning if the host is not down yet.
602 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700603 @param old_boot_id: Not applicable for adb_host.
604 @param command: `adb`, test if the device can be accessed by adb
605 command, or `fastboot`, test if the device can be accessed by
606 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700607
608 @returns True if the device goes down before the timeout, False
609 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700610 """
611 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
612 delay_sec=1)
613 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700614 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700615 raise error.TimeoutException('Device is still up.')
616 return True
617
618 try:
619 _wait_down()
620 logging.debug('Host %s is now down', self.hostname)
621 return True
622 except error.TimeoutException:
623 logging.debug('Host %s is still up after waiting %d seconds',
624 self.hostname, timeout)
625 return False
626
627
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700628 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700629 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700630
631 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700632 """
633 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700634 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700635 self.adb_run('reboot', timeout=10, ignore_timeout=True)
636 if not self.wait_down():
637 raise error.AutoservRebootError(
638 'ADB Device is still up after reboot')
639 if not self.wait_up():
640 raise error.AutoservRebootError(
641 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800642 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800643
644
Alexandru Branciog969ff7c2016-03-30 14:07:15 +0300645 def fastboot_reboot(self):
646 """Do a fastboot reboot to go back to adb.
647
648 @raises AutoservRebootError if reboot failed.
649 """
650 self.fastboot_run('reboot')
651 if not self.wait_down(command=FASTBOOT_CMD):
652 raise error.AutoservRebootError(
653 'Device is still in fastboot mode after reboot')
654 if not self.wait_up():
655 raise error.AutoservRebootError(
656 'Device failed to boot to adb after fastboot reboot.')
657 self._reset_adbd_connection()
658
659
Ralph Nathanb45eb672015-11-18 20:04:39 -0800660 def remount(self):
661 """Remounts paritions on the device read-write.
662
663 Specifically, the /system, /vendor (if present) and /oem (if present)
664 partitions on the device are remounted read-write.
665 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800666 self.adb_run('remount')
667
668
Kevin Cheng549beb42015-11-18 11:42:25 -0800669 @staticmethod
670 def parse_device_serials(devices_output):
671 """Return a list of parsed serials from the output.
672
673 @param devices_output: Output from either an adb or fastboot command.
674
675 @returns List of device serials
676 """
677 devices = []
678 for line in devices_output.splitlines():
679 match = re.search(DEVICE_FINDER_REGEX, line)
680 if match:
681 serial = match.group('SERIAL')
682 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
683 serial = DEVICE_NO_SERIAL_TAG
684 logging.debug('Found Device: %s', serial)
685 devices.append(serial)
686 return devices
687
688
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700689 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700690 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700691
692 @params use_adb: True to get adb accessible devices. Set to False to
693 get fastboot accessible devices.
694
Kevin Chengd19e6c62015-10-28 16:39:39 -0700695 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700696 """
697 if use_adb:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300698 result = self.adb_run('devices').stdout
699 if self.adb_serial and self.adb_serial not in result:
700 self._connect_over_tcpip_as_needed()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700701 else:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300702 result = self.fastboot_run('devices').stdout
703 if (self.fastboot_serial and
704 self.fastboot_serial not in result):
705 # fastboot devices won't list the devices using TCP
706 try:
707 if 'product' in self.fastboot_run('getvar product',
708 timeout=2).stderr:
709 result += '\n%s\tfastboot' % self.fastboot_serial
Kevin Chengcfcb2cf2016-04-13 10:04:36 -0700710 # The main reason we do a general Exception catch here instead
711 # of setting ignore_timeout/status to True is because even when
712 # the fastboot process has been nuked, it still stays around and
713 # so bgjob wants to warn us of this and tries to read the
714 # /proc/<pid>/stack file which then promptly returns an
715 # 'Operation not permitted' error since we're running as moblab
716 # and we don't have permission to read those files.
717 except Exception:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300718 pass
719 return self.parse_device_serials(result)
Simran Basi431010f2013-09-04 10:42:41 -0700720
721
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700722 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700723 """Get a list of devices currently attached to the test station and
724 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700725 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800726 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700727 raise error.AutoservError(
728 'Not given ADB serial but multiple devices detected')
729 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700730
731
732 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700733 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700734 accessible by fastboot command.
735 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700736 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800737 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700738 raise error.AutoservError(
739 'Not given fastboot serial but multiple devices detected')
740 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700741
742
743 def is_up(self, timeout=0, command=ADB_CMD):
744 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700745
746 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700747 @param command: `adb`, the device can be accessed by adb command,
748 or `fastboot`, the device can be accessed by fastboot command.
749 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700750
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700751 @returns True if the device is detectable by given command, False
752 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700753
754 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700755 if command == ADB_CMD:
756 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800757 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800758 # ADB has a device state, if the device is not online, no
759 # subsequent ADB command will complete.
Dan Shi6450e142016-03-11 11:52:20 -0800760 # DUT with single device connected may not have adb_serial set.
761 # Therefore, skip checking if serial is in the list of adb devices
762 # if self.adb_serial is not set.
763 if (serial and serial not in devices) or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800764 logging.debug('Waiting for device to enter the ready state.')
765 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700766 elif command == FASTBOOT_CMD:
767 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800768 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700769 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700770 raise NotImplementedError('Mode %s is not supported' % command)
771
772 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700773
774
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700775 def stop_loggers(self):
776 """Inherited stop_loggers function.
777
778 Calls parent function and captures logcat, since the end of the run
779 is logically the end/stop of the logcat log.
780 """
781 super(ADBHost, self).stop_loggers()
782 # Record logcat log to a temporary file on the teststation.
783 tmp_dir = self.teststation.get_tmp_dir()
Simran Basi242f8de2016-06-08 14:23:43 -0700784 logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
785 teststation_filename = os.path.join(tmp_dir, logcat_filename)
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700786 try:
787 self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
788 timeout=20)
Simran Basid6b49792016-06-07 17:22:03 -0700789 except (error.AutotestHostRunError, error.AutoservRunError,
790 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700791 return
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700792 # Copy-back the log to the drone's results directory.
Simran Basi242f8de2016-06-08 14:23:43 -0700793 results_logcat_filename = os.path.join(self.job.resultdir,
794 logcat_filename)
795 self.teststation.get_file(teststation_filename,
796 results_logcat_filename)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700797 try:
798 self.teststation.run('rm -rf %s' % tmp_dir)
799 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
800 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
801
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700802 self._collect_crash_logs()
803
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700804
Simran Basi431010f2013-09-04 10:42:41 -0700805 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700806 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700807
808 Called as the test ends. Will return the device to USB mode and kill
809 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700810 """
Christopher Wiley08849d52013-11-22 08:57:58 -0800811 # TODO(sbasi) Originally, we would kill the server after each test to
812 # reduce the opportunity for bad server state to hang around.
813 # Unfortunately, there is a period of time after each kill during which
814 # the Android device becomes unusable, and if we start the next test
815 # too quickly, we'll get an error complaining about no ADB device
816 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700817 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800818 # |close| the associated teststation as well.
819 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700820 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700821
822
823 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700824 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700825
826 @param message String message to log into syslog
827 @param tag String tag prefix for syslog
828
829 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700830 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700831
832
833 def get_autodir(self):
834 """Return the directory to install autotest for client side tests."""
835 return '/data/autotest'
836
Kevin Cheng018db352015-09-20 02:22:08 -0700837
Kris Rambishde8f9d12015-12-16 12:42:41 -0800838 def is_device_ready(self):
839 """Return the if the device is ready for ADB commands."""
Dan Shi7075f552016-04-21 15:42:41 -0700840 try:
841 # Retry to avoid possible flakes.
842 is_ready = client_utils.poll_for_condition(
843 lambda: self.adb_run('get-state').stdout.strip() == 'device',
844 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
845 desc='Waiting for device state to be `device`')
846 except client_utils.TimeoutError:
847 is_ready = False
848
849 logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
850 return is_ready
Kris Rambishde8f9d12015-12-16 12:42:41 -0800851
852
Kevin Chengd19e6c62015-10-28 16:39:39 -0700853 def verify_connectivity(self):
854 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800855 if not self.is_device_ready():
856 raise error.AutoservHostError('device state is not in the '
857 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700858
859
Simran Basid3ba3fb2015-09-11 14:35:07 -0700860 def verify_software(self):
861 """Verify working software on an adb_host.
862
Simran Basi38f7ddf2015-09-18 12:25:03 -0700863 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700864 """
Dan Shiab999722015-12-04 14:27:08 -0800865 # Check if adb and fastboot are present.
866 self.teststation.run('which adb')
867 self.teststation.run('which fastboot')
868 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700869
Dan Shi626d5412016-05-16 16:05:13 -0700870 # Apply checks only for Android device.
Dan Shi1e2a98a2016-05-18 12:08:08 -0700871 if self.get_os_type() == OS_TYPE_ANDROID:
Dan Shi626d5412016-05-16 16:05:13 -0700872 # Make sure ro.boot.hardware and ro.build.product match.
Dan Shi8c51bda2016-05-26 12:21:02 -0700873 hardware = self._run_output_with_retry('getprop ro.boot.hardware')
874 product = self._run_output_with_retry('getprop ro.build.product')
Dan Shi1e2a98a2016-05-18 12:08:08 -0700875 if hardware != product:
876 raise error.AutoservHostError('ro.boot.hardware: %s does not '
877 'match to ro.build.product: %s' %
878 (hardware, product))
879
Kevin Cheng018db352015-09-20 02:22:08 -0700880
Simran Basid3ba3fb2015-09-11 14:35:07 -0700881 def verify_job_repo_url(self, tag=''):
882 """Make sure job_repo_url of this host is valid.
883
Simran Basi38f7ddf2015-09-18 12:25:03 -0700884 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700885
886 @param tag: The tag from the server job, in the format
887 <job_id>-<user>/<hostname>, or <hostless> for a server job.
888 """
889 return
Kevin Cheng018db352015-09-20 02:22:08 -0700890
891
Simran Basibeb2bb22016-02-03 15:25:48 -0800892 def repair(self):
893 """Attempt to get the DUT to pass `self.verify()`."""
894 try:
895 self.ensure_adb_mode(timeout=30)
896 return
897 except error.AutoservError as e:
898 logging.error(e)
899 logging.debug('Verifying the device is accessible via fastboot.')
900 self.ensure_bootloader_mode()
901 if not self.job.run_test(
902 'provision_AndroidUpdate', host=self, value=None,
903 force=True, repair=True):
904 raise error.AutoservRepairTotalFailure(
905 'Unable to repair the device.')
906
907
Simran Basi1b023762015-09-25 12:12:20 -0700908 def send_file(self, source, dest, delete_dest=False,
909 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700910 """Copy files from the drone to the device.
911
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400912 Just a note, there is the possibility the test station is localhost
913 which makes some of these steps redundant (e.g. creating tmp dir) but
914 that scenario will undoubtedly be a development scenario (test station
915 is also the moblab) and not the typical live test running scenario so
916 the redundancy I think is harmless.
917
Kevin Cheng018db352015-09-20 02:22:08 -0700918 @param source: The file/directory on the drone to send to the device.
919 @param dest: The destination path on the device to copy to.
920 @param delete_dest: A flag set to choose whether or not to delete
921 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700922 @param preserve_symlinks: Controls if symlinks on the source will be
923 copied as such on the destination or
924 transformed into the referenced
925 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700926 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700927 # If we need to preserve symlinks, let's check if the source is a
928 # symlink itself and if so, just create it on the device.
929 if preserve_symlinks:
930 symlink_target = None
931 try:
932 symlink_target = os.readlink(source)
933 except OSError:
934 # Guess it's not a symlink.
935 pass
936
937 if symlink_target is not None:
938 # Once we create the symlink, let's get out of here.
939 self.run('ln -s %s %s' % (symlink_target, dest))
940 return
941
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400942 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700943 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400944 src_path = os.path.join(tmp_dir, os.path.basename(dest))
945 # Now copy the file over to the test station so you can reference the
946 # file in the push command.
947 self.teststation.send_file(source, src_path,
948 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700949
950 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400951 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700952
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700953 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700954
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400955 # Cleanup the test station.
956 try:
957 self.teststation.run('rm -rf %s' % tmp_dir)
958 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
959 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700960
961
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700962 def _get_file_info(self, dest):
963 """Get permission and possible symlink info about file on the device.
964
965 These files are on the device so we only have shell commands (via adb)
966 to get the info we want. We'll use 'ls' to get it all.
967
968 @param dest: File to get info about.
969
970 @returns a dict of the file permissions and symlink.
971 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800972 # Grab file info.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700973 file_info = self.run_output('ls -ld %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700974 symlink = None
975 perms = 0
976 match = re.match(FILE_INFO_REGEX, file_info)
977 if match:
978 # Check if it's a symlink and grab the linked dest if it is.
979 if match.group('TYPE') == 'l':
980 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
981 if symlink_match:
982 symlink = symlink_match.group('SYMLINK')
983
984 # Set the perms.
985 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
986 if perm != '-':
987 perms |= perm_flag
988
989 return {'perms': perms,
990 'symlink': symlink}
991
992
Simran Basi1b023762015-09-25 12:12:20 -0700993 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
994 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700995 """Copy files from the device to the drone.
996
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400997 Just a note, there is the possibility the test station is localhost
998 which makes some of these steps redundant (e.g. creating tmp dir) but
999 that scenario will undoubtedly be a development scenario (test station
1000 is also the moblab) and not the typical live test running scenario so
1001 the redundancy I think is harmless.
1002
Kevin Cheng018db352015-09-20 02:22:08 -07001003 @param source: The file/directory on the device to copy back to the
1004 drone.
1005 @param dest: The destination path on the drone to copy to.
1006 @param delete_dest: A flag set to choose whether or not to delete
1007 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -07001008 @param preserve_perm: Tells get_file() to try to preserve the sources
1009 permissions on files and dirs.
1010 @param preserve_symlinks: Try to preserve symlinks instead of
1011 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -07001012 """
David Purselle01548b2016-05-11 10:00:42 -07001013 # Stage the files on the test station under teststation_temp_dir.
1014 teststation_temp_dir = self.teststation.get_tmp_dir()
1015 teststation_dest = os.path.join(teststation_temp_dir,
1016 os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -07001017
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001018 source_info = {}
1019 if preserve_symlinks or preserve_perm:
1020 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -07001021
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001022 # If we want to preserve symlinks, just create it here, otherwise pull
1023 # the file off the device.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001024 #
1025 # TODO(sadmac): Directories containing symlinks won't behave as
1026 # expected.
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001027 if preserve_symlinks and source_info['symlink']:
1028 os.symlink(source_info['symlink'], dest)
1029 else:
David Purselle01548b2016-05-11 10:00:42 -07001030 self.adb_run('pull %s %s' % (source, teststation_temp_dir))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001031
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001032 # Copy over the file from the test station and clean up.
David Purselle01548b2016-05-11 10:00:42 -07001033 self.teststation.get_file(teststation_dest, dest,
1034 delete_dest=delete_dest)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001035 try:
David Purselle01548b2016-05-11 10:00:42 -07001036 self.teststation.run('rm -rf %s' % teststation_temp_dir)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001037 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
David Purselle01548b2016-05-11 10:00:42 -07001038 logging.warn('failed to remove dir %s: %s',
1039 teststation_temp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001040
David Pursell788b1b52016-05-19 09:03:31 -07001041 # Source will be copied under dest if either:
1042 # 1. Source is a directory and doesn't end with /.
1043 # 2. Source is a file and dest is a directory.
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001044 command = '[ -d %s ]' % source
1045 source_is_dir = self.run(command,
David Pursell788b1b52016-05-19 09:03:31 -07001046 ignore_status=True).exit_status == 0
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001047
David Pursell788b1b52016-05-19 09:03:31 -07001048 if ((source_is_dir and not source.endswith(os.sep)) or
1049 (not source_is_dir and os.path.isdir(dest))):
1050 receive_path = os.path.join(dest, os.path.basename(source))
1051 else:
1052 receive_path = dest
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001053
David Pursell788b1b52016-05-19 09:03:31 -07001054 # Set the permissions of the received file/dirs.
1055 if os.path.isdir(receive_path):
1056 for root, _dirs, files in os.walk(receive_path):
1057 def process(rel_path, default_perm):
1058 info = self._get_file_info(os.path.join(source,
1059 rel_path))
1060 if info['perms'] != 0:
1061 target = os.path.join(receive_path, rel_path)
1062 if preserve_perm:
1063 os.chmod(target, info['perms'])
1064 else:
1065 os.chmod(target, default_perm)
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001066
David Pursell788b1b52016-05-19 09:03:31 -07001067 rel_root = os.path.relpath(root, receive_path)
1068 process(rel_root, _DEFAULT_DIR_PERMS)
1069 for f in files:
1070 process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
1071 elif preserve_perm:
1072 os.chmod(receive_path, source_info['perms'])
1073 else:
1074 os.chmod(receive_path, _DEFAULT_FILE_PERMS)
Kevin Cheng018db352015-09-20 02:22:08 -07001075
1076
1077 def get_release_version(self):
1078 """Get the release version from the RELEASE_FILE on the device.
1079
1080 @returns The release string in the RELEASE_FILE.
1081
1082 """
1083 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -07001084
1085
1086 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001087 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001088
Kevin Chengd19e6c62015-10-28 16:39:39 -07001089 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001090
1091 @param parent: Parent directory of the returned tmp dir.
1092
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07001093 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001094 """
Kevin Chengd19e6c62015-10-28 16:39:39 -07001095 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
1096 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001097 if not parent.startswith(TMP_DIR):
1098 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -07001099 self.run('mkdir -p %s' % parent)
1100 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
1101 self.tmp_dirs.append(tmp_dir)
1102 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -07001103
1104
1105 def get_platform(self):
1106 """Determine the correct platform label for this host.
1107
1108 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -07001109 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -07001110
1111 @returns a string representing this host's platform.
1112 """
1113 return 'adb'
1114
1115
Gilad Arnolda76bef02015-09-29 13:55:15 -07001116 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -08001117 """Get the OS type of the DUT, e.g., android or brillo.
1118 """
1119 if not self._os_type:
1120 if self.run_output('getprop ro.product.brand') == 'Brillo':
1121 self._os_type = OS_TYPE_BRILLO
1122 else:
1123 self._os_type = OS_TYPE_ANDROID
1124
1125 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001126
1127
1128 def _forward(self, reverse, args):
1129 """Execute a forwarding command.
1130
1131 @param reverse: Whether this is reverse forwarding (Boolean).
1132 @param args: List of command arguments.
1133 """
1134 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001135 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001136
1137
1138 def add_forwarding(self, src, dst, reverse=False, rebind=True):
1139 """Forward a port between the ADB host and device.
1140
1141 Port specifications are any strings accepted as such by ADB, for
1142 example 'tcp:8080'.
1143
1144 @param src: Port specification to forward from.
1145 @param dst: Port specification to forward to.
1146 @param reverse: Do reverse forwarding from device to host (Boolean).
1147 @param rebind: Allow rebinding an already bound port (Boolean).
1148 """
1149 args = []
1150 if not rebind:
1151 args.append('--no-rebind')
1152 args += [src, dst]
1153 self._forward(reverse, args)
1154
1155
1156 def remove_forwarding(self, src=None, reverse=False):
1157 """Removes forwarding on port.
1158
1159 @param src: Port specification, or None to remove all forwarding.
1160 @param reverse: Whether this is reverse forwarding (Boolean).
1161 """
1162 args = []
1163 if src is None:
1164 args.append('--remove-all')
1165 else:
1166 args += ['--remove', src]
1167 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001168
1169
xixuan6cf6d2f2016-01-29 15:29:00 -08001170 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001171 """
1172 Forwards a port securely through a tunnel process from the server
1173 to the DUT for RPC server connection.
1174 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
1175 to the DUT.
1176
1177 @param port: remote port on the DUT.
1178 @param local_port: local forwarding port.
1179
1180 @return: the tunnel process.
1181 """
1182 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001183 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001184
1185
xixuan6cf6d2f2016-01-29 15:29:00 -08001186 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001187 """
1188 Disconnects a previously forwarded port from the server to the DUT for
1189 RPC server connection.
1190 Remove the previously added 'ADB forward' rule to forward the RPC
1191 packets from the AdbHost to the DUT.
1192
1193 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -08001194 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -07001195 @param port: remote port on the DUT.
1196
1197 """
1198 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001199 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001200
1201
1202 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001203 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001204
1205 @raise: error.AutoservError if the device failed to reboot into
1206 bootloader mode.
1207 """
1208 if self.is_up(command=FASTBOOT_CMD):
1209 return
1210 self.adb_run('reboot bootloader')
1211 if not self.wait_up(command=FASTBOOT_CMD):
1212 raise error.AutoservError(
1213 'The device failed to reboot into bootloader mode.')
1214
1215
Dan Shie4e807b2015-12-10 09:04:03 -08001216 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001217 """Ensure the device is up and can be accessed by adb command.
1218
Dan Shie4e807b2015-12-10 09:04:03 -08001219 @param timeout: Time limit in seconds before returning even if the host
1220 is not up.
1221
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001222 @raise: error.AutoservError if the device failed to reboot into
1223 adb mode.
1224 """
1225 if self.is_up():
1226 return
Dan Shi04980372016-03-22 10:57:47 -07001227 # Ignore timeout error to allow `fastboot reboot` to fail quietly and
1228 # check if the device is in adb mode.
1229 self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
Dan Shie4e807b2015-12-10 09:04:03 -08001230 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001231 raise error.AutoservError(
1232 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -08001233 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -07001234
1235
1236 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -08001237 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001238 """Get the Android build information from the build url.
1239
1240 @param build_url: The url to use for downloading Android artifacts.
1241 pattern: http://$devserver:###/static/branch/target/build_id
1242
Dan Shi6450e142016-03-11 11:52:20 -08001243 @return: A dictionary of build information, including keys:
1244 build_target, branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -08001245 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -07001246 """
Dan Shiab999722015-12-04 14:27:08 -08001247 if not build_url:
1248 raise AndroidInstallError('Need build_url to download image files.')
1249
1250 try:
1251 match = re.match(DEVSERVER_URL_REGEX, build_url)
Dan Shi6450e142016-03-11 11:52:20 -08001252 return {'build_target': match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001253 'branch': match.group('BRANCH'),
Dan Shi6450e142016-03-11 11:52:20 -08001254 'target': ('%s-%s' % (match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001255 match.group('BUILD_TYPE'))),
1256 'build_id': match.group('BUILD_ID')}
1257 except (AttributeError, IndexError, ValueError) as e:
1258 raise AndroidInstallError(
1259 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001260
1261
Dan Shia2872172015-10-31 01:16:51 -07001262 @retry.retry(error.AutoservRunError, timeout_min=10)
Simran Basi7756a0b2016-03-16 13:10:07 -07001263 def download_file(self, build_url, file, dest_dir, unzip=False,
1264 unzip_dest=None):
Dan Shia2872172015-10-31 01:16:51 -07001265 """Download the given file from the build url.
1266
1267 @param build_url: The url to use for downloading Android artifacts.
1268 pattern: http://$devserver:###/static/branch/target/build_id
1269 @param file: Name of the file to be downloaded, e.g., boot.img.
1270 @param dest_dir: Destination folder for the file to be downloaded to.
Simran Basi7756a0b2016-03-16 13:10:07 -07001271 @param unzip: If True, unzip the downloaded file.
1272 @param unzip_dest: Location to unzip the downloaded file to. If not
1273 provided, dest_dir is used.
Dan Shia2872172015-10-31 01:16:51 -07001274 """
Dan Shidb0366c2016-02-19 10:36:18 -08001275 # Append the file name to the url if build_url is linked to the folder
1276 # containing the file.
1277 if not build_url.endswith('/%s' % file):
1278 src_url = os.path.join(build_url, file)
1279 else:
1280 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001281 dest_file = os.path.join(dest_dir, file)
1282 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001283 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Simran Basi7756a0b2016-03-16 13:10:07 -07001284 if unzip:
1285 unzip_dest = unzip_dest or dest_dir
1286 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1287 (dest_dir, file, unzip_dest))
Dan Shia2872172015-10-31 01:16:51 -07001288 except:
1289 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001290 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001291 raise
1292
1293
Dan Shiab999722015-12-04 14:27:08 -08001294 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001295 """Download required image files from the given build_url to a local
1296 directory in the machine runs fastboot command.
1297
1298 @param build_url: The url to use for downloading Android artifacts.
1299 pattern: http://$devserver:###/static/branch/target/build_id
1300
1301 @return: Path to the directory contains image files.
1302 """
Dan Shi08ff1282016-02-18 19:51:16 -08001303 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001304
1305 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001306 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001307
1308 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001309 self.download_file(build_url, zipped_image_file, image_dir,
1310 unzip=True)
Dan Shi49d451f2016-04-19 09:25:01 -07001311 images = android_utils.AndroidImageFiles.get_standalone_images(
1312 build_info['build_target'])
1313 for image_file in images:
Dan Shidb0366c2016-02-19 10:36:18 -08001314 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001315
Dan Shia2872172015-10-31 01:16:51 -07001316 return image_dir
1317 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001318 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001319 raise
1320
1321
Dan Shiab999722015-12-04 14:27:08 -08001322 def stage_brillo_image_files(self, build_url):
1323 """Download required brillo image files from the given build_url to a
1324 local directory in the machine runs fastboot command.
1325
1326 @param build_url: The url to use for downloading Android artifacts.
1327 pattern: http://$devserver:###/static/branch/target/build_id
1328
1329 @return: Path to the directory contains image files.
1330 """
Dan Shi08ff1282016-02-18 19:51:16 -08001331 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001332
1333 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1334 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1335 image_dir = self.teststation.get_tmp_dir()
Dan Shiab999722015-12-04 14:27:08 -08001336
1337 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001338 self.download_file(build_url, zipped_image_file, image_dir,
1339 unzip=True)
1340 self.download_file(build_url, vendor_partitions_file, image_dir,
1341 unzip=True,
1342 unzip_dest=os.path.join(image_dir, 'vendor'))
Dan Shiab999722015-12-04 14:27:08 -08001343 return image_dir
1344 except:
1345 self.teststation.run('rm -rf %s' % image_dir)
1346 raise
1347
1348
Simran Basibeb2bb22016-02-03 15:25:48 -08001349 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001350 """Stage a build on a devserver and return the build_url and devserver.
1351
1352 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001353
Dan Shi225b9042015-11-18 10:25:21 -08001354 @returns a tuple with an update URL like:
1355 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1356 and the devserver instance.
1357 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001358 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001359 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001360 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1361 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001362 build_name = devserver.translate(build_name)
Dan Shi6450e142016-03-11 11:52:20 -08001363 branch, target, build_id = utils.parse_launch_control_build(build_name)
Dan Shi08ff1282016-02-18 19:51:16 -08001364 devserver.trigger_download(target, build_id, branch,
Justin Giorgidd05a942016-07-05 20:53:12 -07001365 os=os_type, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001366 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001367
1368
Dan Shie4e807b2015-12-10 09:04:03 -08001369 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001370 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001371 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001372
1373 Following are the steps used here to provision an android device:
1374 1. If build_local_path is not set, download the image zip file, e.g.,
1375 shamu-img-2284311.zip, unzip it.
1376 2. Run fastboot to install following artifacts:
1377 bootloader, radio, boot, system, vendor(only if exists)
1378
1379 Repair is not supported for Android devices yet.
1380
1381 @param build_url: The url to use for downloading Android artifacts.
1382 pattern: http://$devserver:###/static/$build
1383 @param build_local_path: The path to a local folder that contains the
1384 image files needed to provision the device. Note that the folder
1385 is in the machine running adb command, rather than the drone.
1386 @param wipe: If true, userdata will be wiped before flashing.
1387 @param flash_all: If True, all img files found in img_path will be
1388 flashed. Otherwise, only boot and system are flashed.
1389
1390 @raises AndroidInstallError if any error occurs.
1391 """
Dan Shia2872172015-10-31 01:16:51 -07001392 # If the build is not staged in local server yet, clean up the temp
1393 # folder used to store image files after the provision is completed.
1394 delete_build_folder = bool(not build_local_path)
1395
1396 try:
1397 # Download image files needed for provision to a local directory.
1398 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001399 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001400
1401 # Device needs to be in bootloader mode for flashing.
1402 self.ensure_bootloader_mode()
1403
1404 if wipe:
Dan Shi12a4f662016-05-10 14:49:42 -07001405 self._fastboot_run_with_retry('-w')
Dan Shia2872172015-10-31 01:16:51 -07001406
1407 # Get all *.img file in the build_local_path.
1408 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001409 image_files = self.teststation.run(
1410 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001411 images = dict([(os.path.basename(f), f) for f in image_files])
Dan Shi49d451f2016-04-19 09:25:01 -07001412 build_info = self.get_build_info_from_build_url(build_url)
1413 board = build_info['build_target']
1414 all_images = (
1415 android_utils.AndroidImageFiles.get_standalone_images(board)
1416 + android_utils.AndroidImageFiles.get_zipped_images(board))
1417
1418 # Sort images to be flashed, bootloader needs to be the first one.
1419 bootloader = android_utils.AndroidImageFiles.BOOTLOADER
1420 sorted_images = sorted(
1421 images.items(),
1422 key=lambda pair: 0 if pair[0] == bootloader else 1)
1423 for image, image_file in sorted_images:
1424 if image not in all_images:
Dan Shia2872172015-10-31 01:16:51 -07001425 continue
1426 logging.info('Flashing %s...', image_file)
Dan Shi12a4f662016-05-10 14:49:42 -07001427 self._fastboot_run_with_retry('-S 256M flash %s %s' %
1428 (image[:-4], image_file))
Dan Shi49d451f2016-04-19 09:25:01 -07001429 if image == android_utils.AndroidImageFiles.BOOTLOADER:
Dan Shia2872172015-10-31 01:16:51 -07001430 self.fastboot_run('reboot-bootloader')
1431 self.wait_up(command=FASTBOOT_CMD)
1432 except Exception as e:
1433 logging.error('Install Android build failed with error: %s', e)
1434 # Re-raise the exception with type of AndroidInstallError.
1435 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1436 finally:
1437 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001438 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001439 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1440 DEFAULT_WAIT_UP_TIME_SECONDS)
1441 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001442 logging.info('Successfully installed Android build staged at %s.',
1443 build_url)
1444
1445
Dan Shiab999722015-12-04 14:27:08 -08001446 def install_brillo(self, build_url, build_local_path=None):
1447 """Install the Brillo DUT.
1448
1449 Following are the steps used here to provision an android device:
1450 1. If build_local_path is not set, download the image zip file, e.g.,
1451 dragonboard-img-123456.zip, unzip it. And download the vendor
1452 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1453 unzip it to vendor folder.
1454 2. Run provision_device script to install OS images and vendor
1455 partitions.
1456
1457 @param build_url: The url to use for downloading Android artifacts.
1458 pattern: http://$devserver:###/static/$build
1459 @param build_local_path: The path to a local folder that contains the
1460 image files needed to provision the device. Note that the folder
1461 is in the machine running adb command, rather than the drone.
1462
1463 @raises AndroidInstallError if any error occurs.
1464 """
1465 # If the build is not staged in local server yet, clean up the temp
1466 # folder used to store image files after the provision is completed.
1467 delete_build_folder = bool(not build_local_path)
1468
Dan Shiab999722015-12-04 14:27:08 -08001469 try:
1470 # Download image files needed for provision to a local directory.
1471 if not build_local_path:
1472 build_local_path = self.stage_brillo_image_files(build_url)
1473
1474 # Device needs to be in bootloader mode for flashing.
1475 self.ensure_bootloader_mode()
1476
1477 # Run provision_device command to install image files and vendor
1478 # partitions.
1479 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1480 cmd = (BRILLO_PROVISION_CMD %
1481 {'os_image_dir': build_local_path,
1482 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001483 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001484 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001485 self.teststation.run(cmd)
1486 except Exception as e:
1487 logging.error('Install Brillo build failed with error: %s', e)
1488 # Re-raise the exception with type of AndroidInstallError.
1489 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1490 finally:
1491 if delete_build_folder:
1492 self.teststation.run('rm -rf %s' % build_local_path)
1493 self.ensure_adb_mode()
1494 logging.info('Successfully installed Android build staged at %s.',
1495 build_url)
1496
1497
Dan Shibe3636a2016-02-14 22:48:01 -08001498 @property
1499 def job_repo_url_attribute(self):
1500 """Get the host attribute name for job_repo_url, which should append the
1501 adb serial.
1502 """
1503 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1504
1505
Dan Shie4e807b2015-12-10 09:04:03 -08001506 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001507 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001508 """Install the DUT.
1509
1510 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001511 pattern: http://$devserver:###/static/$build. If build_url is
1512 set to None, the code may try _parser.options.image to do the
1513 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001514 @param build_local_path: The path to a local directory that contains the
1515 image files needed to provision the device.
1516 @param wipe: If true, userdata will be wiped before flashing.
1517 @param flash_all: If True, all img files found in img_path will be
1518 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001519
Dan Shibe3636a2016-02-14 22:48:01 -08001520 @returns A tuple of (image_name, host_attributes).
1521 image_name is the name of image installed, e.g.,
1522 git_mnc-release/shamu-userdebug/1234
1523 host_attributes is a dictionary of (attribute, value), which
1524 can be saved to afe_host_attributes table in database. This
1525 method returns a dictionary with a single entry of
1526 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1527 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001528 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001529 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001530 if not build_url and self._parser.options.image:
1531 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001532 self._parser.options.image, os_type=os_type)
1533 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001534 self.install_android(
1535 build_url=build_url, build_local_path=build_local_path,
1536 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001537 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001538 self.install_brillo(
1539 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001540 else:
1541 raise error.InstallError(
1542 'Installation of os type %s is not supported.' %
1543 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001544 return (build_url.split('static/')[-1],
1545 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001546
1547
1548 def list_files_glob(self, path_glob):
1549 """Get a list of files on the device given glob pattern path.
1550
1551 @param path_glob: The path glob that we want to return the list of
1552 files that match the glob. Relative paths will not work as
1553 expected. Supply an absolute path to get the list of files
1554 you're hoping for.
1555
1556 @returns List of files that match the path_glob.
1557 """
1558 # This is just in case path_glob has no path separator.
1559 base_path = os.path.dirname(path_glob) or '.'
1560 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001561 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001562 if result.exit_status != 0:
1563 return []
1564 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001565
1566
Dan Shic716ac62016-05-24 16:47:57 -07001567 @retry.retry(error.AutoservRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
Dan Shida995002016-04-25 23:12:58 -07001568 def install_apk(self, apk, force_reinstall=True):
Kevin Cheng31355942016-01-05 14:23:35 -08001569 """Install the specified apk.
1570
1571 This will install the apk and override it if it's already installed and
1572 will also allow for downgraded apks.
1573
1574 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001575 @param force_reinstall: True to reinstall the apk even if it's already
Dan Shida995002016-04-25 23:12:58 -07001576 installed. Default is set to True.
Dan Shidb0366c2016-02-19 10:36:18 -08001577
1578 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001579 """
Dan Shic716ac62016-05-24 16:47:57 -07001580 try:
1581 client_utils.poll_for_condition(
1582 lambda: self.run('pm list packages',
1583 ignore_status=True).exit_status == 0,
1584 timeout=120)
1585 client_utils.poll_for_condition(
1586 lambda: self.run('service list | grep mount',
1587 ignore_status=True).exit_status == 0,
1588 timeout=120)
1589 return self.adb_run('install %s -d %s' %
1590 ('-r' if force_reinstall else '', apk))
1591 except error.AutoservRunError:
1592 self.reboot()
1593 raise
Dan Shidb0366c2016-02-19 10:36:18 -08001594
1595
1596 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1597 def _confirm_apk_installed(self, package_name):
1598 """Confirm if apk is already installed with the given name.
1599
1600 `pm list packages` command is not reliable some time. The retry helps to
1601 reduce the chance of false negative.
1602
1603 @param package_name: Name of the package, e.g., com.android.phone.
1604
1605 @raise AutoservRunError: If the package is not found or pm list command
1606 failed for any reason.
1607 """
1608 name = 'package:%s' % package_name
1609 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1610
1611
1612 def is_apk_installed(self, package_name):
1613 """Check if apk is already installed with the given name.
1614
1615 @param package_name: Name of the package, e.g., com.android.phone.
1616
1617 @return: True if package is installed. False otherwise.
1618 """
1619 try:
1620 self._confirm_apk_installed(package_name)
1621 return True
1622 except:
1623 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001624
1625
1626 def get_attributes_to_clear_before_provision(self):
1627 """Get a list of attributes to be cleared before machine_install starts.
1628 """
1629 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001630
1631
1632 def get_labels(self):
1633 """Return a list of the labels gathered from the devices connected.
1634
1635 @return: A list of strings that denote the labels from all the devices
1636 connected.
1637 """
1638 return self.labels.get_labels(self)
1639
1640
1641 def update_labels(self):
1642 """Update the labels for this testbed."""
1643 self.labels.update_labels(self)
Dan Shi6450e142016-03-11 11:52:20 -08001644
1645
1646 def stage_server_side_package(self, image=None):
1647 """Stage autotest server-side package on devserver.
1648
1649 @param image: A build name, e.g., git_mnc_dev/shamu-eng/123
1650
1651 @return: A url to the autotest server-side package. Return None if
1652 server-side package is not supported.
1653 @raise: error.AutoservError if fail to locate the build to test with.
1654 """
Dan Shid37736b2016-07-06 15:10:29 -07001655 # If enable_drone_in_restricted_subnet is False, do not set hostname
1656 # in devserver.resolve call, so a devserver in non-restricted subnet
1657 # is picked to stage autotest server package for drone to download.
1658 hostname = self.hostname
1659 if not utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1660 hostname = None
Dan Shi6450e142016-03-11 11:52:20 -08001661 if image:
Dan Shid37736b2016-07-06 15:10:29 -07001662 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001663 else:
1664 job_repo_url = afe_utils.get_host_attribute(
1665 self, self.job_repo_url_attribute)
1666 if job_repo_url:
1667 devserver_url, image = (
1668 tools.get_devserver_build_from_package_url(
1669 job_repo_url, True))
Dan Shid37736b2016-07-06 15:10:29 -07001670 # If enable_drone_in_restricted_subnet is True, use the
1671 # existing devserver. Otherwise, resolve a new one in
1672 # non-restricted subnet.
1673 if utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1674 ds = dev_server.AndroidBuildServer(devserver_url)
1675 else:
1676 ds = dev_server.AndroidBuildServer.resolve(image)
Dan Shi6450e142016-03-11 11:52:20 -08001677 else:
1678 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
1679 if not labels:
1680 raise error.AutoservError(
1681 'Failed to stage server-side package. The host has '
1682 'no job_report_url attribute or version label.')
Kevin Cheng84a71ba2016-07-14 11:03:57 -07001683 image = labels[0][len(self.VERSION_PREFIX + ':'):]
Dan Shid37736b2016-07-06 15:10:29 -07001684 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001685
1686 branch, target, build_id = utils.parse_launch_control_build(image)
1687 build_target, _ = utils.parse_launch_control_target(target)
1688
1689 # For any build older than MIN_VERSION_SUPPORT_SSP, server side
1690 # packaging is not supported.
1691 try:
1692 if int(build_id) < self.MIN_VERSION_SUPPORT_SSP:
1693 logging.warn('Build %s is older than %s. Server side packaging '
1694 'is disabled.', image,
1695 self.MIN_VERSION_SUPPORT_SSP)
1696 return None
1697 except ValueError:
1698 logging.warn('Failed to compare build id in %s with the minimum '
1699 'version that supports server side packaging. Server '
1700 'side packaging is disabled.', image)
1701 return None
1702
1703 ds.stage_artifacts(target, build_id, branch,
1704 artifacts=['autotest_server_package'])
1705 autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
1706 {'build_target': build_target,
1707 'build_id': build_id})
1708 return '%s/static/%s/%s' % (ds.url(), image,
1709 autotest_server_package_name)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07001710
1711
1712 def _sync_time(self):
1713 """Approximate synchronization of time between host and ADB device.
1714
1715 This sets the ADB/Android device's clock to approximately the same
1716 time as the Autotest host for the purposes of comparing Android system
1717 logs such as logcat to logs from the Autotest host system.
1718 """
1719 command = 'date '
1720 sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
1721 if sdk_version < 23:
1722 # Android L and earlier use this format: date -s (format).
1723 command += ('-s %s' %
1724 datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
1725 else:
1726 # Android M and later use this format: date (format).
1727 command += datetime.datetime.now().strftime('%m%d%H%M%Y.%S')
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -07001728 self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1729 ignore_timeout=True)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001730
1731
1732 def _enable_native_crash_logging(self):
1733 """Enable native (non-Java) crash logging.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001734 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001735 if self.get_os_type() == OS_TYPE_BRILLO:
1736 self._enable_brillo_native_crash_logging()
1737 elif self.get_os_type() == OS_TYPE_ANDROID:
1738 self._enable_android_native_crash_logging()
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001739
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001740
1741 def _enable_brillo_native_crash_logging(self):
1742 """Enables native crash logging for a Brillo DUT.
1743 """
Bryan Lewandowski8c96bb22016-07-19 12:56:03 -07001744 try:
1745 self.run('touch /data/misc/metrics/enabled',
1746 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1747 ignore_timeout=True)
1748 # If running, crash_sender will delete crash files every hour.
1749 self.run('stop crash_sender',
1750 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1751 ignore_timeout=True)
1752 except error.AutoservRunError as e:
1753 logging.warn(e)
1754 logging.warn('Failed to enable Brillo native crash logging.')
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001755
1756
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001757 def _enable_android_native_crash_logging(self):
1758 """Enables native crash logging for an Android DUT.
1759 """
1760 # debuggerd should be enabled by default on Android.
1761 result = self.run('pgrep debuggerd',
1762 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1763 ignore_timeout=True, ignore_status=True)
1764 if not result or result.exit_status != 0:
1765 logging.debug('Unable to confirm that debuggerd is running.')
1766
1767
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001768 def _collect_crash_logs(self):
1769 """Copies crash log files from the DUT to the drone.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001770 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001771 if self.get_os_type() == OS_TYPE_BRILLO:
1772 self._collect_crash_logs_dut(BRILLO_NATIVE_CRASH_LOG_DIR)
1773 elif self.get_os_type() == OS_TYPE_ANDROID:
1774 self._collect_crash_logs_dut(ANDROID_TOMBSTONE_CRASH_LOG_DIR)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001775
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001776
1777 def _collect_crash_logs_dut(self, log_directory):
1778 """Copies native crash logs from the Android/Brillo DUT to the drone.
1779
1780 @param log_directory: absolute path of the directory on the DUT where
1781 log files are stored.
1782 """
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001783 files = None
1784 try:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001785 result = self.run('find %s -maxdepth 1 -type f' % log_directory,
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001786 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS)
1787 files = result.stdout.strip().split()
1788 except (error.AutotestHostRunError, error.AutoservRunError,
1789 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001790 logging.debug('Unable to call find %s, unable to find crash logs',
1791 log_directory)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001792 if not files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001793 logging.debug('There are no crash logs on the DUT.')
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001794 return
1795
1796 crash_dir = os.path.join(self.job.resultdir, 'crash')
1797 try:
1798 os.mkdir(crash_dir)
1799 except OSError as e:
1800 if e.errno != errno.EEXIST:
1801 raise e
1802
1803 for f in files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001804 logging.debug('DUT native crash file produced: %s', f)
1805 dest = os.path.join(crash_dir, os.path.basename(f))
1806 self.get_file(source=f, dest=dest)