blob: fb34da6355f19f0db8a79f55d06b5cd00ef2cb73 [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 Cheng85e864a2015-11-30 11:49:34 -080023from autotest_lib.server.hosts import teststation_host
Simran Basi431010f2013-09-04 10:42:41 -070024
25
Dan Shi6ea3e1c2015-10-28 15:19:04 -070026ADB_CMD = 'adb'
27FASTBOOT_CMD = 'fastboot'
Simran Basi431010f2013-09-04 10:42:41 -070028SHELL_CMD = 'shell'
Filipe Brandenburger34363392015-08-13 14:57:45 -070029# Some devices have no serial, then `adb serial` has output such as:
30# (no serial number) device
31# ?????????? device
32DEVICE_NO_SERIAL_MSG = '(no serial number)'
33DEVICE_NO_SERIAL_TAG = '<NO_SERIAL>'
Simran Basi431010f2013-09-04 10:42:41 -070034# Regex to find an adb device. Examples:
35# 0146B5580B01801B device
36# 018e0ecb20c97a62 device
37# 172.22.75.141:5555 device
Mike Frysinger5d7a7092016-02-23 15:14:42 -050038DEVICE_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 -070039 re.escape(DEVICE_NO_SERIAL_MSG) +
Mike Frysinger5d7a7092016-02-23 15:14:42 -050040 r')([:]5555)?[ \t]+(?:device|fastboot)')
Simran Basi431010f2013-09-04 10:42:41 -070041CMD_OUTPUT_PREFIX = 'ADB_CMD_OUTPUT'
42CMD_OUTPUT_REGEX = ('(?P<OUTPUT>[\s\S]*)%s:(?P<EXIT_CODE>\d{1,3})' %
43 CMD_OUTPUT_PREFIX)
Kevin Cheng018db352015-09-20 02:22:08 -070044RELEASE_FILE = 'ro.build.version.release'
Kevin Cheng3a4a57a2015-09-30 12:09:50 -070045BOARD_FILE = 'ro.product.device'
Simran Basi38f7ddf2015-09-18 12:25:03 -070046TMP_DIR = '/data/local/tmp'
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070047# Regex to pull out file type, perms and symlink. Example:
Kevin Chengaaabd0c2015-11-10 16:05:04 -080048# lrwxrwx--- 1 6 root system 2015-09-12 19:21 blah_link -> ./blah
Kevin Cheng92fe6ae2015-10-21 11:45:34 -070049FILE_INFO_REGEX = '^(?P<TYPE>[dl-])(?P<PERMS>[rwx-]{9})'
50FILE_SYMLINK_REGEX = '^.*-> (?P<SYMLINK>.+)'
51# List of the perm stats indexed by the order they are listed in the example
52# supplied above.
53FILE_PERMS_FLAGS = [stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR,
54 stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP,
55 stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH]
Simran Basi431010f2013-09-04 10:42:41 -070056
Dan Shi6ea3e1c2015-10-28 15:19:04 -070057# Default maximum number of seconds to wait for a device to be down.
58DEFAULT_WAIT_DOWN_TIME_SECONDS = 10
59# Default maximum number of seconds to wait for a device to be up.
Dan Shie4e807b2015-12-10 09:04:03 -080060DEFAULT_WAIT_UP_TIME_SECONDS = 300
61# Maximum number of seconds to wait for a device to be up after it's wiped.
Dan Shi50a412a2016-01-05 10:52:40 -080062WAIT_UP_AFTER_WIPE_TIME_SECONDS = 1200
Simran Basi431010f2013-09-04 10:42:41 -070063
Dan Shia2872172015-10-31 01:16:51 -070064OS_TYPE_ANDROID = 'android'
65OS_TYPE_BRILLO = 'brillo'
66
Dan Shie234dea2016-01-20 17:15:17 -080067# Regex to parse build name to get the detailed build information.
68BUILD_REGEX = ('(?P<BRANCH>([^/]+))/(?P<BOARD>([^/]+))-'
69 '(?P<BUILD_TYPE>([^/]+))/(?P<BUILD_ID>([^/]+))')
Dan Shia2872172015-10-31 01:16:51 -070070# Regex to parse devserver url to get the detailed build information. Sample
71# url: http://$devserver:8080/static/branch/target/build_id
Dan Shie234dea2016-01-20 17:15:17 -080072DEVSERVER_URL_REGEX = '.*/%s/*' % BUILD_REGEX
Dan Shia2872172015-10-31 01:16:51 -070073
74ANDROID_IMAGE_FILE_FMT = '%(board)s-img-%(build_id)s.zip'
75ANDROID_BOOTLOADER = 'bootloader.img'
76ANDROID_RADIO = 'radio.img'
77ANDROID_BOOT = 'boot.img'
78ANDROID_SYSTEM = 'system.img'
79ANDROID_VENDOR = 'vendor.img'
Dan Shiab999722015-12-04 14:27:08 -080080BRILLO_VENDOR_PARTITIONS_FILE_FMT = (
81 '%(board)s-vendor_partitions-%(build_id)s.zip')
Dan Shia2872172015-10-31 01:16:51 -070082
83# Image files not inside the image zip file. These files should be downloaded
84# directly from devserver.
85ANDROID_STANDALONE_IMAGES = [ANDROID_BOOTLOADER, ANDROID_RADIO]
86# Image files that are packaged in a zip file, e.g., shamu-img-123456.zip
87ANDROID_ZIPPED_IMAGES = [ANDROID_BOOT, ANDROID_SYSTEM, ANDROID_VENDOR]
88# All image files to be flashed to an Android device.
89ANDROID_IMAGES = ANDROID_STANDALONE_IMAGES + ANDROID_ZIPPED_IMAGES
90
Dan Shiab999722015-12-04 14:27:08 -080091# Command to provision a Brillo device.
92# os_image_dir: The full path of the directory that contains all the Android image
93# files (from the image zip file).
94# vendor_partition_dir: The full path of the directory that contains all the
95# Brillo vendor partitions, and provision-device script.
96BRILLO_PROVISION_CMD = (
Simran Basi7e52c622016-01-05 15:43:51 -080097 'sudo ANDROID_PROVISION_OS_PARTITIONS=%(os_image_dir)s '
Dan Shiab999722015-12-04 14:27:08 -080098 'ANDROID_PROVISION_VENDOR_PARTITIONS=%(vendor_partition_dir)s '
99 '%(vendor_partition_dir)s/provision-device')
Dan Shia2872172015-10-31 01:16:51 -0700100
101class AndroidInstallError(error.InstallError):
102 """Generic error for Android installation related exceptions."""
103
104
Simran Basi724b8a52013-09-30 11:19:31 -0700105class ADBHost(abstract_ssh.AbstractSSHHost):
Simran Basi431010f2013-09-04 10:42:41 -0700106 """This class represents a host running an ADB server."""
107
Simran Basi5ace6f22016-01-06 17:30:44 -0800108 VERSION_PREFIX = provision.ANDROID_BUILD_VERSION_PREFIX
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700109 _LABEL_FUNCTIONS = []
110 _DETECTABLE_LABELS = []
111 label_decorator = functools.partial(utils.add_label_detector,
112 _LABEL_FUNCTIONS,
113 _DETECTABLE_LABELS)
114
Dan Shi225b9042015-11-18 10:25:21 -0800115 _parser = autoserv_parser.autoserv_parser
Simran Basi431010f2013-09-04 10:42:41 -0700116
beeps46dadc92013-11-07 14:07:10 -0800117 @staticmethod
118 def check_host(host, timeout=10):
119 """
120 Check if the given host is an adb host.
121
Simran Basi14622bb2015-11-25 13:23:40 -0800122 If SSH connectivity can't be established, check_host will try to use
123 user 'adb' as well. If SSH connectivity still can't be established
124 then the original SSH user is restored.
125
beeps46dadc92013-11-07 14:07:10 -0800126 @param host: An ssh host representing a device.
127 @param timeout: The timeout for the run command.
128
129
130 @return: True if the host device has adb.
131
132 @raises AutoservRunError: If the command failed.
133 @raises AutoservSSHTimeout: Ssh connection has timed out.
134 """
Dan Shi64e130f2015-12-16 14:45:44 -0800135 # host object may not have user attribute if it's a LocalHost object.
136 current_user = host.user if hasattr(host, 'user') else None
beeps46dadc92013-11-07 14:07:10 -0800137 try:
Simran Basi14622bb2015-11-25 13:23:40 -0800138 if not (host.hostname == 'localhost' or
139 host.verify_ssh_user_access()):
Simran Basi1621c632015-10-14 12:22:23 -0700140 host.user = 'adb'
Simran Basi933c8af2015-04-29 14:05:07 -0700141 result = host.run(
Dan Shia2872172015-10-31 01:16:51 -0700142 'test -f %s' % server_constants.ANDROID_TESTER_FILEFLAG,
Simran Basi933c8af2015-04-29 14:05:07 -0700143 timeout=timeout)
beeps46dadc92013-11-07 14:07:10 -0800144 except (error.AutoservRunError, error.AutoservSSHTimeout):
Dan Shi64e130f2015-12-16 14:45:44 -0800145 if current_user is not None:
146 host.user = current_user
beeps46dadc92013-11-07 14:07:10 -0800147 return False
148 return result.exit_status == 0
149
150
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700151 # TODO(garnold) Remove the 'serials' argument once all clients are made to
152 # not use it.
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700153 def _initialize(self, hostname='localhost', serials=None,
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700154 adb_serial=None, fastboot_serial=None,
Kevin Cheng549beb42015-11-18 11:42:25 -0800155 device_hostname=None, teststation=None, *args, **dargs):
Simran Basi431010f2013-09-04 10:42:41 -0700156 """Initialize an ADB Host.
157
158 This will create an ADB Host. Hostname should always refer to the
Kevin Chengd19e6c62015-10-28 16:39:39 -0700159 test station connected to an Android DUT. This will be the DUT
160 to test with. If there are multiple, serial must be specified or an
161 exception will be raised. If device_hostname is supplied then all
162 ADB commands will run over TCP/IP.
Simran Basi431010f2013-09-04 10:42:41 -0700163
164 @param hostname: Hostname of the machine running ADB.
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700165 @param serials: DEPRECATED (to be removed)
166 @param adb_serial: An ADB device serial. If None, assume a single
167 device is attached (and fail otherwise).
168 @param fastboot_serial: A fastboot device serial. If None, defaults to
169 the ADB serial (or assumes a single device if
170 the latter is None).
Simran Basi431010f2013-09-04 10:42:41 -0700171 @param device_hostname: Hostname or IP of the android device we want to
172 interact with. If supplied all ADB interactions
173 run over TCP/IP.
Kevin Cheng549beb42015-11-18 11:42:25 -0800174 @param teststation: The teststation object ADBHost should use.
Simran Basi431010f2013-09-04 10:42:41 -0700175 """
Simran Basi1bf60eb2015-12-01 16:39:29 -0800176 # Sets up the is_client_install_supported field.
177 super(ADBHost, self)._initialize(hostname=hostname,
178 is_client_install_supported=False,
179 *args, **dargs)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700180 if device_hostname and (adb_serial or fastboot_serial):
181 raise error.AutoservError(
182 'TCP/IP and USB modes are mutually exclusive')
183
Kevin Cheng85e864a2015-11-30 11:49:34 -0800184
Kevin Chengd19e6c62015-10-28 16:39:39 -0700185 self.tmp_dirs = []
Simran Basi431010f2013-09-04 10:42:41 -0700186 self._device_hostname = device_hostname
187 self._use_tcpip = False
Simran Basi1bf60eb2015-12-01 16:39:29 -0800188 # TODO (sbasi/kevcheng): Once the teststation host is committed,
189 # refactor the serial retrieval.
190 adb_serial = adb_serial or self.host_attributes.get('serials', None)
Dan Shi50a412a2016-01-05 10:52:40 -0800191 self.adb_serial = adb_serial
192 self.fastboot_serial = fastboot_serial or adb_serial
Kevin Cheng85e864a2015-11-30 11:49:34 -0800193 self.teststation = (teststation if teststation
194 else teststation_host.create_teststationhost(hostname=hostname))
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700195
196 msg ='Initializing ADB device on host: %s' % hostname
197 if self._device_hostname:
198 msg += ', device hostname: %s' % self._device_hostname
Dan Shi50a412a2016-01-05 10:52:40 -0800199 if self.adb_serial:
200 msg += ', ADB serial: %s' % self.adb_serial
201 if self.fastboot_serial:
202 msg += ', fastboot serial: %s' % self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700203 logging.debug(msg)
204
Simran Basibeb2bb22016-02-03 15:25:48 -0800205 # Try resetting the ADB daemon on the device, however if we are
206 # creating the host to do a repair job, the device maybe inaccesible
207 # via ADB.
208 try:
209 self._reset_adbd_connection()
210 except (error.AutotestHostRunError, error.AutoservRunError) as e:
211 logging.error('Unable to reset the device adb daemon connection: '
212 '%s.', e)
Dan Shiab999722015-12-04 14:27:08 -0800213 self._os_type = None
214
Simran Basi431010f2013-09-04 10:42:41 -0700215
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700216 def _connect_over_tcpip_as_needed(self):
217 """Connect to the ADB device over TCP/IP if so configured."""
218 if not self._device_hostname:
219 return
220 logging.debug('Connecting to device over TCP/IP')
Dan Shi50a412a2016-01-05 10:52:40 -0800221 if self._device_hostname == self.adb_serial:
Simran Basi431010f2013-09-04 10:42:41 -0700222 # We previously had a connection to this device, restart the ADB
223 # server.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700224 self.adb_run('kill-server')
Simran Basi431010f2013-09-04 10:42:41 -0700225 # Ensure that connection commands don't run over TCP/IP.
226 self._use_tcpip = False
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700227 self.adb_run('tcpip 5555', timeout=10, ignore_timeout=True)
Simran Basi431010f2013-09-04 10:42:41 -0700228 time.sleep(2)
229 try:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700230 self.adb_run('connect %s' % self._device_hostname)
Simran Basi431010f2013-09-04 10:42:41 -0700231 except (error.AutoservRunError, error.CmdError) as e:
232 raise error.AutoservError('Failed to connect via TCP/IP: %s' % e)
233 # Allow ADB a bit of time after connecting before interacting with the
234 # device.
235 time.sleep(5)
236 # Switch back to using TCP/IP.
237 self._use_tcpip = True
238
239
Roshan Pius4d7540c2015-12-16 13:30:32 -0800240 def _restart_adbd_with_root_permissions(self):
241 """Restarts the adb daemon with root permissions."""
242 self.adb_run('root')
243 # TODO(ralphnathan): Remove this sleep once b/19749057 is resolved.
244 time.sleep(1)
245 self.adb_run('wait-for-device')
246
247
248 def _reset_adbd_connection(self):
249 """Resets adbd connection to the device after a reboot/initialization"""
250 self._restart_adbd_with_root_permissions()
251 self._connect_over_tcpip_as_needed()
252
253
Kevin Cheng85e864a2015-11-30 11:49:34 -0800254 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800255 def adb_run(self, command, **kwargs):
Simran Basi431010f2013-09-04 10:42:41 -0700256 """Runs an adb command.
257
Kevin Chengd19e6c62015-10-28 16:39:39 -0700258 This command will launch on the test station.
Simran Basi431010f2013-09-04 10:42:41 -0700259
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700260 Refer to _device_run method for docstring for parameters.
261 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800262 return self._device_run(ADB_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700263
264
Kevin Cheng85e864a2015-11-30 11:49:34 -0800265 # pylint: disable=missing-docstring
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800266 def fastboot_run(self, command, **kwargs):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700267 """Runs an fastboot command.
268
Kevin Chengd19e6c62015-10-28 16:39:39 -0700269 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700270
271 Refer to _device_run method for docstring for parameters.
272 """
Gilad Arnoldf17f6fd2015-11-12 14:44:07 -0800273 return self._device_run(FASTBOOT_CMD, command, **kwargs)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700274
275
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700276 def _device_run(self, function, command, shell=False,
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700277 timeout=3600, ignore_status=False, ignore_timeout=False,
278 stdout=utils.TEE_TO_LOGS, stderr=utils.TEE_TO_LOGS,
279 connect_timeout=30, options='', stdin=None, verbose=True,
280 require_sudo=False, args=()):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700281 """Runs a command named `function` on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700282
Kevin Chengd19e6c62015-10-28 16:39:39 -0700283 This command will launch on the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700284
Simran Basi431010f2013-09-04 10:42:41 -0700285 @param command: Command to run.
286 @param shell: If true the command runs in the adb shell otherwise if
287 False it will be passed directly to adb. For example
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700288 reboot with shell=False will call 'adb reboot'. This
289 option only applies to function adb.
Simran Basi431010f2013-09-04 10:42:41 -0700290 @param timeout: Time limit in seconds before attempting to
291 kill the running process. The run() function
292 will take a few seconds longer than 'timeout'
293 to complete if it has to kill the process.
294 @param ignore_status: Do not raise an exception, no matter
295 what the exit code of the command is.
296 @param ignore_timeout: Bool True if command timeouts should be
297 ignored. Will return None on command timeout.
298 @param stdout: Redirect stdout.
299 @param stderr: Redirect stderr.
300 @param connect_timeout: Connection timeout (in seconds)
301 @param options: String with additional ssh command options
302 @param stdin: Stdin to pass (a string) to the executed command
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700303 @param require_sudo: True to require sudo to run the command. Default is
304 False.
Simran Basi431010f2013-09-04 10:42:41 -0700305 @param args: Sequence of strings to pass as arguments to command by
306 quoting them in " and escaping their contents if
307 necessary.
308
309 @returns a CMDResult object.
Simran Basi431010f2013-09-04 10:42:41 -0700310 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700311 if function == ADB_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800312 serial = self.adb_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700313 elif function == FASTBOOT_CMD:
Dan Shi50a412a2016-01-05 10:52:40 -0800314 serial = self.fastboot_serial
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700315 else:
316 raise NotImplementedError('Mode %s is not supported' % function)
317
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700318 if function != ADB_CMD and shell:
319 raise error.CmdError('shell option is only applicable to `adb`.')
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700320
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700321 cmd = '%s%s ' % ('sudo -n ' if require_sudo else '', function)
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700322
323 if serial:
324 cmd += '-s %s ' % serial
325 elif self._use_tcpip:
Simran Basi431010f2013-09-04 10:42:41 -0700326 cmd += '-s %s:5555 ' % self._device_hostname
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700327
Simran Basi431010f2013-09-04 10:42:41 -0700328 if shell:
329 cmd += '%s ' % SHELL_CMD
330 cmd += command
331
Roshan Pius58e5dd32015-10-16 15:16:42 -0700332 if verbose:
333 logging.debug('Command: %s', cmd)
Simran Basi431010f2013-09-04 10:42:41 -0700334
Kevin Cheng85e864a2015-11-30 11:49:34 -0800335 return self.teststation.run(cmd, timeout=timeout,
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400336 ignore_status=ignore_status,
337 ignore_timeout=ignore_timeout, stdout_tee=stdout,
338 stderr_tee=stderr, options=options, stdin=stdin,
339 connect_timeout=connect_timeout, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700340
341
Dan Shie234dea2016-01-20 17:15:17 -0800342 def get_board_name(self):
343 """Get the name of the board, e.g., shamu, dragonboard etc.
344 """
345 return self.run_output('getprop %s' % BOARD_FILE)
346
347
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700348 @label_decorator()
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700349 def get_board(self):
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700350 """Determine the correct board label for the device.
351
352 @returns a string representing this device's board.
353 """
Dan Shie234dea2016-01-20 17:15:17 -0800354 board = self.get_board_name()
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700355 board_os = self.get_os_type()
Kevin Cheng49f7b812015-12-15 15:24:23 -0800356 return constants.BOARD_PREFIX + '-'.join([board_os, board])
Christopher Wiley8e6b08e2013-10-11 12:34:26 -0700357
358
Christopher Wiley08849d52013-11-22 08:57:58 -0800359 def job_start(self):
360 """
361 Disable log collection on adb_hosts.
362
363 TODO(sbasi): crbug.com/305427
Christopher Wiley08849d52013-11-22 08:57:58 -0800364 """
365
366
Simran Basi431010f2013-09-04 10:42:41 -0700367 def run(self, command, timeout=3600, ignore_status=False,
368 ignore_timeout=False, stdout_tee=utils.TEE_TO_LOGS,
369 stderr_tee=utils.TEE_TO_LOGS, connect_timeout=30, options='',
Roshan Pius58e5dd32015-10-16 15:16:42 -0700370 stdin=None, verbose=True, args=()):
Simran Basi431010f2013-09-04 10:42:41 -0700371 """Run a command on the adb device.
372
373 The command given will be ran directly on the adb device; for example
374 'ls' will be ran as: 'abd shell ls'
375
376 @param command: The command line string.
377 @param timeout: Time limit in seconds before attempting to
378 kill the running process. The run() function
379 will take a few seconds longer than 'timeout'
380 to complete if it has to kill the process.
381 @param ignore_status: Do not raise an exception, no matter
382 what the exit code of the command is.
383 @param ignore_timeout: Bool True if command timeouts should be
384 ignored. Will return None on command timeout.
385 @param stdout_tee: Redirect stdout.
386 @param stderr_tee: Redirect stderr.
387 @param connect_timeout: Connection timeout (in seconds).
388 @param options: String with additional ssh command options.
389 @param stdin: Stdin to pass (a string) to the executed command
390 @param args: Sequence of strings to pass as arguments to command by
391 quoting them in " and escaping their contents if
392 necessary.
393
394 @returns A CMDResult object or None if the call timed out and
395 ignore_timeout is True.
396
397 @raises AutoservRunError: If the command failed.
398 @raises AutoservSSHTimeout: Ssh connection has timed out.
Simran Basi431010f2013-09-04 10:42:41 -0700399 """
Filipe Brandenburger68a80072015-07-14 10:39:33 -0700400 command = ('"%s; echo %s:\$?"' %
401 (utils.sh_escape(command), CMD_OUTPUT_PREFIX))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700402 result = self.adb_run(
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700403 command, shell=True, timeout=timeout,
Simran Basi431010f2013-09-04 10:42:41 -0700404 ignore_status=ignore_status, ignore_timeout=ignore_timeout,
405 stdout=stdout_tee, stderr=stderr_tee,
406 connect_timeout=connect_timeout, options=options, stdin=stdin,
Roshan Pius58e5dd32015-10-16 15:16:42 -0700407 verbose=verbose, args=args)
Simran Basi431010f2013-09-04 10:42:41 -0700408 if not result:
409 # In case of timeouts.
410 return None
411
412 parse_output = re.match(CMD_OUTPUT_REGEX, result.stdout)
Roshan Pius5ba5d182015-10-28 09:19:41 -0700413 if not parse_output and not ignore_status:
Simran Basi431010f2013-09-04 10:42:41 -0700414 raise error.AutoservRunError(
Roshan Pius5ba5d182015-10-28 09:19:41 -0700415 'Failed to parse the exit code for command: %s' %
416 command, result)
417 elif parse_output:
418 result.stdout = parse_output.group('OUTPUT')
419 result.exit_status = int(parse_output.group('EXIT_CODE'))
420 if result.exit_status != 0 and not ignore_status:
421 raise error.AutoservRunError(command, result)
Simran Basi431010f2013-09-04 10:42:41 -0700422 return result
423
424
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700425 def wait_up(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS, command=ADB_CMD):
426 """Wait until the remote host is up or the timeout expires.
Simran Basi431010f2013-09-04 10:42:41 -0700427
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700428 Overrides wait_down from AbstractSSHHost.
Simran Basi431010f2013-09-04 10:42:41 -0700429
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700430 @param timeout: Time limit in seconds before returning even if the host
431 is not up.
432 @param command: The command used to test if a device is up, i.e.,
433 accessible by the given command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700434
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700435 @returns True if the host was found to be up before the timeout expires,
436 False otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700437 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700438 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
439 delay_sec=1)
440 def _wait_up():
441 if not self.is_up(command=command):
442 raise error.TimeoutException('Device is still down.')
443 return True
444
445 try:
446 _wait_up()
447 logging.debug('Host %s is now up, and can be accessed by %s.',
448 self.hostname, command)
449 return True
450 except error.TimeoutException:
451 logging.debug('Host %s is still down after waiting %d seconds',
452 self.hostname, timeout)
453 return False
Simran Basi431010f2013-09-04 10:42:41 -0700454
455
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700456 def wait_down(self, timeout=DEFAULT_WAIT_DOWN_TIME_SECONDS,
457 warning_timer=None, old_boot_id=None, command=ADB_CMD):
458 """Wait till the host goes down, i.e., not accessible by given command.
Simran Basi431010f2013-09-04 10:42:41 -0700459
460 Overrides wait_down from AbstractSSHHost.
461
462 @param timeout: Time in seconds to wait for the host to go down.
463 @param warning_timer: Time limit in seconds that will generate
464 a warning if the host is not down yet.
465 Currently ignored.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700466 @param old_boot_id: Not applicable for adb_host.
467 @param command: `adb`, test if the device can be accessed by adb
468 command, or `fastboot`, test if the device can be accessed by
469 fastboot command. Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700470
471 @returns True if the device goes down before the timeout, False
472 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700473 """
474 @retry.retry(error.TimeoutException, timeout_min=timeout/60.0,
475 delay_sec=1)
476 def _wait_down():
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700477 if self.is_up(command=command):
Simran Basi431010f2013-09-04 10:42:41 -0700478 raise error.TimeoutException('Device is still up.')
479 return True
480
481 try:
482 _wait_down()
483 logging.debug('Host %s is now down', self.hostname)
484 return True
485 except error.TimeoutException:
486 logging.debug('Host %s is still up after waiting %d seconds',
487 self.hostname, timeout)
488 return False
489
490
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700491 def reboot(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700492 """Reboot the android device via adb.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700493
494 @raises AutoservRebootError if reboot failed.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700495 """
496 # Not calling super.reboot() as we want to reboot the ADB device not
Kevin Chengd19e6c62015-10-28 16:39:39 -0700497 # the test station we are running ADB on.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700498 self.adb_run('reboot', timeout=10, ignore_timeout=True)
499 if not self.wait_down():
500 raise error.AutoservRebootError(
501 'ADB Device is still up after reboot')
502 if not self.wait_up():
503 raise error.AutoservRebootError(
504 'ADB Device failed to return from reboot.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800505 self._reset_adbd_connection()
Roshan Pius50c1f9c2015-11-30 11:37:49 -0800506
507
Ralph Nathanb45eb672015-11-18 20:04:39 -0800508 def remount(self):
509 """Remounts paritions on the device read-write.
510
511 Specifically, the /system, /vendor (if present) and /oem (if present)
512 partitions on the device are remounted read-write.
513 """
Ralph Nathanb45eb672015-11-18 20:04:39 -0800514 self.adb_run('remount')
515
516
Kevin Cheng549beb42015-11-18 11:42:25 -0800517 @staticmethod
518 def parse_device_serials(devices_output):
519 """Return a list of parsed serials from the output.
520
521 @param devices_output: Output from either an adb or fastboot command.
522
523 @returns List of device serials
524 """
525 devices = []
526 for line in devices_output.splitlines():
527 match = re.search(DEVICE_FINDER_REGEX, line)
528 if match:
529 serial = match.group('SERIAL')
530 if serial == DEVICE_NO_SERIAL_MSG or re.match(r'^\?+$', serial):
531 serial = DEVICE_NO_SERIAL_TAG
532 logging.debug('Found Device: %s', serial)
533 devices.append(serial)
534 return devices
535
536
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700537 def _get_devices(self, use_adb):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700538 """Get a list of devices currently attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700539
540 @params use_adb: True to get adb accessible devices. Set to False to
541 get fastboot accessible devices.
542
Kevin Chengd19e6c62015-10-28 16:39:39 -0700543 @returns a list of devices attached to the test station.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700544 """
545 if use_adb:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700546 result = self.adb_run('devices')
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700547 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700548 result = self.fastboot_run('devices')
Kevin Cheng549beb42015-11-18 11:42:25 -0800549 return self.parse_device_serials(result.stdout)
Simran Basi431010f2013-09-04 10:42:41 -0700550
551
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700552 def adb_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700553 """Get a list of devices currently attached to the test station and
554 accessible with the adb command."""
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700555 devices = self._get_devices(use_adb=True)
Dan Shi50a412a2016-01-05 10:52:40 -0800556 if self.adb_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700557 raise error.AutoservError(
558 'Not given ADB serial but multiple devices detected')
559 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700560
561
562 def fastboot_devices(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700563 """Get a list of devices currently attached to the test station and
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700564 accessible by fastboot command.
565 """
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700566 devices = self._get_devices(use_adb=False)
Dan Shi50a412a2016-01-05 10:52:40 -0800567 if self.fastboot_serial is None and len(devices) > 1:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700568 raise error.AutoservError(
569 'Not given fastboot serial but multiple devices detected')
570 return devices
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700571
572
573 def is_up(self, timeout=0, command=ADB_CMD):
574 """Determine if the specified adb device is up with expected mode.
Simran Basi431010f2013-09-04 10:42:41 -0700575
576 @param timeout: Not currently used.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700577 @param command: `adb`, the device can be accessed by adb command,
578 or `fastboot`, the device can be accessed by fastboot command.
579 Default is set to `adb`.
Simran Basi431010f2013-09-04 10:42:41 -0700580
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700581 @returns True if the device is detectable by given command, False
582 otherwise.
Simran Basi431010f2013-09-04 10:42:41 -0700583
584 """
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700585 if command == ADB_CMD:
586 devices = self.adb_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800587 serial = self.adb_serial
Kris Rambishde8f9d12015-12-16 12:42:41 -0800588 # ADB has a device state, if the device is not online, no
589 # subsequent ADB command will complete.
Dan Shi18848d42016-03-09 13:25:28 -0800590 if serial not in devices or not self.is_device_ready():
Kris Rambishde8f9d12015-12-16 12:42:41 -0800591 logging.debug('Waiting for device to enter the ready state.')
592 return False
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700593 elif command == FASTBOOT_CMD:
594 devices = self.fastboot_devices()
Dan Shi50a412a2016-01-05 10:52:40 -0800595 serial = self.fastboot_serial
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700596 else:
Gilad Arnold2cfa5522015-10-30 13:58:02 -0700597 raise NotImplementedError('Mode %s is not supported' % command)
598
599 return bool(devices and (not serial or serial in devices))
Simran Basi431010f2013-09-04 10:42:41 -0700600
601
602 def close(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700603 """Close the ADBHost object.
Simran Basi431010f2013-09-04 10:42:41 -0700604
605 Called as the test ends. Will return the device to USB mode and kill
606 the ADB server.
Simran Basi431010f2013-09-04 10:42:41 -0700607 """
608 if self._use_tcpip:
609 # Return the device to usb mode.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400610 self.adb_run('usb')
Christopher Wiley08849d52013-11-22 08:57:58 -0800611 # TODO(sbasi) Originally, we would kill the server after each test to
612 # reduce the opportunity for bad server state to hang around.
613 # Unfortunately, there is a period of time after each kill during which
614 # the Android device becomes unusable, and if we start the next test
615 # too quickly, we'll get an error complaining about no ADB device
616 # attached.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700617 #self.adb_run('kill-server')
Roshan Pius39942602015-12-17 13:42:07 -0800618 # |close| the associated teststation as well.
619 self.teststation.close()
Simran Basi431010f2013-09-04 10:42:41 -0700620 return super(ADBHost, self).close()
Kris Rambish60461dc2014-03-11 11:10:18 -0700621
622
623 def syslog(self, message, tag='autotest'):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700624 """Logs a message to syslog on the device.
Kris Rambish60461dc2014-03-11 11:10:18 -0700625
626 @param message String message to log into syslog
627 @param tag String tag prefix for syslog
628
629 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700630 self.run('log -t "%s" "%s"' % (tag, message))
Simran Basid3ba3fb2015-09-11 14:35:07 -0700631
632
633 def get_autodir(self):
634 """Return the directory to install autotest for client side tests."""
635 return '/data/autotest'
636
Kevin Cheng018db352015-09-20 02:22:08 -0700637
Kris Rambishde8f9d12015-12-16 12:42:41 -0800638 def is_device_ready(self):
639 """Return the if the device is ready for ADB commands."""
640 dev_state = self.adb_run('get-state').stdout.strip()
641 logging.debug('Current device state: %s', dev_state)
642 return dev_state == 'device'
643
644
Kevin Chengd19e6c62015-10-28 16:39:39 -0700645 def verify_connectivity(self):
646 """Verify we can connect to the device."""
Kris Rambishde8f9d12015-12-16 12:42:41 -0800647 if not self.is_device_ready():
648 raise error.AutoservHostError('device state is not in the '
649 '\'device\' state.')
Kevin Chengd19e6c62015-10-28 16:39:39 -0700650
651
Simran Basid3ba3fb2015-09-11 14:35:07 -0700652 def verify_software(self):
653 """Verify working software on an adb_host.
654
Simran Basi38f7ddf2015-09-18 12:25:03 -0700655 TODO (crbug.com/532222): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700656 """
Dan Shiab999722015-12-04 14:27:08 -0800657 # Check if adb and fastboot are present.
658 self.teststation.run('which adb')
659 self.teststation.run('which fastboot')
660 self.teststation.run('which unzip')
Simran Basid3ba3fb2015-09-11 14:35:07 -0700661
Kevin Cheng018db352015-09-20 02:22:08 -0700662
Simran Basid3ba3fb2015-09-11 14:35:07 -0700663 def verify_job_repo_url(self, tag=''):
664 """Make sure job_repo_url of this host is valid.
665
Simran Basi38f7ddf2015-09-18 12:25:03 -0700666 TODO (crbug.com/532223): Actually implement this method.
Simran Basid3ba3fb2015-09-11 14:35:07 -0700667
668 @param tag: The tag from the server job, in the format
669 <job_id>-<user>/<hostname>, or <hostless> for a server job.
670 """
671 return
Kevin Cheng018db352015-09-20 02:22:08 -0700672
673
Simran Basibeb2bb22016-02-03 15:25:48 -0800674 def repair(self):
675 """Attempt to get the DUT to pass `self.verify()`."""
676 try:
677 self.ensure_adb_mode(timeout=30)
678 return
679 except error.AutoservError as e:
680 logging.error(e)
681 logging.debug('Verifying the device is accessible via fastboot.')
682 self.ensure_bootloader_mode()
683 if not self.job.run_test(
684 'provision_AndroidUpdate', host=self, value=None,
685 force=True, repair=True):
686 raise error.AutoservRepairTotalFailure(
687 'Unable to repair the device.')
688
689
Simran Basi1b023762015-09-25 12:12:20 -0700690 def send_file(self, source, dest, delete_dest=False,
691 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700692 """Copy files from the drone to the device.
693
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400694 Just a note, there is the possibility the test station is localhost
695 which makes some of these steps redundant (e.g. creating tmp dir) but
696 that scenario will undoubtedly be a development scenario (test station
697 is also the moblab) and not the typical live test running scenario so
698 the redundancy I think is harmless.
699
Kevin Cheng018db352015-09-20 02:22:08 -0700700 @param source: The file/directory on the drone to send to the device.
701 @param dest: The destination path on the device to copy to.
702 @param delete_dest: A flag set to choose whether or not to delete
703 dest on the device if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700704 @param preserve_symlinks: Controls if symlinks on the source will be
705 copied as such on the destination or
706 transformed into the referenced
707 file/directory.
Kevin Cheng018db352015-09-20 02:22:08 -0700708 """
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700709 # If we need to preserve symlinks, let's check if the source is a
710 # symlink itself and if so, just create it on the device.
711 if preserve_symlinks:
712 symlink_target = None
713 try:
714 symlink_target = os.readlink(source)
715 except OSError:
716 # Guess it's not a symlink.
717 pass
718
719 if symlink_target is not None:
720 # Once we create the symlink, let's get out of here.
721 self.run('ln -s %s %s' % (symlink_target, dest))
722 return
723
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400724 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700725 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400726 src_path = os.path.join(tmp_dir, os.path.basename(dest))
727 # Now copy the file over to the test station so you can reference the
728 # file in the push command.
729 self.teststation.send_file(source, src_path,
730 preserve_symlinks=preserve_symlinks)
Kevin Cheng018db352015-09-20 02:22:08 -0700731
732 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400733 self.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700734
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700735 self.adb_run('push %s %s' % (src_path, dest))
Kevin Cheng018db352015-09-20 02:22:08 -0700736
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400737 # Cleanup the test station.
738 try:
739 self.teststation.run('rm -rf %s' % tmp_dir)
740 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
741 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng018db352015-09-20 02:22:08 -0700742
743
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700744 def _get_file_info(self, dest):
745 """Get permission and possible symlink info about file on the device.
746
747 These files are on the device so we only have shell commands (via adb)
748 to get the info we want. We'll use 'ls' to get it all.
749
750 @param dest: File to get info about.
751
752 @returns a dict of the file permissions and symlink.
753 """
Kevin Chengaaabd0c2015-11-10 16:05:04 -0800754 # Grab file info.
755 file_info = self.run_output('ls -l %s' % dest)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700756 symlink = None
757 perms = 0
758 match = re.match(FILE_INFO_REGEX, file_info)
759 if match:
760 # Check if it's a symlink and grab the linked dest if it is.
761 if match.group('TYPE') == 'l':
762 symlink_match = re.match(FILE_SYMLINK_REGEX, file_info)
763 if symlink_match:
764 symlink = symlink_match.group('SYMLINK')
765
766 # Set the perms.
767 for perm, perm_flag in zip(match.group('PERMS'), FILE_PERMS_FLAGS):
768 if perm != '-':
769 perms |= perm_flag
770
771 return {'perms': perms,
772 'symlink': symlink}
773
774
Simran Basi1b023762015-09-25 12:12:20 -0700775 def get_file(self, source, dest, delete_dest=False, preserve_perm=True,
776 preserve_symlinks=False):
Kevin Cheng018db352015-09-20 02:22:08 -0700777 """Copy files from the device to the drone.
778
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400779 Just a note, there is the possibility the test station is localhost
780 which makes some of these steps redundant (e.g. creating tmp dir) but
781 that scenario will undoubtedly be a development scenario (test station
782 is also the moblab) and not the typical live test running scenario so
783 the redundancy I think is harmless.
784
Kevin Cheng018db352015-09-20 02:22:08 -0700785 @param source: The file/directory on the device to copy back to the
786 drone.
787 @param dest: The destination path on the drone to copy to.
788 @param delete_dest: A flag set to choose whether or not to delete
789 dest on the drone if it exists.
Simran Basi1b023762015-09-25 12:12:20 -0700790 @param preserve_perm: Tells get_file() to try to preserve the sources
791 permissions on files and dirs.
792 @param preserve_symlinks: Try to preserve symlinks instead of
793 transforming them into files/dirs on copy.
Kevin Cheng018db352015-09-20 02:22:08 -0700794 """
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400795 # Stage the files on the test station.
Kevin Chengd19e6c62015-10-28 16:39:39 -0700796 tmp_dir = self.teststation.get_tmp_dir()
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400797 dest_path = os.path.join(tmp_dir, os.path.basename(source))
Kevin Cheng018db352015-09-20 02:22:08 -0700798
799 if delete_dest:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400800 self.teststation.run('rm -rf %s' % dest)
Kevin Cheng018db352015-09-20 02:22:08 -0700801
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700802 source_info = {}
803 if preserve_symlinks or preserve_perm:
804 source_info = self._get_file_info(source)
Kevin Cheng018db352015-09-20 02:22:08 -0700805
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700806 # If we want to preserve symlinks, just create it here, otherwise pull
807 # the file off the device.
808 if preserve_symlinks and source_info['symlink']:
809 os.symlink(source_info['symlink'], dest)
810 else:
Roshan Pius95567142015-11-03 09:56:08 -0800811 self.adb_run('pull %s %s' % (source, dest_path))
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700812
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -0400813 # Copy over the file from the test station and clean up.
814 self.teststation.get_file(dest_path, dest)
815 try:
816 self.teststation.run('rm -rf %s' % tmp_dir)
817 except (error.AutoservRunError, error.AutoservSSHTimeout) as e:
818 logging.warn('failed to remove dir %s: %s', tmp_dir, e)
Kevin Cheng92fe6ae2015-10-21 11:45:34 -0700819
820 if preserve_perm:
821 os.chmod(dest, source_info['perms'])
Kevin Cheng018db352015-09-20 02:22:08 -0700822
823
824 def get_release_version(self):
825 """Get the release version from the RELEASE_FILE on the device.
826
827 @returns The release string in the RELEASE_FILE.
828
829 """
830 return self.run_output('getprop %s' % RELEASE_FILE)
Simran Basi38f7ddf2015-09-18 12:25:03 -0700831
832
833 def get_tmp_dir(self, parent=''):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700834 """Return a suitable temporary directory on the device.
Simran Basi38f7ddf2015-09-18 12:25:03 -0700835
Kevin Chengd19e6c62015-10-28 16:39:39 -0700836 We ensure this is a subdirectory of /data/local/tmp.
Simran Basi38f7ddf2015-09-18 12:25:03 -0700837
838 @param parent: Parent directory of the returned tmp dir.
839
Kevin Cheng3a4a57a2015-09-30 12:09:50 -0700840 @returns a path to the temp directory on the host.
Simran Basi38f7ddf2015-09-18 12:25:03 -0700841 """
Kevin Chengd19e6c62015-10-28 16:39:39 -0700842 # TODO(kevcheng): Refactor the cleanup of tmp dir to be inherited
843 # from the parent.
Simran Basi38f7ddf2015-09-18 12:25:03 -0700844 if not parent.startswith(TMP_DIR):
845 parent = os.path.join(TMP_DIR, parent.lstrip(os.path.sep))
Kevin Chengd19e6c62015-10-28 16:39:39 -0700846 self.run('mkdir -p %s' % parent)
847 tmp_dir = self.run_output('mktemp -d -p %s' % parent)
848 self.tmp_dirs.append(tmp_dir)
849 return tmp_dir
Simran Basi1b023762015-09-25 12:12:20 -0700850
851
852 def get_platform(self):
853 """Determine the correct platform label for this host.
854
855 TODO (crbug.com/536250): Figure out what we want to do for adb_host's
Kevin Chengd19e6c62015-10-28 16:39:39 -0700856 get_platform.
Simran Basi1b023762015-09-25 12:12:20 -0700857
858 @returns a string representing this host's platform.
859 """
860 return 'adb'
861
862
Gilad Arnolda76bef02015-09-29 13:55:15 -0700863 def get_os_type(self):
Dan Shiab999722015-12-04 14:27:08 -0800864 """Get the OS type of the DUT, e.g., android or brillo.
865 """
866 if not self._os_type:
867 if self.run_output('getprop ro.product.brand') == 'Brillo':
868 self._os_type = OS_TYPE_BRILLO
869 else:
870 self._os_type = OS_TYPE_ANDROID
871
872 return self._os_type
Gilad Arnolde452b1f2015-10-06 08:48:34 -0700873
874
875 def _forward(self, reverse, args):
876 """Execute a forwarding command.
877
878 @param reverse: Whether this is reverse forwarding (Boolean).
879 @param args: List of command arguments.
880 """
881 cmd = '%s %s' % ('reverse' if reverse else 'forward', ' '.join(args))
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700882 self.adb_run(cmd)
Gilad Arnolde452b1f2015-10-06 08:48:34 -0700883
884
885 def add_forwarding(self, src, dst, reverse=False, rebind=True):
886 """Forward a port between the ADB host and device.
887
888 Port specifications are any strings accepted as such by ADB, for
889 example 'tcp:8080'.
890
891 @param src: Port specification to forward from.
892 @param dst: Port specification to forward to.
893 @param reverse: Do reverse forwarding from device to host (Boolean).
894 @param rebind: Allow rebinding an already bound port (Boolean).
895 """
896 args = []
897 if not rebind:
898 args.append('--no-rebind')
899 args += [src, dst]
900 self._forward(reverse, args)
901
902
903 def remove_forwarding(self, src=None, reverse=False):
904 """Removes forwarding on port.
905
906 @param src: Port specification, or None to remove all forwarding.
907 @param reverse: Whether this is reverse forwarding (Boolean).
908 """
909 args = []
910 if src is None:
911 args.append('--remove-all')
912 else:
913 args += ['--remove', src]
914 self._forward(reverse, args)
Roshan Pius58e5dd32015-10-16 15:16:42 -0700915
916
xixuan6cf6d2f2016-01-29 15:29:00 -0800917 def create_ssh_tunnel(self, port, local_port):
Roshan Pius58e5dd32015-10-16 15:16:42 -0700918 """
919 Forwards a port securely through a tunnel process from the server
920 to the DUT for RPC server connection.
921 Add a 'ADB forward' rule to forward the RPC packets from the AdbHost
922 to the DUT.
923
924 @param port: remote port on the DUT.
925 @param local_port: local forwarding port.
926
927 @return: the tunnel process.
928 """
929 self.add_forwarding('tcp:%s' % port, 'tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -0800930 return super(ADBHost, self).create_ssh_tunnel(port, local_port)
Roshan Pius58e5dd32015-10-16 15:16:42 -0700931
932
xixuan6cf6d2f2016-01-29 15:29:00 -0800933 def disconnect_ssh_tunnel(self, tunnel_proc, port):
Roshan Pius58e5dd32015-10-16 15:16:42 -0700934 """
935 Disconnects a previously forwarded port from the server to the DUT for
936 RPC server connection.
937 Remove the previously added 'ADB forward' rule to forward the RPC
938 packets from the AdbHost to the DUT.
939
940 @param tunnel_proc: the original tunnel process returned from
xixuan6cf6d2f2016-01-29 15:29:00 -0800941 |create_ssh_tunnel|.
Roshan Pius58e5dd32015-10-16 15:16:42 -0700942 @param port: remote port on the DUT.
943
944 """
945 self.remove_forwarding('tcp:%s' % port)
xixuan6cf6d2f2016-01-29 15:29:00 -0800946 super(ADBHost, self).disconnect_ssh_tunnel(tunnel_proc, port)
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700947
948
949 def ensure_bootloader_mode(self):
Kevin Chengd19e6c62015-10-28 16:39:39 -0700950 """Ensure the device is in bootloader mode.
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700951
952 @raise: error.AutoservError if the device failed to reboot into
953 bootloader mode.
954 """
955 if self.is_up(command=FASTBOOT_CMD):
956 return
957 self.adb_run('reboot bootloader')
958 if not self.wait_up(command=FASTBOOT_CMD):
959 raise error.AutoservError(
960 'The device failed to reboot into bootloader mode.')
961
962
Dan Shie4e807b2015-12-10 09:04:03 -0800963 def ensure_adb_mode(self, timeout=DEFAULT_WAIT_UP_TIME_SECONDS):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700964 """Ensure the device is up and can be accessed by adb command.
965
Dan Shie4e807b2015-12-10 09:04:03 -0800966 @param timeout: Time limit in seconds before returning even if the host
967 is not up.
968
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700969 @raise: error.AutoservError if the device failed to reboot into
970 adb mode.
971 """
972 if self.is_up():
973 return
974 self.fastboot_run('reboot')
Dan Shie4e807b2015-12-10 09:04:03 -0800975 if not self.wait_up(timeout=timeout):
Dan Shi6ea3e1c2015-10-28 15:19:04 -0700976 raise error.AutoservError(
977 'The device failed to reboot into adb mode.')
Roshan Pius4d7540c2015-12-16 13:30:32 -0800978 self._reset_adbd_connection()
Dan Shia2872172015-10-31 01:16:51 -0700979
980
981 @classmethod
Dan Shi08ff1282016-02-18 19:51:16 -0800982 def get_build_info_from_build_url(cls, build_url):
Dan Shia2872172015-10-31 01:16:51 -0700983 """Get the Android build information from the build url.
984
985 @param build_url: The url to use for downloading Android artifacts.
986 pattern: http://$devserver:###/static/branch/target/build_id
987
988 @return: A dictionary of build information, including keys: board,
989 branch, target, build_id.
Dan Shiab999722015-12-04 14:27:08 -0800990 @raise AndroidInstallError: If failed to parse build_url.
Dan Shia2872172015-10-31 01:16:51 -0700991 """
Dan Shiab999722015-12-04 14:27:08 -0800992 if not build_url:
993 raise AndroidInstallError('Need build_url to download image files.')
994
995 try:
996 match = re.match(DEVSERVER_URL_REGEX, build_url)
997 return {'board': match.group('BOARD'),
998 'branch': match.group('BRANCH'),
999 'target': ('%s-%s' % (match.group('BOARD'),
1000 match.group('BUILD_TYPE'))),
1001 'build_id': match.group('BUILD_ID')}
1002 except (AttributeError, IndexError, ValueError) as e:
1003 raise AndroidInstallError(
1004 'Failed to parse build url: %s\nError: %s' % (build_url, e))
Dan Shia2872172015-10-31 01:16:51 -07001005
1006
Dan Shia2872172015-10-31 01:16:51 -07001007 @retry.retry(error.AutoservRunError, timeout_min=10)
Dan Shidb0366c2016-02-19 10:36:18 -08001008 def download_file(self, build_url, file, dest_dir):
Dan Shia2872172015-10-31 01:16:51 -07001009 """Download the given file from the build url.
1010
1011 @param build_url: The url to use for downloading Android artifacts.
1012 pattern: http://$devserver:###/static/branch/target/build_id
1013 @param file: Name of the file to be downloaded, e.g., boot.img.
1014 @param dest_dir: Destination folder for the file to be downloaded to.
1015 """
Dan Shidb0366c2016-02-19 10:36:18 -08001016 # Append the file name to the url if build_url is linked to the folder
1017 # containing the file.
1018 if not build_url.endswith('/%s' % file):
1019 src_url = os.path.join(build_url, file)
1020 else:
1021 src_url = build_url
Dan Shia2872172015-10-31 01:16:51 -07001022 dest_file = os.path.join(dest_dir, file)
1023 try:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001024 self.teststation.run('wget -q -O "%s" "%s"' % (dest_file, src_url))
Dan Shia2872172015-10-31 01:16:51 -07001025 except:
1026 # Delete the destination file if download failed.
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001027 self.teststation.run('rm -f "%s"' % dest_file)
Dan Shia2872172015-10-31 01:16:51 -07001028 raise
1029
1030
Dan Shiab999722015-12-04 14:27:08 -08001031 def stage_android_image_files(self, build_url):
Dan Shia2872172015-10-31 01:16:51 -07001032 """Download required image files from the given build_url to a local
1033 directory in the machine runs fastboot command.
1034
1035 @param build_url: The url to use for downloading Android artifacts.
1036 pattern: http://$devserver:###/static/branch/target/build_id
1037
1038 @return: Path to the directory contains image files.
1039 """
Dan Shi08ff1282016-02-18 19:51:16 -08001040 build_info = self.get_build_info_from_build_url(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001041
1042 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
Kevin Cheng85e864a2015-11-30 11:49:34 -08001043 image_dir = self.teststation.get_tmp_dir()
Dan Shia2872172015-10-31 01:16:51 -07001044 image_files = [zipped_image_file] + ANDROID_STANDALONE_IMAGES
1045
1046 try:
1047 for image_file in image_files:
Dan Shidb0366c2016-02-19 10:36:18 -08001048 self.download_file(build_url, image_file, image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001049
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001050 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1051 (image_dir, zipped_image_file, image_dir))
Dan Shia2872172015-10-31 01:16:51 -07001052
1053 return image_dir
1054 except:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001055 self.teststation.run('rm -rf %s' % image_dir)
Dan Shia2872172015-10-31 01:16:51 -07001056 raise
1057
1058
Dan Shiab999722015-12-04 14:27:08 -08001059 def stage_brillo_image_files(self, build_url):
1060 """Download required brillo image files from the given build_url to a
1061 local directory in the machine runs fastboot command.
1062
1063 @param build_url: The url to use for downloading Android artifacts.
1064 pattern: http://$devserver:###/static/branch/target/build_id
1065
1066 @return: Path to the directory contains image files.
1067 """
Dan Shi08ff1282016-02-18 19:51:16 -08001068 build_info = self.get_build_info_from_build_url(build_url)
Dan Shiab999722015-12-04 14:27:08 -08001069
1070 zipped_image_file = ANDROID_IMAGE_FILE_FMT % build_info
1071 vendor_partitions_file = BRILLO_VENDOR_PARTITIONS_FILE_FMT % build_info
1072 image_dir = self.teststation.get_tmp_dir()
1073 image_files = [zipped_image_file, vendor_partitions_file]
1074
1075 try:
1076 for image_file in image_files:
Dan Shidb0366c2016-02-19 10:36:18 -08001077 self.download_file(build_url, image_file, image_dir)
Dan Shiab999722015-12-04 14:27:08 -08001078
1079 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1080 (image_dir, zipped_image_file, image_dir))
1081 self.teststation.run('unzip "%s/%s" -x -d "%s"' %
1082 (image_dir, vendor_partitions_file,
1083 os.path.join(image_dir, 'vendor')))
1084 return image_dir
1085 except:
1086 self.teststation.run('rm -rf %s' % image_dir)
1087 raise
1088
1089
Simran Basibeb2bb22016-02-03 15:25:48 -08001090 def stage_build_for_install(self, build_name, os_type=None):
Dan Shi225b9042015-11-18 10:25:21 -08001091 """Stage a build on a devserver and return the build_url and devserver.
1092
1093 @param build_name: a name like git-master/shamu-userdebug/2040953
Dan Shiab999722015-12-04 14:27:08 -08001094
Dan Shi225b9042015-11-18 10:25:21 -08001095 @returns a tuple with an update URL like:
1096 http://172.22.50.122:8080/git-master/shamu-userdebug/2040953
1097 and the devserver instance.
1098 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001099 os_type = os_type or self.get_os_type()
Dan Shi225b9042015-11-18 10:25:21 -08001100 logging.info('Staging build for installation: %s', build_name)
Dan Shi216389c2015-12-22 11:03:06 -08001101 devserver = dev_server.AndroidBuildServer.resolve(build_name,
1102 self.hostname)
Dan Shiba943532015-12-03 08:58:00 -08001103 build_name = devserver.translate(build_name)
1104 branch, target, build_id = utils.parse_android_build(build_name)
Simran Basibeb2bb22016-02-03 15:25:48 -08001105 is_brillo = os_type == OS_TYPE_BRILLO
Dan Shi08ff1282016-02-18 19:51:16 -08001106 devserver.trigger_download(target, build_id, branch,
1107 is_brillo=is_brillo, synchronous=False)
Dan Shif2fd0762015-12-01 10:09:32 -08001108 return '%s/static/%s' % (devserver.url(), build_name), devserver
Dan Shi225b9042015-11-18 10:25:21 -08001109
1110
Dan Shie4e807b2015-12-10 09:04:03 -08001111 def install_android(self, build_url, build_local_path=None, wipe=True,
Dan Shia2872172015-10-31 01:16:51 -07001112 flash_all=False):
Dan Shiab999722015-12-04 14:27:08 -08001113 """Install the Android DUT.
Dan Shia2872172015-10-31 01:16:51 -07001114
1115 Following are the steps used here to provision an android device:
1116 1. If build_local_path is not set, download the image zip file, e.g.,
1117 shamu-img-2284311.zip, unzip it.
1118 2. Run fastboot to install following artifacts:
1119 bootloader, radio, boot, system, vendor(only if exists)
1120
1121 Repair is not supported for Android devices yet.
1122
1123 @param build_url: The url to use for downloading Android artifacts.
1124 pattern: http://$devserver:###/static/$build
1125 @param build_local_path: The path to a local folder that contains the
1126 image files needed to provision the device. Note that the folder
1127 is in the machine running adb command, rather than the drone.
1128 @param wipe: If true, userdata will be wiped before flashing.
1129 @param flash_all: If True, all img files found in img_path will be
1130 flashed. Otherwise, only boot and system are flashed.
1131
1132 @raises AndroidInstallError if any error occurs.
1133 """
Dan Shia2872172015-10-31 01:16:51 -07001134 # If the build is not staged in local server yet, clean up the temp
1135 # folder used to store image files after the provision is completed.
1136 delete_build_folder = bool(not build_local_path)
1137
1138 try:
1139 # Download image files needed for provision to a local directory.
1140 if not build_local_path:
Dan Shiab999722015-12-04 14:27:08 -08001141 build_local_path = self.stage_android_image_files(build_url)
Dan Shia2872172015-10-31 01:16:51 -07001142
1143 # Device needs to be in bootloader mode for flashing.
1144 self.ensure_bootloader_mode()
1145
1146 if wipe:
Dan Shie4e807b2015-12-10 09:04:03 -08001147 self.fastboot_run('-w')
Dan Shia2872172015-10-31 01:16:51 -07001148
1149 # Get all *.img file in the build_local_path.
1150 list_file_cmd = 'ls -d %s' % os.path.join(build_local_path, '*.img')
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001151 image_files = self.teststation.run(
1152 list_file_cmd).stdout.strip().split()
Dan Shia2872172015-10-31 01:16:51 -07001153 images = dict([(os.path.basename(f), f) for f in image_files])
1154 for image, image_file in images.items():
1155 if image not in ANDROID_IMAGES:
1156 continue
1157 logging.info('Flashing %s...', image_file)
1158 self.fastboot_run('flash %s %s' % (image[:-4], image_file))
1159 if image == ANDROID_BOOTLOADER:
1160 self.fastboot_run('reboot-bootloader')
1161 self.wait_up(command=FASTBOOT_CMD)
1162 except Exception as e:
1163 logging.error('Install Android build failed with error: %s', e)
1164 # Re-raise the exception with type of AndroidInstallError.
1165 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1166 finally:
1167 if delete_build_folder:
Kevin Cheng5f6ed6a2015-10-28 16:18:12 -04001168 self.teststation.run('rm -rf %s' % build_local_path)
Dan Shie4e807b2015-12-10 09:04:03 -08001169 timeout = (WAIT_UP_AFTER_WIPE_TIME_SECONDS if wipe else
1170 DEFAULT_WAIT_UP_TIME_SECONDS)
1171 self.ensure_adb_mode(timeout=timeout)
Dan Shia2872172015-10-31 01:16:51 -07001172 logging.info('Successfully installed Android build staged at %s.',
1173 build_url)
1174
1175
Dan Shiab999722015-12-04 14:27:08 -08001176 def install_brillo(self, build_url, build_local_path=None):
1177 """Install the Brillo DUT.
1178
1179 Following are the steps used here to provision an android device:
1180 1. If build_local_path is not set, download the image zip file, e.g.,
1181 dragonboard-img-123456.zip, unzip it. And download the vendor
1182 partition zip file, e.g., dragonboard-vendor_partitions-123456.zip,
1183 unzip it to vendor folder.
1184 2. Run provision_device script to install OS images and vendor
1185 partitions.
1186
1187 @param build_url: The url to use for downloading Android artifacts.
1188 pattern: http://$devserver:###/static/$build
1189 @param build_local_path: The path to a local folder that contains the
1190 image files needed to provision the device. Note that the folder
1191 is in the machine running adb command, rather than the drone.
1192
1193 @raises AndroidInstallError if any error occurs.
1194 """
1195 # If the build is not staged in local server yet, clean up the temp
1196 # folder used to store image files after the provision is completed.
1197 delete_build_folder = bool(not build_local_path)
1198
Dan Shiab999722015-12-04 14:27:08 -08001199 try:
1200 # Download image files needed for provision to a local directory.
1201 if not build_local_path:
1202 build_local_path = self.stage_brillo_image_files(build_url)
1203
1204 # Device needs to be in bootloader mode for flashing.
1205 self.ensure_bootloader_mode()
1206
1207 # Run provision_device command to install image files and vendor
1208 # partitions.
1209 vendor_partition_dir = os.path.join(build_local_path, 'vendor')
1210 cmd = (BRILLO_PROVISION_CMD %
1211 {'os_image_dir': build_local_path,
1212 'vendor_partition_dir': vendor_partition_dir})
Dan Shi86bd8c02016-03-10 09:21:51 -08001213 if self.fastboot_serial:
1214 cmd += '-s %s ' % self.fastboot_serial
Dan Shiab999722015-12-04 14:27:08 -08001215 self.teststation.run(cmd)
1216 except Exception as e:
1217 logging.error('Install Brillo build failed with error: %s', e)
1218 # Re-raise the exception with type of AndroidInstallError.
1219 raise AndroidInstallError, sys.exc_info()[1], sys.exc_info()[2]
1220 finally:
1221 if delete_build_folder:
1222 self.teststation.run('rm -rf %s' % build_local_path)
1223 self.ensure_adb_mode()
1224 logging.info('Successfully installed Android build staged at %s.',
1225 build_url)
1226
1227
Dan Shibe3636a2016-02-14 22:48:01 -08001228 @property
1229 def job_repo_url_attribute(self):
1230 """Get the host attribute name for job_repo_url, which should append the
1231 adb serial.
1232 """
1233 return '%s_%s' % (constants.JOB_REPO_URL, self.adb_serial)
1234
1235
Dan Shie4e807b2015-12-10 09:04:03 -08001236 def machine_install(self, build_url=None, build_local_path=None, wipe=True,
Simran Basibeb2bb22016-02-03 15:25:48 -08001237 flash_all=False, os_type=None):
Dan Shia2872172015-10-31 01:16:51 -07001238 """Install the DUT.
1239
1240 @param build_url: The url to use for downloading Android artifacts.
Dan Shi225b9042015-11-18 10:25:21 -08001241 pattern: http://$devserver:###/static/$build. If build_url is
1242 set to None, the code may try _parser.options.image to do the
1243 installation. If none of them is set, machine_install will fail.
Dan Shia2872172015-10-31 01:16:51 -07001244 @param build_local_path: The path to a local directory that contains the
1245 image files needed to provision the device.
1246 @param wipe: If true, userdata will be wiped before flashing.
1247 @param flash_all: If True, all img files found in img_path will be
1248 flashed. Otherwise, only boot and system are flashed.
Simran Basi5ace6f22016-01-06 17:30:44 -08001249
Dan Shibe3636a2016-02-14 22:48:01 -08001250 @returns A tuple of (image_name, host_attributes).
1251 image_name is the name of image installed, e.g.,
1252 git_mnc-release/shamu-userdebug/1234
1253 host_attributes is a dictionary of (attribute, value), which
1254 can be saved to afe_host_attributes table in database. This
1255 method returns a dictionary with a single entry of
1256 `job_repo_url_[adb_serial]`: devserver_url, where devserver_url
1257 is a url to the build staged on devserver.
Dan Shia2872172015-10-31 01:16:51 -07001258 """
Simran Basibeb2bb22016-02-03 15:25:48 -08001259 os_type = os_type or self.get_os_type()
Simran Basi5ace6f22016-01-06 17:30:44 -08001260 if not build_url and self._parser.options.image:
1261 build_url, _ = self.stage_build_for_install(
Simran Basibeb2bb22016-02-03 15:25:48 -08001262 self._parser.options.image, os_type=os_type)
1263 if os_type == OS_TYPE_ANDROID:
Dan Shia2872172015-10-31 01:16:51 -07001264 self.install_android(
1265 build_url=build_url, build_local_path=build_local_path,
1266 wipe=wipe, flash_all=flash_all)
Simran Basibeb2bb22016-02-03 15:25:48 -08001267 elif os_type == OS_TYPE_BRILLO:
Dan Shiab999722015-12-04 14:27:08 -08001268 self.install_brillo(
1269 build_url=build_url, build_local_path=build_local_path)
Dan Shia2872172015-10-31 01:16:51 -07001270 else:
1271 raise error.InstallError(
1272 'Installation of os type %s is not supported.' %
1273 self.get_os_type())
Dan Shibe3636a2016-02-14 22:48:01 -08001274 return (build_url.split('static/')[-1],
1275 {self.job_repo_url_attribute: build_url})
Kevin Chengd19e6c62015-10-28 16:39:39 -07001276
1277
1278 def list_files_glob(self, path_glob):
1279 """Get a list of files on the device given glob pattern path.
1280
1281 @param path_glob: The path glob that we want to return the list of
1282 files that match the glob. Relative paths will not work as
1283 expected. Supply an absolute path to get the list of files
1284 you're hoping for.
1285
1286 @returns List of files that match the path_glob.
1287 """
1288 # This is just in case path_glob has no path separator.
1289 base_path = os.path.dirname(path_glob) or '.'
1290 result = self.run('find %s -path \'%s\' -print' %
Christopher Wileyd21d66a2016-03-01 10:58:13 -08001291 (base_path, path_glob), ignore_status=True)
Kevin Chengd19e6c62015-10-28 16:39:39 -07001292 if result.exit_status != 0:
1293 return []
1294 return result.stdout.splitlines()
Kevin Cheng31355942016-01-05 14:23:35 -08001295
1296
Dan Shidb0366c2016-02-19 10:36:18 -08001297 def install_apk(self, apk, force_reinstall=False):
Kevin Cheng31355942016-01-05 14:23:35 -08001298 """Install the specified apk.
1299
1300 This will install the apk and override it if it's already installed and
1301 will also allow for downgraded apks.
1302
1303 @param apk: The path to apk file.
Dan Shidb0366c2016-02-19 10:36:18 -08001304 @param force_reinstall: True to reinstall the apk even if it's already
1305 installed. Default is set to False.
1306
1307 @returns a CMDResult object.
Kevin Cheng31355942016-01-05 14:23:35 -08001308 """
Dan Shidb0366c2016-02-19 10:36:18 -08001309 return self.adb_run('install %s -d %s' %
1310 ('-r' if force_reinstall else '', apk))
1311
1312
1313 @retry.retry(error.AutoservRunError, timeout_min=0.2)
1314 def _confirm_apk_installed(self, package_name):
1315 """Confirm if apk is already installed with the given name.
1316
1317 `pm list packages` command is not reliable some time. The retry helps to
1318 reduce the chance of false negative.
1319
1320 @param package_name: Name of the package, e.g., com.android.phone.
1321
1322 @raise AutoservRunError: If the package is not found or pm list command
1323 failed for any reason.
1324 """
1325 name = 'package:%s' % package_name
1326 self.adb_run('shell pm list packages | grep -w "%s"' % name)
1327
1328
1329 def is_apk_installed(self, package_name):
1330 """Check if apk is already installed with the given name.
1331
1332 @param package_name: Name of the package, e.g., com.android.phone.
1333
1334 @return: True if package is installed. False otherwise.
1335 """
1336 try:
1337 self._confirm_apk_installed(package_name)
1338 return True
1339 except:
1340 return False
Dan Shibe3636a2016-02-14 22:48:01 -08001341
1342
1343 def get_attributes_to_clear_before_provision(self):
1344 """Get a list of attributes to be cleared before machine_install starts.
1345 """
1346 return [self.job_repo_url_attribute]