blob: c13ca9a1b10660a15cd24524b561671545334eb6 [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
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07006import functools
Simran Basi431010f2013-09-04 10:42:41 -07007import logging
Kevin Cheng018db352015-09-20 02:22:08 -07008import os
Simran Basi431010f2013-09-04 10:42:41 -07009import re
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070010import stat
Dan Shia2872172015-10-31 01:16:51 -070011import sys
Simran Basi431010f2013-09-04 10:42:41 -070012import time
13
14import common
15
Simran Basi9c5d3982016-04-01 18:49:44 -070016from autotest_lib.client.bin import utils as client_utils
Dan Shi49d451f2016-04-19 09:25:01 -070017from autotest_lib.client.common_lib import android_utils
Simran Basi431010f2013-09-04 10:42:41 -070018from autotest_lib.client.common_lib import error
Dan Shi6450e142016-03-11 11:52:20 -080019from autotest_lib.client.common_lib import global_config
Dan Shi225b9042015-11-18 10:25:21 -080020from autotest_lib.client.common_lib.cros import dev_server
Simran Basi431010f2013-09-04 10:42:41 -070021from autotest_lib.client.common_lib.cros import retry
Dan Shi6450e142016-03-11 11:52:20 -080022from autotest_lib.server import afe_utils
Dan Shi225b9042015-11-18 10:25:21 -080023from autotest_lib.server import autoserv_parser
Dan Shia2872172015-10-31 01:16:51 -070024from autotest_lib.server import constants as server_constants
Dan Shi225b9042015-11-18 10:25:21 -080025from autotest_lib.server import utils
Simran Basi5ace6f22016-01-06 17:30:44 -080026from autotest_lib.server.cros import provision
Dan Shi6450e142016-03-11 11:52:20 -080027from autotest_lib.server.cros.dynamic_suite import tools
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070028from autotest_lib.server.cros.dynamic_suite import constants
Simran Basi724b8a52013-09-30 11:19:31 -070029from autotest_lib.server.hosts import abstract_ssh
Kevin Chengc6a645a2015-12-18 11:15:10 -080030from autotest_lib.server.hosts import adb_label
31from autotest_lib.server.hosts import base_label
Kevin Cheng85e864a2015-11-30 11:49:34 -080032from autotest_lib.server.hosts import teststation_host
Simran Basi431010f2013-09-04 10:42:41 -070033
34
Dan Shi6450e142016-03-11 11:52:20 -080035CONFIG = global_config.global_config
36
Dan Shi6ea3e1c2015-10-28 15:19:04 -070037ADB_CMD = 'adb'
38FASTBOOT_CMD = 'fastboot'
Simran Basi431010f2013-09-04 10:42:41 -070039SHELL_CMD = 'shell'
Filipe Brandenburger34363392015-08-13 14:57:45 -070040# Some devices have no serial, then `adb serial` has output such as:
41# (no serial number) device
42# ?????????? device
43DEVICE_NO_SERIAL_MSG = '(no serial number)'
44DEVICE_NO_SERIAL_TAG = '<NO_SERIAL>'
Simran Basi431010f2013-09-04 10:42:41 -070045# Regex to find an adb device. Examples:
46# 0146B5580B01801B device
47# 018e0ecb20c97a62 device
48# 172.22.75.141:5555 device
Kevin Cheng224415e2016-04-22 11:32:10 -070049# localhost:22 device
Alexandru Branciogea380fb2016-04-01 16:01:34 +030050DEVICE_FINDER_REGEX = (r'^(?P<SERIAL>([\w-]+)|((tcp:)?' +
51 '\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}([:]5555)?)|' +
Kevin Cheng224415e2016-04-22 11:32:10 -070052 '((tcp:)?localhost([:]22)?)|' +
Filipe Brandenburger34363392015-08-13 14:57:45 -070053 re.escape(DEVICE_NO_SERIAL_MSG) +
Alexandru Branciogea380fb2016-04-01 16:01:34 +030054 r')[ \t]+(?:device|fastboot)')
Simran Basi431010f2013-09-04 10:42:41 -070055CMD_OUTPUT_PREFIX = 'ADB_CMD_OUTPUT'
56CMD_OUTPUT_REGEX = ('(?P<OUTPUT>[\s\S]*)%s:(?P<EXIT_CODE>\d{1,3})' %
57 CMD_OUTPUT_PREFIX)
Kevin Cheng018db352015-09-20 02:22:08 -070058RELEASE_FILE = 'ro.build.version.release'
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070059BOARD_FILE = 'ro.product.device'
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -070060SDK_FILE = 'ro.build.version.sdk'
Simran Basi242f8de2016-06-08 14:23:43 -070061LOGCAT_FILE_FMT = 'logcat_%s.log'
Simran Basi38f7ddf2015-09-18 12:25:03 -070062TMP_DIR = '/data/local/tmp'
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070063# Regex to pull out file type, perms and symlink. Example:
Kevin Chengaaabd0c2015-11-10 16:05:04 -080064# lrwxrwx--- 1 6 root system 2015-09-12 19:21 blah_link -> ./blah
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070065FILE_INFO_REGEX = '^(?P<TYPE>[dl-])(?P<PERMS>[rwx-]{9})'
66FILE_SYMLINK_REGEX = '^.*-> (?P<SYMLINK>.+)'
67# List of the perm stats indexed by the order they are listed in the example
68# supplied above.
69FILE_PERMS_FLAGS = [stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR,
70 stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP,
71 stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH]
Simran Basi431010f2013-09-04 10:42:41 -070072
Dan Shi6ea3e1c2015-10-28 15:19:04 -070073# Default maximum number of seconds to wait for a device to be down.
74DEFAULT_WAIT_DOWN_TIME_SECONDS = 10
75# Default maximum number of seconds to wait for a device to be up.
Dan Shie4e807b2015-12-10 09:04:03 -080076DEFAULT_WAIT_UP_TIME_SECONDS = 300
77# Maximum number of seconds to wait for a device to be up after it's wiped.
Dan Shi50a412a2016-01-05 10:52:40 -080078WAIT_UP_AFTER_WIPE_TIME_SECONDS = 1200
Simran Basi431010f2013-09-04 10:42:41 -070079
Dan Shi7075f552016-04-21 15:42:41 -070080# Default timeout for retrying adb/fastboot command.
81DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS = 10
82
Dan Shia2872172015-10-31 01:16:51 -070083OS_TYPE_ANDROID = 'android'
84OS_TYPE_BRILLO = 'brillo'
85
Dan Shie234dea2016-01-20 17:15:17 -080086# Regex to parse build name to get the detailed build information.
Dan Shi6450e142016-03-11 11:52:20 -080087BUILD_REGEX = ('(?P<BRANCH>([^/]+))/(?P<BUILD_TARGET>([^/]+))-'
Dan Shie234dea2016-01-20 17:15:17 -080088 '(?P<BUILD_TYPE>([^/]+))/(?P<BUILD_ID>([^/]+))')
Dan Shia2872172015-10-31 01:16:51 -070089# Regex to parse devserver url to get the detailed build information. Sample
90# url: http://$devserver:8080/static/branch/target/build_id
Dan Shie234dea2016-01-20 17:15:17 -080091DEVSERVER_URL_REGEX = '.*/%s/*' % BUILD_REGEX
Dan Shia2872172015-10-31 01:16:51 -070092
Dan Shi6450e142016-03-11 11:52:20 -080093ANDROID_IMAGE_FILE_FMT = '%(build_target)s-img-%(build_id)s.zip'
Dan Shi49d451f2016-04-19 09:25:01 -070094
Dan Shiab999722015-12-04 14:27:08 -080095BRILLO_VENDOR_PARTITIONS_FILE_FMT = (
Dan Shi6450e142016-03-11 11:52:20 -080096 '%(build_target)s-vendor_partitions-%(build_id)s.zip')
97AUTOTEST_SERVER_PACKAGE_FILE_FMT = (
98 '%(build_target)s-autotest_server_package-%(build_id)s.tar.bz2')
Simran Basi9228a6f2016-03-29 12:03:37 -070099ADB_DEVICE_PREFIXES = ['product:', 'model:', 'device:']
Dan Shia2872172015-10-31 01:16:51 -0700100
Simran Basi9c5d3982016-04-01 18:49:44 -0700101# Map of product names to build target name.
102PRODUCT_TARGET_MAP = {'dragon' : 'ryu',
103 'flo' : 'razor',
104 'flo_lte' : 'razorg',
105 'gm4g_sprout' : 'seed_l8150',
106 'flounder' : 'volantis',
107 'flounder_lte' : 'volantisg'}
108
Dan Shiab999722015-12-04 14:27:08 -0800109# Command to provision a Brillo device.
110# os_image_dir: The full path of the directory that contains all the Android image
111# files (from the image zip file).
112# vendor_partition_dir: The full path of the directory that contains all the
113# Brillo vendor partitions, and provision-device script.
114BRILLO_PROVISION_CMD = (
Simran Basi7e52c622016-01-05 15:43:51 -0800115 'sudo ANDROID_PROVISION_OS_PARTITIONS=%(os_image_dir)s '
Dan Shiab999722015-12-04 14:27:08 -0800116 'ANDROID_PROVISION_VENDOR_PARTITIONS=%(vendor_partition_dir)s '
117 '%(vendor_partition_dir)s/provision-device')
Dan Shia2872172015-10-31 01:16:51 -0700118
Dan Shi12a4f662016-05-10 14:49:42 -0700119# Default timeout in minutes for fastboot commands.
120DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN = 10
121
David Purselle01548b2016-05-11 10:00:42 -0700122# Default permissions for files/dirs copied from the device.
123_DEFAULT_FILE_PERMS = 0o600
124_DEFAULT_DIR_PERMS = 0o700
125
Dan Shi626d5412016-05-16 16:05:13 -0700126# Constants for getprop return value for a given property.
127PROPERTY_VALUE_TRUE = '1'
128
Dan Shic716ac62016-05-24 16:47:57 -0700129# Timeout used for retrying installing apk. After reinstall apk failed, we try
130# to reboot the device and try again.
131APK_INSTALL_TIMEOUT_MIN = 5
132
Dan Shia2872172015-10-31 01:16:51 -0700133class AndroidInstallError(error.InstallError):
134 """Generic error for Android installation related exceptions."""
135
136
Simran Basi724b8a52013-09-30 11:19:31 -0700137class ADBHost(abstract_ssh.AbstractSSHHost):
Simran Basi431010f2013-09-04 10:42:41 -0700138 """This class represents a host running an ADB server."""
139
Simran Basi5ace6f22016-01-06 17:30:44 -0800140 VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700141 _LABEL_FUNCTIONS = []
142 _DETECTABLE_LABELS = []
143 label_decorator = functools.partial(utils.add_label_detector,
144 _LABEL_FUNCTIONS,
145 _DETECTABLE_LABELS)
146
Dan Shi225b9042015-11-18 10:25:21 -0800147 _parser = autoserv_parser.autoserv_parser
Simran Basi431010f2013-09-04 10:42:41 -0700148
Dan Shi6450e142016-03-11 11:52:20 -0800149 # Minimum build id that supports server side packaging. Older builds may
150 # not have server side package built or with Autotest code change to support
151 # server-side packaging.
152 MIN_VERSION_SUPPORT_SSP = CONFIG.get_config_value(
153 'AUTOSERV', 'min_launch_control_build_id_support_ssp', type=int)
154
beeps46dadc92013-11-07 14:07:10 -0800155 @staticmethod
156 def check_host(host, timeout=10):
157 """
158 Check if the given host is an adb host.
159
Simran Basi14622bb2015-11-25 13:23:40 -0800160 If SSH connectivity can't be established, check_host will try to use
161 user 'adb' as well. If SSH connectivity still can't be established
162 then the original SSH user is restored.
163
beeps46dadc92013-11-07 14:07:10 -0800164 @param host: An ssh host representing a device.
165 @param timeout: The timeout for the run command.
166
167
168 @return: True if the host device has adb.
169
170 @raises AutoservRunError: If the command failed.
171 @raises AutoservSSHTimeout: Ssh connection has timed out.
172 """
Dan Shi64e130f2015-12-16 14:45:44 -0800173 # host object may not have user attribute if it's a LocalHost object.
174 current_user = host.user if hasattr(host, 'user') else None
beeps46dadc92013-11-07 14:07:10 -0800175 try:
Simran Basi14622bb2015-11-25 13:23:40 -0800176 if not (host.hostname == 'localhost' or
177 host.verify_ssh_user_access()):
Simran Basi1621c632015-10-14 12:22:23 -0700178 host.user = 'adb'
Simran Basi933c8af2015-04-29 14:05:07 -0700179 result = host.run(
Dan Shia2872172015-10-31 01:16:51 -0700180 'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
Simran Basi933c8af2015-04-29 14:05:07 -0700181 timeout=timeout)
beeps46dadc92013-11-07 14:07:10 -0800182 except (error.AutoservRunError, error.AutoservSSHTimeout):
Dan Shi64e130f2015-12-16 14:45:44 -0800183 if current_user is not None:
184 host.user = current_user
beeps46dadc92013-11-07 14:07:10 -0800185 return False
186 return result.exit_status == 0
187
188
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700189 # TODO(garnold) Remove the 'serials' argument once all clients are made to
190 # not use it.
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700191 def _initialize(self, hostname='localhost', serials=None,
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700192 adb_serial=None, fastboot_serial=None,
Simran Basi9228a6f2016-03-29 12:03:37 -0700193 teststation=None, *args, **dargs):
Simran Basi431010f2013-09-04 10:42:41 -0700194 """Initialize an ADB Host.
195
196 This will create an ADB Host. Hostname should always refer to the
Kevin Chengd19e6c62015-10-28 16:39:39 -0700197 test station connected to an Android DUT. This will be the DUT
198 to test with. If there are multiple, serial must be specified or an
Simran Basi9228a6f2016-03-29 12:03:37 -0700199 exception will be raised.
Simran Basi431010f2013-09-04 10:42:41 -0700200
201 @param hostname: Hostname of the machine running ADB.
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700202 @param serials: DEPRECATED (to be removed)
203 @param adb_serial: An ADB device serial. If None, assume a single
204 device is attached (and fail otherwise).
205 @param fastboot_serial: A fastboot device serial. If None, defaults to
206 the ADB serial (or assumes a single device if
207 the latter is None).
Kevin Cheng549beb42015-11-18 11:42:25 -0800208 @param teststation: The teststation object ADBHost should use.
Simran Basi431010f2013-09-04 10:42:41 -0700209 """
Simran Basi1bf60eb2015-12-01 16:39:29 -0800210 # Sets up the is_client_install_supported field.
211 super(ADBHost, self)._initialize(hostname=hostname,
212 is_client_install_supported=False,
213 *args, **dargs)
Kevin Cheng85e864a2015-11-30 11:49:34 -0800214
Kevin Chengd19e6c62015-10-28 16:39:39 -0700215 self.tmp_dirs = []
Kevin Chengc6a645a2015-12-18 11:15:10 -0800216 self.labels = base_label.LabelRetriever(adb_label.ADB_LABELS)
Simran Basi1bf60eb2015-12-01 16:39:29 -0800217 # TODO (sbasi/kevcheng): Once the teststation host is committed,
218 # refactor the serial retrieval.
219 adb_serial = adb_serial or self.host_attributes.get('serials', None)
Simran Basi973bf712016-05-26 13:41:34 -0700220 fastboot_serial = fastboot_serial or self.host_attributes.get(
221 'fastboot_serial', None)
Dan Shi50a412a2016-01-05 10:52:40 -0800222 self.adb_serial = adb_serial
Dan Shi3a011ed2016-04-26 12:26:53 -0700223 if adb_serial:
224 adb_prefix = any(adb_serial.startswith(p)
225 for p in ADB_DEVICE_PREFIXES)
226 self.fastboot_serial = (fastboot_serial or
227 ('tcp:%s' % adb_serial.split(':')[0] if
228 ':' in adb_serial and not adb_prefix else adb_serial))
229 self._use_tcpip = ':' in adb_serial and not adb_prefix
230 else:
231 self.fastboot_serial = fastboot_serial or adb_serial
232 self._use_tcpip = False
Kevin Cheng85e864a2015-11-30 11:49:34 -0800233 self.teststation = (teststation if teststation
234 else teststation_host.create_teststationhost(hostname=hostname))
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700235
236 msg ='Initializing ADB device on host: %s' % hostname
Dan Shi50a412a2016-01-05 10:52:40 -0800237 if self.adb_serial:
238 msg += ', ADB serial: %s' % self.adb_serial
239 if self.fastboot_serial:
240 msg += ', fastboot serial: %s' % self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700241 logging.debug(msg)
242
Simran Basibeb2bb22016-02-03 15:25:48 -0800243 # Try resetting the ADB daemon on the device, however if we are
244 # creating the host to do a repair job, the device maybe inaccesible
245 # via ADB.
246 try:
247 self._reset_adbd_connection()
248 except (error.AutotestHostRunError, error.AutoservRunError) as e:
249 logging.error('Unable to reset the device adb daemon connection: '
250 '%s.', e)
Dan Shiab999722015-12-04 14:27:08 -0800251 self._os_type = None
252
Simran Basi431010f2013-09-04 10:42:41 -0700253
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700254 def _connect_over_tcpip_as_needed(self):
255 """Connect to the ADB device over TCP/IP if so configured."""
Simran Basi9228a6f2016-03-29 12:03:37 -0700256 if not self._use_tcpip:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700257 return
258 logging.debug('Connecting to device over TCP/IP')
Simran Basi9228a6f2016-03-29 12:03:37 -0700259 self.adb_run('connect %s' % self.adb_serial)
Simran Basi431010f2013-09-04 10:42:41 -0700260
261
Roshan Pius4d7540c2015-12-16 13:30:32 -0800262 def _restart_adbd_with_root_permissions(self):
263 """Restarts the adb daemon with root permissions."""
Dan Shi922de302016-04-22 15:19:18 -0700264 @retry.retry(error.AutoservRunError, timeout_min=20/60.0, delay_sec=1)
265 def run_adb_root():
266 """Run command `adb root`."""
267 self.adb_run('root')
268
269 # adb command may flake with error "device not found". Retry the root
270 # command to reduce the chance of flake.
271 run_adb_root()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800272 # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
273 time.sleep(1)
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300274 self._connect_over_tcpip_as_needed()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800275 self.adb_run('wait-for-device')
276
277
Simran Basi9228a6f2016-03-29 12:03:37 -0700278 def _set_tcp_port(self):
279 """Ensure the device remains in tcp/ip mode after a reboot."""
280 if not self._use_tcpip:
281 return
282 port = self.adb_serial.split(':')[-1]
283 self.run('setprop persist.adb.tcp.port %s' % port)
284
285
Roshan Pius4d7540c2015-12-16 13:30:32 -0800286 def _reset_adbd_connection(self):
287 """Resets adbd connection to the device after a reboot/initialization"""
Roshan Pius4d7540c2015-12-16 13:30:32 -0800288 self._connect_over_tcpip_as_needed()
Simran Basi9228a6f2016-03-29 12:03:37 -0700289 self._restart_adbd_with_root_permissions()
290 self._set_tcp_port()
Roshan Pius4d7540c2015-12-16 13:30:32 -0800291
292
Kevin Cheng85e864a2015-11-30 11:49:34 -0800293 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800294 def adb_run(self, command, **kwargs):
Simran Basi431010f2013-09-04 10:42:41 -0700295 """Runs an adb command.
296
Kevin Chengd19e6c62015-10-28 16:39:39 -0700297 This command will launch on the test station.
Simran Basi431010f2013-09-04 10:42:41 -0700298
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700299 Refer to _device_run method for docstring for parameters.
300 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800301 return self._device_run(ADB_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700302
303
Kevin Cheng85e864a2015-11-30 11:49:34 -0800304 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800305 def fastboot_run(self, command, **kwargs):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700306 """Runs an fastboot command.
307
Kevin Chengd19e6c62015-10-28 16:39:39 -0700308 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700309
310 Refer to _device_run method for docstring for parameters.
311 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800312 return self._device_run(FASTBOOT_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700313
314
Dan Shi12a4f662016-05-10 14:49:42 -0700315 # pylint: disable=missing-docstring
316 @retry.retry(error.AutoservRunError,
317 timeout_min=DEFAULT_FASTBOOT_RETRY_TIMEOUT_MIN)
318 def _fastboot_run_with_retry(self, command, **kwargs):
319 """Runs an fastboot command with retry.
320
321 This command will launch on the test station.
322
323 Refer to _device_run method for docstring for parameters.
324 """
325 return self.fastboot_run(command, **kwargs)
326
327
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700328 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700329 timeout=3600, ignore_status=False, ignore_timeout=False,
330 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
331 connect_timeout=30, options='', stdin=None, verbose=True,
332 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700333 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700334
Kevin Chengd19e6c62015-10-28 16:39:39 -0700335 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700336
Simran Basi431010f2013-09-04 10:42:41 -0700337 @param command: Command to run.
338 @param shell: If true the command runs in the adb shell otherwise if
339 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700340 reboot with shell=False will call 'adb reboot'. This
341 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700342 @param timeout: Time limit in seconds before attempting to
343 kill the running process. The run() function
344 will take a few seconds longer than 'timeout'
345 to complete if it has to kill the process.
346 @param ignore_status: Do not raise an exception, no matter
347 what the exit code of the command is.
348 @param ignore_timeout: Bool True if command timeouts should be
349 ignored. Will return None on command timeout.
350 @param stdout: Redirect stdout.
351 @param stderr: Redirect stderr.
352 @param connect_timeout: Connection timeout (in seconds)
353 @param options: String with additional ssh command options
354 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700355 @param require_sudo: True to require sudo to run the command. Default is
356 False.
Simran Basi431010f2013-09-04 10:42:41 -0700357 @param args: Sequence of strings to pass as arguments to command by
358 quoting them in " and escaping their contents if
359 necessary.
360
361 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700362 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700363 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800364 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700365 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800366 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700367 else:
368 raise NotImplementedError('Mode %s is not supported' % function)
369
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700370 if function != ADB_CMD and shell:
371 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700372
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700373 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700374
375 if serial:
376 cmd += '-s %s ' % serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700377
Simran Basi431010f2013-09-04 10:42:41 -0700378 if shell:
379 cmd += '%s ' % SHELL_CMD
380 cmd += command
381
Roshan Pius58e5dd32015-10-16 15:16:42 -0700382 if verbose:
383 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700384
Kevin Cheng85e864a2015-11-30 11:49:34 -0800385 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400386 ignore_status=ignore_status,
387 ignore_timeout=ignore_timeout, stdout_tee=stdout,
388 stderr_tee=stderr, options=options, stdin=stdin,
389 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700390
391
Dan Shi8c51bda2016-05-26 12:21:02 -0700392 def _run_output_with_retry(self, cmd):
393 """Call run_output method for the given command with retry.
394
Dan Shi68094122016-06-10 14:29:06 -0700395 adb command can be flaky some time, and the command may fail or return
396 empty string. It may take several retries until a value can be returned.
Dan Shi8c51bda2016-05-26 12:21:02 -0700397
398 @param cmd: The command to run.
399
400 @return: Return value from the command after retry.
401 """
402 try:
403 return client_utils.poll_for_condition(
Dan Shi68094122016-06-10 14:29:06 -0700404 lambda: self.run_output(cmd, ignore_status=True),
Dan Shi8c51bda2016-05-26 12:21:02 -0700405 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
406 sleep_interval=0.5,
407 desc='Get return value for command `%s`' % cmd)
408 except client_utils.TimeoutError:
409 return ''
410
411
Dan Shie234dea2016-01-20 17:15:17 -0800412 def get_board_name(self):
413 """Get the name of the board, e.g., shamu, dragonboard etc.
414 """
Simran Basi9c5d3982016-04-01 18:49:44 -0700415 product = self.run_output('getprop %s' % BOARD_FILE)
416 return PRODUCT_TARGET_MAP.get(product, product)
Dan Shie234dea2016-01-20 17:15:17 -0800417
418
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700419 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700420 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700421 """Determine the correct board label for the device.
422
423 @returns a string representing this device's board.
424 """
Dan Shie234dea2016-01-20 17:15:17 -0800425 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700426 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800427 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700428
429
Christopher Wiley08849d52013-11-22 08:57:58 -0800430 def job_start(self):
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700431 """Overload of parent which intentionally doesn't log certain files.
Dan Shi2d279cf2016-05-27 22:06:10 +0000432
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700433 The parent implementation attempts to log certain Linux files, such as
434 /var/log, which do not exist on Android, thus there is no call to the
435 parent's job_start(). The sync call is made so that logcat logs can be
436 approximately matched to server logs.
Dan Shi2d279cf2016-05-27 22:06:10 +0000437 """
Simran Basid6b49792016-06-07 17:22:03 -0700438 if self.is_up():
439 self._sync_time()
Christopher Wiley08849d52013-11-22 08:57:58 -0800440
441
Simran Basi431010f2013-09-04 10:42:41 -0700442 def run(self, command, timeout=3600, ignore_status=False,
443 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
444 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700445 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700446 """Run a command on the adb device.
447
448 The command given will be ran directly on the adb device; for example
449 'ls' will be ran as: 'abd shell ls'
450
451 @param command: The command line string.
452 @param timeout: Time limit in seconds before attempting to
453 kill the running process. The run() function
454 will take a few seconds longer than 'timeout'
455 to complete if it has to kill the process.
456 @param ignore_status: Do not raise an exception, no matter
457 what the exit code of the command is.
458 @param ignore_timeout: Bool True if command timeouts should be
459 ignored. Will return None on command timeout.
460 @param stdout_tee: Redirect stdout.
461 @param stderr_tee: Redirect stderr.
462 @param connect_timeout: Connection timeout (in seconds).
463 @param options: String with additional ssh command options.
464 @param stdin: Stdin to pass (a string) to the executed command
465 @param args: Sequence of strings to pass as arguments to command by
466 quoting them in " and escaping their contents if
467 necessary.
468
469 @returns A CMDResult object or None if the call timed out and
470 ignore_timeout is True.
471
472 @raises AutoservRunError: If the command failed.
473 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700474 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700475 command = ('"%s; echo %s:\$?"' %
476 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700477 result = self.adb_run(
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700478 command, shell=True, timeout=timeout,
Simran Basi431010f2013-09-04 10:42:41 -0700479 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
480 stdout=stdout_tee, stderr=stderr_tee,
481 connect_timeout=connect_timeout, options=options, stdin=stdin,
Roshan Pius58e5dd32015-10-16 15:16:42 -0700482 verbose=verbose, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700483 if not result:
484 # In case of timeouts.
485 return None
486
487 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
Roshan Pius5ba5d182015-10-28 09:19:41 -0700488 if not parse_output and not ignore_status:
Simran Basi431010f2013-09-04 10:42:41 -0700489 raise error.AutoservRunError(
Roshan Pius5ba5d182015-10-28 09:19:41 -0700490 'Failed to parse the exit code for command: %s' %
491 command, result)
492 elif parse_output:
493 result.stdout = parse_output.group('OUTPUT')
494 result.exit_status = int(parse_output.group('EXIT_CODE'))
495 if result.exit_status != 0 and not ignore_status:
496 raise error.AutoservRunError(command, result)
Simran Basi431010f2013-09-04 10:42:41 -0700497 return result
498
499
Dan Shicf7d2562016-06-16 14:08:23 -0700500 def check_boot_to_adb_complete(self, exception_type=error.TimeoutException):
501 """Check if the device has finished booting and accessible by adb.
502
503 @param exception_type: Type of exception to raise. Default is set to
504 error.TimeoutException for retry.
505
506 @raise exception_type: If the device has not finished booting yet, raise
507 an exception of type `exception_type`.
508 """
509 bootcomplete = self._run_output_with_retry('getprop dev.bootcomplete')
510 if bootcomplete != PROPERTY_VALUE_TRUE:
511 raise exception_type('dev.bootcomplete is %s.' % bootcomplete)
512 if self.get_os_type() == OS_TYPE_ANDROID:
513 boot_completed = self._run_output_with_retry(
514 'getprop sys.boot_completed')
515 if boot_completed != PROPERTY_VALUE_TRUE:
516 raise exception_type('sys.boot_completed is %s.' %
517 boot_completed)
518
519
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700520 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
521 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700522
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700523 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700524
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700525 @param timeout: Time limit in seconds before returning even if the host
526 is not up.
527 @param command: The command used to test if a device is up, i.e.,
528 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700529
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700530 @returns True if the host was found to be up before the timeout expires,
531 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700532 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700533 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
534 delay_sec=1)
535 def _wait_up():
536 if not self.is_up(command=command):
537 raise error.TimeoutException('Device is still down.')
Dan Shicf7d2562016-06-16 14:08:23 -0700538 if command == ADB_CMD:
539 self.check_boot_to_adb_complete()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700540 return True
541
542 try:
543 _wait_up()
544 logging.debug('Host %s is now up, and can be accessed by %s.',
545 self.hostname, command)
546 return True
547 except error.TimeoutException:
548 logging.debug('Host %s is still down after waiting %d seconds',
549 self.hostname, timeout)
550 return False
Simran Basi431010f2013-09-04 10:42:41 -0700551
552
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700553 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
554 warning_timer=None, old_boot_id=None, command=ADB_CMD):
555 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700556
557 Overrides wait_down from AbstractSSHHost.
558
559 @param timeout: Time in seconds to wait for the host to go down.
560 @param warning_timer: Time limit in seconds that will generate
561 a warning if the host is not down yet.
562 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700563 @param old_boot_id: Not applicable for adb_host.
564 @param command: `adb`, test if the device can be accessed by adb
565 command, or `fastboot`, test if the device can be accessed by
566 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700567
568 @returns True if the device goes down before the timeout, False
569 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700570 """
571 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
572 delay_sec=1)
573 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700574 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700575 raise error.TimeoutException('Device is still up.')
576 return True
577
578 try:
579 _wait_down()
580 logging.debug('Host %s is now down', self.hostname)
581 return True
582 except error.TimeoutException:
583 logging.debug('Host %s is still up after waiting %d seconds',
584 self.hostname, timeout)
585 return False
586
587
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700588 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700589 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700590
591 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700592 """
593 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700594 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700595 self.adb_run('reboot', timeout=10, ignore_timeout=True)
596 if not self.wait_down():
597 raise error.AutoservRebootError(
598 'ADB Device is still up after reboot')
599 if not self.wait_up():
600 raise error.AutoservRebootError(
601 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800602 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800603
604
Alexandru Branciog969ff7c2016-03-30 14:07:15 +0300605 def fastboot_reboot(self):
606 """Do a fastboot reboot to go back to adb.
607
608 @raises AutoservRebootError if reboot failed.
609 """
610 self.fastboot_run('reboot')
611 if not self.wait_down(command=FASTBOOT_CMD):
612 raise error.AutoservRebootError(
613 'Device is still in fastboot mode after reboot')
614 if not self.wait_up():
615 raise error.AutoservRebootError(
616 'Device failed to boot to adb after fastboot reboot.')
617 self._reset_adbd_connection()
618
619
Ralph Nathanb45eb672015-11-18 20:04:39 -0800620 def remount(self):
621 """Remounts paritions on the device read-write.
622
623 Specifically, the /system, /vendor (if present) and /oem (if present)
624 partitions on the device are remounted read-write.
625 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800626 self.adb_run('remount')
627
628
Kevin Cheng549beb42015-11-18 11:42:25 -0800629 @staticmethod
630 def parse_device_serials(devices_output):
631 """Return a list of parsed serials from the output.
632
633 @param devices_output: Output from either an adb or fastboot command.
634
635 @returns List of device serials
636 """
637 devices = []
638 for line in devices_output.splitlines():
639 match = re.search(DEVICE_FINDER_REGEX, line)
640 if match:
641 serial = match.group('SERIAL')
642 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
643 serial = DEVICE_NO_SERIAL_TAG
644 logging.debug('Found Device: %s', serial)
645 devices.append(serial)
646 return devices
647
648
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700649 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700650 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700651
652 @params use_adb: True to get adb accessible devices. Set to False to
653 get fastboot accessible devices.
654
Kevin Chengd19e6c62015-10-28 16:39:39 -0700655 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700656 """
657 if use_adb:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300658 result = self.adb_run('devices').stdout
659 if self.adb_serial and self.adb_serial not in result:
660 self._connect_over_tcpip_as_needed()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700661 else:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300662 result = self.fastboot_run('devices').stdout
663 if (self.fastboot_serial and
664 self.fastboot_serial not in result):
665 # fastboot devices won't list the devices using TCP
666 try:
667 if 'product' in self.fastboot_run('getvar product',
668 timeout=2).stderr:
669 result += '\n%s\tfastboot' % self.fastboot_serial
Kevin Chengcfcb2cf2016-04-13 10:04:36 -0700670 # The main reason we do a general Exception catch here instead
671 # of setting ignore_timeout/status to True is because even when
672 # the fastboot process has been nuked, it still stays around and
673 # so bgjob wants to warn us of this and tries to read the
674 # /proc/<pid>/stack file which then promptly returns an
675 # 'Operation not permitted' error since we're running as moblab
676 # and we don't have permission to read those files.
677 except Exception:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300678 pass
679 return self.parse_device_serials(result)
Simran Basi431010f2013-09-04 10:42:41 -0700680
681
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700682 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700683 """Get a list of devices currently attached to the test station and
684 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700685 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800686 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700687 raise error.AutoservError(
688 'Not given ADB serial but multiple devices detected')
689 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700690
691
692 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700693 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700694 accessible by fastboot command.
695 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700696 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800697 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700698 raise error.AutoservError(
699 'Not given fastboot serial but multiple devices detected')
700 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700701
702
703 def is_up(self, timeout=0, command=ADB_CMD):
704 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700705
706 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700707 @param command: `adb`, the device can be accessed by adb command,
708 or `fastboot`, the device can be accessed by fastboot command.
709 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700710
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700711 @returns True if the device is detectable by given command, False
712 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700713
714 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700715 if command == ADB_CMD:
716 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800717 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800718 # ADB has a device state, if the device is not online, no
719 # subsequent ADB command will complete.
Dan Shi6450e142016-03-11 11:52:20 -0800720 # DUT with single device connected may not have adb_serial set.
721 # Therefore, skip checking if serial is in the list of adb devices
722 # if self.adb_serial is not set.
723 if (serial and serial not in devices) or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800724 logging.debug('Waiting for device to enter the ready state.')
725 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700726 elif command == FASTBOOT_CMD:
727 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800728 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700729 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700730 raise NotImplementedError('Mode %s is not supported' % command)
731
732 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700733
734
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700735 def stop_loggers(self):
736 """Inherited stop_loggers function.
737
738 Calls parent function and captures logcat, since the end of the run
739 is logically the end/stop of the logcat log.
740 """
741 super(ADBHost, self).stop_loggers()
742 # Record logcat log to a temporary file on the teststation.
743 tmp_dir = self.teststation.get_tmp_dir()
Simran Basi242f8de2016-06-08 14:23:43 -0700744 logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
745 teststation_filename = os.path.join(tmp_dir, logcat_filename)
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700746 try:
747 self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
748 timeout=20)
Simran Basid6b49792016-06-07 17:22:03 -0700749 except (error.AutotestHostRunError, error.AutoservRunError,
750 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700751 return
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700752 # Copy-back the log to the drone's results directory.
Simran Basi242f8de2016-06-08 14:23:43 -0700753 results_logcat_filename = os.path.join(self.job.resultdir,
754 logcat_filename)
755 self.teststation.get_file(teststation_filename,
756 results_logcat_filename)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700757 try:
758 self.teststation.run('rm -rf %s' % tmp_dir)
759 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
760 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
761
762
Simran Basi431010f2013-09-04 10:42:41 -0700763 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700764 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700765
766 Called as the test ends. Will return the device to USB mode and kill
767 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700768 """
Christopher Wiley08849d52013-11-22 08:57:58 -0800769 # TODO(sbasi) Originally, we would kill the server after each test to
770 # reduce the opportunity for bad server state to hang around.
771 # Unfortunately, there is a period of time after each kill during which
772 # the Android device becomes unusable, and if we start the next test
773 # too quickly, we'll get an error complaining about no ADB device
774 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700775 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800776 # |close| the associated teststation as well.
777 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700778 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700779
780
781 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700782 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700783
784 @param message String message to log into syslog
785 @param tag String tag prefix for syslog
786
787 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700788 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700789
790
791 def get_autodir(self):
792 """Return the directory to install autotest for client side tests."""
793 return '/data/autotest'
794
Kevin Cheng018db352015-09-20 02:22:08 -0700795
Kris Rambishde8f9d12015-12-16 12:42:41 -0800796 def is_device_ready(self):
797 """Return the if the device is ready for ADB commands."""
Dan Shi7075f552016-04-21 15:42:41 -0700798 try:
799 # Retry to avoid possible flakes.
800 is_ready = client_utils.poll_for_condition(
801 lambda: self.adb_run('get-state').stdout.strip() == 'device',
802 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
803 desc='Waiting for device state to be `device`')
804 except client_utils.TimeoutError:
805 is_ready = False
806
807 logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
808 return is_ready
Kris Rambishde8f9d12015-12-16 12:42:41 -0800809
810
Kevin Chengd19e6c62015-10-28 16:39:39 -0700811 def verify_connectivity(self):
812 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800813 if not self.is_device_ready():
814 raise error.AutoservHostError('device state is not in the '
815 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700816
817
Simran Basid3ba3fb2015-09-11 14:35:07 -0700818 def verify_software(self):
819 """Verify working software on an adb_host.
820
Simran Basi38f7ddf2015-09-18 12:25:03 -0700821 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700822 """
Dan Shiab999722015-12-04 14:27:08 -0800823 # Check if adb and fastboot are present.
824 self.teststation.run('which adb')
825 self.teststation.run('which fastboot')
826 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700827
Dan Shi626d5412016-05-16 16:05:13 -0700828 # Apply checks only for Android device.
Dan Shi1e2a98a2016-05-18 12:08:08 -0700829 if self.get_os_type() == OS_TYPE_ANDROID:
Dan Shi626d5412016-05-16 16:05:13 -0700830 # Make sure ro.boot.hardware and ro.build.product match.
Dan Shi8c51bda2016-05-26 12:21:02 -0700831 hardware = self._run_output_with_retry('getprop ro.boot.hardware')
832 product = self._run_output_with_retry('getprop ro.build.product')
Dan Shi1e2a98a2016-05-18 12:08:08 -0700833 if hardware != product:
834 raise error.AutoservHostError('ro.boot.hardware: %s does not '
835 'match to ro.build.product: %s' %
836 (hardware, product))
837
Kevin Cheng018db352015-09-20 02:22:08 -0700838
Simran Basid3ba3fb2015-09-11 14:35:07 -0700839 def verify_job_repo_url(self, tag=''):
840 """Make sure job_repo_url of this host is valid.
841
Simran Basi38f7ddf2015-09-18 12:25:03 -0700842 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700843
844 @param tag: The tag from the server job, in the format
845 <job_id>-<user>/<hostname>, or <hostless> for a server job.
846 """
847 return
Kevin Cheng018db352015-09-20 02:22:08 -0700848
849
Simran Basibeb2bb22016-02-03 15:25:48 -0800850 def repair(self):
851 """Attempt to get the DUT to pass `self.verify()`."""
852 try:
853 self.ensure_adb_mode(timeout=30)
854 return
855 except error.AutoservError as e:
856 logging.error(e)
857 logging.debug('Verifying the device is accessible via fastboot.')
858 self.ensure_bootloader_mode()
859 if not self.job.run_test(
860 'provision_AndroidUpdate', host=self, value=None,
861 force=True, repair=True):
862 raise error.AutoservRepairTotalFailure(
863 'Unable to repair the device.')
864
865
Simran Basi1b023762015-09-25 12:12:20 -0700866 def send_file(self, source, dest, delete_dest=False,
867 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700868 """Copy files from the drone to the device.
869
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400870 Just a note, there is the possibility the test station is localhost
871 which makes some of these steps redundant (e.g. creating tmp dir) but
872 that scenario will undoubtedly be a development scenario (test station
873 is also the moblab) and not the typical live test running scenario so
874 the redundancy I think is harmless.
875
Kevin Cheng018db352015-09-20 02:22:08 -0700876 @param source: The file/directory on the drone to send to the device.
877 @param dest: The destination path on the device to copy to.
878 @param delete_dest: A flag set to choose whether or not to delete
879 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700880 @param preserve_symlinks: Controls if symlinks on the source will be
881 copied as such on the destination or
882 transformed into the referenced
883 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700884 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700885 # If we need to preserve symlinks, let's check if the source is a
886 # symlink itself and if so, just create it on the device.
887 if preserve_symlinks:
888 symlink_target = None
889 try:
890 symlink_target = os.readlink(source)
891 except OSError:
892 # Guess it's not a symlink.
893 pass
894
895 if symlink_target is not None:
896 # Once we create the symlink, let's get out of here.
897 self.run('ln -s %s %s' % (symlink_target, dest))
898 return
899
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400900 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700901 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400902 src_path = os.path.join(tmp_dir, os.path.basename(dest))
903 # Now copy the file over to the test station so you can reference the
904 # file in the push command.
905 self.teststation.send_file(source, src_path,
906 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700907
908 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400909 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700910
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700911 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700912
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400913 # Cleanup the test station.
914 try:
915 self.teststation.run('rm -rf %s' % tmp_dir)
916 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
917 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700918
919
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700920 def _get_file_info(self, dest):
921 """Get permission and possible symlink info about file on the device.
922
923 These files are on the device so we only have shell commands (via adb)
924 to get the info we want. We'll use 'ls' to get it all.
925
926 @param dest: File to get info about.
927
928 @returns a dict of the file permissions and symlink.
929 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800930 # Grab file info.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700931 file_info = self.run_output('ls -ld %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700932 symlink = None
933 perms = 0
934 match = re.match(FILE_INFO_REGEX, file_info)
935 if match:
936 # Check if it's a symlink and grab the linked dest if it is.
937 if match.group('TYPE') == 'l':
938 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
939 if symlink_match:
940 symlink = symlink_match.group('SYMLINK')
941
942 # Set the perms.
943 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
944 if perm != '-':
945 perms |= perm_flag
946
947 return {'perms': perms,
948 'symlink': symlink}
949
950
Simran Basi1b023762015-09-25 12:12:20 -0700951 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
952 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700953 """Copy files from the device to the drone.
954
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400955 Just a note, there is the possibility the test station is localhost
956 which makes some of these steps redundant (e.g. creating tmp dir) but
957 that scenario will undoubtedly be a development scenario (test station
958 is also the moblab) and not the typical live test running scenario so
959 the redundancy I think is harmless.
960
Kevin Cheng018db352015-09-20 02:22:08 -0700961 @param source: The file/directory on the device to copy back to the
962 drone.
963 @param dest: The destination path on the drone to copy to.
964 @param delete_dest: A flag set to choose whether or not to delete
965 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700966 @param preserve_perm: Tells get_file() to try to preserve the sources
967 permissions on files and dirs.
968 @param preserve_symlinks: Try to preserve symlinks instead of
969 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -0700970 """
David Purselle01548b2016-05-11 10:00:42 -0700971 # Stage the files on the test station under teststation_temp_dir.
972 teststation_temp_dir = self.teststation.get_tmp_dir()
973 teststation_dest = os.path.join(teststation_temp_dir,
974 os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -0700975
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700976 source_info = {}
977 if preserve_symlinks or preserve_perm:
978 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -0700979
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700980 # If we want to preserve symlinks, just create it here, otherwise pull
981 # the file off the device.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700982 #
983 # TODO(sadmac): Directories containing symlinks won't behave as
984 # expected.
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700985 if preserve_symlinks and source_info['symlink']:
986 os.symlink(source_info['symlink'], dest)
987 else:
David Purselle01548b2016-05-11 10:00:42 -0700988 self.adb_run('pull %s %s' % (source, teststation_temp_dir))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700989
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400990 # Copy over the file from the test station and clean up.
David Purselle01548b2016-05-11 10:00:42 -0700991 self.teststation.get_file(teststation_dest, dest,
992 delete_dest=delete_dest)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400993 try:
David Purselle01548b2016-05-11 10:00:42 -0700994 self.teststation.run('rm -rf %s' % teststation_temp_dir)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400995 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
David Purselle01548b2016-05-11 10:00:42 -0700996 logging.warn('failed to remove dir %s: %s',
997 teststation_temp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700998
David Pursell788b1b52016-05-19 09:03:31 -0700999 # Source will be copied under dest if either:
1000 # 1. Source is a directory and doesn't end with /.
1001 # 2. Source is a file and dest is a directory.
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001002 command = '[ -d %s ]' % source
1003 source_is_dir = self.run(command,
David Pursell788b1b52016-05-19 09:03:31 -07001004 ignore_status=True).exit_status == 0
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001005
David Pursell788b1b52016-05-19 09:03:31 -07001006 if ((source_is_dir and not source.endswith(os.sep)) or
1007 (not source_is_dir and os.path.isdir(dest))):
1008 receive_path = os.path.join(dest, os.path.basename(source))
1009 else:
1010 receive_path = dest
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001011
David Pursell788b1b52016-05-19 09:03:31 -07001012 # Set the permissions of the received file/dirs.
1013 if os.path.isdir(receive_path):
1014 for root, _dirs, files in os.walk(receive_path):
1015 def process(rel_path, default_perm):
1016 info = self._get_file_info(os.path.join(source,
1017 rel_path))
1018 if info['perms'] != 0:
1019 target = os.path.join(receive_path, rel_path)
1020 if preserve_perm:
1021 os.chmod(target, info['perms'])
1022 else:
1023 os.chmod(target, default_perm)
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001024
David Pursell788b1b52016-05-19 09:03:31 -07001025 rel_root = os.path.relpath(root, receive_path)
1026 process(rel_root, _DEFAULT_DIR_PERMS)
1027 for f in files:
1028 process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
1029 elif preserve_perm:
1030 os.chmod(receive_path, source_info['perms'])
1031 else:
1032 os.chmod(receive_path, _DEFAULT_FILE_PERMS)
Kevin Cheng018db352015-09-20 02:22:08 -07001033
1034
1035 def get_release_version(self):
1036 """Get the release version from the RELEASE_FILE on the device.
1037
1038 @returns The release string in the RELEASE_FILE.
1039
1040 """
1041 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -07001042
1043
1044 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001045 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001046
Kevin Chengd19e6c62015-10-28 16:39:39 -07001047 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001048
1049 @param parent: Parent directory of the returned tmp dir.
1050
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07001051 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001052 """
Kevin Chengd19e6c62015-10-28 16:39:39 -07001053 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
1054 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001055 if not parent.startswith(TMP_DIR):
1056 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -07001057 self.run('mkdir -p %s' % parent)
1058 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
1059 self.tmp_dirs.append(tmp_dir)
1060 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -07001061
1062
1063 def get_platform(self):
1064 """Determine the correct platform label for this host.
1065
1066 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -07001067 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -07001068
1069 @returns a string representing this host's platform.
1070 """
1071 return 'adb'
1072
1073
Gilad Arnolda76bef02015-09-29 13:55:15 -07001074 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -08001075 """Get the OS type of the DUT, e.g., android or brillo.
1076 """
1077 if not self._os_type:
1078 if self.run_output('getprop ro.product.brand') == 'Brillo':
1079 self._os_type = OS_TYPE_BRILLO
1080 else:
1081 self._os_type = OS_TYPE_ANDROID
1082
1083 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001084
1085
1086 def _forward(self, reverse, args):
1087 """Execute a forwarding command.
1088
1089 @param reverse: Whether this is reverse forwarding (Boolean).
1090 @param args: List of command arguments.
1091 """
1092 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001093 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001094
1095
1096 def add_forwarding(self, src, dst, reverse=False, rebind=True):
1097 """Forward a port between the ADB host and device.
1098
1099 Port specifications are any strings accepted as such by ADB, for
1100 example 'tcp:8080'.
1101
1102 @param src: Port specification to forward from.
1103 @param dst: Port specification to forward to.
1104 @param reverse: Do reverse forwarding from device to host (Boolean).
1105 @param rebind: Allow rebinding an already bound port (Boolean).
1106 """
1107 args = []
1108 if not rebind:
1109 args.append('--no-rebind')
1110 args += [src, dst]
1111 self._forward(reverse, args)
1112
1113
1114 def remove_forwarding(self, src=None, reverse=False):
1115 """Removes forwarding on port.
1116
1117 @param src: Port specification, or None to remove all forwarding.
1118 @param reverse: Whether this is reverse forwarding (Boolean).
1119 """
1120 args = []
1121 if src is None:
1122 args.append('--remove-all')
1123 else:
1124 args += ['--remove', src]
1125 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001126
1127
xixuan6cf6d2f2016-01-29 15:29:00 -08001128 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001129 """
1130 Forwards a port securely through a tunnel process from the server
1131 to the DUT for RPC server connection.
1132 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
1133 to the DUT.
1134
1135 @param port: remote port on the DUT.
1136 @param local_port: local forwarding port.
1137
1138 @return: the tunnel process.
1139 """
1140 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001141 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001142
1143
xixuan6cf6d2f2016-01-29 15:29:00 -08001144 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001145 """
1146 Disconnects a previously forwarded port from the server to the DUT for
1147 RPC server connection.
1148 Remove the previously added 'ADB forward' rule to forward the RPC
1149 packets from the AdbHost to the DUT.
1150
1151 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -08001152 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -07001153 @param port: remote port on the DUT.
1154
1155 """
1156 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001157 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001158
1159
1160 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001161 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001162
1163 @raise: error.AutoservError if the device failed to reboot into
1164 bootloader mode.
1165 """
1166 if self.is_up(command=FASTBOOT_CMD):
1167 return
1168 self.adb_run('reboot bootloader')
1169 if not self.wait_up(command=FASTBOOT_CMD):
1170 raise error.AutoservError(
1171 'The device failed to reboot into bootloader mode.')
1172
1173
Dan Shie4e807b2015-12-10 09:04:03 -08001174 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001175 """Ensure the device is up and can be accessed by adb command.
1176
Dan Shie4e807b2015-12-10 09:04:03 -08001177 @param timeout: Time limit in seconds before returning even if the host
1178 is not up.
1179
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001180 @raise: error.AutoservError if the device failed to reboot into
1181 adb mode.
1182 """
1183 if self.is_up():
1184 return
Dan Shi04980372016-03-22 10:57:47 -07001185 # Ignore timeout error to allow `fastboot reboot` to fail quietly and
1186 # check if the device is in adb mode.
1187 self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
Dan Shie4e807b2015-12-10 09:04:03 -08001188 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001189 raise error.AutoservError(
1190 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -08001191 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -07001192
1193
1194 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -08001195 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001196 """Get the Android build information from the build url.
1197
1198 @param build_url: The url to use for downloading Android artifacts.
1199 pattern: http://$devserver:###/static/branch/target/build_id
1200
Dan Shi6450e142016-03-11 11:52:20 -08001201 @return: A dictionary of build information, including keys:
1202 build_target, branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -08001203 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -07001204 """
Dan Shiab999722015-12-04 14:27:08 -08001205 if not build_url:
1206 raise AndroidInstallError('Need build_url to download image files.')
1207
1208 try:
1209 match = re.match(DEVSERVER_URL_REGEX, build_url)
Dan Shi6450e142016-03-11 11:52:20 -08001210 return {'build_target': match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001211 'branch': match.group('BRANCH'),
Dan Shi6450e142016-03-11 11:52:20 -08001212 'target': ('%s-%s' % (match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001213 match.group('BUILD_TYPE'))),
1214 'build_id': match.group('BUILD_ID')}
1215 except (AttributeError, IndexError, ValueError) as e:
1216 raise AndroidInstallError(
1217 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001218
1219
Dan Shia2872172015-10-31 01:16:51 -07001220 @retry.retry(error.AutoservRunError, timeout_min=10)
Simran Basi7756a0b2016-03-16 13:10:07 -07001221 def download_file(self, build_url, file, dest_dir, unzip=False,
1222 unzip_dest=None):
Dan Shia2872172015-10-31 01:16:51 -07001223 """Download the given file from the build url.
1224
1225 @param build_url: The url to use for downloading Android artifacts.
1226 pattern: http://$devserver:###/static/branch/target/build_id
1227 @param file: Name of the file to be downloaded, e.g., boot.img.
1228 @param dest_dir: Destination folder for the file to be downloaded to.
Simran Basi7756a0b2016-03-16 13:10:07 -07001229 @param unzip: If True, unzip the downloaded file.
1230 @param unzip_dest: Location to unzip the downloaded file to. If not
1231 provided, dest_dir is used.
Dan Shia2872172015-10-31 01:16:51 -07001232 """
Dan Shidb0366c2016-02-19 10:36:18 -08001233 # Append the file name to the url if build_url is linked to the folder
1234 # containing the file.
1235 if not build_url.endswith('/%s' % file):
1236 src_url = os.path.join(build_url, file)
1237 else:
1238 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001239 dest_file = os.path.join(dest_dir, file)
1240 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001241 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Simran Basi7756a0b2016-03-16 13:10:07 -07001242 if unzip:
1243 unzip_dest = unzip_dest or dest_dir
1244 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1245 (dest_dir, file, unzip_dest))
Dan Shia2872172015-10-31 01:16:51 -07001246 except:
1247 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001248 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001249 raise
1250
1251
Dan Shiab999722015-12-04 14:27:08 -08001252 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001253 """Download required image files from the given build_url to a local
1254 directory in the machine runs fastboot command.
1255
1256 @param build_url: The url to use for downloading Android artifacts.
1257 pattern: http://$devserver:###/static/branch/target/build_id
1258
1259 @return: Path to the directory contains image files.
1260 """
Dan Shi08ff1282016-02-18 19:51:16 -08001261 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001262
1263 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001264 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001265
1266 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001267 self.download_file(build_url, zipped_image_file, image_dir,
1268 unzip=True)
Dan Shi49d451f2016-04-19 09:25:01 -07001269 images = android_utils.AndroidImageFiles.get_standalone_images(
1270 build_info['build_target'])
1271 for image_file in images:
Dan Shidb0366c2016-02-19 10:36:18 -08001272 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001273
Dan Shia2872172015-10-31 01:16:51 -07001274 return image_dir
1275 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001276 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001277 raise
1278
1279
Dan Shiab999722015-12-04 14:27:08 -08001280 def stage_brillo_image_files(self, build_url):
1281 """Download required brillo image files from the given build_url to a
1282 local directory in the machine runs fastboot command.
1283
1284 @param build_url: The url to use for downloading Android artifacts.
1285 pattern: http://$devserver:###/static/branch/target/build_id
1286
1287 @return: Path to the directory contains image files.
1288 """
Dan Shi08ff1282016-02-18 19:51:16 -08001289 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001290
1291 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1292 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1293 image_dir = self.teststation.get_tmp_dir()
Dan Shiab999722015-12-04 14:27:08 -08001294
1295 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001296 self.download_file(build_url, zipped_image_file, image_dir,
1297 unzip=True)
1298 self.download_file(build_url, vendor_partitions_file, image_dir,
1299 unzip=True,
1300 unzip_dest=os.path.join(image_dir, 'vendor'))
Dan Shiab999722015-12-04 14:27:08 -08001301 return image_dir
1302 except:
1303 self.teststation.run('rm -rf %s' % image_dir)
1304 raise
1305
1306
Simran Basibeb2bb22016-02-03 15:25:48 -08001307 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001308 """Stage a build on a devserver and return the build_url and devserver.
1309
1310 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001311
Dan Shi225b9042015-11-18 10:25:21 -08001312 @returns a tuple with an update URL like:
1313 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1314 and the devserver instance.
1315 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001316 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001317 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001318 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1319 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001320 build_name = devserver.translate(build_name)
Dan Shi6450e142016-03-11 11:52:20 -08001321 branch, target, build_id = utils.parse_launch_control_build(build_name)
Simran Basibeb2bb22016-02-03 15:25:48 -08001322 is_brillo = os_type == OS_TYPE_BRILLO
Dan Shi08ff1282016-02-18 19:51:16 -08001323 devserver.trigger_download(target, build_id, branch,
1324 is_brillo=is_brillo, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001325 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001326
1327
Dan Shie4e807b2015-12-10 09:04:03 -08001328 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001329 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001330 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001331
1332 Following are the steps used here to provision an android device:
1333 1. If build_local_path is not set, download the image zip file, e.g.,
1334 shamu-img-2284311.zip, unzip it.
1335 2. Run fastboot to install following artifacts:
1336 bootloader, radio, boot, system, vendor(only if exists)
1337
1338 Repair is not supported for Android devices yet.
1339
1340 @param build_url: The url to use for downloading Android artifacts.
1341 pattern: http://$devserver:###/static/$build
1342 @param build_local_path: The path to a local folder that contains the
1343 image files needed to provision the device. Note that the folder
1344 is in the machine running adb command, rather than the drone.
1345 @param wipe: If true, userdata will be wiped before flashing.
1346 @param flash_all: If True, all img files found in img_path will be
1347 flashed. Otherwise, only boot and system are flashed.
1348
1349 @raises AndroidInstallError if any error occurs.
1350 """
Dan Shia2872172015-10-31 01:16:51 -07001351 # If the build is not staged in local server yet, clean up the temp
1352 # folder used to store image files after the provision is completed.
1353 delete_build_folder = bool(not build_local_path)
1354
1355 try:
1356 # Download image files needed for provision to a local directory.
1357 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001358 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001359
1360 # Device needs to be in bootloader mode for flashing.
1361 self.ensure_bootloader_mode()
1362
1363 if wipe:
Dan Shi12a4f662016-05-10 14:49:42 -07001364 self._fastboot_run_with_retry('-w')
Dan Shia2872172015-10-31 01:16:51 -07001365
1366 # Get all *.img file in the build_local_path.
1367 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001368 image_files = self.teststation.run(
1369 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001370 images = dict([(os.path.basename(f), f) for f in image_files])
Dan Shi49d451f2016-04-19 09:25:01 -07001371 build_info = self.get_build_info_from_build_url(build_url)
1372 board = build_info['build_target']
1373 all_images = (
1374 android_utils.AndroidImageFiles.get_standalone_images(board)
1375 + android_utils.AndroidImageFiles.get_zipped_images(board))
1376
1377 # Sort images to be flashed, bootloader needs to be the first one.
1378 bootloader = android_utils.AndroidImageFiles.BOOTLOADER
1379 sorted_images = sorted(
1380 images.items(),
1381 key=lambda pair: 0 if pair[0] == bootloader else 1)
1382 for image, image_file in sorted_images:
1383 if image not in all_images:
Dan Shia2872172015-10-31 01:16:51 -07001384 continue
1385 logging.info('Flashing %s...', image_file)
Dan Shi12a4f662016-05-10 14:49:42 -07001386 self._fastboot_run_with_retry('-S 256M flash %s %s' %
1387 (image[:-4], image_file))
Dan Shi49d451f2016-04-19 09:25:01 -07001388 if image == android_utils.AndroidImageFiles.BOOTLOADER:
Dan Shia2872172015-10-31 01:16:51 -07001389 self.fastboot_run('reboot-bootloader')
1390 self.wait_up(command=FASTBOOT_CMD)
1391 except Exception as e:
1392 logging.error('Install Android build failed with error: %s', e)
1393 # Re-raise the exception with type of AndroidInstallError.
1394 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1395 finally:
1396 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001397 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001398 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1399 DEFAULT_WAIT_UP_TIME_SECONDS)
1400 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001401 logging.info('Successfully installed Android build staged at %s.',
1402 build_url)
1403
1404
Dan Shiab999722015-12-04 14:27:08 -08001405 def install_brillo(self, build_url, build_local_path=None):
1406 """Install the Brillo DUT.
1407
1408 Following are the steps used here to provision an android device:
1409 1. If build_local_path is not set, download the image zip file, e.g.,
1410 dragonboard-img-123456.zip, unzip it. And download the vendor
1411 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1412 unzip it to vendor folder.
1413 2. Run provision_device script to install OS images and vendor
1414 partitions.
1415
1416 @param build_url: The url to use for downloading Android artifacts.
1417 pattern: http://$devserver:###/static/$build
1418 @param build_local_path: The path to a local folder that contains the
1419 image files needed to provision the device. Note that the folder
1420 is in the machine running adb command, rather than the drone.
1421
1422 @raises AndroidInstallError if any error occurs.
1423 """
1424 # If the build is not staged in local server yet, clean up the temp
1425 # folder used to store image files after the provision is completed.
1426 delete_build_folder = bool(not build_local_path)
1427
Dan Shiab999722015-12-04 14:27:08 -08001428 try:
1429 # Download image files needed for provision to a local directory.
1430 if not build_local_path:
1431 build_local_path = self.stage_brillo_image_files(build_url)
1432
1433 # Device needs to be in bootloader mode for flashing.
1434 self.ensure_bootloader_mode()
1435
1436 # Run provision_device command to install image files and vendor
1437 # partitions.
1438 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1439 cmd = (BRILLO_PROVISION_CMD %
1440 {'os_image_dir': build_local_path,
1441 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001442 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001443 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001444 self.teststation.run(cmd)
1445 except Exception as e:
1446 logging.error('Install Brillo build failed with error: %s', e)
1447 # Re-raise the exception with type of AndroidInstallError.
1448 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1449 finally:
1450 if delete_build_folder:
1451 self.teststation.run('rm -rf %s' % build_local_path)
1452 self.ensure_adb_mode()
1453 logging.info('Successfully installed Android build staged at %s.',
1454 build_url)
1455
1456
Dan Shibe3636a2016-02-14 22:48:01 -08001457 @property
1458 def job_repo_url_attribute(self):
1459 """Get the host attribute name for job_repo_url, which should append the
1460 adb serial.
1461 """
1462 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1463
1464
Dan Shie4e807b2015-12-10 09:04:03 -08001465 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001466 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001467 """Install the DUT.
1468
1469 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001470 pattern: http://$devserver:###/static/$build. If build_url is
1471 set to None, the code may try _parser.options.image to do the
1472 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001473 @param build_local_path: The path to a local directory that contains the
1474 image files needed to provision the device.
1475 @param wipe: If true, userdata will be wiped before flashing.
1476 @param flash_all: If True, all img files found in img_path will be
1477 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001478
Dan Shibe3636a2016-02-14 22:48:01 -08001479 @returns A tuple of (image_name, host_attributes).
1480 image_name is the name of image installed, e.g.,
1481 git_mnc-release/shamu-userdebug/1234
1482 host_attributes is a dictionary of (attribute, value), which
1483 can be saved to afe_host_attributes table in database. This
1484 method returns a dictionary with a single entry of
1485 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1486 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001487 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001488 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001489 if not build_url and self._parser.options.image:
1490 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001491 self._parser.options.image, os_type=os_type)
1492 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001493 self.install_android(
1494 build_url=build_url, build_local_path=build_local_path,
1495 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001496 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001497 self.install_brillo(
1498 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001499 else:
1500 raise error.InstallError(
1501 'Installation of os type %s is not supported.' %
1502 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001503 return (build_url.split('static/')[-1],
1504 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001505
1506
1507 def list_files_glob(self, path_glob):
1508 """Get a list of files on the device given glob pattern path.
1509
1510 @param path_glob: The path glob that we want to return the list of
1511 files that match the glob. Relative paths will not work as
1512 expected. Supply an absolute path to get the list of files
1513 you're hoping for.
1514
1515 @returns List of files that match the path_glob.
1516 """
1517 # This is just in case path_glob has no path separator.
1518 base_path = os.path.dirname(path_glob) or '.'
1519 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001520 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001521 if result.exit_status != 0:
1522 return []
1523 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001524
1525
Dan Shic716ac62016-05-24 16:47:57 -07001526 @retry.retry(error.AutoservRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
Dan Shida995002016-04-25 23:12:58 -07001527 def install_apk(self, apk, force_reinstall=True):
Kevin Cheng31355942016-01-05 14:23:35 -08001528 """Install the specified apk.
1529
1530 This will install the apk and override it if it's already installed and
1531 will also allow for downgraded apks.
1532
1533 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001534 @param force_reinstall: True to reinstall the apk even if it's already
Dan Shida995002016-04-25 23:12:58 -07001535 installed. Default is set to True.
Dan Shidb0366c2016-02-19 10:36:18 -08001536
1537 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001538 """
Dan Shic716ac62016-05-24 16:47:57 -07001539 try:
1540 client_utils.poll_for_condition(
1541 lambda: self.run('pm list packages',
1542 ignore_status=True).exit_status == 0,
1543 timeout=120)
1544 client_utils.poll_for_condition(
1545 lambda: self.run('service list | grep mount',
1546 ignore_status=True).exit_status == 0,
1547 timeout=120)
1548 return self.adb_run('install %s -d %s' %
1549 ('-r' if force_reinstall else '', apk))
1550 except error.AutoservRunError:
1551 self.reboot()
1552 raise
Dan Shidb0366c2016-02-19 10:36:18 -08001553
1554
1555 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1556 def _confirm_apk_installed(self, package_name):
1557 """Confirm if apk is already installed with the given name.
1558
1559 `pm list packages` command is not reliable some time. The retry helps to
1560 reduce the chance of false negative.
1561
1562 @param package_name: Name of the package, e.g., com.android.phone.
1563
1564 @raise AutoservRunError: If the package is not found or pm list command
1565 failed for any reason.
1566 """
1567 name = 'package:%s' % package_name
1568 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1569
1570
1571 def is_apk_installed(self, package_name):
1572 """Check if apk is already installed with the given name.
1573
1574 @param package_name: Name of the package, e.g., com.android.phone.
1575
1576 @return: True if package is installed. False otherwise.
1577 """
1578 try:
1579 self._confirm_apk_installed(package_name)
1580 return True
1581 except:
1582 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001583
1584
1585 def get_attributes_to_clear_before_provision(self):
1586 """Get a list of attributes to be cleared before machine_install starts.
1587 """
1588 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001589
1590
1591 def get_labels(self):
1592 """Return a list of the labels gathered from the devices connected.
1593
1594 @return: A list of strings that denote the labels from all the devices
1595 connected.
1596 """
1597 return self.labels.get_labels(self)
1598
1599
1600 def update_labels(self):
1601 """Update the labels for this testbed."""
1602 self.labels.update_labels(self)
Dan Shi6450e142016-03-11 11:52:20 -08001603
1604
1605 def stage_server_side_package(self, image=None):
1606 """Stage autotest server-side package on devserver.
1607
1608 @param image: A build name, e.g., git_mnc_dev/shamu-eng/123
1609
1610 @return: A url to the autotest server-side package. Return None if
1611 server-side package is not supported.
1612 @raise: error.AutoservError if fail to locate the build to test with.
1613 """
1614 if image:
1615 ds = dev_server.AndroidBuildServer.resolve(image, self.hostname)
1616 else:
1617 job_repo_url = afe_utils.get_host_attribute(
1618 self, self.job_repo_url_attribute)
1619 if job_repo_url:
1620 devserver_url, image = (
1621 tools.get_devserver_build_from_package_url(
1622 job_repo_url, True))
1623 ds = dev_server.AndroidBuildServer(devserver_url)
1624 else:
1625 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
1626 if not labels:
1627 raise error.AutoservError(
1628 'Failed to stage server-side package. The host has '
1629 'no job_report_url attribute or version label.')
1630 image = labels[0].name[len(self.VERSION_PREFIX)+1:]
1631 ds = dev_server.AndroidBuildServer.resolve(image, self.hostname)
1632
1633 branch, target, build_id = utils.parse_launch_control_build(image)
1634 build_target, _ = utils.parse_launch_control_target(target)
1635
1636 # For any build older than MIN_VERSION_SUPPORT_SSP, server side
1637 # packaging is not supported.
1638 try:
1639 if int(build_id) < self.MIN_VERSION_SUPPORT_SSP:
1640 logging.warn('Build %s is older than %s. Server side packaging '
1641 'is disabled.', image,
1642 self.MIN_VERSION_SUPPORT_SSP)
1643 return None
1644 except ValueError:
1645 logging.warn('Failed to compare build id in %s with the minimum '
1646 'version that supports server side packaging. Server '
1647 'side packaging is disabled.', image)
1648 return None
1649
1650 ds.stage_artifacts(target, build_id, branch,
1651 artifacts=['autotest_server_package'])
1652 autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
1653 {'build_target': build_target,
1654 'build_id': build_id})
1655 return '%s/static/%s/%s' % (ds.url(), image,
1656 autotest_server_package_name)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07001657
1658
1659 def _sync_time(self):
1660 """Approximate synchronization of time between host and ADB device.
1661
1662 This sets the ADB/Android device's clock to approximately the same
1663 time as the Autotest host for the purposes of comparing Android system
1664 logs such as logcat to logs from the Autotest host system.
1665 """
1666 command = 'date '
1667 sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
1668 if sdk_version < 23:
1669 # Android L and earlier use this format: date -s (format).
1670 command += ('-s %s' %
1671 datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
1672 else:
1673 # Android M and later use this format: date (format).
1674 command += datetime.datetime.now().strftime('%m%d%H%M%Y.%S')
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -07001675 self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1676 ignore_timeout=True)