blob: b72c0205db34f08186ae9d453075b11dee8fc85c [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
Keun Soo Yim4231b6e2016-07-31 19:01:05 -070063def create(configs, use_vts_agent=true):
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.
Keun Soo Yim4231b6e2016-07-31 19:01:05 -070069 use_vts_agent: bool, whether to use VTS agent.
Ang Li53bb72b2016-07-19 18:29:37 -070070
71 Returns:
72 A list of AndroidDevice objects.
73 """
Ang Li93420002016-05-10 19:11:44 -070074 if not configs:
75 raise AndroidDeviceError(ANDROID_DEVICE_EMPTY_CONFIG_MSG)
76 elif configs == ANDROID_DEVICE_PICK_ALL_TOKEN:
Ang Li7f0e1c72016-06-14 11:23:49 -070077 ads = get_all_instances()
Ang Li93420002016-05-10 19:11:44 -070078 elif not isinstance(configs, list):
79 raise AndroidDeviceError(ANDROID_DEVICE_NOT_LIST_CONFIG_MSG)
80 elif isinstance(configs[0], str):
81 # Configs is a list of serials.
Ang Li7f0e1c72016-06-14 11:23:49 -070082 ads = get_instances(configs)
Ang Li93420002016-05-10 19:11:44 -070083 else:
84 # Configs is a list of dicts.
Ang Li7f0e1c72016-06-14 11:23:49 -070085 ads = get_instances_with_configs(configs)
Ang Li93420002016-05-10 19:11:44 -070086 connected_ads = list_adb_devices()
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -070087
Ang Li93420002016-05-10 19:11:44 -070088 for ad in ads:
89 if ad.serial not in connected_ads:
Ang Li53bb72b2016-07-19 18:29:37 -070090 raise DoesNotExistError(("Android device %s is specified in config"
91 " but is not attached.") % ad.serial)
Keun Soo Yim4231b6e2016-07-31 19:01:05 -070092 _startServicesOnAds(ads, use_vts_agent)
Ang Li93420002016-05-10 19:11:44 -070093 return ads
94
Ang Lie2139f12016-05-12 17:39:06 -070095
Ang Li93420002016-05-10 19:11:44 -070096def destroy(ads):
Ang Li53bb72b2016-07-19 18:29:37 -070097 """Cleans up AndroidDevice objects.
98
99 Args:
100 ads: A list of AndroidDevice objects.
101 """
Ang Li93420002016-05-10 19:11:44 -0700102 for ad in ads:
Ang Li53bb72b2016-07-19 18:29:37 -0700103 try:
104 ad.cleanUp()
105 except:
106 ad.log.exception("Failed to clean up properly.")
107
108
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700109def _startServicesOnAds(ads, use_vts_agent):
Ang Li53bb72b2016-07-19 18:29:37 -0700110 """Starts long running services on multiple AndroidDevice objects.
111
112 If any one AndroidDevice object fails to start services, cleans up all
113 existing AndroidDevice objects and their services.
114
115 Args:
116 ads: A list of AndroidDevice objects whose services to start.
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700117 use_vts_agent: bool, whether to use the VTS agent.
Ang Li53bb72b2016-07-19 18:29:37 -0700118 """
119 running_ads = []
120 for ad in ads:
121 running_ads.append(ad)
122 try:
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700123 ad.startServices(use_vts_agent)
Ang Li53bb72b2016-07-19 18:29:37 -0700124 except:
125 ad.log.exception("Failed to start some services, abort!")
126 destroy(running_ads)
127 raise
Ang Li93420002016-05-10 19:11:44 -0700128
Ang Lie2139f12016-05-12 17:39:06 -0700129
Ang Li93420002016-05-10 19:11:44 -0700130def _parse_device_list(device_list_str, key):
131 """Parses a byte string representing a list of devices. The string is
132 generated by calling either adb or fastboot.
133
134 Args:
135 device_list_str: Output of adb or fastboot.
136 key: The token that signifies a device in device_list_str.
137
138 Returns:
139 A list of android device serial numbers.
140 """
141 clean_lines = str(device_list_str, 'utf-8').strip().split('\n')
142 results = []
143 for line in clean_lines:
144 tokens = line.strip().split('\t')
145 if len(tokens) == 2 and tokens[1] == key:
146 results.append(tokens[0])
147 return results
148
Ang Lie2139f12016-05-12 17:39:06 -0700149
Ang Li93420002016-05-10 19:11:44 -0700150def list_adb_devices():
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700151 """List all target devices connected to the host and detected by adb.
Ang Li93420002016-05-10 19:11:44 -0700152
153 Returns:
154 A list of android device serials. Empty if there's none.
155 """
156 out = adb.AdbProxy().devices()
157 return _parse_device_list(out, "device")
158
Ang Lie2139f12016-05-12 17:39:06 -0700159
Ang Li93420002016-05-10 19:11:44 -0700160def list_fastboot_devices():
161 """List all android devices connected to the computer that are in in
162 fastboot mode. These are detected by fastboot.
163
164 Returns:
165 A list of android device serials. Empty if there's none.
166 """
167 out = fastboot.FastbootProxy().devices()
168 return _parse_device_list(out, "fastboot")
169
Ang Lie2139f12016-05-12 17:39:06 -0700170
Ang Li7f0e1c72016-06-14 11:23:49 -0700171def get_instances(serials):
Ang Li93420002016-05-10 19:11:44 -0700172 """Create AndroidDevice instances from a list of serials.
173
174 Args:
175 serials: A list of android device serials.
Ang Li93420002016-05-10 19:11:44 -0700176
177 Returns:
178 A list of AndroidDevice objects.
179 """
180 results = []
181 for s in serials:
Ang Li7f0e1c72016-06-14 11:23:49 -0700182 results.append(AndroidDevice(s))
Ang Li93420002016-05-10 19:11:44 -0700183 return results
184
Ang Lie2139f12016-05-12 17:39:06 -0700185
Ang Li7f0e1c72016-06-14 11:23:49 -0700186def get_instances_with_configs(configs):
Ang Li93420002016-05-10 19:11:44 -0700187 """Create AndroidDevice instances from a list of json configs.
188
189 Each config should have the required key-value pair "serial".
190
191 Args:
192 configs: A list of dicts each representing the configuration of one
193 android device.
Ang Li93420002016-05-10 19:11:44 -0700194
195 Returns:
196 A list of AndroidDevice objects.
197 """
198 results = []
199 for c in configs:
200 try:
201 serial = c.pop("serial")
202 except KeyError:
203 raise AndroidDeviceError(('Required value "serial" is missing in '
Ang Lie2139f12016-05-12 17:39:06 -0700204 'AndroidDevice config %s.') % c)
Ang Li7f0e1c72016-06-14 11:23:49 -0700205 ad = AndroidDevice(serial)
Ang Li93420002016-05-10 19:11:44 -0700206 ad.loadConfig(c)
207 results.append(ad)
208 return results
209
Ang Lie2139f12016-05-12 17:39:06 -0700210
Ang Li7f0e1c72016-06-14 11:23:49 -0700211def get_all_instances(include_fastboot=False):
Ang Li93420002016-05-10 19:11:44 -0700212 """Create AndroidDevice instances for all attached android devices.
213
214 Args:
215 include_fastboot: Whether to include devices in bootloader mode or not.
Ang Li93420002016-05-10 19:11:44 -0700216
217 Returns:
218 A list of AndroidDevice objects each representing an android device
219 attached to the computer.
220 """
221 if include_fastboot:
222 serial_list = list_adb_devices() + list_fastboot_devices()
Ang Li7f0e1c72016-06-14 11:23:49 -0700223 return get_instances(serial_list)
224 return get_instances(list_adb_devices())
Ang Li93420002016-05-10 19:11:44 -0700225
Ang Lie2139f12016-05-12 17:39:06 -0700226
Ang Li93420002016-05-10 19:11:44 -0700227def filter_devices(ads, func):
228 """Finds the AndroidDevice instances from a list that match certain
229 conditions.
230
231 Args:
232 ads: A list of AndroidDevice instances.
233 func: A function that takes an AndroidDevice object and returns True
234 if the device satisfies the filter condition.
235
236 Returns:
237 A list of AndroidDevice instances that satisfy the filter condition.
238 """
239 results = []
240 for ad in ads:
241 if func(ad):
242 results.append(ad)
243 return results
244
Ang Lie2139f12016-05-12 17:39:06 -0700245
Ang Li93420002016-05-10 19:11:44 -0700246def get_device(ads, **kwargs):
247 """Finds a unique AndroidDevice instance from a list that has specific
248 attributes of certain values.
249
250 Example:
251 get_device(android_devices, label="foo", phone_number="1234567890")
252 get_device(android_devices, model="angler")
253
254 Args:
255 ads: A list of AndroidDevice instances.
256 kwargs: keyword arguments used to filter AndroidDevice instances.
257
258 Returns:
259 The target AndroidDevice instance.
260
261 Raises:
262 AndroidDeviceError is raised if none or more than one device is
263 matched.
264 """
Ang Lie2139f12016-05-12 17:39:06 -0700265
Ang Li93420002016-05-10 19:11:44 -0700266 def _get_device_filter(ad):
267 for k, v in kwargs.items():
268 if not hasattr(ad, k):
269 return False
270 elif getattr(ad, k) != v:
271 return False
272 return True
Ang Lie2139f12016-05-12 17:39:06 -0700273
Ang Li93420002016-05-10 19:11:44 -0700274 filtered = filter_devices(ads, _get_device_filter)
275 if not filtered:
276 raise AndroidDeviceError(("Could not find a target device that matches"
277 " condition: %s.") % kwargs)
278 elif len(filtered) == 1:
279 return filtered[0]
280 else:
281 serials = [ad.serial for ad in filtered]
282 raise AndroidDeviceError("More than one device matched: %s" % serials)
283
Ang Lie2139f12016-05-12 17:39:06 -0700284
Ang Li93420002016-05-10 19:11:44 -0700285def takeBugReports(ads, test_name, begin_time):
286 """Takes bug reports on a list of android devices.
287
288 If you want to take a bug report, call this function with a list of
289 android_device objects in on_fail. But reports will be taken on all the
290 devices in the list concurrently. Bug report takes a relative long
291 time to take, so use this cautiously.
292
293 Args:
294 ads: A list of AndroidDevice instances.
295 test_name: Name of the test case that triggered this bug report.
296 begin_time: Logline format timestamp taken when the test started.
297 """
298 begin_time = vts_logger.normalizeLogLineTimestamp(begin_time)
Ang Lie2139f12016-05-12 17:39:06 -0700299
Ang Li93420002016-05-10 19:11:44 -0700300 def take_br(test_name, begin_time, ad):
301 ad.takeBugReport(test_name, begin_time)
Ang Lie2139f12016-05-12 17:39:06 -0700302
Ang Li93420002016-05-10 19:11:44 -0700303 args = [(test_name, begin_time, ad) for ad in ads]
304 utils.concurrent_exec(take_br, args)
305
Ang Lie2139f12016-05-12 17:39:06 -0700306
Ang Li7f0e1c72016-06-14 11:23:49 -0700307class AndroidDevice(object):
Ang Li93420002016-05-10 19:11:44 -0700308 """Class representing an android device.
309
Ang Li53bb72b2016-07-19 18:29:37 -0700310 Each object of this class represents one Android device. The object holds
311 handles to adb, fastboot, and various RPC clients.
Ang Li93420002016-05-10 19:11:44 -0700312
313 Attributes:
314 serial: A string that's the serial number of the Androi device.
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700315 device_command_port: int, the port number used on the Android device
316 for adb port forwarding (for command-response sessions).
317 device_callback_port: int, the port number used on the Android device
318 for adb port reverse forwarding (for callback sessions).
Ang Lie014a8b2016-06-28 18:24:52 -0700319 log: A logger project with a device-specific prefix for each line -
320 [AndroidDevice|<serial>]
Ang Li93420002016-05-10 19:11:44 -0700321 log_path: A string that is the path where all logs collected on this
322 android device should be stored.
323 adb_logcat_process: A process that collects the adb logcat.
324 adb_logcat_file_path: A string that's the full path to the adb logcat
325 file collected, if any.
Ang Lie014a8b2016-06-28 18:24:52 -0700326 vts_agent_process: A process that runs the HAL agent.
Ang Li93420002016-05-10 19:11:44 -0700327 adb: An AdbProxy object used for interacting with the device via adb.
328 fastboot: A FastbootProxy object used for interacting with the device
329 via fastboot.
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700330 host_command_port: the host-side port for runner to agent sessions
331 (to send commands and receive responses).
332 host_callback_port: the host-side port for agent to runner sessions
333 (to get callbacks from agent).
Ang Li53bb72b2016-07-19 18:29:37 -0700334 hal: HalMirror, in charge of all communications with the HAL layer.
335 lib: LibMirror, in charge of all communications with static and shared
336 native libs.
337 shell: ShellMirror, in charge of all communications with shell.
Ang Li93420002016-05-10 19:11:44 -0700338 """
339
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700340 def __init__(self, serial="", device_callback_port=5010):
Ang Li93420002016-05-10 19:11:44 -0700341 self.serial = serial
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700342 self.device_command_port = None
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700343 self.device_callback_port = device_callback_port
Ang Lie014a8b2016-06-28 18:24:52 -0700344 self.log = AndroidDeviceLoggerAdapter(logging.getLogger(),
345 {"serial": self.serial})
346 base_log_path = getattr(logging, "log_path", "/tmp/logs/")
Ang Li7f0e1c72016-06-14 11:23:49 -0700347 self.log_path = os.path.join(base_log_path, "AndroidDevice%s" % serial)
Ang Li93420002016-05-10 19:11:44 -0700348 self.adb_logcat_process = None
349 self.adb_logcat_file_path = None
Ang Lie014a8b2016-06-28 18:24:52 -0700350 self.vts_agent_process = None
Ang Li93420002016-05-10 19:11:44 -0700351 self.adb = adb.AdbProxy(serial)
352 self.fastboot = fastboot.FastbootProxy(serial)
353 if not self.isBootloaderMode:
354 self.rootAdb()
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700355 self.host_command_port = adb.get_available_host_port()
356 self.host_callback_port = adb.get_available_host_port()
Ang Lie014a8b2016-06-28 18:24:52 -0700357 self.adb.reverse_tcp_forward(self.device_callback_port,
358 self.host_callback_port)
Ang Li53bb72b2016-07-19 18:29:37 -0700359 self.hal = None
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700360 self.lib = None
361 self.shell = None
Ang Li93420002016-05-10 19:11:44 -0700362
363 def __del__(self):
Ang Li53bb72b2016-07-19 18:29:37 -0700364 self.cleanUp()
365
366 def cleanUp(self):
367 """Cleans up the AndroidDevice object and releases any resources it
368 claimed.
369 """
370 self.stopServices()
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700371 if self.host_command_port:
372 self.adb.forward("--remove tcp:%s" % self.host_command_port)
Ang Li93420002016-05-10 19:11:44 -0700373
374 @property
375 def isBootloaderMode(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700376 """True if the device is in bootloader mode."""
Ang Li93420002016-05-10 19:11:44 -0700377 return self.serial in list_fastboot_devices()
378
379 @property
380 def isAdbRoot(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700381 """True if adb is running as root for this device."""
382 id_str = self.adb.shell("id -u").decode("utf-8")
383 self.log.info(id_str)
384 return "root" in id_str
Ang Li93420002016-05-10 19:11:44 -0700385
386 @property
387 def model(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700388 """The Android code name for the device."""
Ang Li93420002016-05-10 19:11:44 -0700389 # If device is in bootloader mode, get mode name from fastboot.
390 if self.isBootloaderMode:
391 out = self.fastboot.getvar("product").strip()
392 # "out" is never empty because of the "total time" message fastboot
393 # writes to stderr.
394 lines = out.decode("utf-8").split('\n', 1)
395 if lines:
396 tokens = lines[0].split(' ')
397 if len(tokens) > 1:
398 return tokens[1].lower()
399 return None
400 out = self.adb.shell('getprop | grep ro.build.product')
401 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
402 if model == "sprout":
403 return model
404 else:
405 out = self.adb.shell('getprop | grep ro.product.name')
406 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
407 return model
408
409 @property
Ang Li93420002016-05-10 19:11:44 -0700410 def isAdbLogcatOn(self):
411 """Whether there is an ongoing adb logcat collection.
412 """
413 if self.adb_logcat_process:
414 return True
415 return False
416
417 def loadConfig(self, config):
418 """Add attributes to the AndroidDevice object based on json config.
419
420 Args:
421 config: A dictionary representing the configs.
422
423 Raises:
424 AndroidDeviceError is raised if the config is trying to overwrite
425 an existing attribute.
426 """
427 for k, v in config.items():
428 if hasattr(self, k):
Ang Li7f0e1c72016-06-14 11:23:49 -0700429 raise AndroidDeviceError(
430 "Attempting to set existing attribute %s on %s" %
431 (k, self.serial))
Ang Li93420002016-05-10 19:11:44 -0700432 setattr(self, k, v)
433
434 def rootAdb(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700435 """Changes adb to root mode for this device."""
Ang Li93420002016-05-10 19:11:44 -0700436 if not self.isAdbRoot:
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700437 try:
438 self.adb.root()
Keun Soo Yima5a0dc22016-07-16 17:56:19 -0700439 self.adb.wait_for_device()
440 self.adb.remount()
Keun Soo Yim731e9172016-07-16 17:48:39 -0700441 self.adb.wait_for_device()
442 except adb.AdbError as e:
443 # adb wait-for-device is not always possible in the lab
Keun Soo Yima5a0dc22016-07-16 17:56:19 -0700444 # continue with an assumption it's done by the harness.
Keun Soo Yim731e9172016-07-16 17:48:39 -0700445 logging.exception(e)
Ang Li93420002016-05-10 19:11:44 -0700446
Ang Li93420002016-05-10 19:11:44 -0700447 def startAdbLogcat(self):
448 """Starts a standing adb logcat collection in separate subprocesses and
449 save the logcat in a file.
450 """
451 if self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700452 raise AndroidDeviceError(("Android device %s already has an adb "
Ang Lie2139f12016-05-12 17:39:06 -0700453 "logcat thread going on. Cannot start "
Ang Li7f0e1c72016-06-14 11:23:49 -0700454 "another one.") % self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700455 f_name = "adblog,%s,%s.txt" % (self.model, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700456 utils.create_dir(self.log_path)
457 logcat_file_path = os.path.join(self.log_path, f_name)
458 try:
459 extra_params = self.adb_logcat_param
460 except AttributeError:
461 extra_params = "-b all"
Ang Li7f0e1c72016-06-14 11:23:49 -0700462 cmd = "adb -s %s logcat -v threadtime %s >> %s" % (
Ang Li93420002016-05-10 19:11:44 -0700463 self.serial, extra_params, logcat_file_path)
464 self.adb_logcat_process = utils.start_standing_subprocess(cmd)
465 self.adb_logcat_file_path = logcat_file_path
466
467 def stopAdbLogcat(self):
468 """Stops the adb logcat collection subprocess.
469 """
470 if not self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700471 raise AndroidDeviceError(
472 "Android device %s does not have an ongoing adb logcat collection."
473 % self.serial)
Ang Li93420002016-05-10 19:11:44 -0700474 utils.stop_standing_subprocess(self.adb_logcat_process)
475 self.adb_logcat_process = None
476
477 def takeBugReport(self, test_name, begin_time):
478 """Takes a bug report on the device and stores it in a file.
479
480 Args:
481 test_name: Name of the test case that triggered this bug report.
482 begin_time: Logline format timestamp taken when the test started.
483 """
484 br_path = os.path.join(self.log_path, "BugReports")
485 utils.create_dir(br_path)
Ang Li7f0e1c72016-06-14 11:23:49 -0700486 base_name = ",%s,%s.txt" % (begin_time, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700487 test_name_len = utils.MAX_FILENAME_LEN - len(base_name)
488 out_name = test_name[:test_name_len] + base_name
489 full_out_path = os.path.join(br_path, out_name.replace(' ', '\ '))
490 self.log.info("Taking bugreport for %s on %s", test_name, self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700491 self.adb.bugreport(" > %s" % full_out_path)
Ang Li93420002016-05-10 19:11:44 -0700492 self.log.info("Bugreport for %s taken at %s", test_name, full_out_path)
493
Ang Li93420002016-05-10 19:11:44 -0700494 @utils.timeout(15 * 60)
495 def waitForBootCompletion(self):
496 """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED.
497
498 This function times out after 15 minutes.
499 """
Keun Soo Yim731e9172016-07-16 17:48:39 -0700500 try:
501 self.adb.wait_for_device()
502 except adb.AdbError as e:
503 # adb wait-for-device is not always possible in the lab
504 logging.exception(e)
Ang Li93420002016-05-10 19:11:44 -0700505 while True:
506 try:
507 out = self.adb.shell("getprop sys.boot_completed")
508 completed = out.decode('utf-8').strip()
509 if completed == '1':
510 return
511 except adb.AdbError:
512 # adb shell calls may fail during certain period of booting
513 # process, which is normal. Ignoring these errors.
514 pass
515 time.sleep(5)
516
517 def reboot(self):
Ang Li7f0e1c72016-06-14 11:23:49 -0700518 """Reboots the device and wait for device to complete booting.
Ang Li93420002016-05-10 19:11:44 -0700519
520 This is probably going to print some error messages in console. Only
521 use if there's no other option.
522
Ang Li93420002016-05-10 19:11:44 -0700523 Raises:
524 AndroidDeviceError is raised if waiting for completion timed
525 out.
526 """
527 if self.isBootloaderMode:
528 self.fastboot.reboot()
529 return
530 has_adb_log = self.isAdbLogcatOn
Ang Lie014a8b2016-06-28 18:24:52 -0700531 has_vts_agent = True if self.vts_agent_process else False
Ang Li93420002016-05-10 19:11:44 -0700532 if has_adb_log:
533 self.stopAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700534 if has_vts_agent:
535 self.stopVtsAgent()
Ang Li93420002016-05-10 19:11:44 -0700536 self.adb.reboot()
537 self.waitForBootCompletion()
538 self.rootAdb()
Ang Li93420002016-05-10 19:11:44 -0700539 if has_adb_log:
540 self.startAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700541 if has_vts_agent:
542 self.startVtsAgent()
Sahil Jain06dd6a22016-06-24 13:47:37 -0700543
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700544 def startServices(self, use_vts_agent):
Ang Li53bb72b2016-07-19 18:29:37 -0700545 """Starts long running services on the android device.
546
547 1. Start adb logcat capture.
548 2. Start VtsAgent.
549 3. Create HalMirror
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700550
551 Args:
552 use_vts_agent: bool, whether to use the VTS agent.
Ang Li53bb72b2016-07-19 18:29:37 -0700553 """
554 try:
555 self.startAdbLogcat()
556 except:
557 self.log.exception("Failed to start adb logcat!")
558 raise
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700559 if use_vts_agent:
560 self.startVtsAgent()
561 self.device_command_port = int(
562 self.adb.shell("cat /data/local/tmp/vts_tcp_server_port"))
563 logging.info("device_command_port: %s", self.device_command_port)
564 self.adb.tcp_forward(self.host_command_port, self.device_command_port)
565 self.hal = hal_mirror.HalMirror(self.host_command_port,
566 self.host_callback_port)
567 self.lib = lib_mirror.LibMirror(self.host_command_port)
568 self.shell = shell_mirror.ShellMirror(self.host_command_port)
569 else:
570 logging.info("not using VTS agent.")
Ang Li53bb72b2016-07-19 18:29:37 -0700571
572 def stopServices(self):
573 """Stops long running services on the android device.
574 """
575 if self.adb_logcat_process:
576 self.stopAdbLogcat()
577 self.stopVtsAgent()
578 if self.hal:
579 self.hal.CleanUp()
580
Ang Lie014a8b2016-06-28 18:24:52 -0700581 def startVtsAgent(self):
582 """Start HAL agent on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700583
584 This function starts the target side native agent and is persisted
Ang Lie014a8b2016-06-28 18:24:52 -0700585 throughout the test run.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700586 """
Keun Soo Yimab7fb062016-07-13 14:47:19 -0700587 self.log.info("start a VTS agent")
Ang Lie014a8b2016-06-28 18:24:52 -0700588 if self.vts_agent_process:
589 raise AndroidDeviceError("HAL agent is already running on %s." %
590 self.serial)
Keun Soo Yima066dd52016-07-01 15:18:28 -0700591
592 cleanup_commands = [
Keun Soo Yim02da0272016-07-19 07:56:38 -0700593 "rm -f /data/local/tmp/vts_driver_*",
Ang Li53bb72b2016-07-19 18:29:37 -0700594 "rm -f /data/local/tmp/vts_agent_callback*"
595 ]
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700596 kill_commands = ["killall vts_hal_agent32", "killall vts_hal_agent64",
597 "killall fuzzer32", "killall fuzzer64",
598 "killall vts_shell_driver32",
Yuexi Ma674e59d2016-07-19 15:39:54 -0700599 "killall vts_shell_driver64"]
Keun Soo Yima066dd52016-07-01 15:18:28 -0700600 cleanup_commands.extend(kill_commands)
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700601 chmod_commands = [
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700602 "chmod 755 %s/32/vts_hal_agent32" % DEFAULT_AGENT_BASE_DIR,
603 "chmod 755 %s/64/vts_hal_agent64" % DEFAULT_AGENT_BASE_DIR,
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700604 "chmod 755 %s/32/fuzzer32" % DEFAULT_AGENT_BASE_DIR,
Keun Soo Yim02da0272016-07-19 07:56:38 -0700605 "chmod 755 %s/64/fuzzer64" % DEFAULT_AGENT_BASE_DIR,
606 "chmod 755 %s/32/vts_shell_driver32" % DEFAULT_AGENT_BASE_DIR,
Ang Li53bb72b2016-07-19 18:29:37 -0700607 "chmod 755 %s/64/vts_shell_driver64" % DEFAULT_AGENT_BASE_DIR
608 ]
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700609 cleanup_commands.extend(chmod_commands)
Keun Soo Yima066dd52016-07-01 15:18:28 -0700610 for cmd in cleanup_commands:
Sahil Jain06dd6a22016-06-24 13:47:37 -0700611 try:
612 self.adb.shell(cmd)
Keun Soo Yimab7fb062016-07-13 14:47:19 -0700613 except adb.AdbError as e:
614 self.log.warning(
Ang Li53bb72b2016-07-19 18:29:37 -0700615 "A command to setup the env to start the VTS Agent failed %s",
616 e)
Ang Lie014a8b2016-06-28 18:24:52 -0700617 vts_agent_log_path = os.path.join(self.log_path, "vts_agent.log")
Keun Soo Yimd2aa5b82016-07-30 20:12:19 -0700618 for bitness in ['64', '32']:
619 cmd = (
620 'adb -s {s} shell LD_LIBRARY_PATH={path}/{bitness} '
621 '{path}/{bitness}/vts_hal_agent{bitness}'
622 ' {path}/32/fuzzer32 {path}/64/fuzzer64 {path}/spec'
623 ' {path}/32/vts_shell_driver32 {path}/64/vts_shell_driver64 >> {log}'
624 ).format(s=self.serial,
625 bitness=bitness,
626 path=DEFAULT_AGENT_BASE_DIR,
627 log=vts_agent_log_path)
628 try:
629 self.vts_agent_process = utils.start_standing_subprocess(
630 cmd, check_health_delay=1)
631 except utils.VTSUtilsError as e:
632 logging.exception(e)
633 with open(vts_agent_log_path, 'r') as log_file:
634 logging.error("VTS agent output:\n")
635 logging.error(log_file.read())
636 # one common cause is that 64-bit executable is not supported
637 # in low API level devices.
638 if bitness == '32':
639 raise
640 else:
641 logging.error('retrying using a 32-bit binary.')
Sahil Jain06dd6a22016-06-24 13:47:37 -0700642
Ang Lie014a8b2016-06-28 18:24:52 -0700643 def stopVtsAgent(self):
644 """Stop the HAL agent running on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700645 """
Ang Lie014a8b2016-06-28 18:24:52 -0700646 if self.vts_agent_process:
647 utils.stop_standing_subprocess(self.vts_agent_process)
648 self.vts_agent_process = None
Sahil Jain06dd6a22016-06-24 13:47:37 -0700649
Sahil Jain06dd6a22016-06-24 13:47:37 -0700650
Ang Lie014a8b2016-06-28 18:24:52 -0700651class AndroidDeviceLoggerAdapter(logging.LoggerAdapter):
652 """A wrapper class that attaches a prefix to all log lines from an
653 AndroidDevice object.
654 """
655
656 def process(self, msg, kwargs):
657 """Process every log message written via the wrapped logger object.
658
659 We are adding the prefix "[AndroidDevice|<serial>]" to all log lines.
660
661 Args:
662 msg: string, the original log message.
663 kwargs: dict, the key value pairs that can be used to modify the
664 original log message.
665 """
666 msg = "[AndroidDevice|%s] %s" % (self.extra["serial"], msg)
667 return (msg, kwargs)