blob: f260873f53100de384cbbdb1db44cad6ee20889d [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.
Kevin Cheng3a4a57a2015-09-30 12:09:50 -07004import functools
Simran Basi431010f2013-09-04 10:42:41 -07005import logging
Kevin Cheng018db352015-09-20 02:22:08 -07006import os
Simran Basi431010f2013-09-04 10:42:41 -07007import re
Kevin Cheng92fe6ae2015-10-21 11:45:34 -07008import stat
Dan Shia2872172015-10-31 01:16:51 -07009import sys
Simran Basi431010f2013-09-04 10:42:41 -070010import time
11
12import common
13
14from autotest_lib.client.common_lib import error
Dan Shi225b9042015-11-18 10:25:21 -080015from autotest_lib.client.common_lib.cros import dev_server
Simran Basi431010f2013-09-04 10:42:41 -070016from autotest_lib.client.common_lib.cros import retry
Dan Shi225b9042015-11-18 10:25:21 -080017from autotest_lib.server import autoserv_parser
Dan Shia2872172015-10-31 01:16:51 -070018from autotest_lib.server import constants as server_constants
Dan Shi225b9042015-11-18 10:25:21 -080019from autotest_lib.server import utils
Simran Basi5ace6f22016-01-06 17:30:44 -080020from autotest_lib.server.cros import provision
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070021from autotest_lib.server.cros.dynamic_suite import constants
Simran Basi724b8a52013-09-30 11:19:31 -070022from autotest_lib.server.hosts import abstract_ssh
Kevin Chengc6a645a2015-12-18 11:15:10 -080023from autotest_lib.server.hosts import adb_label
24from autotest_lib.server.hosts import base_label
Kevin Cheng85e864a2015-11-30 11:49:34 -080025from autotest_lib.server.hosts import teststation_host
Simran Basi431010f2013-09-04 10:42:41 -070026
27
Dan Shi6ea3e1c2015-10-28 15:19:04 -070028ADB_CMD = 'adb'
29FASTBOOT_CMD = 'fastboot'
Simran Basi431010f2013-09-04 10:42:41 -070030SHELL_CMD = 'shell'
Filipe Brandenburger34363392015-08-13 14:57:45 -070031# Some devices have no serial, then `adb serial` has output such as:
32# (no serial number) device
33# ?????????? device
34DEVICE_NO_SERIAL_MSG = '(no serial number)'
35DEVICE_NO_SERIAL_TAG = '<NO_SERIAL>'
Simran Basi431010f2013-09-04 10:42:41 -070036# Regex to find an adb device. Examples:
37# 0146B5580B01801B device
38# 018e0ecb20c97a62 device
39# 172.22.75.141:5555 device
Mike Frysinger5d7a7092016-02-23 15:14:42 -050040DEVICE_FINDER_REGEX = (r'^(?P<SERIAL>([\w-]+)|(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})|' +
Filipe Brandenburger34363392015-08-13 14:57:45 -070041 re.escape(DEVICE_NO_SERIAL_MSG) +
Mike Frysinger5d7a7092016-02-23 15:14:42 -050042 r')([:]5555)?[ \t]+(?:device|fastboot)')
Simran Basi431010f2013-09-04 10:42:41 -070043CMD_OUTPUT_PREFIX = 'ADB_CMD_OUTPUT'
44CMD_OUTPUT_REGEX = ('(?P<OUTPUT>[\s\S]*)%s:(?P<EXIT_CODE>\d{1,3})' %
45 CMD_OUTPUT_PREFIX)
Kevin Cheng018db352015-09-20 02:22:08 -070046RELEASE_FILE = 'ro.build.version.release'
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070047BOARD_FILE = 'ro.product.device'
Simran Basi38f7ddf2015-09-18 12:25:03 -070048TMP_DIR = '/data/local/tmp'
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070049# Regex to pull out file type, perms and symlink. Example:
Kevin Chengaaabd0c2015-11-10 16:05:04 -080050# lrwxrwx--- 1 6 root system 2015-09-12 19:21 blah_link -> ./blah
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070051FILE_INFO_REGEX = '^(?P<TYPE>[dl-])(?P<PERMS>[rwx-]{9})'
52FILE_SYMLINK_REGEX = '^.*-> (?P<SYMLINK>.+)'
53# List of the perm stats indexed by the order they are listed in the example
54# supplied above.
55FILE_PERMS_FLAGS = [stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR,
56 stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP,
57 stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH]
Simran Basi431010f2013-09-04 10:42:41 -070058
Dan Shi6ea3e1c2015-10-28 15:19:04 -070059# Default maximum number of seconds to wait for a device to be down.
60DEFAULT_WAIT_DOWN_TIME_SECONDS = 10
61# Default maximum number of seconds to wait for a device to be up.
Dan Shie4e807b2015-12-10 09:04:03 -080062DEFAULT_WAIT_UP_TIME_SECONDS = 300
63# Maximum number of seconds to wait for a device to be up after it's wiped.
Dan Shi50a412a2016-01-05 10:52:40 -080064WAIT_UP_AFTER_WIPE_TIME_SECONDS = 1200
Simran Basi431010f2013-09-04 10:42:41 -070065
Dan Shia2872172015-10-31 01:16:51 -070066OS_TYPE_ANDROID = 'android'
67OS_TYPE_BRILLO = 'brillo'
68
Dan Shie234dea2016-01-20 17:15:17 -080069# Regex to parse build name to get the detailed build information.
70BUILD_REGEX = ('(?P<BRANCH>([^/]+))/(?P<BOARD>([^/]+))-'
71 '(?P<BUILD_TYPE>([^/]+))/(?P<BUILD_ID>([^/]+))')
Dan Shia2872172015-10-31 01:16:51 -070072# Regex to parse devserver url to get the detailed build information. Sample
73# url: http://$devserver:8080/static/branch/target/build_id
Dan Shie234dea2016-01-20 17:15:17 -080074DEVSERVER_URL_REGEX = '.*/%s/*' % BUILD_REGEX
Dan Shia2872172015-10-31 01:16:51 -070075
76ANDROID_IMAGE_FILE_FMT = '%(board)s-img-%(build_id)s.zip'
77ANDROID_BOOTLOADER = 'bootloader.img'
78ANDROID_RADIO = 'radio.img'
79ANDROID_BOOT = 'boot.img'
80ANDROID_SYSTEM = 'system.img'
81ANDROID_VENDOR = 'vendor.img'
Dan Shiab999722015-12-04 14:27:08 -080082BRILLO_VENDOR_PARTITIONS_FILE_FMT = (
83 '%(board)s-vendor_partitions-%(build_id)s.zip')
Dan Shia2872172015-10-31 01:16:51 -070084
85# Image files not inside the image zip file. These files should be downloaded
86# directly from devserver.
87ANDROID_STANDALONE_IMAGES = [ANDROID_BOOTLOADER, ANDROID_RADIO]
88# Image files that are packaged in a zip file, e.g., shamu-img-123456.zip
89ANDROID_ZIPPED_IMAGES = [ANDROID_BOOT, ANDROID_SYSTEM, ANDROID_VENDOR]
90# All image files to be flashed to an Android device.
91ANDROID_IMAGES = ANDROID_STANDALONE_IMAGES + ANDROID_ZIPPED_IMAGES
92
Dan Shiab999722015-12-04 14:27:08 -080093# Command to provision a Brillo device.
94# os_image_dir: The full path of the directory that contains all the Android image
95# files (from the image zip file).
96# vendor_partition_dir: The full path of the directory that contains all the
97# Brillo vendor partitions, and provision-device script.
98BRILLO_PROVISION_CMD = (
Simran Basi7e52c622016-01-05 15:43:51 -080099 'sudo ANDROID_PROVISION_OS_PARTITIONS=%(os_image_dir)s '
Dan Shiab999722015-12-04 14:27:08 -0800100 'ANDROID_PROVISION_VENDOR_PARTITIONS=%(vendor_partition_dir)s '
101 '%(vendor_partition_dir)s/provision-device')
Dan Shia2872172015-10-31 01:16:51 -0700102
103class AndroidInstallError(error.InstallError):
104 """Generic error for Android installation related exceptions."""
105
106
Simran Basi724b8a52013-09-30 11:19:31 -0700107class ADBHost(abstract_ssh.AbstractSSHHost):
Simran Basi431010f2013-09-04 10:42:41 -0700108 """This class represents a host running an ADB server."""
109
Simran Basi5ace6f22016-01-06 17:30:44 -0800110 VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700111 _LABEL_FUNCTIONS = []
112 _DETECTABLE_LABELS = []
113 label_decorator = functools.partial(utils.add_label_detector,
114 _LABEL_FUNCTIONS,
115 _DETECTABLE_LABELS)
116
Dan Shi225b9042015-11-18 10:25:21 -0800117 _parser = autoserv_parser.autoserv_parser
Simran Basi431010f2013-09-04 10:42:41 -0700118
beeps46dadc92013-11-07 14:07:10 -0800119 @staticmethod
120 def check_host(host, timeout=10):
121 """
122 Check if the given host is an adb host.
123
Simran Basi14622bb2015-11-25 13:23:40 -0800124 If SSH connectivity can't be established, check_host will try to use
125 user 'adb' as well. If SSH connectivity still can't be established
126 then the original SSH user is restored.
127
beeps46dadc92013-11-07 14:07:10 -0800128 @param host: An ssh host representing a device.
129 @param timeout: The timeout for the run command.
130
131
132 @return: True if the host device has adb.
133
134 @raises AutoservRunError: If the command failed.
135 @raises AutoservSSHTimeout: Ssh connection has timed out.
136 """
Dan Shi64e130f2015-12-16 14:45:44 -0800137 # host object may not have user attribute if it's a LocalHost object.
138 current_user = host.user if hasattr(host, 'user') else None
beeps46dadc92013-11-07 14:07:10 -0800139 try:
Simran Basi14622bb2015-11-25 13:23:40 -0800140 if not (host.hostname == 'localhost' or
141 host.verify_ssh_user_access()):
Simran Basi1621c632015-10-14 12:22:23 -0700142 host.user = 'adb'
Simran Basi933c8af2015-04-29 14:05:07 -0700143 result = host.run(
Dan Shia2872172015-10-31 01:16:51 -0700144 'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
Simran Basi933c8af2015-04-29 14:05:07 -0700145 timeout=timeout)
beeps46dadc92013-11-07 14:07:10 -0800146 except (error.AutoservRunError, error.AutoservSSHTimeout):
Dan Shi64e130f2015-12-16 14:45:44 -0800147 if current_user is not None:
148 host.user = current_user
beeps46dadc92013-11-07 14:07:10 -0800149 return False
150 return result.exit_status == 0
151
152
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700153 # TODO(garnold) Remove the 'serials' argument once all clients are made to
154 # not use it.
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700155 def _initialize(self, hostname='localhost', serials=None,
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700156 adb_serial=None, fastboot_serial=None,
Kevin Cheng549beb42015-11-18 11:42:25 -0800157 device_hostname=None, teststation=None, *args, **dargs):
Simran Basi431010f2013-09-04 10:42:41 -0700158 """Initialize an ADB Host.
159
160 This will create an ADB Host. Hostname should always refer to the
Kevin Chengd19e6c62015-10-28 16:39:39 -0700161 test station connected to an Android DUT. This will be the DUT
162 to test with. If there are multiple, serial must be specified or an
163 exception will be raised. If device_hostname is supplied then all
164 ADB commands will run over TCP/IP.
Simran Basi431010f2013-09-04 10:42:41 -0700165
166 @param hostname: Hostname of the machine running ADB.
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700167 @param serials: DEPRECATED (to be removed)
168 @param adb_serial: An ADB device serial. If None, assume a single
169 device is attached (and fail otherwise).
170 @param fastboot_serial: A fastboot device serial. If None, defaults to
171 the ADB serial (or assumes a single device if
172 the latter is None).
Simran Basi431010f2013-09-04 10:42:41 -0700173 @param device_hostname: Hostname or IP of the android device we want to
174 interact with. If supplied all ADB interactions
175 run over TCP/IP.
Kevin Cheng549beb42015-11-18 11:42:25 -0800176 @param teststation: The teststation object ADBHost should use.
Simran Basi431010f2013-09-04 10:42:41 -0700177 """
Simran Basi1bf60eb2015-12-01 16:39:29 -0800178 # Sets up the is_client_install_supported field.
179 super(ADBHost, self)._initialize(hostname=hostname,
180 is_client_install_supported=False,
181 *args, **dargs)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700182 if device_hostname and (adb_serial or fastboot_serial):
183 raise error.AutoservError(
184 'TCP/IP and USB modes are mutually exclusive')
185
Kevin Cheng85e864a2015-11-30 11:49:34 -0800186
Kevin Chengd19e6c62015-10-28 16:39:39 -0700187 self.tmp_dirs = []
Kevin Chengc6a645a2015-12-18 11:15:10 -0800188 self.labels = base_label.LabelRetriever(adb_label.ADB_LABELS)
Simran Basi431010f2013-09-04 10:42:41 -0700189 self._device_hostname = device_hostname
190 self._use_tcpip = False
Simran Basi1bf60eb2015-12-01 16:39:29 -0800191 # TODO (sbasi/kevcheng): Once the teststation host is committed,
192 # refactor the serial retrieval.
193 adb_serial = adb_serial or self.host_attributes.get('serials', None)
Dan Shi50a412a2016-01-05 10:52:40 -0800194 self.adb_serial = adb_serial
195 self.fastboot_serial = fastboot_serial or adb_serial
Kevin Cheng85e864a2015-11-30 11:49:34 -0800196 self.teststation = (teststation if teststation
197 else teststation_host.create_teststationhost(hostname=hostname))
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700198
199 msg ='Initializing ADB device on host: %s' % hostname
200 if self._device_hostname:
201 msg += ', device hostname: %s' % self._device_hostname
Dan Shi50a412a2016-01-05 10:52:40 -0800202 if self.adb_serial:
203 msg += ', ADB serial: %s' % self.adb_serial
204 if self.fastboot_serial:
205 msg += ', fastboot serial: %s' % self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700206 logging.debug(msg)
207
Simran Basibeb2bb22016-02-03 15:25:48 -0800208 # Try resetting the ADB daemon on the device, however if we are
209 # creating the host to do a repair job, the device maybe inaccesible
210 # via ADB.
211 try:
212 self._reset_adbd_connection()
213 except (error.AutotestHostRunError, error.AutoservRunError) as e:
214 logging.error('Unable to reset the device adb daemon connection: '
215 '%s.', e)
Dan Shiab999722015-12-04 14:27:08 -0800216 self._os_type = None
217
Simran Basi431010f2013-09-04 10:42:41 -0700218
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700219 def _connect_over_tcpip_as_needed(self):
220 """Connect to the ADB device over TCP/IP if so configured."""
221 if not self._device_hostname:
222 return
223 logging.debug('Connecting to device over TCP/IP')
Dan Shi50a412a2016-01-05 10:52:40 -0800224 if self._device_hostname == self.adb_serial:
Simran Basi431010f2013-09-04 10:42:41 -0700225 # We previously had a connection to this device, restart the ADB
226 # server.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700227 self.adb_run('kill-server')
Simran Basi431010f2013-09-04 10:42:41 -0700228 # Ensure that connection commands don't run over TCP/IP.
229 self._use_tcpip = False
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700230 self.adb_run('tcpip 5555', timeout=10, ignore_timeout=True)
Simran Basi431010f2013-09-04 10:42:41 -0700231 time.sleep(2)
232 try:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700233 self.adb_run('connect %s' % self._device_hostname)
Simran Basi431010f2013-09-04 10:42:41 -0700234 except (error.AutoservRunError, error.CmdError) as e:
235 raise error.AutoservError('Failed to connect via TCP/IP: %s' % e)
236 # Allow ADB a bit of time after connecting before interacting with the
237 # device.
238 time.sleep(5)
239 # Switch back to using TCP/IP.
240 self._use_tcpip = True
241
242
Roshan Pius4d7540c2015-12-16 13:30:32 -0800243 def _restart_adbd_with_root_permissions(self):
244 """Restarts the adb daemon with root permissions."""
245 self.adb_run('root')
246 # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
247 time.sleep(1)
248 self.adb_run('wait-for-device')
249
250
251 def _reset_adbd_connection(self):
252 """Resets adbd connection to the device after a reboot/initialization"""
253 self._restart_adbd_with_root_permissions()
254 self._connect_over_tcpip_as_needed()
255
256
Kevin Cheng85e864a2015-11-30 11:49:34 -0800257 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800258 def adb_run(self, command, **kwargs):
Simran Basi431010f2013-09-04 10:42:41 -0700259 """Runs an adb command.
260
Kevin Chengd19e6c62015-10-28 16:39:39 -0700261 This command will launch on the test station.
Simran Basi431010f2013-09-04 10:42:41 -0700262
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700263 Refer to _device_run method for docstring for parameters.
264 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800265 return self._device_run(ADB_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700266
267
Kevin Cheng85e864a2015-11-30 11:49:34 -0800268 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800269 def fastboot_run(self, command, **kwargs):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700270 """Runs an fastboot command.
271
Kevin Chengd19e6c62015-10-28 16:39:39 -0700272 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700273
274 Refer to _device_run method for docstring for parameters.
275 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800276 return self._device_run(FASTBOOT_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700277
278
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700279 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700280 timeout=3600, ignore_status=False, ignore_timeout=False,
281 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
282 connect_timeout=30, options='', stdin=None, verbose=True,
283 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700284 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700285
Kevin Chengd19e6c62015-10-28 16:39:39 -0700286 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700287
Simran Basi431010f2013-09-04 10:42:41 -0700288 @param command: Command to run.
289 @param shell: If true the command runs in the adb shell otherwise if
290 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700291 reboot with shell=False will call 'adb reboot'. This
292 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700293 @param timeout: Time limit in seconds before attempting to
294 kill the running process. The run() function
295 will take a few seconds longer than 'timeout'
296 to complete if it has to kill the process.
297 @param ignore_status: Do not raise an exception, no matter
298 what the exit code of the command is.
299 @param ignore_timeout: Bool True if command timeouts should be
300 ignored. Will return None on command timeout.
301 @param stdout: Redirect stdout.
302 @param stderr: Redirect stderr.
303 @param connect_timeout: Connection timeout (in seconds)
304 @param options: String with additional ssh command options
305 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700306 @param require_sudo: True to require sudo to run the command. Default is
307 False.
Simran Basi431010f2013-09-04 10:42:41 -0700308 @param args: Sequence of strings to pass as arguments to command by
309 quoting them in " and escaping their contents if
310 necessary.
311
312 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700313 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700314 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800315 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700316 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800317 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700318 else:
319 raise NotImplementedError('Mode %s is not supported' % function)
320
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700321 if function != ADB_CMD and shell:
322 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700323
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700324 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700325
326 if serial:
327 cmd += '-s %s ' % serial
328 elif self._use_tcpip:
Simran Basi431010f2013-09-04 10:42:41 -0700329 cmd += '-s %s:5555 ' % self._device_hostname
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700330
Simran Basi431010f2013-09-04 10:42:41 -0700331 if shell:
332 cmd += '%s ' % SHELL_CMD
333 cmd += command
334
Roshan Pius58e5dd32015-10-16 15:16:42 -0700335 if verbose:
336 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700337
Kevin Cheng85e864a2015-11-30 11:49:34 -0800338 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400339 ignore_status=ignore_status,
340 ignore_timeout=ignore_timeout, stdout_tee=stdout,
341 stderr_tee=stderr, options=options, stdin=stdin,
342 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700343
344
Dan Shie234dea2016-01-20 17:15:17 -0800345 def get_board_name(self):
346 """Get the name of the board, e.g., shamu, dragonboard etc.
347 """
348 return self.run_output('getprop %s' % BOARD_FILE)
349
350
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700351 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700352 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700353 """Determine the correct board label for the device.
354
355 @returns a string representing this device's board.
356 """
Dan Shie234dea2016-01-20 17:15:17 -0800357 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700358 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800359 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700360
361
Christopher Wiley08849d52013-11-22 08:57:58 -0800362 def job_start(self):
363 """
364 Disable log collection on adb_hosts.
365
366 TODO(sbasi): crbug.com/305427
Christopher Wiley08849d52013-11-22 08:57:58 -0800367 """
368
369
Simran Basi431010f2013-09-04 10:42:41 -0700370 def run(self, command, timeout=3600, ignore_status=False,
371 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
372 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700373 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700374 """Run a command on the adb device.
375
376 The command given will be ran directly on the adb device; for example
377 'ls' will be ran as: 'abd shell ls'
378
379 @param command: The command line string.
380 @param timeout: Time limit in seconds before attempting to
381 kill the running process. The run() function
382 will take a few seconds longer than 'timeout'
383 to complete if it has to kill the process.
384 @param ignore_status: Do not raise an exception, no matter
385 what the exit code of the command is.
386 @param ignore_timeout: Bool True if command timeouts should be
387 ignored. Will return None on command timeout.
388 @param stdout_tee: Redirect stdout.
389 @param stderr_tee: Redirect stderr.
390 @param connect_timeout: Connection timeout (in seconds).
391 @param options: String with additional ssh command options.
392 @param stdin: Stdin to pass (a string) to the executed command
393 @param args: Sequence of strings to pass as arguments to command by
394 quoting them in " and escaping their contents if
395 necessary.
396
397 @returns A CMDResult object or None if the call timed out and
398 ignore_timeout is True.
399
400 @raises AutoservRunError: If the command failed.
401 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700402 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700403 command = ('"%s; echo %s:\$?"' %
404 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700405 result = self.adb_run(
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700406 command, shell=True, timeout=timeout,
Simran Basi431010f2013-09-04 10:42:41 -0700407 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
408 stdout=stdout_tee, stderr=stderr_tee,
409 connect_timeout=connect_timeout, options=options, stdin=stdin,
Roshan Pius58e5dd32015-10-16 15:16:42 -0700410 verbose=verbose, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700411 if not result:
412 # In case of timeouts.
413 return None
414
415 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
Roshan Pius5ba5d182015-10-28 09:19:41 -0700416 if not parse_output and not ignore_status:
Simran Basi431010f2013-09-04 10:42:41 -0700417 raise error.AutoservRunError(
Roshan Pius5ba5d182015-10-28 09:19:41 -0700418 'Failed to parse the exit code for command: %s' %
419 command, result)
420 elif parse_output:
421 result.stdout = parse_output.group('OUTPUT')
422 result.exit_status = int(parse_output.group('EXIT_CODE'))
423 if result.exit_status != 0 and not ignore_status:
424 raise error.AutoservRunError(command, result)
Simran Basi431010f2013-09-04 10:42:41 -0700425 return result
426
427
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700428 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
429 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700430
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700431 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700432
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700433 @param timeout: Time limit in seconds before returning even if the host
434 is not up.
435 @param command: The command used to test if a device is up, i.e.,
436 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700437
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700438 @returns True if the host was found to be up before the timeout expires,
439 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700440 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700441 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
442 delay_sec=1)
443 def _wait_up():
444 if not self.is_up(command=command):
445 raise error.TimeoutException('Device is still down.')
446 return True
447
448 try:
449 _wait_up()
450 logging.debug('Host %s is now up, and can be accessed by %s.',
451 self.hostname, command)
452 return True
453 except error.TimeoutException:
454 logging.debug('Host %s is still down after waiting %d seconds',
455 self.hostname, timeout)
456 return False
Simran Basi431010f2013-09-04 10:42:41 -0700457
458
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700459 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
460 warning_timer=None, old_boot_id=None, command=ADB_CMD):
461 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700462
463 Overrides wait_down from AbstractSSHHost.
464
465 @param timeout: Time in seconds to wait for the host to go down.
466 @param warning_timer: Time limit in seconds that will generate
467 a warning if the host is not down yet.
468 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700469 @param old_boot_id: Not applicable for adb_host.
470 @param command: `adb`, test if the device can be accessed by adb
471 command, or `fastboot`, test if the device can be accessed by
472 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700473
474 @returns True if the device goes down before the timeout, False
475 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700476 """
477 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
478 delay_sec=1)
479 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700480 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700481 raise error.TimeoutException('Device is still up.')
482 return True
483
484 try:
485 _wait_down()
486 logging.debug('Host %s is now down', self.hostname)
487 return True
488 except error.TimeoutException:
489 logging.debug('Host %s is still up after waiting %d seconds',
490 self.hostname, timeout)
491 return False
492
493
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700494 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700495 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700496
497 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700498 """
499 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700500 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700501 self.adb_run('reboot', timeout=10, ignore_timeout=True)
502 if not self.wait_down():
503 raise error.AutoservRebootError(
504 'ADB Device is still up after reboot')
505 if not self.wait_up():
506 raise error.AutoservRebootError(
507 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800508 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800509
510
Ralph Nathanb45eb672015-11-18 20:04:39 -0800511 def remount(self):
512 """Remounts paritions on the device read-write.
513
514 Specifically, the /system, /vendor (if present) and /oem (if present)
515 partitions on the device are remounted read-write.
516 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800517 self.adb_run('remount')
518
519
Kevin Cheng549beb42015-11-18 11:42:25 -0800520 @staticmethod
521 def parse_device_serials(devices_output):
522 """Return a list of parsed serials from the output.
523
524 @param devices_output: Output from either an adb or fastboot command.
525
526 @returns List of device serials
527 """
528 devices = []
529 for line in devices_output.splitlines():
530 match = re.search(DEVICE_FINDER_REGEX, line)
531 if match:
532 serial = match.group('SERIAL')
533 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
534 serial = DEVICE_NO_SERIAL_TAG
535 logging.debug('Found Device: %s', serial)
536 devices.append(serial)
537 return devices
538
539
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700540 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700541 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700542
543 @params use_adb: True to get adb accessible devices. Set to False to
544 get fastboot accessible devices.
545
Kevin Chengd19e6c62015-10-28 16:39:39 -0700546 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700547 """
548 if use_adb:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700549 result = self.adb_run('devices')
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700550 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700551 result = self.fastboot_run('devices')
Kevin Cheng549beb42015-11-18 11:42:25 -0800552 return self.parse_device_serials(result.stdout)
Simran Basi431010f2013-09-04 10:42:41 -0700553
554
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700555 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700556 """Get a list of devices currently attached to the test station and
557 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700558 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800559 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700560 raise error.AutoservError(
561 'Not given ADB serial but multiple devices detected')
562 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700563
564
565 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700566 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700567 accessible by fastboot command.
568 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700569 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800570 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700571 raise error.AutoservError(
572 'Not given fastboot serial but multiple devices detected')
573 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700574
575
576 def is_up(self, timeout=0, command=ADB_CMD):
577 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700578
579 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700580 @param command: `adb`, the device can be accessed by adb command,
581 or `fastboot`, the device can be accessed by fastboot command.
582 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700583
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700584 @returns True if the device is detectable by given command, False
585 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700586
587 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700588 if command == ADB_CMD:
589 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800590 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800591 # ADB has a device state, if the device is not online, no
592 # subsequent ADB command will complete.
Dan Shi18848d42016-03-09 13:25:28 -0800593 if serial not in devices or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800594 logging.debug('Waiting for device to enter the ready state.')
595 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700596 elif command == FASTBOOT_CMD:
597 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800598 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700599 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700600 raise NotImplementedError('Mode %s is not supported' % command)
601
602 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700603
604
605 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700606 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700607
608 Called as the test ends. Will return the device to USB mode and kill
609 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700610 """
611 if self._use_tcpip:
612 # Return the device to usb mode.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400613 self.adb_run('usb')
Christopher Wiley08849d52013-11-22 08:57:58 -0800614 # TODO(sbasi) Originally, we would kill the server after each test to
615 # reduce the opportunity for bad server state to hang around.
616 # Unfortunately, there is a period of time after each kill during which
617 # the Android device becomes unusable, and if we start the next test
618 # too quickly, we'll get an error complaining about no ADB device
619 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700620 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800621 # |close| the associated teststation as well.
622 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700623 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700624
625
626 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700627 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700628
629 @param message String message to log into syslog
630 @param tag String tag prefix for syslog
631
632 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700633 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700634
635
636 def get_autodir(self):
637 """Return the directory to install autotest for client side tests."""
638 return '/data/autotest'
639
Kevin Cheng018db352015-09-20 02:22:08 -0700640
Kris Rambishde8f9d12015-12-16 12:42:41 -0800641 def is_device_ready(self):
642 """Return the if the device is ready for ADB commands."""
643 dev_state = self.adb_run('get-state').stdout.strip()
644 logging.debug('Current device state: %s', dev_state)
645 return dev_state == 'device'
646
647
Kevin Chengd19e6c62015-10-28 16:39:39 -0700648 def verify_connectivity(self):
649 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800650 if not self.is_device_ready():
651 raise error.AutoservHostError('device state is not in the '
652 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700653
654
Simran Basid3ba3fb2015-09-11 14:35:07 -0700655 def verify_software(self):
656 """Verify working software on an adb_host.
657
Simran Basi38f7ddf2015-09-18 12:25:03 -0700658 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700659 """
Dan Shiab999722015-12-04 14:27:08 -0800660 # Check if adb and fastboot are present.
661 self.teststation.run('which adb')
662 self.teststation.run('which fastboot')
663 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700664
Kevin Cheng018db352015-09-20 02:22:08 -0700665
Simran Basid3ba3fb2015-09-11 14:35:07 -0700666 def verify_job_repo_url(self, tag=''):
667 """Make sure job_repo_url of this host is valid.
668
Simran Basi38f7ddf2015-09-18 12:25:03 -0700669 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700670
671 @param tag: The tag from the server job, in the format
672 <job_id>-<user>/<hostname>, or <hostless> for a server job.
673 """
674 return
Kevin Cheng018db352015-09-20 02:22:08 -0700675
676
Simran Basibeb2bb22016-02-03 15:25:48 -0800677 def repair(self):
678 """Attempt to get the DUT to pass `self.verify()`."""
679 try:
680 self.ensure_adb_mode(timeout=30)
681 return
682 except error.AutoservError as e:
683 logging.error(e)
684 logging.debug('Verifying the device is accessible via fastboot.')
685 self.ensure_bootloader_mode()
686 if not self.job.run_test(
687 'provision_AndroidUpdate', host=self, value=None,
688 force=True, repair=True):
689 raise error.AutoservRepairTotalFailure(
690 'Unable to repair the device.')
691
692
Simran Basi1b023762015-09-25 12:12:20 -0700693 def send_file(self, source, dest, delete_dest=False,
694 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700695 """Copy files from the drone to the device.
696
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400697 Just a note, there is the possibility the test station is localhost
698 which makes some of these steps redundant (e.g. creating tmp dir) but
699 that scenario will undoubtedly be a development scenario (test station
700 is also the moblab) and not the typical live test running scenario so
701 the redundancy I think is harmless.
702
Kevin Cheng018db352015-09-20 02:22:08 -0700703 @param source: The file/directory on the drone to send to the device.
704 @param dest: The destination path on the device to copy to.
705 @param delete_dest: A flag set to choose whether or not to delete
706 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700707 @param preserve_symlinks: Controls if symlinks on the source will be
708 copied as such on the destination or
709 transformed into the referenced
710 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700711 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700712 # If we need to preserve symlinks, let's check if the source is a
713 # symlink itself and if so, just create it on the device.
714 if preserve_symlinks:
715 symlink_target = None
716 try:
717 symlink_target = os.readlink(source)
718 except OSError:
719 # Guess it's not a symlink.
720 pass
721
722 if symlink_target is not None:
723 # Once we create the symlink, let's get out of here.
724 self.run('ln -s %s %s' % (symlink_target, dest))
725 return
726
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400727 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700728 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400729 src_path = os.path.join(tmp_dir, os.path.basename(dest))
730 # Now copy the file over to the test station so you can reference the
731 # file in the push command.
732 self.teststation.send_file(source, src_path,
733 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700734
735 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400736 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700737
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700738 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700739
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400740 # Cleanup the test station.
741 try:
742 self.teststation.run('rm -rf %s' % tmp_dir)
743 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
744 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700745
746
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700747 def _get_file_info(self, dest):
748 """Get permission and possible symlink info about file on the device.
749
750 These files are on the device so we only have shell commands (via adb)
751 to get the info we want. We'll use 'ls' to get it all.
752
753 @param dest: File to get info about.
754
755 @returns a dict of the file permissions and symlink.
756 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800757 # Grab file info.
758 file_info = self.run_output('ls -l %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700759 symlink = None
760 perms = 0
761 match = re.match(FILE_INFO_REGEX, file_info)
762 if match:
763 # Check if it's a symlink and grab the linked dest if it is.
764 if match.group('TYPE') == 'l':
765 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
766 if symlink_match:
767 symlink = symlink_match.group('SYMLINK')
768
769 # Set the perms.
770 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
771 if perm != '-':
772 perms |= perm_flag
773
774 return {'perms': perms,
775 'symlink': symlink}
776
777
Simran Basi1b023762015-09-25 12:12:20 -0700778 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
779 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700780 """Copy files from the device to the drone.
781
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400782 Just a note, there is the possibility the test station is localhost
783 which makes some of these steps redundant (e.g. creating tmp dir) but
784 that scenario will undoubtedly be a development scenario (test station
785 is also the moblab) and not the typical live test running scenario so
786 the redundancy I think is harmless.
787
Kevin Cheng018db352015-09-20 02:22:08 -0700788 @param source: The file/directory on the device to copy back to the
789 drone.
790 @param dest: The destination path on the drone to copy to.
791 @param delete_dest: A flag set to choose whether or not to delete
792 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700793 @param preserve_perm: Tells get_file() to try to preserve the sources
794 permissions on files and dirs.
795 @param preserve_symlinks: Try to preserve symlinks instead of
796 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -0700797 """
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400798 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700799 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400800 dest_path = os.path.join(tmp_dir, os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -0700801
802 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400803 self.teststation.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700804
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700805 source_info = {}
806 if preserve_symlinks or preserve_perm:
807 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -0700808
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700809 # If we want to preserve symlinks, just create it here, otherwise pull
810 # the file off the device.
811 if preserve_symlinks and source_info['symlink']:
812 os.symlink(source_info['symlink'], dest)
813 else:
Roshan Pius95567142015-11-03 09:56:08 -0800814 self.adb_run('pull %s %s' % (source, dest_path))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700815
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400816 # Copy over the file from the test station and clean up.
817 self.teststation.get_file(dest_path, dest)
818 try:
819 self.teststation.run('rm -rf %s' % tmp_dir)
820 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
821 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700822
823 if preserve_perm:
824 os.chmod(dest, source_info['perms'])
Kevin Cheng018db352015-09-20 02:22:08 -0700825
826
827 def get_release_version(self):
828 """Get the release version from the RELEASE_FILE on the device.
829
830 @returns The release string in the RELEASE_FILE.
831
832 """
833 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -0700834
835
836 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700837 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -0700838
Kevin Chengd19e6c62015-10-28 16:39:39 -0700839 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -0700840
841 @param parent: Parent directory of the returned tmp dir.
842
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700843 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -0700844 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700845 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
846 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -0700847 if not parent.startswith(TMP_DIR):
848 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -0700849 self.run('mkdir -p %s' % parent)
850 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
851 self.tmp_dirs.append(tmp_dir)
852 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -0700853
854
855 def get_platform(self):
856 """Determine the correct platform label for this host.
857
858 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -0700859 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -0700860
861 @returns a string representing this host's platform.
862 """
863 return 'adb'
864
865
Gilad Arnolda76bef02015-09-29 13:55:15 -0700866 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -0800867 """Get the OS type of the DUT, e.g., android or brillo.
868 """
869 if not self._os_type:
870 if self.run_output('getprop ro.product.brand') == 'Brillo':
871 self._os_type = OS_TYPE_BRILLO
872 else:
873 self._os_type = OS_TYPE_ANDROID
874
875 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -0700876
877
878 def _forward(self, reverse, args):
879 """Execute a forwarding command.
880
881 @param reverse: Whether this is reverse forwarding (Boolean).
882 @param args: List of command arguments.
883 """
884 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700885 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -0700886
887
888 def add_forwarding(self, src, dst, reverse=False, rebind=True):
889 """Forward a port between the ADB host and device.
890
891 Port specifications are any strings accepted as such by ADB, for
892 example 'tcp:8080'.
893
894 @param src: Port specification to forward from.
895 @param dst: Port specification to forward to.
896 @param reverse: Do reverse forwarding from device to host (Boolean).
897 @param rebind: Allow rebinding an already bound port (Boolean).
898 """
899 args = []
900 if not rebind:
901 args.append('--no-rebind')
902 args += [src, dst]
903 self._forward(reverse, args)
904
905
906 def remove_forwarding(self, src=None, reverse=False):
907 """Removes forwarding on port.
908
909 @param src: Port specification, or None to remove all forwarding.
910 @param reverse: Whether this is reverse forwarding (Boolean).
911 """
912 args = []
913 if src is None:
914 args.append('--remove-all')
915 else:
916 args += ['--remove', src]
917 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -0700918
919
xixuan6cf6d2f2016-01-29 15:29:00 -0800920 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -0700921 """
922 Forwards a port securely through a tunnel process from the server
923 to the DUT for RPC server connection.
924 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
925 to the DUT.
926
927 @param port: remote port on the DUT.
928 @param local_port: local forwarding port.
929
930 @return: the tunnel process.
931 """
932 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -0800933 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -0700934
935
xixuan6cf6d2f2016-01-29 15:29:00 -0800936 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -0700937 """
938 Disconnects a previously forwarded port from the server to the DUT for
939 RPC server connection.
940 Remove the previously added 'ADB forward' rule to forward the RPC
941 packets from the AdbHost to the DUT.
942
943 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -0800944 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -0700945 @param port: remote port on the DUT.
946
947 """
948 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -0800949 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700950
951
952 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700953 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700954
955 @raise: error.AutoservError if the device failed to reboot into
956 bootloader mode.
957 """
958 if self.is_up(command=FASTBOOT_CMD):
959 return
960 self.adb_run('reboot bootloader')
961 if not self.wait_up(command=FASTBOOT_CMD):
962 raise error.AutoservError(
963 'The device failed to reboot into bootloader mode.')
964
965
Dan Shie4e807b2015-12-10 09:04:03 -0800966 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700967 """Ensure the device is up and can be accessed by adb command.
968
Dan Shie4e807b2015-12-10 09:04:03 -0800969 @param timeout: Time limit in seconds before returning even if the host
970 is not up.
971
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700972 @raise: error.AutoservError if the device failed to reboot into
973 adb mode.
974 """
975 if self.is_up():
976 return
977 self.fastboot_run('reboot')
Dan Shie4e807b2015-12-10 09:04:03 -0800978 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700979 raise error.AutoservError(
980 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800981 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -0700982
983
984 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -0800985 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -0700986 """Get the Android build information from the build url.
987
988 @param build_url: The url to use for downloading Android artifacts.
989 pattern: http://$devserver:###/static/branch/target/build_id
990
991 @return: A dictionary of build information, including keys: board,
992 branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -0800993 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -0700994 """
Dan Shiab999722015-12-04 14:27:08 -0800995 if not build_url:
996 raise AndroidInstallError('Need build_url to download image files.')
997
998 try:
999 match = re.match(DEVSERVER_URL_REGEX, build_url)
1000 return {'board': match.group('BOARD'),
1001 'branch': match.group('BRANCH'),
1002 'target': ('%s-%s' % (match.group('BOARD'),
1003 match.group('BUILD_TYPE'))),
1004 'build_id': match.group('BUILD_ID')}
1005 except (AttributeError, IndexError, ValueError) as e:
1006 raise AndroidInstallError(
1007 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001008
1009
Dan Shia2872172015-10-31 01:16:51 -07001010 @retry.retry(error.AutoservRunError, timeout_min=10)
Dan Shidb0366c2016-02-19 10:36:18 -08001011 def download_file(self, build_url, file, dest_dir):
Dan Shia2872172015-10-31 01:16:51 -07001012 """Download the given file from the build url.
1013
1014 @param build_url: The url to use for downloading Android artifacts.
1015 pattern: http://$devserver:###/static/branch/target/build_id
1016 @param file: Name of the file to be downloaded, e.g., boot.img.
1017 @param dest_dir: Destination folder for the file to be downloaded to.
1018 """
Dan Shidb0366c2016-02-19 10:36:18 -08001019 # Append the file name to the url if build_url is linked to the folder
1020 # containing the file.
1021 if not build_url.endswith('/%s' % file):
1022 src_url = os.path.join(build_url, file)
1023 else:
1024 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001025 dest_file = os.path.join(dest_dir, file)
1026 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001027 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Dan Shia2872172015-10-31 01:16:51 -07001028 except:
1029 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001030 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001031 raise
1032
1033
Dan Shiab999722015-12-04 14:27:08 -08001034 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001035 """Download required image files from the given build_url to a local
1036 directory in the machine runs fastboot command.
1037
1038 @param build_url: The url to use for downloading Android artifacts.
1039 pattern: http://$devserver:###/static/branch/target/build_id
1040
1041 @return: Path to the directory contains image files.
1042 """
Dan Shi08ff1282016-02-18 19:51:16 -08001043 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001044
1045 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001046 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001047 image_files = [zipped_image_file] + ANDROID_STANDALONE_IMAGES
1048
1049 try:
1050 for image_file in image_files:
Dan Shidb0366c2016-02-19 10:36:18 -08001051 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001052
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001053 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1054 (image_dir, zipped_image_file, image_dir))
Dan Shia2872172015-10-31 01:16:51 -07001055
1056 return image_dir
1057 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001058 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001059 raise
1060
1061
Dan Shiab999722015-12-04 14:27:08 -08001062 def stage_brillo_image_files(self, build_url):
1063 """Download required brillo image files from the given build_url to a
1064 local directory in the machine runs fastboot command.
1065
1066 @param build_url: The url to use for downloading Android artifacts.
1067 pattern: http://$devserver:###/static/branch/target/build_id
1068
1069 @return: Path to the directory contains image files.
1070 """
Dan Shi08ff1282016-02-18 19:51:16 -08001071 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001072
1073 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1074 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1075 image_dir = self.teststation.get_tmp_dir()
1076 image_files = [zipped_image_file, vendor_partitions_file]
1077
1078 try:
1079 for image_file in image_files:
Dan Shidb0366c2016-02-19 10:36:18 -08001080 self.download_file(build_url, image_file, image_dir)
Dan Shiab999722015-12-04 14:27:08 -08001081
1082 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1083 (image_dir, zipped_image_file, image_dir))
1084 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1085 (image_dir, vendor_partitions_file,
1086 os.path.join(image_dir, 'vendor')))
1087 return image_dir
1088 except:
1089 self.teststation.run('rm -rf %s' % image_dir)
1090 raise
1091
1092
Simran Basibeb2bb22016-02-03 15:25:48 -08001093 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001094 """Stage a build on a devserver and return the build_url and devserver.
1095
1096 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001097
Dan Shi225b9042015-11-18 10:25:21 -08001098 @returns a tuple with an update URL like:
1099 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1100 and the devserver instance.
1101 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001102 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001103 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001104 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1105 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001106 build_name = devserver.translate(build_name)
1107 branch, target, build_id = utils.parse_android_build(build_name)
Simran Basibeb2bb22016-02-03 15:25:48 -08001108 is_brillo = os_type == OS_TYPE_BRILLO
Dan Shi08ff1282016-02-18 19:51:16 -08001109 devserver.trigger_download(target, build_id, branch,
1110 is_brillo=is_brillo, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001111 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001112
1113
Dan Shie4e807b2015-12-10 09:04:03 -08001114 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001115 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001116 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001117
1118 Following are the steps used here to provision an android device:
1119 1. If build_local_path is not set, download the image zip file, e.g.,
1120 shamu-img-2284311.zip, unzip it.
1121 2. Run fastboot to install following artifacts:
1122 bootloader, radio, boot, system, vendor(only if exists)
1123
1124 Repair is not supported for Android devices yet.
1125
1126 @param build_url: The url to use for downloading Android artifacts.
1127 pattern: http://$devserver:###/static/$build
1128 @param build_local_path: The path to a local folder that contains the
1129 image files needed to provision the device. Note that the folder
1130 is in the machine running adb command, rather than the drone.
1131 @param wipe: If true, userdata will be wiped before flashing.
1132 @param flash_all: If True, all img files found in img_path will be
1133 flashed. Otherwise, only boot and system are flashed.
1134
1135 @raises AndroidInstallError if any error occurs.
1136 """
Dan Shia2872172015-10-31 01:16:51 -07001137 # If the build is not staged in local server yet, clean up the temp
1138 # folder used to store image files after the provision is completed.
1139 delete_build_folder = bool(not build_local_path)
1140
1141 try:
1142 # Download image files needed for provision to a local directory.
1143 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001144 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001145
1146 # Device needs to be in bootloader mode for flashing.
1147 self.ensure_bootloader_mode()
1148
1149 if wipe:
Dan Shie4e807b2015-12-10 09:04:03 -08001150 self.fastboot_run('-w')
Dan Shia2872172015-10-31 01:16:51 -07001151
1152 # Get all *.img file in the build_local_path.
1153 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001154 image_files = self.teststation.run(
1155 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001156 images = dict([(os.path.basename(f), f) for f in image_files])
1157 for image, image_file in images.items():
1158 if image not in ANDROID_IMAGES:
1159 continue
1160 logging.info('Flashing %s...', image_file)
Dan Shie9913d32016-03-09 14:17:26 -08001161 self.fastboot_run('-S 512M flash %s %s' %
1162 (image[:-4], image_file))
Dan Shia2872172015-10-31 01:16:51 -07001163 if image == ANDROID_BOOTLOADER:
1164 self.fastboot_run('reboot-bootloader')
1165 self.wait_up(command=FASTBOOT_CMD)
1166 except Exception as e:
1167 logging.error('Install Android build failed with error: %s', e)
1168 # Re-raise the exception with type of AndroidInstallError.
1169 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1170 finally:
1171 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001172 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001173 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1174 DEFAULT_WAIT_UP_TIME_SECONDS)
1175 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001176 logging.info('Successfully installed Android build staged at %s.',
1177 build_url)
1178
1179
Dan Shiab999722015-12-04 14:27:08 -08001180 def install_brillo(self, build_url, build_local_path=None):
1181 """Install the Brillo DUT.
1182
1183 Following are the steps used here to provision an android device:
1184 1. If build_local_path is not set, download the image zip file, e.g.,
1185 dragonboard-img-123456.zip, unzip it. And download the vendor
1186 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1187 unzip it to vendor folder.
1188 2. Run provision_device script to install OS images and vendor
1189 partitions.
1190
1191 @param build_url: The url to use for downloading Android artifacts.
1192 pattern: http://$devserver:###/static/$build
1193 @param build_local_path: The path to a local folder that contains the
1194 image files needed to provision the device. Note that the folder
1195 is in the machine running adb command, rather than the drone.
1196
1197 @raises AndroidInstallError if any error occurs.
1198 """
1199 # If the build is not staged in local server yet, clean up the temp
1200 # folder used to store image files after the provision is completed.
1201 delete_build_folder = bool(not build_local_path)
1202
Dan Shiab999722015-12-04 14:27:08 -08001203 try:
1204 # Download image files needed for provision to a local directory.
1205 if not build_local_path:
1206 build_local_path = self.stage_brillo_image_files(build_url)
1207
1208 # Device needs to be in bootloader mode for flashing.
1209 self.ensure_bootloader_mode()
1210
1211 # Run provision_device command to install image files and vendor
1212 # partitions.
1213 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1214 cmd = (BRILLO_PROVISION_CMD %
1215 {'os_image_dir': build_local_path,
1216 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001217 if self.fastboot_serial:
Dan Shi91b42352016-03-10 22:12:22 -08001218 cmd += ' -s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001219 self.teststation.run(cmd)
1220 except Exception as e:
1221 logging.error('Install Brillo build failed with error: %s', e)
1222 # Re-raise the exception with type of AndroidInstallError.
1223 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1224 finally:
1225 if delete_build_folder:
1226 self.teststation.run('rm -rf %s' % build_local_path)
1227 self.ensure_adb_mode()
1228 logging.info('Successfully installed Android build staged at %s.',
1229 build_url)
1230
1231
Dan Shibe3636a2016-02-14 22:48:01 -08001232 @property
1233 def job_repo_url_attribute(self):
1234 """Get the host attribute name for job_repo_url, which should append the
1235 adb serial.
1236 """
1237 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1238
1239
Dan Shie4e807b2015-12-10 09:04:03 -08001240 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001241 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001242 """Install the DUT.
1243
1244 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001245 pattern: http://$devserver:###/static/$build. If build_url is
1246 set to None, the code may try _parser.options.image to do the
1247 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001248 @param build_local_path: The path to a local directory that contains the
1249 image files needed to provision the device.
1250 @param wipe: If true, userdata will be wiped before flashing.
1251 @param flash_all: If True, all img files found in img_path will be
1252 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001253
Dan Shibe3636a2016-02-14 22:48:01 -08001254 @returns A tuple of (image_name, host_attributes).
1255 image_name is the name of image installed, e.g.,
1256 git_mnc-release/shamu-userdebug/1234
1257 host_attributes is a dictionary of (attribute, value), which
1258 can be saved to afe_host_attributes table in database. This
1259 method returns a dictionary with a single entry of
1260 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1261 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001262 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001263 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001264 if not build_url and self._parser.options.image:
1265 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001266 self._parser.options.image, os_type=os_type)
1267 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001268 self.install_android(
1269 build_url=build_url, build_local_path=build_local_path,
1270 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001271 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001272 self.install_brillo(
1273 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001274 else:
1275 raise error.InstallError(
1276 'Installation of os type %s is not supported.' %
1277 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001278 return (build_url.split('static/')[-1],
1279 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001280
1281
1282 def list_files_glob(self, path_glob):
1283 """Get a list of files on the device given glob pattern path.
1284
1285 @param path_glob: The path glob that we want to return the list of
1286 files that match the glob. Relative paths will not work as
1287 expected. Supply an absolute path to get the list of files
1288 you're hoping for.
1289
1290 @returns List of files that match the path_glob.
1291 """
1292 # This is just in case path_glob has no path separator.
1293 base_path = os.path.dirname(path_glob) or '.'
1294 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001295 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001296 if result.exit_status != 0:
1297 return []
1298 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001299
1300
Dan Shidb0366c2016-02-19 10:36:18 -08001301 def install_apk(self, apk, force_reinstall=False):
Kevin Cheng31355942016-01-05 14:23:35 -08001302 """Install the specified apk.
1303
1304 This will install the apk and override it if it's already installed and
1305 will also allow for downgraded apks.
1306
1307 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001308 @param force_reinstall: True to reinstall the apk even if it's already
1309 installed. Default is set to False.
1310
1311 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001312 """
Dan Shidb0366c2016-02-19 10:36:18 -08001313 return self.adb_run('install %s -d %s' %
1314 ('-r' if force_reinstall else '', apk))
1315
1316
1317 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1318 def _confirm_apk_installed(self, package_name):
1319 """Confirm if apk is already installed with the given name.
1320
1321 `pm list packages` command is not reliable some time. The retry helps to
1322 reduce the chance of false negative.
1323
1324 @param package_name: Name of the package, e.g., com.android.phone.
1325
1326 @raise AutoservRunError: If the package is not found or pm list command
1327 failed for any reason.
1328 """
1329 name = 'package:%s' % package_name
1330 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1331
1332
1333 def is_apk_installed(self, package_name):
1334 """Check if apk is already installed with the given name.
1335
1336 @param package_name: Name of the package, e.g., com.android.phone.
1337
1338 @return: True if package is installed. False otherwise.
1339 """
1340 try:
1341 self._confirm_apk_installed(package_name)
1342 return True
1343 except:
1344 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001345
1346
1347 def get_attributes_to_clear_before_provision(self):
1348 """Get a list of attributes to be cleared before machine_install starts.
1349 """
1350 return [self.job_repo_url_attribute]
Kevin Chengc6a645a2015-12-18 11:15:10 -08001351
1352
1353 def get_labels(self):
1354 """Return a list of the labels gathered from the devices connected.
1355
1356 @return: A list of strings that denote the labels from all the devices
1357 connected.
1358 """
1359 return self.labels.get_labels(self)
1360
1361
1362 def update_labels(self):
1363 """Update the labels for this testbed."""
1364 self.labels.update_labels(self)