blob: a4bf9caf2a314f9ba18f2385615e4a76a7caedb2 [file] [log] [blame]
Ang Li93420002016-05-10 19:11:44 -07001#!/usr/bin/env python3.4
2#
3# Copyright 2016 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17from builtins import str
18from builtins import open
19
Ang Li7f0e1c72016-06-14 11:23:49 -070020import logging
Ang Li93420002016-05-10 19:11:44 -070021import os
22import time
23import traceback
Sahil Jain06dd6a22016-06-24 13:47:37 -070024import threading
25import socket
26import Queue
Ang Li93420002016-05-10 19:11:44 -070027
28from vts.runners.host import logger as vts_logger
29from vts.runners.host import signals
30from vts.runners.host import utils
Ang Li7f0e1c72016-06-14 11:23:49 -070031from vts.utils.python.controllers import adb
32from vts.utils.python.controllers import event_dispatcher
33from vts.utils.python.controllers import fastboot
Sahil Jain06dd6a22016-06-24 13:47:37 -070034from vts.runners.host.tcp_client import vts_tcp_client
Ang Li7f0e1c72016-06-14 11:23:49 -070035from vts.utils.python.mirror import hal_mirror
Keun Soo Yim63d67512016-07-01 17:13:47 -070036from vts.utils.python.mirror import shell_mirror
Keun Soo Yim39bc0b92016-07-06 18:27:15 -070037from vts.utils.python.mirror import lib_mirror
Sahil Jain06dd6a22016-06-24 13:47:37 -070038from vts.runners.host import errors
39import subprocess
Ang Li93420002016-05-10 19:11:44 -070040
41VTS_CONTROLLER_CONFIG_NAME = "AndroidDevice"
42VTS_CONTROLLER_REFERENCE_NAME = "android_devices"
43
44ANDROID_DEVICE_PICK_ALL_TOKEN = "*"
45# Key name for adb logcat extra params in config file.
46ANDROID_DEVICE_ADB_LOGCAT_PARAM_KEY = "adb_logcat_param"
47ANDROID_DEVICE_EMPTY_CONFIG_MSG = "Configuration is empty, abort!"
48ANDROID_DEVICE_NOT_LIST_CONFIG_MSG = "Configuration should be a list, abort!"
49
Sahil Jain06dd6a22016-06-24 13:47:37 -070050# Target-side directory where the VTS binaries are uploaded
51DEFAULT_AGENT_BASE_DIR = "/data/local/tmp"
52# Time for which the current is put on sleep when the client is unable to
53# make a connection.
54THREAD_SLEEP_TIME = 1
55# Max number of attempts that the client can make to connect to the agent
56MAX_AGENT_CONNECT_RETRIES = 10
57
Ang Lie2139f12016-05-12 17:39:06 -070058
Ang Li93420002016-05-10 19:11:44 -070059class AndroidDeviceError(signals.ControllerError):
60 pass
61
Ang Lie2139f12016-05-12 17:39:06 -070062
Ang Li7f0e1c72016-06-14 11:23:49 -070063def create(configs):
Ang Li53bb72b2016-07-19 18:29:37 -070064 """Creates AndroidDevice controller objects.
65
66 Args:
67 configs: A list of dicts, each representing a configuration for an
68 Android device.
69
70 Returns:
71 A list of AndroidDevice objects.
72 """
Ang Li93420002016-05-10 19:11:44 -070073 if not configs:
74 raise AndroidDeviceError(ANDROID_DEVICE_EMPTY_CONFIG_MSG)
75 elif configs == ANDROID_DEVICE_PICK_ALL_TOKEN:
Ang Li7f0e1c72016-06-14 11:23:49 -070076 ads = get_all_instances()
Ang Li93420002016-05-10 19:11:44 -070077 elif not isinstance(configs, list):
78 raise AndroidDeviceError(ANDROID_DEVICE_NOT_LIST_CONFIG_MSG)
79 elif isinstance(configs[0], str):
80 # Configs is a list of serials.
Ang Li7f0e1c72016-06-14 11:23:49 -070081 ads = get_instances(configs)
Ang Li93420002016-05-10 19:11:44 -070082 else:
83 # Configs is a list of dicts.
Ang Li7f0e1c72016-06-14 11:23:49 -070084 ads = get_instances_with_configs(configs)
Ang Li93420002016-05-10 19:11:44 -070085 connected_ads = list_adb_devices()
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -070086
Ang Li93420002016-05-10 19:11:44 -070087 for ad in ads:
88 if ad.serial not in connected_ads:
Ang Li53bb72b2016-07-19 18:29:37 -070089 raise DoesNotExistError(("Android device %s is specified in config"
90 " but is not attached.") % ad.serial)
91 _startServicesOnAds(ads)
Ang Li93420002016-05-10 19:11:44 -070092 return ads
93
Ang Lie2139f12016-05-12 17:39:06 -070094
Ang Li93420002016-05-10 19:11:44 -070095def destroy(ads):
Ang Li53bb72b2016-07-19 18:29:37 -070096 """Cleans up AndroidDevice objects.
97
98 Args:
99 ads: A list of AndroidDevice objects.
100 """
Ang Li93420002016-05-10 19:11:44 -0700101 for ad in ads:
Ang Li53bb72b2016-07-19 18:29:37 -0700102 try:
103 ad.cleanUp()
104 except:
105 ad.log.exception("Failed to clean up properly.")
106
107
108def _startServicesOnAds(ads):
109 """Starts long running services on multiple AndroidDevice objects.
110
111 If any one AndroidDevice object fails to start services, cleans up all
112 existing AndroidDevice objects and their services.
113
114 Args:
115 ads: A list of AndroidDevice objects whose services to start.
116 """
117 running_ads = []
118 for ad in ads:
119 running_ads.append(ad)
120 try:
Keun Soo Yim9b4f0cb2016-07-20 10:08:59 -0700121 ad.startServices()
Ang Li53bb72b2016-07-19 18:29:37 -0700122 except:
123 ad.log.exception("Failed to start some services, abort!")
124 destroy(running_ads)
125 raise
Ang Li93420002016-05-10 19:11:44 -0700126
Ang Lie2139f12016-05-12 17:39:06 -0700127
Ang Li93420002016-05-10 19:11:44 -0700128def _parse_device_list(device_list_str, key):
129 """Parses a byte string representing a list of devices. The string is
130 generated by calling either adb or fastboot.
131
132 Args:
133 device_list_str: Output of adb or fastboot.
134 key: The token that signifies a device in device_list_str.
135
136 Returns:
137 A list of android device serial numbers.
138 """
139 clean_lines = str(device_list_str, 'utf-8').strip().split('\n')
140 results = []
141 for line in clean_lines:
142 tokens = line.strip().split('\t')
143 if len(tokens) == 2 and tokens[1] == key:
144 results.append(tokens[0])
145 return results
146
Ang Lie2139f12016-05-12 17:39:06 -0700147
Ang Li93420002016-05-10 19:11:44 -0700148def list_adb_devices():
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700149 """List all target devices connected to the host and detected by adb.
Ang Li93420002016-05-10 19:11:44 -0700150
151 Returns:
152 A list of android device serials. Empty if there's none.
153 """
154 out = adb.AdbProxy().devices()
155 return _parse_device_list(out, "device")
156
Ang Lie2139f12016-05-12 17:39:06 -0700157
Ang Li93420002016-05-10 19:11:44 -0700158def list_fastboot_devices():
159 """List all android devices connected to the computer that are in in
160 fastboot mode. These are detected by fastboot.
161
162 Returns:
163 A list of android device serials. Empty if there's none.
164 """
165 out = fastboot.FastbootProxy().devices()
166 return _parse_device_list(out, "fastboot")
167
Ang Lie2139f12016-05-12 17:39:06 -0700168
Ang Li7f0e1c72016-06-14 11:23:49 -0700169def get_instances(serials):
Ang Li93420002016-05-10 19:11:44 -0700170 """Create AndroidDevice instances from a list of serials.
171
172 Args:
173 serials: A list of android device serials.
Ang Li93420002016-05-10 19:11:44 -0700174
175 Returns:
176 A list of AndroidDevice objects.
177 """
178 results = []
179 for s in serials:
Ang Li7f0e1c72016-06-14 11:23:49 -0700180 results.append(AndroidDevice(s))
Ang Li93420002016-05-10 19:11:44 -0700181 return results
182
Ang Lie2139f12016-05-12 17:39:06 -0700183
Ang Li7f0e1c72016-06-14 11:23:49 -0700184def get_instances_with_configs(configs):
Ang Li93420002016-05-10 19:11:44 -0700185 """Create AndroidDevice instances from a list of json configs.
186
187 Each config should have the required key-value pair "serial".
188
189 Args:
190 configs: A list of dicts each representing the configuration of one
191 android device.
Ang Li93420002016-05-10 19:11:44 -0700192
193 Returns:
194 A list of AndroidDevice objects.
195 """
196 results = []
197 for c in configs:
198 try:
199 serial = c.pop("serial")
200 except KeyError:
201 raise AndroidDeviceError(('Required value "serial" is missing in '
Ang Lie2139f12016-05-12 17:39:06 -0700202 'AndroidDevice config %s.') % c)
Ang Li7f0e1c72016-06-14 11:23:49 -0700203 ad = AndroidDevice(serial)
Ang Li93420002016-05-10 19:11:44 -0700204 ad.loadConfig(c)
205 results.append(ad)
206 return results
207
Ang Lie2139f12016-05-12 17:39:06 -0700208
Ang Li7f0e1c72016-06-14 11:23:49 -0700209def get_all_instances(include_fastboot=False):
Ang Li93420002016-05-10 19:11:44 -0700210 """Create AndroidDevice instances for all attached android devices.
211
212 Args:
213 include_fastboot: Whether to include devices in bootloader mode or not.
Ang Li93420002016-05-10 19:11:44 -0700214
215 Returns:
216 A list of AndroidDevice objects each representing an android device
217 attached to the computer.
218 """
219 if include_fastboot:
220 serial_list = list_adb_devices() + list_fastboot_devices()
Ang Li7f0e1c72016-06-14 11:23:49 -0700221 return get_instances(serial_list)
222 return get_instances(list_adb_devices())
Ang Li93420002016-05-10 19:11:44 -0700223
Ang Lie2139f12016-05-12 17:39:06 -0700224
Ang Li93420002016-05-10 19:11:44 -0700225def filter_devices(ads, func):
226 """Finds the AndroidDevice instances from a list that match certain
227 conditions.
228
229 Args:
230 ads: A list of AndroidDevice instances.
231 func: A function that takes an AndroidDevice object and returns True
232 if the device satisfies the filter condition.
233
234 Returns:
235 A list of AndroidDevice instances that satisfy the filter condition.
236 """
237 results = []
238 for ad in ads:
239 if func(ad):
240 results.append(ad)
241 return results
242
Ang Lie2139f12016-05-12 17:39:06 -0700243
Ang Li93420002016-05-10 19:11:44 -0700244def get_device(ads, **kwargs):
245 """Finds a unique AndroidDevice instance from a list that has specific
246 attributes of certain values.
247
248 Example:
249 get_device(android_devices, label="foo", phone_number="1234567890")
250 get_device(android_devices, model="angler")
251
252 Args:
253 ads: A list of AndroidDevice instances.
254 kwargs: keyword arguments used to filter AndroidDevice instances.
255
256 Returns:
257 The target AndroidDevice instance.
258
259 Raises:
260 AndroidDeviceError is raised if none or more than one device is
261 matched.
262 """
Ang Lie2139f12016-05-12 17:39:06 -0700263
Ang Li93420002016-05-10 19:11:44 -0700264 def _get_device_filter(ad):
265 for k, v in kwargs.items():
266 if not hasattr(ad, k):
267 return False
268 elif getattr(ad, k) != v:
269 return False
270 return True
Ang Lie2139f12016-05-12 17:39:06 -0700271
Ang Li93420002016-05-10 19:11:44 -0700272 filtered = filter_devices(ads, _get_device_filter)
273 if not filtered:
274 raise AndroidDeviceError(("Could not find a target device that matches"
275 " condition: %s.") % kwargs)
276 elif len(filtered) == 1:
277 return filtered[0]
278 else:
279 serials = [ad.serial for ad in filtered]
280 raise AndroidDeviceError("More than one device matched: %s" % serials)
281
Ang Lie2139f12016-05-12 17:39:06 -0700282
Ang Li93420002016-05-10 19:11:44 -0700283def takeBugReports(ads, test_name, begin_time):
284 """Takes bug reports on a list of android devices.
285
286 If you want to take a bug report, call this function with a list of
287 android_device objects in on_fail. But reports will be taken on all the
288 devices in the list concurrently. Bug report takes a relative long
289 time to take, so use this cautiously.
290
291 Args:
292 ads: A list of AndroidDevice instances.
293 test_name: Name of the test case that triggered this bug report.
294 begin_time: Logline format timestamp taken when the test started.
295 """
296 begin_time = vts_logger.normalizeLogLineTimestamp(begin_time)
Ang Lie2139f12016-05-12 17:39:06 -0700297
Ang Li93420002016-05-10 19:11:44 -0700298 def take_br(test_name, begin_time, ad):
299 ad.takeBugReport(test_name, begin_time)
Ang Lie2139f12016-05-12 17:39:06 -0700300
Ang Li93420002016-05-10 19:11:44 -0700301 args = [(test_name, begin_time, ad) for ad in ads]
302 utils.concurrent_exec(take_br, args)
303
Ang Lie2139f12016-05-12 17:39:06 -0700304
Ang Li7f0e1c72016-06-14 11:23:49 -0700305class AndroidDevice(object):
Ang Li93420002016-05-10 19:11:44 -0700306 """Class representing an android device.
307
Ang Li53bb72b2016-07-19 18:29:37 -0700308 Each object of this class represents one Android device. The object holds
309 handles to adb, fastboot, and various RPC clients.
Ang Li93420002016-05-10 19:11:44 -0700310
311 Attributes:
312 serial: A string that's the serial number of the Androi device.
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700313 device_command_port: int, the port number used on the Android device
314 for adb port forwarding (for command-response sessions).
315 device_callback_port: int, the port number used on the Android device
316 for adb port reverse forwarding (for callback sessions).
Ang Lie014a8b2016-06-28 18:24:52 -0700317 log: A logger project with a device-specific prefix for each line -
318 [AndroidDevice|<serial>]
Ang Li93420002016-05-10 19:11:44 -0700319 log_path: A string that is the path where all logs collected on this
320 android device should be stored.
321 adb_logcat_process: A process that collects the adb logcat.
322 adb_logcat_file_path: A string that's the full path to the adb logcat
323 file collected, if any.
Ang Lie014a8b2016-06-28 18:24:52 -0700324 vts_agent_process: A process that runs the HAL agent.
Ang Li93420002016-05-10 19:11:44 -0700325 adb: An AdbProxy object used for interacting with the device via adb.
326 fastboot: A FastbootProxy object used for interacting with the device
327 via fastboot.
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700328 host_command_port: the host-side port for runner to agent sessions
329 (to send commands and receive responses).
330 host_callback_port: the host-side port for agent to runner sessions
331 (to get callbacks from agent).
Ang Li53bb72b2016-07-19 18:29:37 -0700332 hal: HalMirror, in charge of all communications with the HAL layer.
333 lib: LibMirror, in charge of all communications with static and shared
334 native libs.
335 shell: ShellMirror, in charge of all communications with shell.
Ang Li93420002016-05-10 19:11:44 -0700336 """
337
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700338 def __init__(self, serial="", device_callback_port=5010):
Ang Li93420002016-05-10 19:11:44 -0700339 self.serial = serial
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700340 self.device_command_port = None
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700341 self.device_callback_port = device_callback_port
Ang Lie014a8b2016-06-28 18:24:52 -0700342 self.log = AndroidDeviceLoggerAdapter(logging.getLogger(),
343 {"serial": self.serial})
344 base_log_path = getattr(logging, "log_path", "/tmp/logs/")
Ang Li7f0e1c72016-06-14 11:23:49 -0700345 self.log_path = os.path.join(base_log_path, "AndroidDevice%s" % serial)
Ang Li93420002016-05-10 19:11:44 -0700346 self.adb_logcat_process = None
347 self.adb_logcat_file_path = None
Ang Lie014a8b2016-06-28 18:24:52 -0700348 self.vts_agent_process = None
Ang Li93420002016-05-10 19:11:44 -0700349 self.adb = adb.AdbProxy(serial)
350 self.fastboot = fastboot.FastbootProxy(serial)
351 if not self.isBootloaderMode:
352 self.rootAdb()
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700353 self.host_command_port = adb.get_available_host_port()
354 self.host_callback_port = adb.get_available_host_port()
Ang Lie014a8b2016-06-28 18:24:52 -0700355 self.adb.reverse_tcp_forward(self.device_callback_port,
356 self.host_callback_port)
Ang Li53bb72b2016-07-19 18:29:37 -0700357 self.hal = None
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700358 self.lib = None
359 self.shell = None
Ang Li93420002016-05-10 19:11:44 -0700360
361 def __del__(self):
Ang Li53bb72b2016-07-19 18:29:37 -0700362 self.cleanUp()
363
364 def cleanUp(self):
365 """Cleans up the AndroidDevice object and releases any resources it
366 claimed.
367 """
368 self.stopServices()
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700369 if self.host_command_port:
370 self.adb.forward("--remove tcp:%s" % self.host_command_port)
Ang Li93420002016-05-10 19:11:44 -0700371
372 @property
373 def isBootloaderMode(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700374 """True if the device is in bootloader mode."""
Ang Li93420002016-05-10 19:11:44 -0700375 return self.serial in list_fastboot_devices()
376
377 @property
378 def isAdbRoot(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700379 """True if adb is running as root for this device."""
380 id_str = self.adb.shell("id -u").decode("utf-8")
381 self.log.info(id_str)
382 return "root" in id_str
Ang Li93420002016-05-10 19:11:44 -0700383
384 @property
385 def model(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700386 """The Android code name for the device."""
Ang Li93420002016-05-10 19:11:44 -0700387 # If device is in bootloader mode, get mode name from fastboot.
388 if self.isBootloaderMode:
389 out = self.fastboot.getvar("product").strip()
390 # "out" is never empty because of the "total time" message fastboot
391 # writes to stderr.
392 lines = out.decode("utf-8").split('\n', 1)
393 if lines:
394 tokens = lines[0].split(' ')
395 if len(tokens) > 1:
396 return tokens[1].lower()
397 return None
398 out = self.adb.shell('getprop | grep ro.build.product')
399 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
400 if model == "sprout":
401 return model
402 else:
403 out = self.adb.shell('getprop | grep ro.product.name')
404 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
405 return model
406
407 @property
Ang Li93420002016-05-10 19:11:44 -0700408 def isAdbLogcatOn(self):
409 """Whether there is an ongoing adb logcat collection.
410 """
411 if self.adb_logcat_process:
412 return True
413 return False
414
415 def loadConfig(self, config):
416 """Add attributes to the AndroidDevice object based on json config.
417
418 Args:
419 config: A dictionary representing the configs.
420
421 Raises:
422 AndroidDeviceError is raised if the config is trying to overwrite
423 an existing attribute.
424 """
425 for k, v in config.items():
426 if hasattr(self, k):
Ang Li7f0e1c72016-06-14 11:23:49 -0700427 raise AndroidDeviceError(
428 "Attempting to set existing attribute %s on %s" %
429 (k, self.serial))
Ang Li93420002016-05-10 19:11:44 -0700430 setattr(self, k, v)
431
432 def rootAdb(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700433 """Changes adb to root mode for this device."""
Ang Li93420002016-05-10 19:11:44 -0700434 if not self.isAdbRoot:
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700435 try:
436 self.adb.root()
Keun Soo Yima5a0dc22016-07-16 17:56:19 -0700437 self.adb.wait_for_device()
438 self.adb.remount()
Keun Soo Yim731e9172016-07-16 17:48:39 -0700439 self.adb.wait_for_device()
440 except adb.AdbError as e:
441 # adb wait-for-device is not always possible in the lab
Keun Soo Yima5a0dc22016-07-16 17:56:19 -0700442 # continue with an assumption it's done by the harness.
Keun Soo Yim731e9172016-07-16 17:48:39 -0700443 logging.exception(e)
Ang Li93420002016-05-10 19:11:44 -0700444
Ang Li93420002016-05-10 19:11:44 -0700445 def startAdbLogcat(self):
446 """Starts a standing adb logcat collection in separate subprocesses and
447 save the logcat in a file.
448 """
449 if self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700450 raise AndroidDeviceError(("Android device %s already has an adb "
Ang Lie2139f12016-05-12 17:39:06 -0700451 "logcat thread going on. Cannot start "
Ang Li7f0e1c72016-06-14 11:23:49 -0700452 "another one.") % self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700453 f_name = "adblog,%s,%s.txt" % (self.model, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700454 utils.create_dir(self.log_path)
455 logcat_file_path = os.path.join(self.log_path, f_name)
456 try:
457 extra_params = self.adb_logcat_param
458 except AttributeError:
459 extra_params = "-b all"
Ang Li7f0e1c72016-06-14 11:23:49 -0700460 cmd = "adb -s %s logcat -v threadtime %s >> %s" % (
Ang Li93420002016-05-10 19:11:44 -0700461 self.serial, extra_params, logcat_file_path)
462 self.adb_logcat_process = utils.start_standing_subprocess(cmd)
463 self.adb_logcat_file_path = logcat_file_path
464
465 def stopAdbLogcat(self):
466 """Stops the adb logcat collection subprocess.
467 """
468 if not self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700469 raise AndroidDeviceError(
470 "Android device %s does not have an ongoing adb logcat collection."
471 % self.serial)
Ang Li93420002016-05-10 19:11:44 -0700472 utils.stop_standing_subprocess(self.adb_logcat_process)
473 self.adb_logcat_process = None
474
475 def takeBugReport(self, test_name, begin_time):
476 """Takes a bug report on the device and stores it in a file.
477
478 Args:
479 test_name: Name of the test case that triggered this bug report.
480 begin_time: Logline format timestamp taken when the test started.
481 """
482 br_path = os.path.join(self.log_path, "BugReports")
483 utils.create_dir(br_path)
Ang Li7f0e1c72016-06-14 11:23:49 -0700484 base_name = ",%s,%s.txt" % (begin_time, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700485 test_name_len = utils.MAX_FILENAME_LEN - len(base_name)
486 out_name = test_name[:test_name_len] + base_name
487 full_out_path = os.path.join(br_path, out_name.replace(' ', '\ '))
488 self.log.info("Taking bugreport for %s on %s", test_name, self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700489 self.adb.bugreport(" > %s" % full_out_path)
Ang Li93420002016-05-10 19:11:44 -0700490 self.log.info("Bugreport for %s taken at %s", test_name, full_out_path)
491
Ang Li93420002016-05-10 19:11:44 -0700492 @utils.timeout(15 * 60)
493 def waitForBootCompletion(self):
494 """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED.
495
496 This function times out after 15 minutes.
497 """
Keun Soo Yim731e9172016-07-16 17:48:39 -0700498 try:
499 self.adb.wait_for_device()
500 except adb.AdbError as e:
501 # adb wait-for-device is not always possible in the lab
502 logging.exception(e)
Ang Li93420002016-05-10 19:11:44 -0700503 while True:
504 try:
505 out = self.adb.shell("getprop sys.boot_completed")
506 completed = out.decode('utf-8').strip()
507 if completed == '1':
508 return
509 except adb.AdbError:
510 # adb shell calls may fail during certain period of booting
511 # process, which is normal. Ignoring these errors.
512 pass
513 time.sleep(5)
514
515 def reboot(self):
Ang Li7f0e1c72016-06-14 11:23:49 -0700516 """Reboots the device and wait for device to complete booting.
Ang Li93420002016-05-10 19:11:44 -0700517
518 This is probably going to print some error messages in console. Only
519 use if there's no other option.
520
Ang Li93420002016-05-10 19:11:44 -0700521 Raises:
522 AndroidDeviceError is raised if waiting for completion timed
523 out.
524 """
525 if self.isBootloaderMode:
526 self.fastboot.reboot()
527 return
528 has_adb_log = self.isAdbLogcatOn
Ang Lie014a8b2016-06-28 18:24:52 -0700529 has_vts_agent = True if self.vts_agent_process else False
Ang Li93420002016-05-10 19:11:44 -0700530 if has_adb_log:
531 self.stopAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700532 if has_vts_agent:
533 self.stopVtsAgent()
Ang Li93420002016-05-10 19:11:44 -0700534 self.adb.reboot()
535 self.waitForBootCompletion()
536 self.rootAdb()
Ang Li93420002016-05-10 19:11:44 -0700537 if has_adb_log:
538 self.startAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700539 if has_vts_agent:
540 self.startVtsAgent()
Sahil Jain06dd6a22016-06-24 13:47:37 -0700541
Ang Li53bb72b2016-07-19 18:29:37 -0700542 def startServices(self):
543 """Starts long running services on the android device.
544
545 1. Start adb logcat capture.
546 2. Start VtsAgent.
547 3. Create HalMirror
548 """
549 try:
550 self.startAdbLogcat()
551 except:
552 self.log.exception("Failed to start adb logcat!")
553 raise
554 self.startVtsAgent()
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700555 self.device_command_port = int(
556 self.adb.shell("cat /data/local/tmp/vts_tcp_server_port"))
557 logging.info("device_command_port: %s", self.device_command_port)
558 self.adb.tcp_forward(self.host_command_port, self.device_command_port)
Ang Li53bb72b2016-07-19 18:29:37 -0700559 self.hal = hal_mirror.HalMirror(self.host_command_port,
560 self.host_callback_port)
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700561 self.lib = lib_mirror.LibMirror(self.host_command_port)
562 self.shell = shell_mirror.ShellMirror(self.host_command_port)
Ang Li53bb72b2016-07-19 18:29:37 -0700563
564 def stopServices(self):
565 """Stops long running services on the android device.
566 """
567 if self.adb_logcat_process:
568 self.stopAdbLogcat()
569 self.stopVtsAgent()
570 if self.hal:
571 self.hal.CleanUp()
572
Ang Lie014a8b2016-06-28 18:24:52 -0700573 def startVtsAgent(self):
574 """Start HAL agent on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700575
576 This function starts the target side native agent and is persisted
Ang Lie014a8b2016-06-28 18:24:52 -0700577 throughout the test run.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700578 """
Keun Soo Yimab7fb062016-07-13 14:47:19 -0700579 self.log.info("start a VTS agent")
Ang Lie014a8b2016-06-28 18:24:52 -0700580 if self.vts_agent_process:
581 raise AndroidDeviceError("HAL agent is already running on %s." %
582 self.serial)
Keun Soo Yima066dd52016-07-01 15:18:28 -0700583
584 cleanup_commands = [
Keun Soo Yim02da0272016-07-19 07:56:38 -0700585 "rm -f /data/local/tmp/vts_driver_*",
Ang Li53bb72b2016-07-19 18:29:37 -0700586 "rm -f /data/local/tmp/vts_agent_callback*"
587 ]
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700588 kill_commands = ["killall vts_hal_agent32", "killall vts_hal_agent64",
589 "killall fuzzer32", "killall fuzzer64",
590 "killall vts_shell_driver32",
Yuexi Ma674e59d2016-07-19 15:39:54 -0700591 "killall vts_shell_driver64"]
Keun Soo Yima066dd52016-07-01 15:18:28 -0700592 cleanup_commands.extend(kill_commands)
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700593 chmod_commands = [
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700594 "chmod 755 %s/32/vts_hal_agent32" % DEFAULT_AGENT_BASE_DIR,
595 "chmod 755 %s/64/vts_hal_agent64" % DEFAULT_AGENT_BASE_DIR,
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700596 "chmod 755 %s/32/fuzzer32" % DEFAULT_AGENT_BASE_DIR,
Keun Soo Yim02da0272016-07-19 07:56:38 -0700597 "chmod 755 %s/64/fuzzer64" % DEFAULT_AGENT_BASE_DIR,
598 "chmod 755 %s/32/vts_shell_driver32" % DEFAULT_AGENT_BASE_DIR,
Ang Li53bb72b2016-07-19 18:29:37 -0700599 "chmod 755 %s/64/vts_shell_driver64" % DEFAULT_AGENT_BASE_DIR
600 ]
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700601 cleanup_commands.extend(chmod_commands)
Keun Soo Yima066dd52016-07-01 15:18:28 -0700602 for cmd in cleanup_commands:
Sahil Jain06dd6a22016-06-24 13:47:37 -0700603 try:
604 self.adb.shell(cmd)
Keun Soo Yimab7fb062016-07-13 14:47:19 -0700605 except adb.AdbError as e:
606 self.log.warning(
Ang Li53bb72b2016-07-19 18:29:37 -0700607 "A command to setup the env to start the VTS Agent failed %s",
608 e)
Ang Lie014a8b2016-06-28 18:24:52 -0700609 vts_agent_log_path = os.path.join(self.log_path, "vts_agent.log")
Keun Soo Yimd2aa5b82016-07-30 20:12:19 -0700610 for bitness in ['64', '32']:
611 cmd = (
612 'adb -s {s} shell LD_LIBRARY_PATH={path}/{bitness} '
613 '{path}/{bitness}/vts_hal_agent{bitness}'
614 ' {path}/32/fuzzer32 {path}/64/fuzzer64 {path}/spec'
615 ' {path}/32/vts_shell_driver32 {path}/64/vts_shell_driver64 >> {log}'
616 ).format(s=self.serial,
617 bitness=bitness,
618 path=DEFAULT_AGENT_BASE_DIR,
619 log=vts_agent_log_path)
620 try:
621 self.vts_agent_process = utils.start_standing_subprocess(
622 cmd, check_health_delay=1)
623 except utils.VTSUtilsError as e:
624 logging.exception(e)
625 with open(vts_agent_log_path, 'r') as log_file:
626 logging.error("VTS agent output:\n")
627 logging.error(log_file.read())
628 # one common cause is that 64-bit executable is not supported
629 # in low API level devices.
630 if bitness == '32':
631 raise
632 else:
633 logging.error('retrying using a 32-bit binary.')
Sahil Jain06dd6a22016-06-24 13:47:37 -0700634
Ang Lie014a8b2016-06-28 18:24:52 -0700635 def stopVtsAgent(self):
636 """Stop the HAL agent running on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700637 """
Ang Lie014a8b2016-06-28 18:24:52 -0700638 if self.vts_agent_process:
639 utils.stop_standing_subprocess(self.vts_agent_process)
640 self.vts_agent_process = None
Sahil Jain06dd6a22016-06-24 13:47:37 -0700641
Sahil Jain06dd6a22016-06-24 13:47:37 -0700642
Ang Lie014a8b2016-06-28 18:24:52 -0700643class AndroidDeviceLoggerAdapter(logging.LoggerAdapter):
644 """A wrapper class that attaches a prefix to all log lines from an
645 AndroidDevice object.
646 """
647
648 def process(self, msg, kwargs):
649 """Process every log message written via the wrapped logger object.
650
651 We are adding the prefix "[AndroidDevice|<serial>]" to all log lines.
652
653 Args:
654 msg: string, the original log message.
655 kwargs: dict, the key value pairs that can be used to modify the
656 original log message.
657 """
658 msg = "[AndroidDevice|%s] %s" % (self.extra["serial"], msg)
659 return (msg, kwargs)