blob: eae37e7939d352f22d5be797db9c14e3e770cb25 [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
Simran Basie6c4f142016-06-23 17:10:04 -0700328 def _log_adb_pid(self):
329 """Log the pid of adb server.
330
331 adb's server is known to have bugs and randomly restart. BY logging
332 the server's pid it will allow us to better debug random adb failures.
333 """
334 adb_pid = self.teststation.run('pgrep -f "adb.*server"')
335 logging.debug('ADB Server PID: %s', adb_pid.stdout)
336
337
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700338 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700339 timeout=3600, ignore_status=False, ignore_timeout=False,
340 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
341 connect_timeout=30, options='', stdin=None, verbose=True,
342 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700343 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700344
Kevin Chengd19e6c62015-10-28 16:39:39 -0700345 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700346
Simran Basi431010f2013-09-04 10:42:41 -0700347 @param command: Command to run.
348 @param shell: If true the command runs in the adb shell otherwise if
349 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700350 reboot with shell=False will call 'adb reboot'. This
351 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700352 @param timeout: Time limit in seconds before attempting to
353 kill the running process. The run() function
354 will take a few seconds longer than 'timeout'
355 to complete if it has to kill the process.
356 @param ignore_status: Do not raise an exception, no matter
357 what the exit code of the command is.
358 @param ignore_timeout: Bool True if command timeouts should be
359 ignored. Will return None on command timeout.
360 @param stdout: Redirect stdout.
361 @param stderr: Redirect stderr.
362 @param connect_timeout: Connection timeout (in seconds)
363 @param options: String with additional ssh command options
364 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700365 @param require_sudo: True to require sudo to run the command. Default is
366 False.
Simran Basi431010f2013-09-04 10:42:41 -0700367 @param args: Sequence of strings to pass as arguments to command by
368 quoting them in " and escaping their contents if
369 necessary.
370
371 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700372 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700373 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800374 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700375 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800376 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700377 else:
378 raise NotImplementedError('Mode %s is not supported' % function)
379
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700380 if function != ADB_CMD and shell:
381 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700382
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700383 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700384
385 if serial:
386 cmd += '-s %s ' % serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700387
Simran Basi431010f2013-09-04 10:42:41 -0700388 if shell:
389 cmd += '%s ' % SHELL_CMD
390 cmd += command
391
Simran Basie6c4f142016-06-23 17:10:04 -0700392 self._log_adb_pid()
393
Roshan Pius58e5dd32015-10-16 15:16:42 -0700394 if verbose:
395 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700396
Kevin Cheng85e864a2015-11-30 11:49:34 -0800397 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400398 ignore_status=ignore_status,
399 ignore_timeout=ignore_timeout, stdout_tee=stdout,
400 stderr_tee=stderr, options=options, stdin=stdin,
401 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700402
403
Dan Shi8c51bda2016-05-26 12:21:02 -0700404 def _run_output_with_retry(self, cmd):
405 """Call run_output method for the given command with retry.
406
Dan Shi68094122016-06-10 14:29:06 -0700407 adb command can be flaky some time, and the command may fail or return
408 empty string. It may take several retries until a value can be returned.
Dan Shi8c51bda2016-05-26 12:21:02 -0700409
410 @param cmd: The command to run.
411
412 @return: Return value from the command after retry.
413 """
414 try:
415 return client_utils.poll_for_condition(
Dan Shi68094122016-06-10 14:29:06 -0700416 lambda: self.run_output(cmd, ignore_status=True),
Dan Shi8c51bda2016-05-26 12:21:02 -0700417 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
418 sleep_interval=0.5,
419 desc='Get return value for command `%s`' % cmd)
420 except client_utils.TimeoutError:
421 return ''
422
423
Dan Shie234dea2016-01-20 17:15:17 -0800424 def get_board_name(self):
425 """Get the name of the board, e.g., shamu, dragonboard etc.
426 """
Simran Basi9c5d3982016-04-01 18:49:44 -0700427 product = self.run_output('getprop %s' % BOARD_FILE)
428 return PRODUCT_TARGET_MAP.get(product, product)
Dan Shie234dea2016-01-20 17:15:17 -0800429
430
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700431 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700432 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700433 """Determine the correct board label for the device.
434
435 @returns a string representing this device's board.
436 """
Dan Shie234dea2016-01-20 17:15:17 -0800437 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700438 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800439 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700440
441
Christopher Wiley08849d52013-11-22 08:57:58 -0800442 def job_start(self):
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700443 """Overload of parent which intentionally doesn't log certain files.
Dan Shi2d279cf2016-05-27 22:06:10 +0000444
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700445 The parent implementation attempts to log certain Linux files, such as
446 /var/log, which do not exist on Android, thus there is no call to the
447 parent's job_start(). The sync call is made so that logcat logs can be
448 approximately matched to server logs.
Dan Shi2d279cf2016-05-27 22:06:10 +0000449 """
Simran Basid6b49792016-06-07 17:22:03 -0700450 if self.is_up():
451 self._sync_time()
Christopher Wiley08849d52013-11-22 08:57:58 -0800452
453
Simran Basi431010f2013-09-04 10:42:41 -0700454 def run(self, command, timeout=3600, ignore_status=False,
455 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
456 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700457 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700458 """Run a command on the adb device.
459
460 The command given will be ran directly on the adb device; for example
461 'ls' will be ran as: 'abd shell ls'
462
463 @param command: The command line string.
464 @param timeout: Time limit in seconds before attempting to
465 kill the running process. The run() function
466 will take a few seconds longer than 'timeout'
467 to complete if it has to kill the process.
468 @param ignore_status: Do not raise an exception, no matter
469 what the exit code of the command is.
470 @param ignore_timeout: Bool True if command timeouts should be
471 ignored. Will return None on command timeout.
472 @param stdout_tee: Redirect stdout.
473 @param stderr_tee: Redirect stderr.
474 @param connect_timeout: Connection timeout (in seconds).
475 @param options: String with additional ssh command options.
476 @param stdin: Stdin to pass (a string) to the executed command
477 @param args: Sequence of strings to pass as arguments to command by
478 quoting them in " and escaping their contents if
479 necessary.
480
481 @returns A CMDResult object or None if the call timed out and
482 ignore_timeout is True.
483
484 @raises AutoservRunError: If the command failed.
485 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700486 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700487 command = ('"%s; echo %s:\$?"' %
488 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700489 result = self.adb_run(
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700490 command, shell=True, timeout=timeout,
Simran Basi431010f2013-09-04 10:42:41 -0700491 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
492 stdout=stdout_tee, stderr=stderr_tee,
493 connect_timeout=connect_timeout, options=options, stdin=stdin,
Roshan Pius58e5dd32015-10-16 15:16:42 -0700494 verbose=verbose, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700495 if not result:
496 # In case of timeouts.
497 return None
498
499 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
Roshan Pius5ba5d182015-10-28 09:19:41 -0700500 if not parse_output and not ignore_status:
Simran Basi431010f2013-09-04 10:42:41 -0700501 raise error.AutoservRunError(
Roshan Pius5ba5d182015-10-28 09:19:41 -0700502 'Failed to parse the exit code for command: %s' %
503 command, result)
504 elif parse_output:
505 result.stdout = parse_output.group('OUTPUT')
506 result.exit_status = int(parse_output.group('EXIT_CODE'))
507 if result.exit_status != 0 and not ignore_status:
508 raise error.AutoservRunError(command, result)
Simran Basi431010f2013-09-04 10:42:41 -0700509 return result
510
511
Dan Shicf7d2562016-06-16 14:08:23 -0700512 def check_boot_to_adb_complete(self, exception_type=error.TimeoutException):
513 """Check if the device has finished booting and accessible by adb.
514
515 @param exception_type: Type of exception to raise. Default is set to
516 error.TimeoutException for retry.
517
518 @raise exception_type: If the device has not finished booting yet, raise
519 an exception of type `exception_type`.
520 """
521 bootcomplete = self._run_output_with_retry('getprop dev.bootcomplete')
522 if bootcomplete != PROPERTY_VALUE_TRUE:
523 raise exception_type('dev.bootcomplete is %s.' % bootcomplete)
524 if self.get_os_type() == OS_TYPE_ANDROID:
525 boot_completed = self._run_output_with_retry(
526 'getprop sys.boot_completed')
527 if boot_completed != PROPERTY_VALUE_TRUE:
528 raise exception_type('sys.boot_completed is %s.' %
529 boot_completed)
530
531
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700532 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
533 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700534
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700535 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700536
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700537 @param timeout: Time limit in seconds before returning even if the host
538 is not up.
539 @param command: The command used to test if a device is up, i.e.,
540 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700541
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700542 @returns True if the host was found to be up before the timeout expires,
543 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700544 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700545 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
546 delay_sec=1)
547 def _wait_up():
548 if not self.is_up(command=command):
549 raise error.TimeoutException('Device is still down.')
Dan Shicf7d2562016-06-16 14:08:23 -0700550 if command == ADB_CMD:
551 self.check_boot_to_adb_complete()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700552 return True
553
554 try:
555 _wait_up()
556 logging.debug('Host %s is now up, and can be accessed by %s.',
557 self.hostname, command)
558 return True
559 except error.TimeoutException:
560 logging.debug('Host %s is still down after waiting %d seconds',
561 self.hostname, timeout)
562 return False
Simran Basi431010f2013-09-04 10:42:41 -0700563
564
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700565 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
566 warning_timer=None, old_boot_id=None, command=ADB_CMD):
567 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700568
569 Overrides wait_down from AbstractSSHHost.
570
571 @param timeout: Time in seconds to wait for the host to go down.
572 @param warning_timer: Time limit in seconds that will generate
573 a warning if the host is not down yet.
574 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700575 @param old_boot_id: Not applicable for adb_host.
576 @param command: `adb`, test if the device can be accessed by adb
577 command, or `fastboot`, test if the device can be accessed by
578 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700579
580 @returns True if the device goes down before the timeout, False
581 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700582 """
583 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
584 delay_sec=1)
585 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700586 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700587 raise error.TimeoutException('Device is still up.')
588 return True
589
590 try:
591 _wait_down()
592 logging.debug('Host %s is now down', self.hostname)
593 return True
594 except error.TimeoutException:
595 logging.debug('Host %s is still up after waiting %d seconds',
596 self.hostname, timeout)
597 return False
598
599
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700600 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700601 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700602
603 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700604 """
605 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700606 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700607 self.adb_run('reboot', timeout=10, ignore_timeout=True)
608 if not self.wait_down():
609 raise error.AutoservRebootError(
610 'ADB Device is still up after reboot')
611 if not self.wait_up():
612 raise error.AutoservRebootError(
613 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800614 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800615
616
Alexandru Branciog969ff7c2016-03-30 14:07:15 +0300617 def fastboot_reboot(self):
618 """Do a fastboot reboot to go back to adb.
619
620 @raises AutoservRebootError if reboot failed.
621 """
622 self.fastboot_run('reboot')
623 if not self.wait_down(command=FASTBOOT_CMD):
624 raise error.AutoservRebootError(
625 'Device is still in fastboot mode after reboot')
626 if not self.wait_up():
627 raise error.AutoservRebootError(
628 'Device failed to boot to adb after fastboot reboot.')
629 self._reset_adbd_connection()
630
631
Ralph Nathanb45eb672015-11-18 20:04:39 -0800632 def remount(self):
633 """Remounts paritions on the device read-write.
634
635 Specifically, the /system, /vendor (if present) and /oem (if present)
636 partitions on the device are remounted read-write.
637 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800638 self.adb_run('remount')
639
640
Kevin Cheng549beb42015-11-18 11:42:25 -0800641 @staticmethod
642 def parse_device_serials(devices_output):
643 """Return a list of parsed serials from the output.
644
645 @param devices_output: Output from either an adb or fastboot command.
646
647 @returns List of device serials
648 """
649 devices = []
650 for line in devices_output.splitlines():
651 match = re.search(DEVICE_FINDER_REGEX, line)
652 if match:
653 serial = match.group('SERIAL')
654 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
655 serial = DEVICE_NO_SERIAL_TAG
656 logging.debug('Found Device: %s', serial)
657 devices.append(serial)
658 return devices
659
660
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700661 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700662 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700663
664 @params use_adb: True to get adb accessible devices. Set to False to
665 get fastboot accessible devices.
666
Kevin Chengd19e6c62015-10-28 16:39:39 -0700667 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700668 """
669 if use_adb:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300670 result = self.adb_run('devices').stdout
671 if self.adb_serial and self.adb_serial not in result:
672 self._connect_over_tcpip_as_needed()
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700673 else:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300674 result = self.fastboot_run('devices').stdout
675 if (self.fastboot_serial and
676 self.fastboot_serial not in result):
677 # fastboot devices won't list the devices using TCP
678 try:
679 if 'product' in self.fastboot_run('getvar product',
680 timeout=2).stderr:
681 result += '\n%s\tfastboot' % self.fastboot_serial
Kevin Chengcfcb2cf2016-04-13 10:04:36 -0700682 # The main reason we do a general Exception catch here instead
683 # of setting ignore_timeout/status to True is because even when
684 # the fastboot process has been nuked, it still stays around and
685 # so bgjob wants to warn us of this and tries to read the
686 # /proc/<pid>/stack file which then promptly returns an
687 # 'Operation not permitted' error since we're running as moblab
688 # and we don't have permission to read those files.
689 except Exception:
Alexandru Branciogea380fb2016-04-01 16:01:34 +0300690 pass
691 return self.parse_device_serials(result)
Simran Basi431010f2013-09-04 10:42:41 -0700692
693
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700694 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700695 """Get a list of devices currently attached to the test station and
696 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700697 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800698 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700699 raise error.AutoservError(
700 'Not given ADB serial but multiple devices detected')
701 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700702
703
704 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700705 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700706 accessible by fastboot command.
707 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700708 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800709 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700710 raise error.AutoservError(
711 'Not given fastboot serial but multiple devices detected')
712 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700713
714
715 def is_up(self, timeout=0, command=ADB_CMD):
716 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700717
718 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700719 @param command: `adb`, the device can be accessed by adb command,
720 or `fastboot`, the device can be accessed by fastboot command.
721 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700722
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700723 @returns True if the device is detectable by given command, False
724 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700725
726 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700727 if command == ADB_CMD:
728 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800729 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800730 # ADB has a device state, if the device is not online, no
731 # subsequent ADB command will complete.
Dan Shi6450e142016-03-11 11:52:20 -0800732 # DUT with single device connected may not have adb_serial set.
733 # Therefore, skip checking if serial is in the list of adb devices
734 # if self.adb_serial is not set.
735 if (serial and serial not in devices) or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800736 logging.debug('Waiting for device to enter the ready state.')
737 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700738 elif command == FASTBOOT_CMD:
739 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800740 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700741 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700742 raise NotImplementedError('Mode %s is not supported' % command)
743
744 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700745
746
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700747 def stop_loggers(self):
748 """Inherited stop_loggers function.
749
750 Calls parent function and captures logcat, since the end of the run
751 is logically the end/stop of the logcat log.
752 """
753 super(ADBHost, self).stop_loggers()
754 # Record logcat log to a temporary file on the teststation.
755 tmp_dir = self.teststation.get_tmp_dir()
Simran Basi242f8de2016-06-08 14:23:43 -0700756 logcat_filename = LOGCAT_FILE_FMT % self.adb_serial
757 teststation_filename = os.path.join(tmp_dir, logcat_filename)
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700758 try:
759 self.adb_run('logcat -v time -d > "%s"' % (teststation_filename),
760 timeout=20)
Simran Basid6b49792016-06-07 17:22:03 -0700761 except (error.AutotestHostRunError, error.AutoservRunError,
762 error.AutoservSSHTimeout, error.CmdTimeoutError):
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -0700763 return
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700764 # Copy-back the log to the drone's results directory.
Simran Basi242f8de2016-06-08 14:23:43 -0700765 results_logcat_filename = os.path.join(self.job.resultdir,
766 logcat_filename)
767 self.teststation.get_file(teststation_filename,
768 results_logcat_filename)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -0700769 try:
770 self.teststation.run('rm -rf %s' % tmp_dir)
771 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
772 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
773
774
Simran Basi431010f2013-09-04 10:42:41 -0700775 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700776 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700777
778 Called as the test ends. Will return the device to USB mode and kill
779 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700780 """
Christopher Wiley08849d52013-11-22 08:57:58 -0800781 # TODO(sbasi) Originally, we would kill the server after each test to
782 # reduce the opportunity for bad server state to hang around.
783 # Unfortunately, there is a period of time after each kill during which
784 # the Android device becomes unusable, and if we start the next test
785 # too quickly, we'll get an error complaining about no ADB device
786 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700787 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800788 # |close| the associated teststation as well.
789 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700790 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700791
792
793 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700794 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700795
796 @param message String message to log into syslog
797 @param tag String tag prefix for syslog
798
799 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700800 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700801
802
803 def get_autodir(self):
804 """Return the directory to install autotest for client side tests."""
805 return '/data/autotest'
806
Kevin Cheng018db352015-09-20 02:22:08 -0700807
Kris Rambishde8f9d12015-12-16 12:42:41 -0800808 def is_device_ready(self):
809 """Return the if the device is ready for ADB commands."""
Dan Shi7075f552016-04-21 15:42:41 -0700810 try:
811 # Retry to avoid possible flakes.
812 is_ready = client_utils.poll_for_condition(
813 lambda: self.adb_run('get-state').stdout.strip() == 'device',
814 timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS, sleep_interval=1,
815 desc='Waiting for device state to be `device`')
816 except client_utils.TimeoutError:
817 is_ready = False
818
819 logging.debug('Device state is %sready', '' if is_ready else 'NOT ')
820 return is_ready
Kris Rambishde8f9d12015-12-16 12:42:41 -0800821
822
Kevin Chengd19e6c62015-10-28 16:39:39 -0700823 def verify_connectivity(self):
824 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800825 if not self.is_device_ready():
826 raise error.AutoservHostError('device state is not in the '
827 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700828
829
Simran Basid3ba3fb2015-09-11 14:35:07 -0700830 def verify_software(self):
831 """Verify working software on an adb_host.
832
Simran Basi38f7ddf2015-09-18 12:25:03 -0700833 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700834 """
Dan Shiab999722015-12-04 14:27:08 -0800835 # Check if adb and fastboot are present.
836 self.teststation.run('which adb')
837 self.teststation.run('which fastboot')
838 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700839
Dan Shi626d5412016-05-16 16:05:13 -0700840 # Apply checks only for Android device.
Dan Shi1e2a98a2016-05-18 12:08:08 -0700841 if self.get_os_type() == OS_TYPE_ANDROID:
Dan Shi626d5412016-05-16 16:05:13 -0700842 # Make sure ro.boot.hardware and ro.build.product match.
Dan Shi8c51bda2016-05-26 12:21:02 -0700843 hardware = self._run_output_with_retry('getprop ro.boot.hardware')
844 product = self._run_output_with_retry('getprop ro.build.product')
Dan Shi1e2a98a2016-05-18 12:08:08 -0700845 if hardware != product:
846 raise error.AutoservHostError('ro.boot.hardware: %s does not '
847 'match to ro.build.product: %s' %
848 (hardware, product))
849
Kevin Cheng018db352015-09-20 02:22:08 -0700850
Simran Basid3ba3fb2015-09-11 14:35:07 -0700851 def verify_job_repo_url(self, tag=''):
852 """Make sure job_repo_url of this host is valid.
853
Simran Basi38f7ddf2015-09-18 12:25:03 -0700854 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700855
856 @param tag: The tag from the server job, in the format
857 <job_id>-<user>/<hostname>, or <hostless> for a server job.
858 """
859 return
Kevin Cheng018db352015-09-20 02:22:08 -0700860
861
Simran Basibeb2bb22016-02-03 15:25:48 -0800862 def repair(self):
863 """Attempt to get the DUT to pass `self.verify()`."""
864 try:
865 self.ensure_adb_mode(timeout=30)
866 return
867 except error.AutoservError as e:
868 logging.error(e)
869 logging.debug('Verifying the device is accessible via fastboot.')
870 self.ensure_bootloader_mode()
871 if not self.job.run_test(
872 'provision_AndroidUpdate', host=self, value=None,
873 force=True, repair=True):
874 raise error.AutoservRepairTotalFailure(
875 'Unable to repair the device.')
876
877
Simran Basi1b023762015-09-25 12:12:20 -0700878 def send_file(self, source, dest, delete_dest=False,
879 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700880 """Copy files from the drone to the device.
881
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400882 Just a note, there is the possibility the test station is localhost
883 which makes some of these steps redundant (e.g. creating tmp dir) but
884 that scenario will undoubtedly be a development scenario (test station
885 is also the moblab) and not the typical live test running scenario so
886 the redundancy I think is harmless.
887
Kevin Cheng018db352015-09-20 02:22:08 -0700888 @param source: The file/directory on the drone to send to the device.
889 @param dest: The destination path on the device to copy to.
890 @param delete_dest: A flag set to choose whether or not to delete
891 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700892 @param preserve_symlinks: Controls if symlinks on the source will be
893 copied as such on the destination or
894 transformed into the referenced
895 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700896 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700897 # If we need to preserve symlinks, let's check if the source is a
898 # symlink itself and if so, just create it on the device.
899 if preserve_symlinks:
900 symlink_target = None
901 try:
902 symlink_target = os.readlink(source)
903 except OSError:
904 # Guess it's not a symlink.
905 pass
906
907 if symlink_target is not None:
908 # Once we create the symlink, let's get out of here.
909 self.run('ln -s %s %s' % (symlink_target, dest))
910 return
911
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400912 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700913 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400914 src_path = os.path.join(tmp_dir, os.path.basename(dest))
915 # Now copy the file over to the test station so you can reference the
916 # file in the push command.
917 self.teststation.send_file(source, src_path,
918 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700919
920 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400921 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700922
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700923 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700924
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400925 # Cleanup the test station.
926 try:
927 self.teststation.run('rm -rf %s' % tmp_dir)
928 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
929 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700930
931
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700932 def _get_file_info(self, dest):
933 """Get permission and possible symlink info about file on the device.
934
935 These files are on the device so we only have shell commands (via adb)
936 to get the info we want. We'll use 'ls' to get it all.
937
938 @param dest: File to get info about.
939
940 @returns a dict of the file permissions and symlink.
941 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800942 # Grab file info.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700943 file_info = self.run_output('ls -ld %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700944 symlink = None
945 perms = 0
946 match = re.match(FILE_INFO_REGEX, file_info)
947 if match:
948 # Check if it's a symlink and grab the linked dest if it is.
949 if match.group('TYPE') == 'l':
950 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
951 if symlink_match:
952 symlink = symlink_match.group('SYMLINK')
953
954 # Set the perms.
955 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
956 if perm != '-':
957 perms |= perm_flag
958
959 return {'perms': perms,
960 'symlink': symlink}
961
962
Simran Basi1b023762015-09-25 12:12:20 -0700963 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
964 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700965 """Copy files from the device to the drone.
966
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400967 Just a note, there is the possibility the test station is localhost
968 which makes some of these steps redundant (e.g. creating tmp dir) but
969 that scenario will undoubtedly be a development scenario (test station
970 is also the moblab) and not the typical live test running scenario so
971 the redundancy I think is harmless.
972
Kevin Cheng018db352015-09-20 02:22:08 -0700973 @param source: The file/directory on the device to copy back to the
974 drone.
975 @param dest: The destination path on the drone to copy to.
976 @param delete_dest: A flag set to choose whether or not to delete
977 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700978 @param preserve_perm: Tells get_file() to try to preserve the sources
979 permissions on files and dirs.
980 @param preserve_symlinks: Try to preserve symlinks instead of
981 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -0700982 """
David Purselle01548b2016-05-11 10:00:42 -0700983 # Stage the files on the test station under teststation_temp_dir.
984 teststation_temp_dir = self.teststation.get_tmp_dir()
985 teststation_dest = os.path.join(teststation_temp_dir,
986 os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -0700987
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700988 source_info = {}
989 if preserve_symlinks or preserve_perm:
990 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -0700991
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700992 # If we want to preserve symlinks, just create it here, otherwise pull
993 # the file off the device.
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -0700994 #
995 # TODO(sadmac): Directories containing symlinks won't behave as
996 # expected.
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700997 if preserve_symlinks and source_info['symlink']:
998 os.symlink(source_info['symlink'], dest)
999 else:
David Purselle01548b2016-05-11 10:00:42 -07001000 self.adb_run('pull %s %s' % (source, teststation_temp_dir))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001001
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001002 # Copy over the file from the test station and clean up.
David Purselle01548b2016-05-11 10:00:42 -07001003 self.teststation.get_file(teststation_dest, dest,
1004 delete_dest=delete_dest)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001005 try:
David Purselle01548b2016-05-11 10:00:42 -07001006 self.teststation.run('rm -rf %s' % teststation_temp_dir)
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001007 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
David Purselle01548b2016-05-11 10:00:42 -07001008 logging.warn('failed to remove dir %s: %s',
1009 teststation_temp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07001010
David Pursell788b1b52016-05-19 09:03:31 -07001011 # Source will be copied under dest if either:
1012 # 1. Source is a directory and doesn't end with /.
1013 # 2. Source is a file and dest is a directory.
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001014 command = '[ -d %s ]' % source
1015 source_is_dir = self.run(command,
David Pursell788b1b52016-05-19 09:03:31 -07001016 ignore_status=True).exit_status == 0
Bindu Mahadev594a80e2016-06-01 10:39:49 -07001017
David Pursell788b1b52016-05-19 09:03:31 -07001018 if ((source_is_dir and not source.endswith(os.sep)) or
1019 (not source_is_dir and os.path.isdir(dest))):
1020 receive_path = os.path.join(dest, os.path.basename(source))
1021 else:
1022 receive_path = dest
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001023
David Pursell788b1b52016-05-19 09:03:31 -07001024 # Set the permissions of the received file/dirs.
1025 if os.path.isdir(receive_path):
1026 for root, _dirs, files in os.walk(receive_path):
1027 def process(rel_path, default_perm):
1028 info = self._get_file_info(os.path.join(source,
1029 rel_path))
1030 if info['perms'] != 0:
1031 target = os.path.join(receive_path, rel_path)
1032 if preserve_perm:
1033 os.chmod(target, info['perms'])
1034 else:
1035 os.chmod(target, default_perm)
Casey Dahlinf6bc8ed2016-04-13 14:33:48 -07001036
David Pursell788b1b52016-05-19 09:03:31 -07001037 rel_root = os.path.relpath(root, receive_path)
1038 process(rel_root, _DEFAULT_DIR_PERMS)
1039 for f in files:
1040 process(os.path.join(rel_root, f), _DEFAULT_FILE_PERMS)
1041 elif preserve_perm:
1042 os.chmod(receive_path, source_info['perms'])
1043 else:
1044 os.chmod(receive_path, _DEFAULT_FILE_PERMS)
Kevin Cheng018db352015-09-20 02:22:08 -07001045
1046
1047 def get_release_version(self):
1048 """Get the release version from the RELEASE_FILE on the device.
1049
1050 @returns The release string in the RELEASE_FILE.
1051
1052 """
1053 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -07001054
1055
1056 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001057 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001058
Kevin Chengd19e6c62015-10-28 16:39:39 -07001059 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001060
1061 @param parent: Parent directory of the returned tmp dir.
1062
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07001063 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001064 """
Kevin Chengd19e6c62015-10-28 16:39:39 -07001065 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
1066 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -07001067 if not parent.startswith(TMP_DIR):
1068 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -07001069 self.run('mkdir -p %s' % parent)
1070 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
1071 self.tmp_dirs.append(tmp_dir)
1072 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -07001073
1074
1075 def get_platform(self):
1076 """Determine the correct platform label for this host.
1077
1078 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -07001079 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -07001080
1081 @returns a string representing this host's platform.
1082 """
1083 return 'adb'
1084
1085
Gilad Arnolda76bef02015-09-29 13:55:15 -07001086 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -08001087 """Get the OS type of the DUT, e.g., android or brillo.
1088 """
1089 if not self._os_type:
1090 if self.run_output('getprop ro.product.brand') == 'Brillo':
1091 self._os_type = OS_TYPE_BRILLO
1092 else:
1093 self._os_type = OS_TYPE_ANDROID
1094
1095 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001096
1097
1098 def _forward(self, reverse, args):
1099 """Execute a forwarding command.
1100
1101 @param reverse: Whether this is reverse forwarding (Boolean).
1102 @param args: List of command arguments.
1103 """
1104 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001105 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -07001106
1107
1108 def add_forwarding(self, src, dst, reverse=False, rebind=True):
1109 """Forward a port between the ADB host and device.
1110
1111 Port specifications are any strings accepted as such by ADB, for
1112 example 'tcp:8080'.
1113
1114 @param src: Port specification to forward from.
1115 @param dst: Port specification to forward to.
1116 @param reverse: Do reverse forwarding from device to host (Boolean).
1117 @param rebind: Allow rebinding an already bound port (Boolean).
1118 """
1119 args = []
1120 if not rebind:
1121 args.append('--no-rebind')
1122 args += [src, dst]
1123 self._forward(reverse, args)
1124
1125
1126 def remove_forwarding(self, src=None, reverse=False):
1127 """Removes forwarding on port.
1128
1129 @param src: Port specification, or None to remove all forwarding.
1130 @param reverse: Whether this is reverse forwarding (Boolean).
1131 """
1132 args = []
1133 if src is None:
1134 args.append('--remove-all')
1135 else:
1136 args += ['--remove', src]
1137 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001138
1139
xixuan6cf6d2f2016-01-29 15:29:00 -08001140 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001141 """
1142 Forwards a port securely through a tunnel process from the server
1143 to the DUT for RPC server connection.
1144 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
1145 to the DUT.
1146
1147 @param port: remote port on the DUT.
1148 @param local_port: local forwarding port.
1149
1150 @return: the tunnel process.
1151 """
1152 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001153 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -07001154
1155
xixuan6cf6d2f2016-01-29 15:29:00 -08001156 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -07001157 """
1158 Disconnects a previously forwarded port from the server to the DUT for
1159 RPC server connection.
1160 Remove the previously added 'ADB forward' rule to forward the RPC
1161 packets from the AdbHost to the DUT.
1162
1163 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -08001164 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -07001165 @param port: remote port on the DUT.
1166
1167 """
1168 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -08001169 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001170
1171
1172 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -07001173 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001174
1175 @raise: error.AutoservError if the device failed to reboot into
1176 bootloader mode.
1177 """
1178 if self.is_up(command=FASTBOOT_CMD):
1179 return
1180 self.adb_run('reboot bootloader')
1181 if not self.wait_up(command=FASTBOOT_CMD):
1182 raise error.AutoservError(
1183 'The device failed to reboot into bootloader mode.')
1184
1185
Dan Shie4e807b2015-12-10 09:04:03 -08001186 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001187 """Ensure the device is up and can be accessed by adb command.
1188
Dan Shie4e807b2015-12-10 09:04:03 -08001189 @param timeout: Time limit in seconds before returning even if the host
1190 is not up.
1191
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001192 @raise: error.AutoservError if the device failed to reboot into
1193 adb mode.
1194 """
1195 if self.is_up():
1196 return
Dan Shi04980372016-03-22 10:57:47 -07001197 # Ignore timeout error to allow `fastboot reboot` to fail quietly and
1198 # check if the device is in adb mode.
1199 self.fastboot_run('reboot', timeout=timeout, ignore_timeout=True)
Dan Shie4e807b2015-12-10 09:04:03 -08001200 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -07001201 raise error.AutoservError(
1202 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -08001203 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -07001204
1205
1206 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -08001207 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001208 """Get the Android build information from the build url.
1209
1210 @param build_url: The url to use for downloading Android artifacts.
1211 pattern: http://$devserver:###/static/branch/target/build_id
1212
Dan Shi6450e142016-03-11 11:52:20 -08001213 @return: A dictionary of build information, including keys:
1214 build_target, branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -08001215 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -07001216 """
Dan Shiab999722015-12-04 14:27:08 -08001217 if not build_url:
1218 raise AndroidInstallError('Need build_url to download image files.')
1219
1220 try:
1221 match = re.match(DEVSERVER_URL_REGEX, build_url)
Dan Shi6450e142016-03-11 11:52:20 -08001222 return {'build_target': match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001223 'branch': match.group('BRANCH'),
Dan Shi6450e142016-03-11 11:52:20 -08001224 'target': ('%s-%s' % (match.group('BUILD_TARGET'),
Dan Shiab999722015-12-04 14:27:08 -08001225 match.group('BUILD_TYPE'))),
1226 'build_id': match.group('BUILD_ID')}
1227 except (AttributeError, IndexError, ValueError) as e:
1228 raise AndroidInstallError(
1229 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001230
1231
Dan Shia2872172015-10-31 01:16:51 -07001232 @retry.retry(error.AutoservRunError, timeout_min=10)
Simran Basi7756a0b2016-03-16 13:10:07 -07001233 def download_file(self, build_url, file, dest_dir, unzip=False,
1234 unzip_dest=None):
Dan Shia2872172015-10-31 01:16:51 -07001235 """Download the given file from the build url.
1236
1237 @param build_url: The url to use for downloading Android artifacts.
1238 pattern: http://$devserver:###/static/branch/target/build_id
1239 @param file: Name of the file to be downloaded, e.g., boot.img.
1240 @param dest_dir: Destination folder for the file to be downloaded to.
Simran Basi7756a0b2016-03-16 13:10:07 -07001241 @param unzip: If True, unzip the downloaded file.
1242 @param unzip_dest: Location to unzip the downloaded file to. If not
1243 provided, dest_dir is used.
Dan Shia2872172015-10-31 01:16:51 -07001244 """
Dan Shidb0366c2016-02-19 10:36:18 -08001245 # Append the file name to the url if build_url is linked to the folder
1246 # containing the file.
1247 if not build_url.endswith('/%s' % file):
1248 src_url = os.path.join(build_url, file)
1249 else:
1250 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001251 dest_file = os.path.join(dest_dir, file)
1252 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001253 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Simran Basi7756a0b2016-03-16 13:10:07 -07001254 if unzip:
1255 unzip_dest = unzip_dest or dest_dir
1256 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1257 (dest_dir, file, unzip_dest))
Dan Shia2872172015-10-31 01:16:51 -07001258 except:
1259 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001260 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001261 raise
1262
1263
Dan Shiab999722015-12-04 14:27:08 -08001264 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001265 """Download required image files from the given build_url to a local
1266 directory in the machine runs fastboot command.
1267
1268 @param build_url: The url to use for downloading Android artifacts.
1269 pattern: http://$devserver:###/static/branch/target/build_id
1270
1271 @return: Path to the directory contains image files.
1272 """
Dan Shi08ff1282016-02-18 19:51:16 -08001273 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001274
1275 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001276 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001277
1278 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001279 self.download_file(build_url, zipped_image_file, image_dir,
1280 unzip=True)
Dan Shi49d451f2016-04-19 09:25:01 -07001281 images = android_utils.AndroidImageFiles.get_standalone_images(
1282 build_info['build_target'])
1283 for image_file in images:
Dan Shidb0366c2016-02-19 10:36:18 -08001284 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001285
Dan Shia2872172015-10-31 01:16:51 -07001286 return image_dir
1287 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001288 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001289 raise
1290
1291
Dan Shiab999722015-12-04 14:27:08 -08001292 def stage_brillo_image_files(self, build_url):
1293 """Download required brillo image files from the given build_url to a
1294 local directory in the machine runs fastboot command.
1295
1296 @param build_url: The url to use for downloading Android artifacts.
1297 pattern: http://$devserver:###/static/branch/target/build_id
1298
1299 @return: Path to the directory contains image files.
1300 """
Dan Shi08ff1282016-02-18 19:51:16 -08001301 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001302
1303 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1304 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1305 image_dir = self.teststation.get_tmp_dir()
Dan Shiab999722015-12-04 14:27:08 -08001306
1307 try:
Simran Basi7756a0b2016-03-16 13:10:07 -07001308 self.download_file(build_url, zipped_image_file, image_dir,
1309 unzip=True)
1310 self.download_file(build_url, vendor_partitions_file, image_dir,
1311 unzip=True,
1312 unzip_dest=os.path.join(image_dir, 'vendor'))
Dan Shiab999722015-12-04 14:27:08 -08001313 return image_dir
1314 except:
1315 self.teststation.run('rm -rf %s' % image_dir)
1316 raise
1317
1318
Simran Basibeb2bb22016-02-03 15:25:48 -08001319 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001320 """Stage a build on a devserver and return the build_url and devserver.
1321
1322 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001323
Dan Shi225b9042015-11-18 10:25:21 -08001324 @returns a tuple with an update URL like:
1325 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1326 and the devserver instance.
1327 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001328 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001329 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001330 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1331 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001332 build_name = devserver.translate(build_name)
Dan Shi6450e142016-03-11 11:52:20 -08001333 branch, target, build_id = utils.parse_launch_control_build(build_name)
Simran Basibeb2bb22016-02-03 15:25:48 -08001334 is_brillo = os_type == OS_TYPE_BRILLO
Dan Shi08ff1282016-02-18 19:51:16 -08001335 devserver.trigger_download(target, build_id, branch,
1336 is_brillo=is_brillo, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001337 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001338
1339
Dan Shie4e807b2015-12-10 09:04:03 -08001340 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001341 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001342 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001343
1344 Following are the steps used here to provision an android device:
1345 1. If build_local_path is not set, download the image zip file, e.g.,
1346 shamu-img-2284311.zip, unzip it.
1347 2. Run fastboot to install following artifacts:
1348 bootloader, radio, boot, system, vendor(only if exists)
1349
1350 Repair is not supported for Android devices yet.
1351
1352 @param build_url: The url to use for downloading Android artifacts.
1353 pattern: http://$devserver:###/static/$build
1354 @param build_local_path: The path to a local folder that contains the
1355 image files needed to provision the device. Note that the folder
1356 is in the machine running adb command, rather than the drone.
1357 @param wipe: If true, userdata will be wiped before flashing.
1358 @param flash_all: If True, all img files found in img_path will be
1359 flashed. Otherwise, only boot and system are flashed.
1360
1361 @raises AndroidInstallError if any error occurs.
1362 """
Dan Shia2872172015-10-31 01:16:51 -07001363 # If the build is not staged in local server yet, clean up the temp
1364 # folder used to store image files after the provision is completed.
1365 delete_build_folder = bool(not build_local_path)
1366
1367 try:
1368 # Download image files needed for provision to a local directory.
1369 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001370 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001371
1372 # Device needs to be in bootloader mode for flashing.
1373 self.ensure_bootloader_mode()
1374
1375 if wipe:
Dan Shi12a4f662016-05-10 14:49:42 -07001376 self._fastboot_run_with_retry('-w')
Dan Shia2872172015-10-31 01:16:51 -07001377
1378 # Get all *.img file in the build_local_path.
1379 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001380 image_files = self.teststation.run(
1381 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001382 images = dict([(os.path.basename(f), f) for f in image_files])
Dan Shi49d451f2016-04-19 09:25:01 -07001383 build_info = self.get_build_info_from_build_url(build_url)
1384 board = build_info['build_target']
1385 all_images = (
1386 android_utils.AndroidImageFiles.get_standalone_images(board)
1387 + android_utils.AndroidImageFiles.get_zipped_images(board))
1388
1389 # Sort images to be flashed, bootloader needs to be the first one.
1390 bootloader = android_utils.AndroidImageFiles.BOOTLOADER
1391 sorted_images = sorted(
1392 images.items(),
1393 key=lambda pair: 0 if pair[0] == bootloader else 1)
1394 for image, image_file in sorted_images:
1395 if image not in all_images:
Dan Shia2872172015-10-31 01:16:51 -07001396 continue
1397 logging.info('Flashing %s...', image_file)
Dan Shi12a4f662016-05-10 14:49:42 -07001398 self._fastboot_run_with_retry('-S 256M flash %s %s' %
1399 (image[:-4], image_file))
Dan Shi49d451f2016-04-19 09:25:01 -07001400 if image == android_utils.AndroidImageFiles.BOOTLOADER:
Dan Shia2872172015-10-31 01:16:51 -07001401 self.fastboot_run('reboot-bootloader')
1402 self.wait_up(command=FASTBOOT_CMD)
1403 except Exception as e:
1404 logging.error('Install Android build failed with error: %s', e)
1405 # Re-raise the exception with type of AndroidInstallError.
1406 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1407 finally:
1408 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001409 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001410 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1411 DEFAULT_WAIT_UP_TIME_SECONDS)
1412 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001413 logging.info('Successfully installed Android build staged at %s.',
1414 build_url)
1415
1416
Dan Shiab999722015-12-04 14:27:08 -08001417 def install_brillo(self, build_url, build_local_path=None):
1418 """Install the Brillo DUT.
1419
1420 Following are the steps used here to provision an android device:
1421 1. If build_local_path is not set, download the image zip file, e.g.,
1422 dragonboard-img-123456.zip, unzip it. And download the vendor
1423 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1424 unzip it to vendor folder.
1425 2. Run provision_device script to install OS images and vendor
1426 partitions.
1427
1428 @param build_url: The url to use for downloading Android artifacts.
1429 pattern: http://$devserver:###/static/$build
1430 @param build_local_path: The path to a local folder that contains the
1431 image files needed to provision the device. Note that the folder
1432 is in the machine running adb command, rather than the drone.
1433
1434 @raises AndroidInstallError if any error occurs.
1435 """
1436 # If the build is not staged in local server yet, clean up the temp
1437 # folder used to store image files after the provision is completed.
1438 delete_build_folder = bool(not build_local_path)
1439
Dan Shiab999722015-12-04 14:27:08 -08001440 try:
1441 # Download image files needed for provision to a local directory.
1442 if not build_local_path:
1443 build_local_path = self.stage_brillo_image_files(build_url)
1444
1445 # Device needs to be in bootloader mode for flashing.
1446 self.ensure_bootloader_mode()
1447
1448 # Run provision_device command to install image files and vendor
1449 # partitions.
1450 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1451 cmd = (BRILLO_PROVISION_CMD %
1452 {'os_image_dir': build_local_path,
1453 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001454 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001455 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001456 self.teststation.run(cmd)
1457 except Exception as e:
1458 logging.error('Install Brillo build failed with error: %s', e)
1459 # Re-raise the exception with type of AndroidInstallError.
1460 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1461 finally:
1462 if delete_build_folder:
1463 self.teststation.run('rm -rf %s' % build_local_path)
1464 self.ensure_adb_mode()
1465 logging.info('Successfully installed Android build staged at %s.',
1466 build_url)
1467
1468
Dan Shibe3636a2016-02-14 22:48:01 -08001469 @property
1470 def job_repo_url_attribute(self):
1471 """Get the host attribute name for job_repo_url, which should append the
1472 adb serial.
1473 """
1474 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1475
1476
Dan Shie4e807b2015-12-10 09:04:03 -08001477 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001478 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001479 """Install the DUT.
1480
1481 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001482 pattern: http://$devserver:###/static/$build. If build_url is
1483 set to None, the code may try _parser.options.image to do the
1484 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001485 @param build_local_path: The path to a local directory that contains the
1486 image files needed to provision the device.
1487 @param wipe: If true, userdata will be wiped before flashing.
1488 @param flash_all: If True, all img files found in img_path will be
1489 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001490
Dan Shibe3636a2016-02-14 22:48:01 -08001491 @returns A tuple of (image_name, host_attributes).
1492 image_name is the name of image installed, e.g.,
1493 git_mnc-release/shamu-userdebug/1234
1494 host_attributes is a dictionary of (attribute, value), which
1495 can be saved to afe_host_attributes table in database. This
1496 method returns a dictionary with a single entry of
1497 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1498 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001499 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001500 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001501 if not build_url and self._parser.options.image:
1502 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001503 self._parser.options.image, os_type=os_type)
1504 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001505 self.install_android(
1506 build_url=build_url, build_local_path=build_local_path,
1507 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001508 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001509 self.install_brillo(
1510 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001511 else:
1512 raise error.InstallError(
1513 'Installation of os type %s is not supported.' %
1514 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001515 return (build_url.split('static/')[-1],
1516 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001517
1518
1519 def list_files_glob(self, path_glob):
1520 """Get a list of files on the device given glob pattern path.
1521
1522 @param path_glob: The path glob that we want to return the list of
1523 files that match the glob. Relative paths will not work as
1524 expected. Supply an absolute path to get the list of files
1525 you're hoping for.
1526
1527 @returns List of files that match the path_glob.
1528 """
1529 # This is just in case path_glob has no path separator.
1530 base_path = os.path.dirname(path_glob) or '.'
1531 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001532 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001533 if result.exit_status != 0:
1534 return []
1535 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001536
1537
Dan Shic716ac62016-05-24 16:47:57 -07001538 @retry.retry(error.AutoservRunError, timeout_min=APK_INSTALL_TIMEOUT_MIN)
Dan Shida995002016-04-25 23:12:58 -07001539 def install_apk(self, apk, force_reinstall=True):
Kevin Cheng31355942016-01-05 14:23:35 -08001540 """Install the specified apk.
1541
1542 This will install the apk and override it if it's already installed and
1543 will also allow for downgraded apks.
1544
1545 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001546 @param force_reinstall: True to reinstall the apk even if it's already
Dan Shida995002016-04-25 23:12:58 -07001547 installed. Default is set to True.
Dan Shidb0366c2016-02-19 10:36:18 -08001548
1549 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001550 """
Dan Shic716ac62016-05-24 16:47:57 -07001551 try:
1552 client_utils.poll_for_condition(
1553 lambda: self.run('pm list packages',
1554 ignore_status=True).exit_status == 0,
1555 timeout=120)
1556 client_utils.poll_for_condition(
1557 lambda: self.run('service list | grep mount',
1558 ignore_status=True).exit_status == 0,
1559 timeout=120)
1560 return self.adb_run('install %s -d %s' %
1561 ('-r' if force_reinstall else '', apk))
1562 except error.AutoservRunError:
1563 self.reboot()
1564 raise
Dan Shidb0366c2016-02-19 10:36:18 -08001565
1566
1567 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1568 def _confirm_apk_installed(self, package_name):
1569 """Confirm if apk is already installed with the given name.
1570
1571 `pm list packages` command is not reliable some time. The retry helps to
1572 reduce the chance of false negative.
1573
1574 @param package_name: Name of the package, e.g., com.android.phone.
1575
1576 @raise AutoservRunError: If the package is not found or pm list command
1577 failed for any reason.
1578 """
1579 name = 'package:%s' % package_name
1580 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1581
1582
1583 def is_apk_installed(self, package_name):
1584 """Check if apk is already installed with the given name.
1585
1586 @param package_name: Name of the package, e.g., com.android.phone.
1587
1588 @return: True if package is installed. False otherwise.
1589 """
1590 try:
1591 self._confirm_apk_installed(package_name)
1592 return True
1593 except:
1594 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001595
1596
1597 def get_attributes_to_clear_before_provision(self):
1598 """Get a list of attributes to be cleared before machine_install starts.
1599 """
1600 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001601
1602
1603 def get_labels(self):
1604 """Return a list of the labels gathered from the devices connected.
1605
1606 @return: A list of strings that denote the labels from all the devices
1607 connected.
1608 """
1609 return self.labels.get_labels(self)
1610
1611
1612 def update_labels(self):
1613 """Update the labels for this testbed."""
1614 self.labels.update_labels(self)
Dan Shi6450e142016-03-11 11:52:20 -08001615
1616
1617 def stage_server_side_package(self, image=None):
1618 """Stage autotest server-side package on devserver.
1619
1620 @param image: A build name, e.g., git_mnc_dev/shamu-eng/123
1621
1622 @return: A url to the autotest server-side package. Return None if
1623 server-side package is not supported.
1624 @raise: error.AutoservError if fail to locate the build to test with.
1625 """
1626 if image:
1627 ds = dev_server.AndroidBuildServer.resolve(image, self.hostname)
1628 else:
1629 job_repo_url = afe_utils.get_host_attribute(
1630 self, self.job_repo_url_attribute)
1631 if job_repo_url:
1632 devserver_url, image = (
1633 tools.get_devserver_build_from_package_url(
1634 job_repo_url, True))
1635 ds = dev_server.AndroidBuildServer(devserver_url)
1636 else:
1637 labels = afe_utils.get_labels(self, self.VERSION_PREFIX)
1638 if not labels:
1639 raise error.AutoservError(
1640 'Failed to stage server-side package. The host has '
1641 'no job_report_url attribute or version label.')
1642 image = labels[0].name[len(self.VERSION_PREFIX)+1:]
1643 ds = dev_server.AndroidBuildServer.resolve(image, self.hostname)
1644
1645 branch, target, build_id = utils.parse_launch_control_build(image)
1646 build_target, _ = utils.parse_launch_control_target(target)
1647
1648 # For any build older than MIN_VERSION_SUPPORT_SSP, server side
1649 # packaging is not supported.
1650 try:
1651 if int(build_id) < self.MIN_VERSION_SUPPORT_SSP:
1652 logging.warn('Build %s is older than %s. Server side packaging '
1653 'is disabled.', image,
1654 self.MIN_VERSION_SUPPORT_SSP)
1655 return None
1656 except ValueError:
1657 logging.warn('Failed to compare build id in %s with the minimum '
1658 'version that supports server side packaging. Server '
1659 'side packaging is disabled.', image)
1660 return None
1661
1662 ds.stage_artifacts(target, build_id, branch,
1663 artifacts=['autotest_server_package'])
1664 autotest_server_package_name = (AUTOTEST_SERVER_PACKAGE_FILE_FMT %
1665 {'build_target': build_target,
1666 'build_id': build_id})
1667 return '%s/static/%s/%s' % (ds.url(), image,
1668 autotest_server_package_name)
Bryan Lewandowski0f3f0112016-05-27 15:17:19 -07001669
1670
1671 def _sync_time(self):
1672 """Approximate synchronization of time between host and ADB device.
1673
1674 This sets the ADB/Android device's clock to approximately the same
1675 time as the Autotest host for the purposes of comparing Android system
1676 logs such as logcat to logs from the Autotest host system.
1677 """
1678 command = 'date '
1679 sdk_version = int(self.run('getprop %s' % SDK_FILE).stdout)
1680 if sdk_version < 23:
1681 # Android L and earlier use this format: date -s (format).
1682 command += ('-s %s' %
1683 datetime.datetime.now().strftime('%Y%m%d.%H%M%S'))
1684 else:
1685 # Android M and later use this format: date (format).
1686 command += datetime.datetime.now().strftime('%m%d%H%M%Y.%S')
Bryan Lewandowskiea4a06d2016-06-03 11:25:54 -07001687 self.run(command, timeout=DEFAULT_COMMAND_RETRY_TIMEOUT_SECONDS,
1688 ignore_timeout=True)