blob: 7ecbdade04ee98ed46df3389bf4b7c400b949049 [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
Sahil Jain06dd6a22016-06-24 13:47:37 -070036from vts.runners.host import errors
37import subprocess
Ang Li93420002016-05-10 19:11:44 -070038
39VTS_CONTROLLER_CONFIG_NAME = "AndroidDevice"
40VTS_CONTROLLER_REFERENCE_NAME = "android_devices"
41
42ANDROID_DEVICE_PICK_ALL_TOKEN = "*"
43# Key name for adb logcat extra params in config file.
44ANDROID_DEVICE_ADB_LOGCAT_PARAM_KEY = "adb_logcat_param"
45ANDROID_DEVICE_EMPTY_CONFIG_MSG = "Configuration is empty, abort!"
46ANDROID_DEVICE_NOT_LIST_CONFIG_MSG = "Configuration should be a list, abort!"
47
Sahil Jain06dd6a22016-06-24 13:47:37 -070048# Target-side directory where the VTS binaries are uploaded
49DEFAULT_AGENT_BASE_DIR = "/data/local/tmp"
50# Time for which the current is put on sleep when the client is unable to
51# make a connection.
52THREAD_SLEEP_TIME = 1
53# Max number of attempts that the client can make to connect to the agent
54MAX_AGENT_CONNECT_RETRIES = 10
55
Ang Lie2139f12016-05-12 17:39:06 -070056
Ang Li93420002016-05-10 19:11:44 -070057class AndroidDeviceError(signals.ControllerError):
58 pass
59
Ang Lie2139f12016-05-12 17:39:06 -070060
Ang Li7f0e1c72016-06-14 11:23:49 -070061def create(configs):
Ang Li93420002016-05-10 19:11:44 -070062 if not configs:
63 raise AndroidDeviceError(ANDROID_DEVICE_EMPTY_CONFIG_MSG)
64 elif configs == ANDROID_DEVICE_PICK_ALL_TOKEN:
Ang Li7f0e1c72016-06-14 11:23:49 -070065 ads = get_all_instances()
Ang Li93420002016-05-10 19:11:44 -070066 elif not isinstance(configs, list):
67 raise AndroidDeviceError(ANDROID_DEVICE_NOT_LIST_CONFIG_MSG)
68 elif isinstance(configs[0], str):
69 # Configs is a list of serials.
Ang Li7f0e1c72016-06-14 11:23:49 -070070 ads = get_instances(configs)
Ang Li93420002016-05-10 19:11:44 -070071 else:
72 # Configs is a list of dicts.
Ang Li7f0e1c72016-06-14 11:23:49 -070073 ads = get_instances_with_configs(configs)
Ang Li93420002016-05-10 19:11:44 -070074 connected_ads = list_adb_devices()
75 for ad in ads:
76 if ad.serial not in connected_ads:
Ang Lie2139f12016-05-12 17:39:06 -070077 raise AndroidDeviceError(
78 ("Android device %s is specified in config"
79 " but is not attached.") % ad.serial)
Ang Li93420002016-05-10 19:11:44 -070080 ad.startAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -070081 ad.startVtsAgent()
Ang Li93420002016-05-10 19:11:44 -070082 return ads
83
Ang Lie2139f12016-05-12 17:39:06 -070084
Ang Li93420002016-05-10 19:11:44 -070085def destroy(ads):
86 for ad in ads:
Ang Lie014a8b2016-06-28 18:24:52 -070087 ad.stopVtsAgent()
Ang Li93420002016-05-10 19:11:44 -070088 if ad.adb_logcat_process:
89 ad.stopAdbLogcat()
90
Ang Lie2139f12016-05-12 17:39:06 -070091
Ang Li93420002016-05-10 19:11:44 -070092def _parse_device_list(device_list_str, key):
93 """Parses a byte string representing a list of devices. The string is
94 generated by calling either adb or fastboot.
95
96 Args:
97 device_list_str: Output of adb or fastboot.
98 key: The token that signifies a device in device_list_str.
99
100 Returns:
101 A list of android device serial numbers.
102 """
103 clean_lines = str(device_list_str, 'utf-8').strip().split('\n')
104 results = []
105 for line in clean_lines:
106 tokens = line.strip().split('\t')
107 if len(tokens) == 2 and tokens[1] == key:
108 results.append(tokens[0])
109 return results
110
Ang Lie2139f12016-05-12 17:39:06 -0700111
Ang Li93420002016-05-10 19:11:44 -0700112def list_adb_devices():
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700113 """List all target devices connected to the host and detected by adb.
Ang Li93420002016-05-10 19:11:44 -0700114
115 Returns:
116 A list of android device serials. Empty if there's none.
117 """
118 out = adb.AdbProxy().devices()
119 return _parse_device_list(out, "device")
120
Ang Lie2139f12016-05-12 17:39:06 -0700121
Ang Li93420002016-05-10 19:11:44 -0700122def list_fastboot_devices():
123 """List all android devices connected to the computer that are in in
124 fastboot mode. These are detected by fastboot.
125
126 Returns:
127 A list of android device serials. Empty if there's none.
128 """
129 out = fastboot.FastbootProxy().devices()
130 return _parse_device_list(out, "fastboot")
131
Ang Lie2139f12016-05-12 17:39:06 -0700132
Ang Li7f0e1c72016-06-14 11:23:49 -0700133def get_instances(serials):
Ang Li93420002016-05-10 19:11:44 -0700134 """Create AndroidDevice instances from a list of serials.
135
136 Args:
137 serials: A list of android device serials.
Ang Li93420002016-05-10 19:11:44 -0700138
139 Returns:
140 A list of AndroidDevice objects.
141 """
142 results = []
143 for s in serials:
Ang Li7f0e1c72016-06-14 11:23:49 -0700144 results.append(AndroidDevice(s))
Ang Li93420002016-05-10 19:11:44 -0700145 return results
146
Ang Lie2139f12016-05-12 17:39:06 -0700147
Ang Li7f0e1c72016-06-14 11:23:49 -0700148def get_instances_with_configs(configs):
Ang Li93420002016-05-10 19:11:44 -0700149 """Create AndroidDevice instances from a list of json configs.
150
151 Each config should have the required key-value pair "serial".
152
153 Args:
154 configs: A list of dicts each representing the configuration of one
155 android device.
Ang Li93420002016-05-10 19:11:44 -0700156
157 Returns:
158 A list of AndroidDevice objects.
159 """
160 results = []
161 for c in configs:
162 try:
163 serial = c.pop("serial")
164 except KeyError:
165 raise AndroidDeviceError(('Required value "serial" is missing in '
Ang Lie2139f12016-05-12 17:39:06 -0700166 'AndroidDevice config %s.') % c)
Ang Li7f0e1c72016-06-14 11:23:49 -0700167 ad = AndroidDevice(serial)
Ang Li93420002016-05-10 19:11:44 -0700168 ad.loadConfig(c)
169 results.append(ad)
170 return results
171
Ang Lie2139f12016-05-12 17:39:06 -0700172
Ang Li7f0e1c72016-06-14 11:23:49 -0700173def get_all_instances(include_fastboot=False):
Ang Li93420002016-05-10 19:11:44 -0700174 """Create AndroidDevice instances for all attached android devices.
175
176 Args:
177 include_fastboot: Whether to include devices in bootloader mode or not.
Ang Li93420002016-05-10 19:11:44 -0700178
179 Returns:
180 A list of AndroidDevice objects each representing an android device
181 attached to the computer.
182 """
183 if include_fastboot:
184 serial_list = list_adb_devices() + list_fastboot_devices()
Ang Li7f0e1c72016-06-14 11:23:49 -0700185 return get_instances(serial_list)
186 return get_instances(list_adb_devices())
Ang Li93420002016-05-10 19:11:44 -0700187
Ang Lie2139f12016-05-12 17:39:06 -0700188
Ang Li93420002016-05-10 19:11:44 -0700189def filter_devices(ads, func):
190 """Finds the AndroidDevice instances from a list that match certain
191 conditions.
192
193 Args:
194 ads: A list of AndroidDevice instances.
195 func: A function that takes an AndroidDevice object and returns True
196 if the device satisfies the filter condition.
197
198 Returns:
199 A list of AndroidDevice instances that satisfy the filter condition.
200 """
201 results = []
202 for ad in ads:
203 if func(ad):
204 results.append(ad)
205 return results
206
Ang Lie2139f12016-05-12 17:39:06 -0700207
Ang Li93420002016-05-10 19:11:44 -0700208def get_device(ads, **kwargs):
209 """Finds a unique AndroidDevice instance from a list that has specific
210 attributes of certain values.
211
212 Example:
213 get_device(android_devices, label="foo", phone_number="1234567890")
214 get_device(android_devices, model="angler")
215
216 Args:
217 ads: A list of AndroidDevice instances.
218 kwargs: keyword arguments used to filter AndroidDevice instances.
219
220 Returns:
221 The target AndroidDevice instance.
222
223 Raises:
224 AndroidDeviceError is raised if none or more than one device is
225 matched.
226 """
Ang Lie2139f12016-05-12 17:39:06 -0700227
Ang Li93420002016-05-10 19:11:44 -0700228 def _get_device_filter(ad):
229 for k, v in kwargs.items():
230 if not hasattr(ad, k):
231 return False
232 elif getattr(ad, k) != v:
233 return False
234 return True
Ang Lie2139f12016-05-12 17:39:06 -0700235
Ang Li93420002016-05-10 19:11:44 -0700236 filtered = filter_devices(ads, _get_device_filter)
237 if not filtered:
238 raise AndroidDeviceError(("Could not find a target device that matches"
239 " condition: %s.") % kwargs)
240 elif len(filtered) == 1:
241 return filtered[0]
242 else:
243 serials = [ad.serial for ad in filtered]
244 raise AndroidDeviceError("More than one device matched: %s" % serials)
245
Ang Lie2139f12016-05-12 17:39:06 -0700246
Ang Li93420002016-05-10 19:11:44 -0700247def takeBugReports(ads, test_name, begin_time):
248 """Takes bug reports on a list of android devices.
249
250 If you want to take a bug report, call this function with a list of
251 android_device objects in on_fail. But reports will be taken on all the
252 devices in the list concurrently. Bug report takes a relative long
253 time to take, so use this cautiously.
254
255 Args:
256 ads: A list of AndroidDevice instances.
257 test_name: Name of the test case that triggered this bug report.
258 begin_time: Logline format timestamp taken when the test started.
259 """
260 begin_time = vts_logger.normalizeLogLineTimestamp(begin_time)
Ang Lie2139f12016-05-12 17:39:06 -0700261
Ang Li93420002016-05-10 19:11:44 -0700262 def take_br(test_name, begin_time, ad):
263 ad.takeBugReport(test_name, begin_time)
Ang Lie2139f12016-05-12 17:39:06 -0700264
Ang Li93420002016-05-10 19:11:44 -0700265 args = [(test_name, begin_time, ad) for ad in ads]
266 utils.concurrent_exec(take_br, args)
267
Ang Lie2139f12016-05-12 17:39:06 -0700268
Ang Li7f0e1c72016-06-14 11:23:49 -0700269class AndroidDevice(object):
Ang Li93420002016-05-10 19:11:44 -0700270 """Class representing an android device.
271
272 Each object of this class represents one Android device in ACTS, including
273 handles to adb, fastboot, and sl4a clients. In addition to direct adb
274 commands, this object also uses adb port forwarding to talk to the Android
275 device.
276
277 Attributes:
278 serial: A string that's the serial number of the Androi device.
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700279 device_command_port: int, the port number used on the Android device
280 for adb port forwarding (for command-response sessions).
281 device_callback_port: int, the port number used on the Android device
282 for adb port reverse forwarding (for callback sessions).
Ang Lie014a8b2016-06-28 18:24:52 -0700283 log: A logger project with a device-specific prefix for each line -
284 [AndroidDevice|<serial>]
Ang Li93420002016-05-10 19:11:44 -0700285 log_path: A string that is the path where all logs collected on this
286 android device should be stored.
287 adb_logcat_process: A process that collects the adb logcat.
288 adb_logcat_file_path: A string that's the full path to the adb logcat
289 file collected, if any.
Ang Lie014a8b2016-06-28 18:24:52 -0700290 vts_agent_process: A process that runs the HAL agent.
Ang Li93420002016-05-10 19:11:44 -0700291 adb: An AdbProxy object used for interacting with the device via adb.
292 fastboot: A FastbootProxy object used for interacting with the device
293 via fastboot.
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700294 host_command_port: the host-side port for runner to agent sessions
295 (to send commands and receive responses).
296 host_callback_port: the host-side port for agent to runner sessions
297 (to get callbacks from agent).
Ang Li93420002016-05-10 19:11:44 -0700298 """
299
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700300 def __init__(self, serial="", device_port=5001, device_callback_port=5010):
Ang Li93420002016-05-10 19:11:44 -0700301 self.serial = serial
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700302 self.device_command_port = device_port
303 self.device_callback_port = device_callback_port
Ang Lie014a8b2016-06-28 18:24:52 -0700304 self.log = AndroidDeviceLoggerAdapter(logging.getLogger(),
305 {"serial": self.serial})
306 base_log_path = getattr(logging, "log_path", "/tmp/logs/")
Ang Li7f0e1c72016-06-14 11:23:49 -0700307 self.log_path = os.path.join(base_log_path, "AndroidDevice%s" % serial)
Ang Li93420002016-05-10 19:11:44 -0700308 self.adb_logcat_process = None
309 self.adb_logcat_file_path = None
Ang Lie014a8b2016-06-28 18:24:52 -0700310 self.vts_agent_process = None
Ang Li93420002016-05-10 19:11:44 -0700311 self.adb = adb.AdbProxy(serial)
312 self.fastboot = fastboot.FastbootProxy(serial)
313 if not self.isBootloaderMode:
314 self.rootAdb()
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700315 self.host_command_port = adb.get_available_host_port()
316 self.host_callback_port = adb.get_available_host_port()
317 self.adb.tcp_forward(self.host_command_port, self.device_command_port)
Ang Lie014a8b2016-06-28 18:24:52 -0700318 self.adb.reverse_tcp_forward(self.device_callback_port,
319 self.host_callback_port)
320 self.hal = hal_mirror.HalMirror(self.host_command_port,
321 self.host_callback_port)
Ang Li93420002016-05-10 19:11:44 -0700322
323 def __del__(self):
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700324 if self.host_command_port:
325 self.adb.forward("--remove tcp:%s" % self.host_command_port)
Ang Li93420002016-05-10 19:11:44 -0700326 if self.adb_logcat_process:
327 self.stopAdbLogcat()
328
329 @property
330 def isBootloaderMode(self):
331 """True if the device is in bootloader mode.
332 """
333 return self.serial in list_fastboot_devices()
334
335 @property
336 def isAdbRoot(self):
337 """True if adb is running as root for this device.
338 """
339 return "root" in self.adb.shell("id -u").decode("utf-8")
340
341 @property
342 def model(self):
343 """The Android code name for the device.
344 """
345 # If device is in bootloader mode, get mode name from fastboot.
346 if self.isBootloaderMode:
347 out = self.fastboot.getvar("product").strip()
348 # "out" is never empty because of the "total time" message fastboot
349 # writes to stderr.
350 lines = out.decode("utf-8").split('\n', 1)
351 if lines:
352 tokens = lines[0].split(' ')
353 if len(tokens) > 1:
354 return tokens[1].lower()
355 return None
356 out = self.adb.shell('getprop | grep ro.build.product')
357 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
358 if model == "sprout":
359 return model
360 else:
361 out = self.adb.shell('getprop | grep ro.product.name')
362 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
363 return model
364
365 @property
Ang Li93420002016-05-10 19:11:44 -0700366 def isAdbLogcatOn(self):
367 """Whether there is an ongoing adb logcat collection.
368 """
369 if self.adb_logcat_process:
370 return True
371 return False
372
373 def loadConfig(self, config):
374 """Add attributes to the AndroidDevice object based on json config.
375
376 Args:
377 config: A dictionary representing the configs.
378
379 Raises:
380 AndroidDeviceError is raised if the config is trying to overwrite
381 an existing attribute.
382 """
383 for k, v in config.items():
384 if hasattr(self, k):
Ang Li7f0e1c72016-06-14 11:23:49 -0700385 raise AndroidDeviceError(
386 "Attempting to set existing attribute %s on %s" %
387 (k, self.serial))
Ang Li93420002016-05-10 19:11:44 -0700388 setattr(self, k, v)
389
390 def rootAdb(self):
391 """Change adb to root mode for this device.
392 """
393 if not self.isAdbRoot:
394 self.adb.root()
395 self.adb.wait_for_device()
396 self.adb.remount()
397 self.adb.wait_for_device()
398
Ang Li93420002016-05-10 19:11:44 -0700399 def startAdbLogcat(self):
400 """Starts a standing adb logcat collection in separate subprocesses and
401 save the logcat in a file.
402 """
403 if self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700404 raise AndroidDeviceError(("Android device %s already has an adb "
Ang Lie2139f12016-05-12 17:39:06 -0700405 "logcat thread going on. Cannot start "
Ang Li7f0e1c72016-06-14 11:23:49 -0700406 "another one.") % self.serial)
Ang Li93420002016-05-10 19:11:44 -0700407 # Disable adb log spam filter.
408 self.adb.shell("logpersist.start")
Ang Li7f0e1c72016-06-14 11:23:49 -0700409 f_name = "adblog,%s,%s.txt" % (self.model, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700410 utils.create_dir(self.log_path)
411 logcat_file_path = os.path.join(self.log_path, f_name)
412 try:
413 extra_params = self.adb_logcat_param
414 except AttributeError:
415 extra_params = "-b all"
Ang Li7f0e1c72016-06-14 11:23:49 -0700416 cmd = "adb -s %s logcat -v threadtime %s >> %s" % (
Ang Li93420002016-05-10 19:11:44 -0700417 self.serial, extra_params, logcat_file_path)
418 self.adb_logcat_process = utils.start_standing_subprocess(cmd)
419 self.adb_logcat_file_path = logcat_file_path
420
421 def stopAdbLogcat(self):
422 """Stops the adb logcat collection subprocess.
423 """
424 if not self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700425 raise AndroidDeviceError(
426 "Android device %s does not have an ongoing adb logcat collection."
427 % self.serial)
Ang Li93420002016-05-10 19:11:44 -0700428 utils.stop_standing_subprocess(self.adb_logcat_process)
429 self.adb_logcat_process = None
430
431 def takeBugReport(self, test_name, begin_time):
432 """Takes a bug report on the device and stores it in a file.
433
434 Args:
435 test_name: Name of the test case that triggered this bug report.
436 begin_time: Logline format timestamp taken when the test started.
437 """
438 br_path = os.path.join(self.log_path, "BugReports")
439 utils.create_dir(br_path)
Ang Li7f0e1c72016-06-14 11:23:49 -0700440 base_name = ",%s,%s.txt" % (begin_time, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700441 test_name_len = utils.MAX_FILENAME_LEN - len(base_name)
442 out_name = test_name[:test_name_len] + base_name
443 full_out_path = os.path.join(br_path, out_name.replace(' ', '\ '))
444 self.log.info("Taking bugreport for %s on %s", test_name, self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700445 self.adb.bugreport(" > %s" % full_out_path)
Ang Li93420002016-05-10 19:11:44 -0700446 self.log.info("Bugreport for %s taken at %s", test_name, full_out_path)
447
Ang Li93420002016-05-10 19:11:44 -0700448 @utils.timeout(15 * 60)
449 def waitForBootCompletion(self):
450 """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED.
451
452 This function times out after 15 minutes.
453 """
454 self.adb.wait_for_device()
455 while True:
456 try:
457 out = self.adb.shell("getprop sys.boot_completed")
458 completed = out.decode('utf-8').strip()
459 if completed == '1':
460 return
461 except adb.AdbError:
462 # adb shell calls may fail during certain period of booting
463 # process, which is normal. Ignoring these errors.
464 pass
465 time.sleep(5)
466
467 def reboot(self):
Ang Li7f0e1c72016-06-14 11:23:49 -0700468 """Reboots the device and wait for device to complete booting.
Ang Li93420002016-05-10 19:11:44 -0700469
470 This is probably going to print some error messages in console. Only
471 use if there's no other option.
472
Ang Li93420002016-05-10 19:11:44 -0700473 Raises:
474 AndroidDeviceError is raised if waiting for completion timed
475 out.
476 """
477 if self.isBootloaderMode:
478 self.fastboot.reboot()
479 return
480 has_adb_log = self.isAdbLogcatOn
Ang Lie014a8b2016-06-28 18:24:52 -0700481 has_vts_agent = True if self.vts_agent_process else False
Ang Li93420002016-05-10 19:11:44 -0700482 if has_adb_log:
483 self.stopAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700484 if has_vts_agent:
485 self.stopVtsAgent()
Ang Li93420002016-05-10 19:11:44 -0700486 self.adb.reboot()
487 self.waitForBootCompletion()
488 self.rootAdb()
Ang Li93420002016-05-10 19:11:44 -0700489 if has_adb_log:
490 self.startAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700491 if has_vts_agent:
492 self.startVtsAgent()
Sahil Jain06dd6a22016-06-24 13:47:37 -0700493
Ang Lie014a8b2016-06-28 18:24:52 -0700494 def startVtsAgent(self):
495 """Start HAL agent on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700496
497 This function starts the target side native agent and is persisted
Ang Lie014a8b2016-06-28 18:24:52 -0700498 throughout the test run.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700499 """
Ang Lie014a8b2016-06-28 18:24:52 -0700500 if self.vts_agent_process:
501 raise AndroidDeviceError("HAL agent is already running on %s." %
502 self.serial)
503 kill_commands = ["killall vts_hal_agent", "killall fuzzer32",
504 "killall fuzzer64"]
505 for cmd in kill_commands:
Sahil Jain06dd6a22016-06-24 13:47:37 -0700506 try:
507 self.adb.shell(cmd)
Ang Lie014a8b2016-06-28 18:24:52 -0700508 except adb.AdbError:
509 # Ignore errors from killall in case process was not running.
510 pass
511 vts_agent_log_path = os.path.join(self.log_path, "vts_agent.log")
512 cmd = (
513 'adb -s {s} shell LD_LIBRARY_PATH={path}/64 {path}/64/vts_hal_agent'
514 ' {path}/32/fuzzer32 {path}/64/fuzzer64 {path}/spec >> {log}'
515 ).format(s=self.serial,
516 path=DEFAULT_AGENT_BASE_DIR,
517 log=vts_agent_log_path)
518 self.vts_agent_process = utils.start_standing_subprocess(
519 cmd, check_health_delay=1)
Sahil Jain06dd6a22016-06-24 13:47:37 -0700520
Ang Lie014a8b2016-06-28 18:24:52 -0700521 def stopVtsAgent(self):
522 """Stop the HAL agent running on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700523 """
Ang Lie014a8b2016-06-28 18:24:52 -0700524 if self.vts_agent_process:
525 utils.stop_standing_subprocess(self.vts_agent_process)
526 self.vts_agent_process = None
Sahil Jain06dd6a22016-06-24 13:47:37 -0700527
Sahil Jain06dd6a22016-06-24 13:47:37 -0700528
Ang Lie014a8b2016-06-28 18:24:52 -0700529class AndroidDeviceLoggerAdapter(logging.LoggerAdapter):
530 """A wrapper class that attaches a prefix to all log lines from an
531 AndroidDevice object.
532 """
533
534 def process(self, msg, kwargs):
535 """Process every log message written via the wrapped logger object.
536
537 We are adding the prefix "[AndroidDevice|<serial>]" to all log lines.
538
539 Args:
540 msg: string, the original log message.
541 kwargs: dict, the key value pairs that can be used to modify the
542 original log message.
543 """
544 msg = "[AndroidDevice|%s] %s" % (self.extra["serial"], msg)
545 return (msg, kwargs)