blob: 7e2799ca0929bd45fbcd7fbc8a561ea9ab347f10 [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,
Justin Giorgiea3de262016-08-08 15:28:57 -0700594 warning_timer=None, old_boot_id=None, command=ADB_CMD,
595 boot_id=None):
596 """Wait till the host goes down.
597
598 Return when the host is down (not accessible via the command) OR when
599 the device's boot_id changes (if a boot_id was provided).
Simran Basi431010f2013-09-04 10:42:41 -0700600
601 Overrides wait_down from AbstractSSHHost.
602
603 @param timeout: Time in seconds to wait for the host to go down.
604 @param warning_timer: Time limit in seconds that will generate
605 a warning if the host is not down yet.
606 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700607 @param old_boot_id: Not applicable for adb_host.
608 @param command: `adb`, test if the device can be accessed by adb
609 command, or `fastboot`, test if the device can be accessed by
610 fastboot command. Default is set to `adb`.
Justin Giorgiea3de262016-08-08 15:28:57 -0700611 @param boot_id: UUID of previous boot (consider the device down when the
612 boot_id changes from this value). Ignored if None.
Simran Basi431010f2013-09-04 10:42:41 -0700613
614 @returns True if the device goes down before the timeout, False
615 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700616 """
617 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
618 delay_sec=1)
619 def _wait_down():
Justin Giorgiea3de262016-08-08 15:28:57 -0700620 up = self.is_up(command=command)
621 if not up:
622 return True
623 if boot_id:
624 try:
625 new_boot_id = self.get_boot_id()
626 if new_boot_id != boot_id:
627 return True
628 except (error.AutotestHostRunError, error.AutoservHostError):
629 pass
630 raise error.TimeoutException('Device is still up.')
Simran Basi431010f2013-09-04 10:42:41 -0700631
632 try:
633 _wait_down()
634 logging.debug('Host %s is now down', self.hostname)
635 return True
636 except error.TimeoutException:
637 logging.debug('Host %s is still up after waiting %d seconds',
638 self.hostname, timeout)
639 return False
640
641
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700642 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700643 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700644
645 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700646 """
647 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700648 # the test station we are running ADB on.
Justin Giorgiea3de262016-08-08 15:28:57 -0700649 boot_id = self.get_boot_id()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700650 self.adb_run('reboot', timeout=10, ignore_timeout=True)
Justin Giorgiea3de262016-08-08 15:28:57 -0700651 if not self.wait_down(boot_id=boot_id):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700652 raise error.AutoservRebootError(
653 'ADB Device is still up after reboot')
654 if not self.wait_up():
655 raise error.AutoservRebootError(
656 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800657 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800658
659
Alexandru Branciog969ff7c2016-03-30 14:07:15 +0300660 def fastboot_reboot(self):
661 """Do a fastboot reboot to go back to adb.
662
663 @raises AutoservRebootError if reboot failed.
664 """
665 self.fastboot_run('reboot')
666 if not self.wait_down(command=FASTBOOT_CMD):
667 raise error.AutoservRebootError(
668 'Device is still in fastboot mode after reboot')
669 if not self.wait_up():
670 raise error.AutoservRebootError(
671 'Device failed to boot to adb after fastboot reboot.')
672 self._reset_adbd_connection()
673
674
Ralph Nathanb45eb672015-11-18 20:04:39 -0800675 def remount(self):
676 """Remounts paritions on the device read-write.
677
678 Specifically, the /system, /vendor (if present) and /oem (if present)
679 partitions on the device are remounted read-write.
680 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800681 self.adb_run('remount')
682
683
Kevin Cheng549beb42015-11-18 11:42:25 -0800684 @staticmethod
685 def parse_device_serials(devices_output):
686 """Return a list of parsed serials from the output.
687
688 @param devices_output: Output from either an adb or fastboot command.
689
690 @returns List of device serials
691 """
692 devices = []
693 for line in devices_output.splitlines():
694 match = re.search(DEVICE_FINDER_REGEX, line)
695 if match:
696 serial = match.group('SERIAL')
697 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
698 serial = DEVICE_NO_SERIAL_TAG
699 logging.debug('Found Device: %s', serial)
700 devices.append(serial)
701 return devices
702
703
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700704 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700705 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700706
707 @params use_adb: True to get adb accessible devices. Set to False to
708 get fastboot accessible devices.
709
Kevin Chengd19e6c62015-10-28 16:39:39 -0700710 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700711 """
712 if use_adb:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300713 result = self.adb_run('devices').stdout
714 if self.adb_serial and self.adb_serial not in result:
715 self._connect_over_tcpip_as_needed()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700716 else:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300717 result = self.fastboot_run('devices').stdout
718 if (self.fastboot_serial and
719 self.fastboot_serial not in result):
720 # fastboot devices won't list the devices using TCP
721 try:
722 if 'product' in self.fastboot_run('getvar product',
723 timeout=2).stderr:
724 result += '\n%s\tfastboot' % self.fastboot_serial
Kevin Chengcfcb2cf2016-04-13 10:04:36 -0700725 # The main reason we do a general Exception catch here instead
726 # of setting ignore_timeout/status to True is because even when
727 # the fastboot process has been nuked, it still stays around and
728 # so bgjob wants to warn us of this and tries to read the
729 # /proc/<pid>/stack file which then promptly returns an
730 # 'Operation not permitted' error since we're running as moblab
731 # and we don't have permission to read those files.
732 except Exception:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300733 pass
734 return self.parse_device_serials(result)
Simran Basi431010f2013-09-04 10:42:41 -0700735
736
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700737 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700738 """Get a list of devices currently attached to the test station and
739 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700740 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800741 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700742 raise error.AutoservError(
743 'Not given ADB serial but multiple devices detected')
744 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700745
746
747 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700748 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700749 accessible by fastboot command.
750 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700751 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800752 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700753 raise error.AutoservError(
754 'Not given fastboot serial but multiple devices detected')
755 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700756
757
758 def is_up(self, timeout=0, command=ADB_CMD):
759 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700760
761 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700762 @param command: `adb`, the device can be accessed by adb command,
763 or `fastboot`, the device can be accessed by fastboot command.
764 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700765
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700766 @returns True if the device is detectable by given command, False
767 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700768
769 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700770 if command == ADB_CMD:
771 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800772 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800773 # ADB has a device state, if the device is not online, no
774 # subsequent ADB command will complete.
Dan Shi6450e142016-03-11 11:52:20 -0800775 # DUT with single device connected may not have adb_serial set.
776 # Therefore, skip checking if serial is in the list of adb devices
777 # if self.adb_serial is not set.
778 if (serial and serial not in devices) or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800779 logging.debug('Waiting for device to enter the ready state.')
780 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700781 elif command == FASTBOOT_CMD:
782 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800783 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700784 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700785 raise NotImplementedError('Mode %s is not supported' % command)
786
787 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700788
789
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700790 def stop_loggers(self):
791 """Inherited stop_loggers function.
792
793 Calls parent function and captures logcat, since the end of the run
794 is logically the end/stop of the logcat log.
795 """
796 super(ADBHost, self).stop_loggers()
797 # Record logcat log to a temporary file on the teststation.
798 tmp_dir = self.teststation.get_tmp_dir()
Simran Basi242f8de2016-06-08 14:23:43 -0700799 logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
800 teststation_filename = os.path.join(tmp_dir, logcat_filename)
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700801 try:
802 self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
803 timeout=20)
Simran Basid6b49792016-06-07 17:22:03 -0700804 except (error.AutotestHostRunError, error.AutoservRunError,
805 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700806 return
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700807 # Copy-back the log to the drone's results directory.
Simran Basi242f8de2016-06-08 14:23:43 -0700808 results_logcat_filename = os.path.join(self.job.resultdir,
809 logcat_filename)
810 self.teststation.get_file(teststation_filename,
811 results_logcat_filename)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700812 try:
813 self.teststation.run('rm -rf %s' % tmp_dir)
814 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
815 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
816
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -0700817 self._collect_crash_logs()
818
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700819
Simran Basi431010f2013-09-04 10:42:41 -0700820 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700821 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700822
823 Called as the test ends. Will return the device to USB mode and kill
824 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700825 """
Christopher Wiley08849d52013-11-22 08:57:58 -0800826 # TODO(sbasi) Originally, we would kill the server after each test to
827 # reduce the opportunity for bad server state to hang around.
828 # Unfortunately, there is a period of time after each kill during which
829 # the Android device becomes unusable, and if we start the next test
830 # too quickly, we'll get an error complaining about no ADB device
831 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700832 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800833 # |close| the associated teststation as well.
834 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700835 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700836
837
838 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700839 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700840
841 @param message String message to log into syslog
842 @param tag String tag prefix for syslog
843
844 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700845 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700846
847
848 def get_autodir(self):
849 """Return the directory to install autotest for client side tests."""
850 return '/data/autotest'
851
Kevin Cheng018db352015-09-20 02:22:08 -0700852
Kris Rambishde8f9d12015-12-16 12:42:41 -0800853 def is_device_ready(self):
854 """Return the if the device is ready for ADB commands."""
Dan Shi7075f552016-04-21 15:42:41 -0700855 try:
856 # Retry to avoid possible flakes.
857 is_ready = client_utils.poll_for_condition(
858 lambda: self.adb_run('get-state').stdout.strip() == 'device',
859 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
860 desc='Waiting for device state to be `device`')
861 except client_utils.TimeoutError:
862 is_ready = False
863
864 logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
865 return is_ready
Kris Rambishde8f9d12015-12-16 12:42:41 -0800866
867
Kevin Chengd19e6c62015-10-28 16:39:39 -0700868 def verify_connectivity(self):
869 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800870 if not self.is_device_ready():
871 raise error.AutoservHostError('device state is not in the '
872 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700873
874
Simran Basid3ba3fb2015-09-11 14:35:07 -0700875 def verify_software(self):
876 """Verify working software on an adb_host.
877
Simran Basi38f7ddf2015-09-18 12:25:03 -0700878 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700879 """
Dan Shiab999722015-12-04 14:27:08 -0800880 # Check if adb and fastboot are present.
881 self.teststation.run('which adb')
882 self.teststation.run('which fastboot')
883 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700884
Dan Shi626d5412016-05-16 16:05:13 -0700885 # Apply checks only for Android device.
Dan Shi1e2a98a2016-05-18 12:08:08 -0700886 if self.get_os_type() == OS_TYPE_ANDROID:
Dan Shi626d5412016-05-16 16:05:13 -0700887 # Make sure ro.boot.hardware and ro.build.product match.
Dan Shi8c51bda2016-05-26 12:21:02 -0700888 hardware = self._run_output_with_retry('getprop ro.boot.hardware')
889 product = self._run_output_with_retry('getprop ro.build.product')
Dan Shi1e2a98a2016-05-18 12:08:08 -0700890 if hardware != product:
891 raise error.AutoservHostError('ro.boot.hardware: %s does not '
892 'match to ro.build.product: %s' %
893 (hardware, product))
894
Kevin Cheng018db352015-09-20 02:22:08 -0700895
Simran Basid3ba3fb2015-09-11 14:35:07 -0700896 def verify_job_repo_url(self, tag=''):
897 """Make sure job_repo_url of this host is valid.
898
Simran Basi38f7ddf2015-09-18 12:25:03 -0700899 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700900
901 @param tag: The tag from the server job, in the format
902 <job_id>-<user>/<hostname>, or <hostless> for a server job.
903 """
904 return
Kevin Cheng018db352015-09-20 02:22:08 -0700905
906
Simran Basibeb2bb22016-02-03 15:25:48 -0800907 def repair(self):
908 """Attempt to get the DUT to pass `self.verify()`."""
909 try:
910 self.ensure_adb_mode(timeout=30)
911 return
912 except error.AutoservError as e:
913 logging.error(e)
914 logging.debug('Verifying the device is accessible via fastboot.')
915 self.ensure_bootloader_mode()
916 if not self.job.run_test(
917 'provision_AndroidUpdate', host=self, value=None,
918 force=True, repair=True):
919 raise error.AutoservRepairTotalFailure(
920 'Unable to repair the device.')
921
922
Simran Basi1b023762015-09-25 12:12:20 -0700923 def send_file(self, source, dest, delete_dest=False,
924 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700925 """Copy files from the drone to the device.
926
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400927 Just a note, there is the possibility the test station is localhost
928 which makes some of these steps redundant (e.g. creating tmp dir) but
929 that scenario will undoubtedly be a development scenario (test station
930 is also the moblab) and not the typical live test running scenario so
931 the redundancy I think is harmless.
932
Kevin Cheng018db352015-09-20 02:22:08 -0700933 @param source: The file/directory on the drone to send to the device.
934 @param dest: The destination path on the device to copy to.
935 @param delete_dest: A flag set to choose whether or not to delete
936 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700937 @param preserve_symlinks: Controls if symlinks on the source will be
938 copied as such on the destination or
939 transformed into the referenced
940 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700941 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700942 # If we need to preserve symlinks, let's check if the source is a
943 # symlink itself and if so, just create it on the device.
944 if preserve_symlinks:
945 symlink_target = None
946 try:
947 symlink_target = os.readlink(source)
948 except OSError:
949 # Guess it's not a symlink.
950 pass
951
952 if symlink_target is not None:
953 # Once we create the symlink, let's get out of here.
954 self.run('ln -s %s %s' % (symlink_target, dest))
955 return
956
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400957 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700958 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400959 src_path = os.path.join(tmp_dir, os.path.basename(dest))
960 # Now copy the file over to the test station so you can reference the
961 # file in the push command.
962 self.teststation.send_file(source, src_path,
963 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700964
965 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400966 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700967
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700968 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700969
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400970 # Cleanup the test station.
971 try:
972 self.teststation.run('rm -rf %s' % tmp_dir)
973 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
974 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700975
976
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700977 def _get_file_info(self, dest):
978 """Get permission and possible symlink info about file on the device.
979
980 These files are on the device so we only have shell commands (via adb)
981 to get the info we want. We'll use 'ls' to get it all.
982
983 @param dest: File to get info about.
984
985 @returns a dict of the file permissions and symlink.
986 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800987 # Grab file info.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700988 file_info = self.run_output('ls -ld %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700989 symlink = None
990 perms = 0
991 match = re.match(FILE_INFO_REGEX, file_info)
992 if match:
993 # Check if it's a symlink and grab the linked dest if it is.
994 if match.group('TYPE') == 'l':
995 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
996 if symlink_match:
997 symlink = symlink_match.group('SYMLINK')
998
999 # Set the perms.
1000 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
1001 if perm != '-':
1002 perms |= perm_flag
1003
1004 return {'perms': perms,
1005 'symlink': symlink}
1006
1007
Simran Basi1b023762015-09-25 12:12:20 -07001008 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
1009 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -07001010 """Copy files from the device to the drone.
1011
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001012 Just a note, there is the possibility the test station is localhost
1013 which makes some of these steps redundant (e.g. creating tmp dir) but
1014 that scenario will undoubtedly be a development scenario (test station
1015 is also the moblab) and not the typical live test running scenario so
1016 the redundancy I think is harmless.
1017
Kevin Cheng018db352015-09-20 02:22:08 -07001018 @param source: The file/directory on the device to copy back to the
1019 drone.
1020 @param dest: The destination path on the drone to copy to.
1021 @param delete_dest: A flag set to choose whether or not to delete
1022 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -07001023 @param preserve_perm: Tells get_file() to try to preserve the sources
1024 permissions on files and dirs.
1025 @param preserve_symlinks: Try to preserve symlinks instead of
1026 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -07001027 """
David Purselle01548b2016-05-11 10:00:42 -07001028 # Stage the files on the test station under teststation_temp_dir.
1029 teststation_temp_dir = self.teststation.get_tmp_dir()
1030 teststation_dest = os.path.join(teststation_temp_dir,
1031 os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -07001032
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001033 source_info = {}
1034 if preserve_symlinks or preserve_perm:
1035 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -07001036
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001037 # If we want to preserve symlinks, just create it here, otherwise pull
1038 # the file off the device.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001039 #
1040 # TODO(sadmac): Directories containing symlinks won't behave as
1041 # expected.
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001042 if preserve_symlinks and source_info['symlink']:
1043 os.symlink(source_info['symlink'], dest)
1044 else:
David Purselle01548b2016-05-11 10:00:42 -07001045 self.adb_run('pull %s %s' % (source, teststation_temp_dir))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001046
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001047 # Copy over the file from the test station and clean up.
David Purselle01548b2016-05-11 10:00:42 -07001048 self.teststation.get_file(teststation_dest, dest,
1049 delete_dest=delete_dest)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001050 try:
David Purselle01548b2016-05-11 10:00:42 -07001051 self.teststation.run('rm -rf %s' % teststation_temp_dir)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001052 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
David Purselle01548b2016-05-11 10:00:42 -07001053 logging.warn('failed to remove dir %s: %s',
1054 teststation_temp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001055
David Pursell788b1b52016-05-19 09:03:31 -07001056 # Source will be copied under dest if either:
1057 # 1. Source is a directory and doesn't end with /.
1058 # 2. Source is a file and dest is a directory.
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001059 command = '[ -d %s ]' % source
1060 source_is_dir = self.run(command,
David Pursell788b1b52016-05-19 09:03:31 -07001061 ignore_status=True).exit_status == 0
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001062
David Pursell788b1b52016-05-19 09:03:31 -07001063 if ((source_is_dir and not source.endswith(os.sep)) or
1064 (not source_is_dir and os.path.isdir(dest))):
1065 receive_path = os.path.join(dest, os.path.basename(source))
1066 else:
1067 receive_path = dest
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001068
David Pursell788b1b52016-05-19 09:03:31 -07001069 # Set the permissions of the received file/dirs.
1070 if os.path.isdir(receive_path):
1071 for root, _dirs, files in os.walk(receive_path):
1072 def process(rel_path, default_perm):
1073 info = self._get_file_info(os.path.join(source,
1074 rel_path))
1075 if info['perms'] != 0:
1076 target = os.path.join(receive_path, rel_path)
1077 if preserve_perm:
1078 os.chmod(target, info['perms'])
1079 else:
1080 os.chmod(target, default_perm)
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001081
David Pursell788b1b52016-05-19 09:03:31 -07001082 rel_root = os.path.relpath(root, receive_path)
1083 process(rel_root, _DEFAULT_DIR_PERMS)
1084 for f in files:
1085 process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
1086 elif preserve_perm:
1087 os.chmod(receive_path, source_info['perms'])
1088 else:
1089 os.chmod(receive_path, _DEFAULT_FILE_PERMS)
Kevin Cheng018db352015-09-20 02:22:08 -07001090
1091
1092 def get_release_version(self):
1093 """Get the release version from the RELEASE_FILE on the device.
1094
1095 @returns The release string in the RELEASE_FILE.
1096
1097 """
1098 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -07001099
1100
1101 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001102 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001103
Kevin Chengd19e6c62015-10-28 16:39:39 -07001104 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001105
1106 @param parent: Parent directory of the returned tmp dir.
1107
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07001108 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001109 """
Kevin Chengd19e6c62015-10-28 16:39:39 -07001110 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
1111 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001112 if not parent.startswith(TMP_DIR):
1113 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -07001114 self.run('mkdir -p %s' % parent)
1115 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
1116 self.tmp_dirs.append(tmp_dir)
1117 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -07001118
1119
1120 def get_platform(self):
1121 """Determine the correct platform label for this host.
1122
1123 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -07001124 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -07001125
1126 @returns a string representing this host's platform.
1127 """
1128 return 'adb'
1129
1130
Gilad Arnolda76bef02015-09-29 13:55:15 -07001131 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -08001132 """Get the OS type of the DUT, e.g., android or brillo.
1133 """
1134 if not self._os_type:
1135 if self.run_output('getprop ro.product.brand') == 'Brillo':
1136 self._os_type = OS_TYPE_BRILLO
1137 else:
1138 self._os_type = OS_TYPE_ANDROID
1139
1140 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001141
1142
1143 def _forward(self, reverse, args):
1144 """Execute a forwarding command.
1145
1146 @param reverse: Whether this is reverse forwarding (Boolean).
1147 @param args: List of command arguments.
1148 """
1149 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001150 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001151
1152
1153 def add_forwarding(self, src, dst, reverse=False, rebind=True):
1154 """Forward a port between the ADB host and device.
1155
1156 Port specifications are any strings accepted as such by ADB, for
1157 example 'tcp:8080'.
1158
1159 @param src: Port specification to forward from.
1160 @param dst: Port specification to forward to.
1161 @param reverse: Do reverse forwarding from device to host (Boolean).
1162 @param rebind: Allow rebinding an already bound port (Boolean).
1163 """
1164 args = []
1165 if not rebind:
1166 args.append('--no-rebind')
1167 args += [src, dst]
1168 self._forward(reverse, args)
1169
1170
1171 def remove_forwarding(self, src=None, reverse=False):
1172 """Removes forwarding on port.
1173
1174 @param src: Port specification, or None to remove all forwarding.
1175 @param reverse: Whether this is reverse forwarding (Boolean).
1176 """
1177 args = []
1178 if src is None:
1179 args.append('--remove-all')
1180 else:
1181 args += ['--remove', src]
1182 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001183
1184
xixuan6cf6d2f2016-01-29 15:29:00 -08001185 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001186 """
1187 Forwards a port securely through a tunnel process from the server
1188 to the DUT for RPC server connection.
1189 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
1190 to the DUT.
1191
1192 @param port: remote port on the DUT.
1193 @param local_port: local forwarding port.
1194
1195 @return: the tunnel process.
1196 """
1197 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001198 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001199
1200
xixuan6cf6d2f2016-01-29 15:29:00 -08001201 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001202 """
1203 Disconnects a previously forwarded port from the server to the DUT for
1204 RPC server connection.
1205 Remove the previously added 'ADB forward' rule to forward the RPC
1206 packets from the AdbHost to the DUT.
1207
1208 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -08001209 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -07001210 @param port: remote port on the DUT.
1211
1212 """
1213 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001214 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001215
1216
1217 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001218 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001219
1220 @raise: error.AutoservError if the device failed to reboot into
1221 bootloader mode.
1222 """
1223 if self.is_up(command=FASTBOOT_CMD):
1224 return
1225 self.adb_run('reboot bootloader')
1226 if not self.wait_up(command=FASTBOOT_CMD):
1227 raise error.AutoservError(
1228 'The device failed to reboot into bootloader mode.')
1229
1230
Dan Shie4e807b2015-12-10 09:04:03 -08001231 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001232 """Ensure the device is up and can be accessed by adb command.
1233
Dan Shie4e807b2015-12-10 09:04:03 -08001234 @param timeout: Time limit in seconds before returning even if the host
1235 is not up.
1236
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001237 @raise: error.AutoservError if the device failed to reboot into
1238 adb mode.
1239 """
1240 if self.is_up():
1241 return
Dan Shi04980372016-03-22 10:57:47 -07001242 # Ignore timeout error to allow `fastboot reboot` to fail quietly and
1243 # check if the device is in adb mode.
1244 self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
Dan Shie4e807b2015-12-10 09:04:03 -08001245 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001246 raise error.AutoservError(
1247 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -08001248 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -07001249
1250
1251 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -08001252 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001253 """Get the Android build information from the build url.
1254
1255 @param build_url: The url to use for downloading Android artifacts.
1256 pattern: http://$devserver:###/static/branch/target/build_id
1257
Dan Shi6450e142016-03-11 11:52:20 -08001258 @return: A dictionary of build information, including keys:
1259 build_target, branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -08001260 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -07001261 """
Dan Shiab999722015-12-04 14:27:08 -08001262 if not build_url:
1263 raise AndroidInstallError('Need build_url to download image files.')
1264
1265 try:
1266 match = re.match(DEVSERVER_URL_REGEX, build_url)
Dan Shi6450e142016-03-11 11:52:20 -08001267 return {'build_target': match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001268 'branch': match.group('BRANCH'),
Dan Shi6450e142016-03-11 11:52:20 -08001269 'target': ('%s-%s' % (match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001270 match.group('BUILD_TYPE'))),
1271 'build_id': match.group('BUILD_ID')}
1272 except (AttributeError, IndexError, ValueError) as e:
1273 raise AndroidInstallError(
1274 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001275
1276
Dan Shia2872172015-10-31 01:16:51 -07001277 @retry.retry(error.AutoservRunError, timeout_min=10)
Simran Basi7756a0b2016-03-16 13:10:07 -07001278 def download_file(self, build_url, file, dest_dir, unzip=False,
1279 unzip_dest=None):
Dan Shia2872172015-10-31 01:16:51 -07001280 """Download the given file from the build url.
1281
1282 @param build_url: The url to use for downloading Android artifacts.
1283 pattern: http://$devserver:###/static/branch/target/build_id
1284 @param file: Name of the file to be downloaded, e.g., boot.img.
1285 @param dest_dir: Destination folder for the file to be downloaded to.
Simran Basi7756a0b2016-03-16 13:10:07 -07001286 @param unzip: If True, unzip the downloaded file.
1287 @param unzip_dest: Location to unzip the downloaded file to. If not
1288 provided, dest_dir is used.
Dan Shia2872172015-10-31 01:16:51 -07001289 """
Dan Shidb0366c2016-02-19 10:36:18 -08001290 # Append the file name to the url if build_url is linked to the folder
1291 # containing the file.
1292 if not build_url.endswith('/%s' % file):
1293 src_url = os.path.join(build_url, file)
1294 else:
1295 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001296 dest_file = os.path.join(dest_dir, file)
1297 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001298 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Simran Basi7756a0b2016-03-16 13:10:07 -07001299 if unzip:
1300 unzip_dest = unzip_dest or dest_dir
1301 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1302 (dest_dir, file, unzip_dest))
Dan Shia2872172015-10-31 01:16:51 -07001303 except:
1304 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001305 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001306 raise
1307
1308
Dan Shiab999722015-12-04 14:27:08 -08001309 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001310 """Download required image files from the given build_url to a local
1311 directory in the machine runs fastboot command.
1312
1313 @param build_url: The url to use for downloading Android artifacts.
1314 pattern: http://$devserver:###/static/branch/target/build_id
1315
1316 @return: Path to the directory contains image files.
1317 """
Dan Shi08ff1282016-02-18 19:51:16 -08001318 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001319
1320 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001321 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001322
1323 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001324 self.download_file(build_url, zipped_image_file, image_dir,
1325 unzip=True)
Dan Shi49d451f2016-04-19 09:25:01 -07001326 images = android_utils.AndroidImageFiles.get_standalone_images(
1327 build_info['build_target'])
1328 for image_file in images:
Dan Shidb0366c2016-02-19 10:36:18 -08001329 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001330
Dan Shia2872172015-10-31 01:16:51 -07001331 return image_dir
1332 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001333 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001334 raise
1335
1336
Dan Shiab999722015-12-04 14:27:08 -08001337 def stage_brillo_image_files(self, build_url):
1338 """Download required brillo image files from the given build_url to a
1339 local directory in the machine runs fastboot command.
1340
1341 @param build_url: The url to use for downloading Android artifacts.
1342 pattern: http://$devserver:###/static/branch/target/build_id
1343
1344 @return: Path to the directory contains image files.
1345 """
Dan Shi08ff1282016-02-18 19:51:16 -08001346 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001347
1348 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1349 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1350 image_dir = self.teststation.get_tmp_dir()
Dan Shiab999722015-12-04 14:27:08 -08001351
1352 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001353 self.download_file(build_url, zipped_image_file, image_dir,
1354 unzip=True)
1355 self.download_file(build_url, vendor_partitions_file, image_dir,
1356 unzip=True,
1357 unzip_dest=os.path.join(image_dir, 'vendor'))
Dan Shiab999722015-12-04 14:27:08 -08001358 return image_dir
1359 except:
1360 self.teststation.run('rm -rf %s' % image_dir)
1361 raise
1362
1363
Simran Basibeb2bb22016-02-03 15:25:48 -08001364 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001365 """Stage a build on a devserver and return the build_url and devserver.
1366
1367 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001368
Dan Shi225b9042015-11-18 10:25:21 -08001369 @returns a tuple with an update URL like:
1370 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1371 and the devserver instance.
1372 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001373 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001374 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001375 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1376 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001377 build_name = devserver.translate(build_name)
Dan Shi6450e142016-03-11 11:52:20 -08001378 branch, target, build_id = utils.parse_launch_control_build(build_name)
Dan Shi08ff1282016-02-18 19:51:16 -08001379 devserver.trigger_download(target, build_id, branch,
Justin Giorgidd05a942016-07-05 20:53:12 -07001380 os=os_type, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001381 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001382
1383
Dan Shie4e807b2015-12-10 09:04:03 -08001384 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001385 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001386 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001387
1388 Following are the steps used here to provision an android device:
1389 1. If build_local_path is not set, download the image zip file, e.g.,
1390 shamu-img-2284311.zip, unzip it.
1391 2. Run fastboot to install following artifacts:
1392 bootloader, radio, boot, system, vendor(only if exists)
1393
1394 Repair is not supported for Android devices yet.
1395
1396 @param build_url: The url to use for downloading Android artifacts.
1397 pattern: http://$devserver:###/static/$build
1398 @param build_local_path: The path to a local folder that contains the
1399 image files needed to provision the device. Note that the folder
1400 is in the machine running adb command, rather than the drone.
1401 @param wipe: If true, userdata will be wiped before flashing.
1402 @param flash_all: If True, all img files found in img_path will be
1403 flashed. Otherwise, only boot and system are flashed.
1404
1405 @raises AndroidInstallError if any error occurs.
1406 """
Dan Shia2872172015-10-31 01:16:51 -07001407 # If the build is not staged in local server yet, clean up the temp
1408 # folder used to store image files after the provision is completed.
1409 delete_build_folder = bool(not build_local_path)
1410
1411 try:
1412 # Download image files needed for provision to a local directory.
1413 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001414 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001415
1416 # Device needs to be in bootloader mode for flashing.
1417 self.ensure_bootloader_mode()
1418
1419 if wipe:
Dan Shi12a4f662016-05-10 14:49:42 -07001420 self._fastboot_run_with_retry('-w')
Dan Shia2872172015-10-31 01:16:51 -07001421
1422 # Get all *.img file in the build_local_path.
1423 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001424 image_files = self.teststation.run(
1425 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001426 images = dict([(os.path.basename(f), f) for f in image_files])
Dan Shi49d451f2016-04-19 09:25:01 -07001427 build_info = self.get_build_info_from_build_url(build_url)
1428 board = build_info['build_target']
1429 all_images = (
1430 android_utils.AndroidImageFiles.get_standalone_images(board)
1431 + android_utils.AndroidImageFiles.get_zipped_images(board))
1432
1433 # Sort images to be flashed, bootloader needs to be the first one.
1434 bootloader = android_utils.AndroidImageFiles.BOOTLOADER
1435 sorted_images = sorted(
1436 images.items(),
1437 key=lambda pair: 0 if pair[0] == bootloader else 1)
1438 for image, image_file in sorted_images:
1439 if image not in all_images:
Dan Shia2872172015-10-31 01:16:51 -07001440 continue
1441 logging.info('Flashing %s...', image_file)
Dan Shi12a4f662016-05-10 14:49:42 -07001442 self._fastboot_run_with_retry('-S 256M flash %s %s' %
1443 (image[:-4], image_file))
Dan Shi49d451f2016-04-19 09:25:01 -07001444 if image == android_utils.AndroidImageFiles.BOOTLOADER:
Dan Shia2872172015-10-31 01:16:51 -07001445 self.fastboot_run('reboot-bootloader')
1446 self.wait_up(command=FASTBOOT_CMD)
1447 except Exception as e:
1448 logging.error('Install Android build failed with error: %s', e)
1449 # Re-raise the exception with type of AndroidInstallError.
1450 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1451 finally:
1452 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001453 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001454 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1455 DEFAULT_WAIT_UP_TIME_SECONDS)
1456 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001457 logging.info('Successfully installed Android build staged at %s.',
1458 build_url)
1459
1460
Dan Shiab999722015-12-04 14:27:08 -08001461 def install_brillo(self, build_url, build_local_path=None):
1462 """Install the Brillo DUT.
1463
1464 Following are the steps used here to provision an android device:
1465 1. If build_local_path is not set, download the image zip file, e.g.,
1466 dragonboard-img-123456.zip, unzip it. And download the vendor
1467 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1468 unzip it to vendor folder.
1469 2. Run provision_device script to install OS images and vendor
1470 partitions.
1471
1472 @param build_url: The url to use for downloading Android artifacts.
1473 pattern: http://$devserver:###/static/$build
1474 @param build_local_path: The path to a local folder that contains the
1475 image files needed to provision the device. Note that the folder
1476 is in the machine running adb command, rather than the drone.
1477
1478 @raises AndroidInstallError if any error occurs.
1479 """
1480 # If the build is not staged in local server yet, clean up the temp
1481 # folder used to store image files after the provision is completed.
1482 delete_build_folder = bool(not build_local_path)
1483
Dan Shiab999722015-12-04 14:27:08 -08001484 try:
1485 # Download image files needed for provision to a local directory.
1486 if not build_local_path:
1487 build_local_path = self.stage_brillo_image_files(build_url)
1488
1489 # Device needs to be in bootloader mode for flashing.
1490 self.ensure_bootloader_mode()
1491
1492 # Run provision_device command to install image files and vendor
1493 # partitions.
1494 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1495 cmd = (BRILLO_PROVISION_CMD %
1496 {'os_image_dir': build_local_path,
1497 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001498 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001499 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001500 self.teststation.run(cmd)
1501 except Exception as e:
1502 logging.error('Install Brillo build failed with error: %s', e)
1503 # Re-raise the exception with type of AndroidInstallError.
1504 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1505 finally:
1506 if delete_build_folder:
1507 self.teststation.run('rm -rf %s' % build_local_path)
1508 self.ensure_adb_mode()
1509 logging.info('Successfully installed Android build staged at %s.',
1510 build_url)
1511
1512
Dan Shibe3636a2016-02-14 22:48:01 -08001513 @property
1514 def job_repo_url_attribute(self):
1515 """Get the host attribute name for job_repo_url, which should append the
1516 adb serial.
1517 """
1518 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1519
1520
Dan Shie4e807b2015-12-10 09:04:03 -08001521 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001522 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001523 """Install the DUT.
1524
1525 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001526 pattern: http://$devserver:###/static/$build. If build_url is
1527 set to None, the code may try _parser.options.image to do the
1528 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001529 @param build_local_path: The path to a local directory that contains the
1530 image files needed to provision the device.
1531 @param wipe: If true, userdata will be wiped before flashing.
1532 @param flash_all: If True, all img files found in img_path will be
1533 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001534
Dan Shibe3636a2016-02-14 22:48:01 -08001535 @returns A tuple of (image_name, host_attributes).
1536 image_name is the name of image installed, e.g.,
1537 git_mnc-release/shamu-userdebug/1234
1538 host_attributes is a dictionary of (attribute, value), which
1539 can be saved to afe_host_attributes table in database. This
1540 method returns a dictionary with a single entry of
1541 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1542 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001543 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001544 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001545 if not build_url and self._parser.options.image:
1546 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001547 self._parser.options.image, os_type=os_type)
1548 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001549 self.install_android(
1550 build_url=build_url, build_local_path=build_local_path,
1551 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001552 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001553 self.install_brillo(
1554 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001555 else:
1556 raise error.InstallError(
1557 'Installation of os type %s is not supported.' %
1558 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001559 return (build_url.split('static/')[-1],
1560 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001561
1562
1563 def list_files_glob(self, path_glob):
1564 """Get a list of files on the device given glob pattern path.
1565
1566 @param path_glob: The path glob that we want to return the list of
1567 files that match the glob. Relative paths will not work as
1568 expected. Supply an absolute path to get the list of files
1569 you're hoping for.
1570
1571 @returns List of files that match the path_glob.
1572 """
1573 # This is just in case path_glob has no path separator.
1574 base_path = os.path.dirname(path_glob) or '.'
1575 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001576 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001577 if result.exit_status != 0:
1578 return []
1579 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001580
1581
Dan Shic716ac62016-05-24 16:47:57 -07001582 @retry.retry(error.AutoservRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
Dan Shida995002016-04-25 23:12:58 -07001583 def install_apk(self, apk, force_reinstall=True):
Kevin Cheng31355942016-01-05 14:23:35 -08001584 """Install the specified apk.
1585
1586 This will install the apk and override it if it's already installed and
1587 will also allow for downgraded apks.
1588
1589 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001590 @param force_reinstall: True to reinstall the apk even if it's already
Dan Shida995002016-04-25 23:12:58 -07001591 installed. Default is set to True.
Dan Shidb0366c2016-02-19 10:36:18 -08001592
1593 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001594 """
Dan Shic716ac62016-05-24 16:47:57 -07001595 try:
1596 client_utils.poll_for_condition(
1597 lambda: self.run('pm list packages',
1598 ignore_status=True).exit_status == 0,
1599 timeout=120)
1600 client_utils.poll_for_condition(
1601 lambda: self.run('service list | grep mount',
1602 ignore_status=True).exit_status == 0,
1603 timeout=120)
1604 return self.adb_run('install %s -d %s' %
1605 ('-r' if force_reinstall else '', apk))
1606 except error.AutoservRunError:
1607 self.reboot()
1608 raise
Dan Shidb0366c2016-02-19 10:36:18 -08001609
1610
1611 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1612 def _confirm_apk_installed(self, package_name):
1613 """Confirm if apk is already installed with the given name.
1614
1615 `pm list packages` command is not reliable some time. The retry helps to
1616 reduce the chance of false negative.
1617
1618 @param package_name: Name of the package, e.g., com.android.phone.
1619
1620 @raise AutoservRunError: If the package is not found or pm list command
1621 failed for any reason.
1622 """
1623 name = 'package:%s' % package_name
1624 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1625
1626
1627 def is_apk_installed(self, package_name):
1628 """Check if apk is already installed with the given name.
1629
1630 @param package_name: Name of the package, e.g., com.android.phone.
1631
1632 @return: True if package is installed. False otherwise.
1633 """
1634 try:
1635 self._confirm_apk_installed(package_name)
1636 return True
1637 except:
1638 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001639
1640
1641 def get_attributes_to_clear_before_provision(self):
1642 """Get a list of attributes to be cleared before machine_install starts.
1643 """
1644 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001645
1646
1647 def get_labels(self):
1648 """Return a list of the labels gathered from the devices connected.
1649
1650 @return: A list of strings that denote the labels from all the devices
1651 connected.
1652 """
1653 return self.labels.get_labels(self)
1654
1655
1656 def update_labels(self):
1657 """Update the labels for this testbed."""
1658 self.labels.update_labels(self)
Dan Shi6450e142016-03-11 11:52:20 -08001659
1660
1661 def stage_server_side_package(self, image=None):
1662 """Stage autotest server-side package on devserver.
1663
1664 @param image: A build name, e.g., git_mnc_dev/shamu-eng/123
1665
1666 @return: A url to the autotest server-side package. Return None if
1667 server-side package is not supported.
1668 @raise: error.AutoservError if fail to locate the build to test with.
1669 """
Dan Shid37736b2016-07-06 15:10:29 -07001670 # If enable_drone_in_restricted_subnet is False, do not set hostname
1671 # in devserver.resolve call, so a devserver in non-restricted subnet
1672 # is picked to stage autotest server package for drone to download.
1673 hostname = self.hostname
1674 if not utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1675 hostname = None
Dan Shi6450e142016-03-11 11:52:20 -08001676 if image:
Dan Shid37736b2016-07-06 15:10:29 -07001677 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001678 else:
1679 job_repo_url = afe_utils.get_host_attribute(
1680 self, self.job_repo_url_attribute)
1681 if job_repo_url:
1682 devserver_url, image = (
1683 tools.get_devserver_build_from_package_url(
1684 job_repo_url, True))
Dan Shid37736b2016-07-06 15:10:29 -07001685 # If enable_drone_in_restricted_subnet is True, use the
1686 # existing devserver. Otherwise, resolve a new one in
1687 # non-restricted subnet.
1688 if utils.ENABLE_DRONE_IN_RESTRICTED_SUBNET:
1689 ds = dev_server.AndroidBuildServer(devserver_url)
1690 else:
1691 ds = dev_server.AndroidBuildServer.resolve(image)
Dan Shi6450e142016-03-11 11:52:20 -08001692 else:
1693 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
1694 if not labels:
1695 raise error.AutoservError(
1696 'Failed to stage server-side package. The host has '
1697 'no job_report_url attribute or version label.')
Kevin Cheng84a71ba2016-07-14 11:03:57 -07001698 image = labels[0][len(self.VERSION_PREFIX + ':'):]
Dan Shid37736b2016-07-06 15:10:29 -07001699 ds = dev_server.AndroidBuildServer.resolve(image, hostname)
Dan Shi6450e142016-03-11 11:52:20 -08001700
1701 branch, target, build_id = utils.parse_launch_control_build(image)
1702 build_target, _ = utils.parse_launch_control_target(target)
1703
1704 # For any build older than MIN_VERSION_SUPPORT_SSP, server side
1705 # packaging is not supported.
1706 try:
1707 if int(build_id) < self.MIN_VERSION_SUPPORT_SSP:
1708 logging.warn('Build %s is older than %s. Server side packaging '
1709 'is disabled.', image,
1710 self.MIN_VERSION_SUPPORT_SSP)
1711 return None
1712 except ValueError:
1713 logging.warn('Failed to compare build id in %s with the minimum '
1714 'version that supports server side packaging. Server '
1715 'side packaging is disabled.', image)
1716 return None
1717
1718 ds.stage_artifacts(target, build_id, branch,
1719 artifacts=['autotest_server_package'])
1720 autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
1721 {'build_target': build_target,
1722 'build_id': build_id})
1723 return '%s/static/%s/%s' % (ds.url(), image,
1724 autotest_server_package_name)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07001725
1726
1727 def _sync_time(self):
1728 """Approximate synchronization of time between host and ADB device.
1729
1730 This sets the ADB/Android device's clock to approximately the same
1731 time as the Autotest host for the purposes of comparing Android system
1732 logs such as logcat to logs from the Autotest host system.
1733 """
1734 command = 'date '
1735 sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
1736 if sdk_version < 23:
1737 # Android L and earlier use this format: date -s (format).
1738 command += ('-s %s' %
1739 datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
1740 else:
Alex Deymob244ddb2016-07-20 19:51:30 -07001741 # Android M and later use this format: date -u (format).
1742 command += ('-u %s' %
1743 datetime.datetime.utcnow().strftime('%m%d%H%M%Y.%S'))
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -07001744 self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1745 ignore_timeout=True)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001746
1747
1748 def _enable_native_crash_logging(self):
1749 """Enable native (non-Java) crash logging.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001750 """
Ralph Nathan3b758a32016-08-11 17:48:46 -07001751 # TODO(b/30820403): Enable Brillo native crash logging.
1752 # if self.get_os_type() == OS_TYPE_BRILLO:
1753 # self._enable_brillo_native_crash_logging()
1754 if self.get_os_type() == OS_TYPE_ANDROID:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001755 self._enable_android_native_crash_logging()
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001756
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001757
1758 def _enable_brillo_native_crash_logging(self):
1759 """Enables native crash logging for a Brillo DUT.
1760 """
Bryan Lewandowski8c96bb22016-07-19 12:56:03 -07001761 try:
1762 self.run('touch /data/misc/metrics/enabled',
1763 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1764 ignore_timeout=True)
1765 # If running, crash_sender will delete crash files every hour.
1766 self.run('stop crash_sender',
1767 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1768 ignore_timeout=True)
1769 except error.AutoservRunError as e:
1770 logging.warn(e)
1771 logging.warn('Failed to enable Brillo native crash logging.')
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001772
1773
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001774 def _enable_android_native_crash_logging(self):
1775 """Enables native crash logging for an Android DUT.
1776 """
1777 # debuggerd should be enabled by default on Android.
1778 result = self.run('pgrep debuggerd',
1779 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1780 ignore_timeout=True, ignore_status=True)
1781 if not result or result.exit_status != 0:
1782 logging.debug('Unable to confirm that debuggerd is running.')
1783
1784
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001785 def _collect_crash_logs(self):
1786 """Copies crash log files from the DUT to the drone.
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001787 """
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001788 if self.get_os_type() == OS_TYPE_BRILLO:
1789 self._collect_crash_logs_dut(BRILLO_NATIVE_CRASH_LOG_DIR)
1790 elif self.get_os_type() == OS_TYPE_ANDROID:
1791 self._collect_crash_logs_dut(ANDROID_TOMBSTONE_CRASH_LOG_DIR)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001792
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001793
1794 def _collect_crash_logs_dut(self, log_directory):
1795 """Copies native crash logs from the Android/Brillo DUT to the drone.
1796
1797 @param log_directory: absolute path of the directory on the DUT where
1798 log files are stored.
1799 """
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001800 files = None
1801 try:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001802 result = self.run('find %s -maxdepth 1 -type f' % log_directory,
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001803 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS)
1804 files = result.stdout.strip().split()
1805 except (error.AutotestHostRunError, error.AutoservRunError,
1806 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001807 logging.debug('Unable to call find %s, unable to find crash logs',
1808 log_directory)
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001809 if not files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001810 logging.debug('There are no crash logs on the DUT.')
Bryan Lewandowski11f8aed2016-06-29 15:44:40 -07001811 return
1812
1813 crash_dir = os.path.join(self.job.resultdir, 'crash')
1814 try:
1815 os.mkdir(crash_dir)
1816 except OSError as e:
1817 if e.errno != errno.EEXIST:
1818 raise e
1819
1820 for f in files:
Bryan Lewandowski68646b62016-07-12 10:24:57 -07001821 logging.debug('DUT native crash file produced: %s', f)
1822 dest = os.path.join(crash_dir, os.path.basename(f))
1823 self.get_file(source=f, dest=dest)