blob: b7241b847ca4190fb2937309a38a107c0f156095 [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 Yimcbd8c052016-06-20 15:10:58 -0700338 def __init__(self, serial="", device_port=5001, device_callback_port=5010):
Ang Li93420002016-05-10 19:11:44 -0700339 self.serial = serial
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700340 self.device_command_port = device_port
341 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()
355 self.adb.tcp_forward(self.host_command_port, self.device_command_port)
Ang Lie014a8b2016-06-28 18:24:52 -0700356 self.adb.reverse_tcp_forward(self.device_callback_port,
357 self.host_callback_port)
Ang Li53bb72b2016-07-19 18:29:37 -0700358 self.hal = None
Keun Soo Yim39bc0b92016-07-06 18:27:15 -0700359 self.lib = lib_mirror.LibMirror(self.host_command_port)
Keun Soo Yim63d67512016-07-01 17:13:47 -0700360 self.shell = shell_mirror.ShellMirror(self.host_command_port)
Ang Li93420002016-05-10 19:11:44 -0700361
362 def __del__(self):
Ang Li53bb72b2016-07-19 18:29:37 -0700363 self.cleanUp()
364
365 def cleanUp(self):
366 """Cleans up the AndroidDevice object and releases any resources it
367 claimed.
368 """
369 self.stopServices()
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700370 if self.host_command_port:
371 self.adb.forward("--remove tcp:%s" % self.host_command_port)
Ang Li93420002016-05-10 19:11:44 -0700372
373 @property
374 def isBootloaderMode(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700375 """True if the device is in bootloader mode."""
Ang Li93420002016-05-10 19:11:44 -0700376 return self.serial in list_fastboot_devices()
377
378 @property
379 def isAdbRoot(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700380 """True if adb is running as root for this device."""
381 id_str = self.adb.shell("id -u").decode("utf-8")
382 self.log.info(id_str)
383 return "root" in id_str
Ang Li93420002016-05-10 19:11:44 -0700384
385 @property
386 def model(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700387 """The Android code name for the device."""
Ang Li93420002016-05-10 19:11:44 -0700388 # If device is in bootloader mode, get mode name from fastboot.
389 if self.isBootloaderMode:
390 out = self.fastboot.getvar("product").strip()
391 # "out" is never empty because of the "total time" message fastboot
392 # writes to stderr.
393 lines = out.decode("utf-8").split('\n', 1)
394 if lines:
395 tokens = lines[0].split(' ')
396 if len(tokens) > 1:
397 return tokens[1].lower()
398 return None
399 out = self.adb.shell('getprop | grep ro.build.product')
400 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
401 if model == "sprout":
402 return model
403 else:
404 out = self.adb.shell('getprop | grep ro.product.name')
405 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
406 return model
407
408 @property
Ang Li93420002016-05-10 19:11:44 -0700409 def isAdbLogcatOn(self):
410 """Whether there is an ongoing adb logcat collection.
411 """
412 if self.adb_logcat_process:
413 return True
414 return False
415
416 def loadConfig(self, config):
417 """Add attributes to the AndroidDevice object based on json config.
418
419 Args:
420 config: A dictionary representing the configs.
421
422 Raises:
423 AndroidDeviceError is raised if the config is trying to overwrite
424 an existing attribute.
425 """
426 for k, v in config.items():
427 if hasattr(self, k):
Ang Li7f0e1c72016-06-14 11:23:49 -0700428 raise AndroidDeviceError(
429 "Attempting to set existing attribute %s on %s" %
430 (k, self.serial))
Ang Li93420002016-05-10 19:11:44 -0700431 setattr(self, k, v)
432
433 def rootAdb(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700434 """Changes adb to root mode for this device."""
Ang Li93420002016-05-10 19:11:44 -0700435 if not self.isAdbRoot:
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700436 try:
437 self.adb.root()
Keun Soo Yima5a0dc22016-07-16 17:56:19 -0700438 self.adb.wait_for_device()
439 self.adb.remount()
Keun Soo Yim731e9172016-07-16 17:48:39 -0700440 self.adb.wait_for_device()
441 except adb.AdbError as e:
442 # adb wait-for-device is not always possible in the lab
Keun Soo Yima5a0dc22016-07-16 17:56:19 -0700443 # continue with an assumption it's done by the harness.
Keun Soo Yim731e9172016-07-16 17:48:39 -0700444 logging.exception(e)
Ang Li93420002016-05-10 19:11:44 -0700445
Ang Li93420002016-05-10 19:11:44 -0700446 def startAdbLogcat(self):
447 """Starts a standing adb logcat collection in separate subprocesses and
448 save the logcat in a file.
449 """
450 if self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700451 raise AndroidDeviceError(("Android device %s already has an adb "
Ang Lie2139f12016-05-12 17:39:06 -0700452 "logcat thread going on. Cannot start "
Ang Li7f0e1c72016-06-14 11:23:49 -0700453 "another one.") % self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700454 f_name = "adblog,%s,%s.txt" % (self.model, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700455 utils.create_dir(self.log_path)
456 logcat_file_path = os.path.join(self.log_path, f_name)
457 try:
458 extra_params = self.adb_logcat_param
459 except AttributeError:
460 extra_params = "-b all"
Ang Li7f0e1c72016-06-14 11:23:49 -0700461 cmd = "adb -s %s logcat -v threadtime %s >> %s" % (
Ang Li93420002016-05-10 19:11:44 -0700462 self.serial, extra_params, logcat_file_path)
463 self.adb_logcat_process = utils.start_standing_subprocess(cmd)
464 self.adb_logcat_file_path = logcat_file_path
465
466 def stopAdbLogcat(self):
467 """Stops the adb logcat collection subprocess.
468 """
469 if not self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700470 raise AndroidDeviceError(
471 "Android device %s does not have an ongoing adb logcat collection."
472 % self.serial)
Ang Li93420002016-05-10 19:11:44 -0700473 utils.stop_standing_subprocess(self.adb_logcat_process)
474 self.adb_logcat_process = None
475
476 def takeBugReport(self, test_name, begin_time):
477 """Takes a bug report on the device and stores it in a file.
478
479 Args:
480 test_name: Name of the test case that triggered this bug report.
481 begin_time: Logline format timestamp taken when the test started.
482 """
483 br_path = os.path.join(self.log_path, "BugReports")
484 utils.create_dir(br_path)
Ang Li7f0e1c72016-06-14 11:23:49 -0700485 base_name = ",%s,%s.txt" % (begin_time, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700486 test_name_len = utils.MAX_FILENAME_LEN - len(base_name)
487 out_name = test_name[:test_name_len] + base_name
488 full_out_path = os.path.join(br_path, out_name.replace(' ', '\ '))
489 self.log.info("Taking bugreport for %s on %s", test_name, self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700490 self.adb.bugreport(" > %s" % full_out_path)
Ang Li93420002016-05-10 19:11:44 -0700491 self.log.info("Bugreport for %s taken at %s", test_name, full_out_path)
492
Ang Li93420002016-05-10 19:11:44 -0700493 @utils.timeout(15 * 60)
494 def waitForBootCompletion(self):
495 """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED.
496
497 This function times out after 15 minutes.
498 """
Keun Soo Yim731e9172016-07-16 17:48:39 -0700499 try:
500 self.adb.wait_for_device()
501 except adb.AdbError as e:
502 # adb wait-for-device is not always possible in the lab
503 logging.exception(e)
Ang Li93420002016-05-10 19:11:44 -0700504 while True:
505 try:
506 out = self.adb.shell("getprop sys.boot_completed")
507 completed = out.decode('utf-8').strip()
508 if completed == '1':
509 return
510 except adb.AdbError:
511 # adb shell calls may fail during certain period of booting
512 # process, which is normal. Ignoring these errors.
513 pass
514 time.sleep(5)
515
516 def reboot(self):
Ang Li7f0e1c72016-06-14 11:23:49 -0700517 """Reboots the device and wait for device to complete booting.
Ang Li93420002016-05-10 19:11:44 -0700518
519 This is probably going to print some error messages in console. Only
520 use if there's no other option.
521
Ang Li93420002016-05-10 19:11:44 -0700522 Raises:
523 AndroidDeviceError is raised if waiting for completion timed
524 out.
525 """
526 if self.isBootloaderMode:
527 self.fastboot.reboot()
528 return
529 has_adb_log = self.isAdbLogcatOn
Ang Lie014a8b2016-06-28 18:24:52 -0700530 has_vts_agent = True if self.vts_agent_process else False
Ang Li93420002016-05-10 19:11:44 -0700531 if has_adb_log:
532 self.stopAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700533 if has_vts_agent:
534 self.stopVtsAgent()
Ang Li93420002016-05-10 19:11:44 -0700535 self.adb.reboot()
536 self.waitForBootCompletion()
537 self.rootAdb()
Ang Li93420002016-05-10 19:11:44 -0700538 if has_adb_log:
539 self.startAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700540 if has_vts_agent:
541 self.startVtsAgent()
Sahil Jain06dd6a22016-06-24 13:47:37 -0700542
Ang Li53bb72b2016-07-19 18:29:37 -0700543 def startServices(self):
544 """Starts long running services on the android device.
545
546 1. Start adb logcat capture.
547 2. Start VtsAgent.
548 3. Create HalMirror
549 """
550 try:
551 self.startAdbLogcat()
552 except:
553 self.log.exception("Failed to start adb logcat!")
554 raise
555 self.startVtsAgent()
556 self.hal = hal_mirror.HalMirror(self.host_command_port,
557 self.host_callback_port)
558
559 def stopServices(self):
560 """Stops long running services on the android device.
561 """
562 if self.adb_logcat_process:
563 self.stopAdbLogcat()
564 self.stopVtsAgent()
565 if self.hal:
566 self.hal.CleanUp()
567
Ang Lie014a8b2016-06-28 18:24:52 -0700568 def startVtsAgent(self):
569 """Start HAL agent on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700570
571 This function starts the target side native agent and is persisted
Ang Lie014a8b2016-06-28 18:24:52 -0700572 throughout the test run.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700573 """
Keun Soo Yimab7fb062016-07-13 14:47:19 -0700574 self.log.info("start a VTS agent")
Ang Lie014a8b2016-06-28 18:24:52 -0700575 if self.vts_agent_process:
576 raise AndroidDeviceError("HAL agent is already running on %s." %
577 self.serial)
Keun Soo Yima066dd52016-07-01 15:18:28 -0700578
579 cleanup_commands = [
Keun Soo Yim02da0272016-07-19 07:56:38 -0700580 "rm -f /data/local/tmp/vts_driver_*",
Ang Li53bb72b2016-07-19 18:29:37 -0700581 "rm -f /data/local/tmp/vts_agent_callback*"
582 ]
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700583 kill_commands = ["killall vts_hal_agent32", "killall vts_hal_agent64",
584 "killall fuzzer32", "killall fuzzer64",
585 "killall vts_shell_driver32",
Yuexi Ma674e59d2016-07-19 15:39:54 -0700586 "killall vts_shell_driver64"]
Keun Soo Yima066dd52016-07-01 15:18:28 -0700587 cleanup_commands.extend(kill_commands)
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700588 chmod_commands = [
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700589 "chmod 755 %s/32/vts_hal_agent32" % DEFAULT_AGENT_BASE_DIR,
590 "chmod 755 %s/64/vts_hal_agent64" % DEFAULT_AGENT_BASE_DIR,
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700591 "chmod 755 %s/32/fuzzer32" % DEFAULT_AGENT_BASE_DIR,
Keun Soo Yim02da0272016-07-19 07:56:38 -0700592 "chmod 755 %s/64/fuzzer64" % DEFAULT_AGENT_BASE_DIR,
593 "chmod 755 %s/32/vts_shell_driver32" % DEFAULT_AGENT_BASE_DIR,
Ang Li53bb72b2016-07-19 18:29:37 -0700594 "chmod 755 %s/64/vts_shell_driver64" % DEFAULT_AGENT_BASE_DIR
595 ]
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700596 cleanup_commands.extend(chmod_commands)
Keun Soo Yima066dd52016-07-01 15:18:28 -0700597 for cmd in cleanup_commands:
Sahil Jain06dd6a22016-06-24 13:47:37 -0700598 try:
599 self.adb.shell(cmd)
Keun Soo Yimab7fb062016-07-13 14:47:19 -0700600 except adb.AdbError as e:
601 self.log.warning(
Ang Li53bb72b2016-07-19 18:29:37 -0700602 "A command to setup the env to start the VTS Agent failed %s",
603 e)
Ang Lie014a8b2016-06-28 18:24:52 -0700604 vts_agent_log_path = os.path.join(self.log_path, "vts_agent.log")
605 cmd = (
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700606 'adb -s {s} shell LD_LIBRARY_PATH={path}/64 '
607 '{path}/64/vts_hal_agent64'
Keun Soo Yima066dd52016-07-01 15:18:28 -0700608 ' {path}/32/fuzzer32 {path}/64/fuzzer64 {path}/spec'
609 ' {path}/32/vts_shell_driver32 {path}/64/vts_shell_driver64 >> {log}'
Ang Lie014a8b2016-06-28 18:24:52 -0700610 ).format(s=self.serial,
611 path=DEFAULT_AGENT_BASE_DIR,
612 log=vts_agent_log_path)
613 self.vts_agent_process = utils.start_standing_subprocess(
Ang Li53bb72b2016-07-19 18:29:37 -0700614 cmd,
615 check_health_delay=1)
Sahil Jain06dd6a22016-06-24 13:47:37 -0700616
Ang Lie014a8b2016-06-28 18:24:52 -0700617 def stopVtsAgent(self):
618 """Stop the HAL agent running on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700619 """
Ang Lie014a8b2016-06-28 18:24:52 -0700620 if self.vts_agent_process:
621 utils.stop_standing_subprocess(self.vts_agent_process)
622 self.vts_agent_process = None
Sahil Jain06dd6a22016-06-24 13:47:37 -0700623
Sahil Jain06dd6a22016-06-24 13:47:37 -0700624
Ang Lie014a8b2016-06-28 18:24:52 -0700625class AndroidDeviceLoggerAdapter(logging.LoggerAdapter):
626 """A wrapper class that attaches a prefix to all log lines from an
627 AndroidDevice object.
628 """
629
630 def process(self, msg, kwargs):
631 """Process every log message written via the wrapped logger object.
632
633 We are adding the prefix "[AndroidDevice|<serial>]" to all log lines.
634
635 Args:
636 msg: string, the original log message.
637 kwargs: dict, the key value pairs that can be used to modify the
638 original log message.
639 """
640 msg = "[AndroidDevice|%s] %s" % (self.extra["serial"], msg)
641 return (msg, kwargs)