blob: aa704fcee075833ab167fd1be9721f9e58813d14 [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
Keun Soo Yime34754e2016-08-15 11:25:15 -070028from vts.runners.host import keys
Ang Li93420002016-05-10 19:11:44 -070029from vts.runners.host import logger as vts_logger
30from vts.runners.host import signals
31from vts.runners.host import utils
Ang Li7f0e1c72016-06-14 11:23:49 -070032from vts.utils.python.controllers import adb
33from vts.utils.python.controllers import event_dispatcher
34from vts.utils.python.controllers import fastboot
Sahil Jain06dd6a22016-06-24 13:47:37 -070035from vts.runners.host.tcp_client import vts_tcp_client
Ang Li7f0e1c72016-06-14 11:23:49 -070036from vts.utils.python.mirror import hal_mirror
Keun Soo Yim63d67512016-07-01 17:13:47 -070037from vts.utils.python.mirror import shell_mirror
Keun Soo Yim39bc0b92016-07-06 18:27:15 -070038from vts.utils.python.mirror import lib_mirror
Sahil Jain06dd6a22016-06-24 13:47:37 -070039from vts.runners.host import errors
40import subprocess
Ang Li93420002016-05-10 19:11:44 -070041
42VTS_CONTROLLER_CONFIG_NAME = "AndroidDevice"
43VTS_CONTROLLER_REFERENCE_NAME = "android_devices"
44
45ANDROID_DEVICE_PICK_ALL_TOKEN = "*"
46# Key name for adb logcat extra params in config file.
47ANDROID_DEVICE_ADB_LOGCAT_PARAM_KEY = "adb_logcat_param"
48ANDROID_DEVICE_EMPTY_CONFIG_MSG = "Configuration is empty, abort!"
49ANDROID_DEVICE_NOT_LIST_CONFIG_MSG = "Configuration should be a list, abort!"
50
Keun Soo Yime34754e2016-08-15 11:25:15 -070051ANDROID_PRODUCT_TYPE_UNKNOWN = "unknown"
52
Sahil Jain06dd6a22016-06-24 13:47:37 -070053# Target-side directory where the VTS binaries are uploaded
54DEFAULT_AGENT_BASE_DIR = "/data/local/tmp"
55# Time for which the current is put on sleep when the client is unable to
56# make a connection.
57THREAD_SLEEP_TIME = 1
58# Max number of attempts that the client can make to connect to the agent
59MAX_AGENT_CONNECT_RETRIES = 10
60
Ang Li93420002016-05-10 19:11:44 -070061class AndroidDeviceError(signals.ControllerError):
62 pass
63
Ang Lie2139f12016-05-12 17:39:06 -070064
Keun Soo Yimf2b590c2016-07-31 19:54:18 -070065def create(configs, use_vts_agent=True):
Ang Li53bb72b2016-07-19 18:29:37 -070066 """Creates AndroidDevice controller objects.
67
68 Args:
69 configs: A list of dicts, each representing a configuration for an
70 Android device.
Keun Soo Yim4231b6e2016-07-31 19:01:05 -070071 use_vts_agent: bool, whether to use VTS agent.
Ang Li53bb72b2016-07-19 18:29:37 -070072
73 Returns:
74 A list of AndroidDevice objects.
75 """
Ang Li93420002016-05-10 19:11:44 -070076 if not configs:
77 raise AndroidDeviceError(ANDROID_DEVICE_EMPTY_CONFIG_MSG)
78 elif configs == ANDROID_DEVICE_PICK_ALL_TOKEN:
Ang Li7f0e1c72016-06-14 11:23:49 -070079 ads = get_all_instances()
Ang Li93420002016-05-10 19:11:44 -070080 elif not isinstance(configs, list):
81 raise AndroidDeviceError(ANDROID_DEVICE_NOT_LIST_CONFIG_MSG)
82 elif isinstance(configs[0], str):
83 # Configs is a list of serials.
Ang Li7f0e1c72016-06-14 11:23:49 -070084 ads = get_instances(configs)
Ang Li93420002016-05-10 19:11:44 -070085 else:
86 # Configs is a list of dicts.
Ang Li7f0e1c72016-06-14 11:23:49 -070087 ads = get_instances_with_configs(configs)
Ang Li93420002016-05-10 19:11:44 -070088 connected_ads = list_adb_devices()
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -070089
Ang Li93420002016-05-10 19:11:44 -070090 for ad in ads:
91 if ad.serial not in connected_ads:
Ang Li53bb72b2016-07-19 18:29:37 -070092 raise DoesNotExistError(("Android device %s is specified in config"
93 " but is not attached.") % ad.serial)
Keun Soo Yim4231b6e2016-07-31 19:01:05 -070094 _startServicesOnAds(ads, use_vts_agent)
Ang Li93420002016-05-10 19:11:44 -070095 return ads
96
Ang Lie2139f12016-05-12 17:39:06 -070097
Ang Li93420002016-05-10 19:11:44 -070098def destroy(ads):
Ang Li53bb72b2016-07-19 18:29:37 -070099 """Cleans up AndroidDevice objects.
100
101 Args:
102 ads: A list of AndroidDevice objects.
103 """
Ang Li93420002016-05-10 19:11:44 -0700104 for ad in ads:
Ang Li53bb72b2016-07-19 18:29:37 -0700105 try:
106 ad.cleanUp()
107 except:
108 ad.log.exception("Failed to clean up properly.")
109
110
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700111def _startServicesOnAds(ads, use_vts_agent):
Ang Li53bb72b2016-07-19 18:29:37 -0700112 """Starts long running services on multiple AndroidDevice objects.
113
114 If any one AndroidDevice object fails to start services, cleans up all
115 existing AndroidDevice objects and their services.
116
117 Args:
118 ads: A list of AndroidDevice objects whose services to start.
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700119 use_vts_agent: bool, whether to use the VTS agent.
Ang Li53bb72b2016-07-19 18:29:37 -0700120 """
121 running_ads = []
122 for ad in ads:
123 running_ads.append(ad)
124 try:
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700125 ad.startServices(use_vts_agent)
Ang Li53bb72b2016-07-19 18:29:37 -0700126 except:
127 ad.log.exception("Failed to start some services, abort!")
128 destroy(running_ads)
129 raise
Ang Li93420002016-05-10 19:11:44 -0700130
Ang Lie2139f12016-05-12 17:39:06 -0700131
Ang Li93420002016-05-10 19:11:44 -0700132def _parse_device_list(device_list_str, key):
133 """Parses a byte string representing a list of devices. The string is
134 generated by calling either adb or fastboot.
135
136 Args:
137 device_list_str: Output of adb or fastboot.
138 key: The token that signifies a device in device_list_str.
139
140 Returns:
141 A list of android device serial numbers.
142 """
143 clean_lines = str(device_list_str, 'utf-8').strip().split('\n')
144 results = []
145 for line in clean_lines:
146 tokens = line.strip().split('\t')
147 if len(tokens) == 2 and tokens[1] == key:
148 results.append(tokens[0])
149 return results
150
Ang Lie2139f12016-05-12 17:39:06 -0700151
Ang Li93420002016-05-10 19:11:44 -0700152def list_adb_devices():
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700153 """List all target devices connected to the host and detected by adb.
Ang Li93420002016-05-10 19:11:44 -0700154
155 Returns:
156 A list of android device serials. Empty if there's none.
157 """
158 out = adb.AdbProxy().devices()
159 return _parse_device_list(out, "device")
160
Ang Lie2139f12016-05-12 17:39:06 -0700161
Ang Li93420002016-05-10 19:11:44 -0700162def list_fastboot_devices():
163 """List all android devices connected to the computer that are in in
164 fastboot mode. These are detected by fastboot.
165
166 Returns:
167 A list of android device serials. Empty if there's none.
168 """
169 out = fastboot.FastbootProxy().devices()
170 return _parse_device_list(out, "fastboot")
171
Ang Lie2139f12016-05-12 17:39:06 -0700172
Ang Li7f0e1c72016-06-14 11:23:49 -0700173def get_instances(serials):
Ang Li93420002016-05-10 19:11:44 -0700174 """Create AndroidDevice instances from a list of serials.
175
176 Args:
177 serials: A list of android device serials.
Ang Li93420002016-05-10 19:11:44 -0700178
179 Returns:
180 A list of AndroidDevice objects.
181 """
182 results = []
183 for s in serials:
Ang Li7f0e1c72016-06-14 11:23:49 -0700184 results.append(AndroidDevice(s))
Ang Li93420002016-05-10 19:11:44 -0700185 return results
186
Ang Lie2139f12016-05-12 17:39:06 -0700187
Ang Li7f0e1c72016-06-14 11:23:49 -0700188def get_instances_with_configs(configs):
Ang Li93420002016-05-10 19:11:44 -0700189 """Create AndroidDevice instances from a list of json configs.
190
191 Each config should have the required key-value pair "serial".
192
193 Args:
194 configs: A list of dicts each representing the configuration of one
195 android device.
Ang Li93420002016-05-10 19:11:44 -0700196
197 Returns:
198 A list of AndroidDevice objects.
199 """
200 results = []
201 for c in configs:
202 try:
Keun Soo Yime34754e2016-08-15 11:25:15 -0700203 serial = c.pop(keys.ConfigKeys.IKEY_SERIAL)
Ang Li93420002016-05-10 19:11:44 -0700204 except KeyError:
Keun Soo Yime34754e2016-08-15 11:25:15 -0700205 raise AndroidDeviceError(
206 ('Required value %s is missing in '
207 'AndroidDevice config %s.') % (keys.ConfigKeys.IKEY_SERIAL,
208 c))
209 try:
210 product_type = c.pop(keys.ConfigKeys.IKEY_PRODUCT_TYPE)
211 except KeyError:
212 logging.error(
213 'Required value %s is missing in '
214 'AndroidDevice config %s.',
215 keys.ConfigKeys.IKEY_PRODUCT_TYPE, c)
216 product_type = ANDROID_PRODUCT_TYPE_UNKNOWN
217
218 ad = AndroidDevice(serial, product_type)
Ang Li93420002016-05-10 19:11:44 -0700219 ad.loadConfig(c)
220 results.append(ad)
221 return results
222
Ang Lie2139f12016-05-12 17:39:06 -0700223
Ang Li7f0e1c72016-06-14 11:23:49 -0700224def get_all_instances(include_fastboot=False):
Ang Li93420002016-05-10 19:11:44 -0700225 """Create AndroidDevice instances for all attached android devices.
226
227 Args:
228 include_fastboot: Whether to include devices in bootloader mode or not.
Ang Li93420002016-05-10 19:11:44 -0700229
230 Returns:
231 A list of AndroidDevice objects each representing an android device
232 attached to the computer.
233 """
234 if include_fastboot:
235 serial_list = list_adb_devices() + list_fastboot_devices()
Ang Li7f0e1c72016-06-14 11:23:49 -0700236 return get_instances(serial_list)
237 return get_instances(list_adb_devices())
Ang Li93420002016-05-10 19:11:44 -0700238
Ang Lie2139f12016-05-12 17:39:06 -0700239
Ang Li93420002016-05-10 19:11:44 -0700240def filter_devices(ads, func):
241 """Finds the AndroidDevice instances from a list that match certain
242 conditions.
243
244 Args:
245 ads: A list of AndroidDevice instances.
246 func: A function that takes an AndroidDevice object and returns True
247 if the device satisfies the filter condition.
248
249 Returns:
250 A list of AndroidDevice instances that satisfy the filter condition.
251 """
252 results = []
253 for ad in ads:
254 if func(ad):
255 results.append(ad)
256 return results
257
Ang Lie2139f12016-05-12 17:39:06 -0700258
Ang Li93420002016-05-10 19:11:44 -0700259def get_device(ads, **kwargs):
260 """Finds a unique AndroidDevice instance from a list that has specific
261 attributes of certain values.
262
263 Example:
264 get_device(android_devices, label="foo", phone_number="1234567890")
265 get_device(android_devices, model="angler")
266
267 Args:
268 ads: A list of AndroidDevice instances.
269 kwargs: keyword arguments used to filter AndroidDevice instances.
270
271 Returns:
272 The target AndroidDevice instance.
273
274 Raises:
275 AndroidDeviceError is raised if none or more than one device is
276 matched.
277 """
Ang Lie2139f12016-05-12 17:39:06 -0700278
Ang Li93420002016-05-10 19:11:44 -0700279 def _get_device_filter(ad):
280 for k, v in kwargs.items():
281 if not hasattr(ad, k):
282 return False
283 elif getattr(ad, k) != v:
284 return False
285 return True
Ang Lie2139f12016-05-12 17:39:06 -0700286
Ang Li93420002016-05-10 19:11:44 -0700287 filtered = filter_devices(ads, _get_device_filter)
288 if not filtered:
289 raise AndroidDeviceError(("Could not find a target device that matches"
290 " condition: %s.") % kwargs)
291 elif len(filtered) == 1:
292 return filtered[0]
293 else:
294 serials = [ad.serial for ad in filtered]
295 raise AndroidDeviceError("More than one device matched: %s" % serials)
296
Ang Lie2139f12016-05-12 17:39:06 -0700297
Ang Li93420002016-05-10 19:11:44 -0700298def takeBugReports(ads, test_name, begin_time):
299 """Takes bug reports on a list of android devices.
300
301 If you want to take a bug report, call this function with a list of
302 android_device objects in on_fail. But reports will be taken on all the
303 devices in the list concurrently. Bug report takes a relative long
304 time to take, so use this cautiously.
305
306 Args:
307 ads: A list of AndroidDevice instances.
308 test_name: Name of the test case that triggered this bug report.
309 begin_time: Logline format timestamp taken when the test started.
310 """
311 begin_time = vts_logger.normalizeLogLineTimestamp(begin_time)
Ang Lie2139f12016-05-12 17:39:06 -0700312
Ang Li93420002016-05-10 19:11:44 -0700313 def take_br(test_name, begin_time, ad):
314 ad.takeBugReport(test_name, begin_time)
Ang Lie2139f12016-05-12 17:39:06 -0700315
Ang Li93420002016-05-10 19:11:44 -0700316 args = [(test_name, begin_time, ad) for ad in ads]
317 utils.concurrent_exec(take_br, args)
318
Ang Lie2139f12016-05-12 17:39:06 -0700319
Ang Li7f0e1c72016-06-14 11:23:49 -0700320class AndroidDevice(object):
Ang Li93420002016-05-10 19:11:44 -0700321 """Class representing an android device.
322
Ang Li53bb72b2016-07-19 18:29:37 -0700323 Each object of this class represents one Android device. The object holds
324 handles to adb, fastboot, and various RPC clients.
Ang Li93420002016-05-10 19:11:44 -0700325
326 Attributes:
Keun Soo Yime34754e2016-08-15 11:25:15 -0700327 serial: A string that's the serial number of the Android device.
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700328 device_command_port: int, the port number used on the Android device
329 for adb port forwarding (for command-response sessions).
330 device_callback_port: int, the port number used on the Android device
331 for adb port reverse forwarding (for callback sessions).
Ang Lie014a8b2016-06-28 18:24:52 -0700332 log: A logger project with a device-specific prefix for each line -
333 [AndroidDevice|<serial>]
Ang Li93420002016-05-10 19:11:44 -0700334 log_path: A string that is the path where all logs collected on this
335 android device should be stored.
336 adb_logcat_process: A process that collects the adb logcat.
337 adb_logcat_file_path: A string that's the full path to the adb logcat
338 file collected, if any.
Ang Lie014a8b2016-06-28 18:24:52 -0700339 vts_agent_process: A process that runs the HAL agent.
Ang Li93420002016-05-10 19:11:44 -0700340 adb: An AdbProxy object used for interacting with the device via adb.
341 fastboot: A FastbootProxy object used for interacting with the device
342 via fastboot.
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700343 host_command_port: the host-side port for runner to agent sessions
344 (to send commands and receive responses).
345 host_callback_port: the host-side port for agent to runner sessions
346 (to get callbacks from agent).
Ang Li53bb72b2016-07-19 18:29:37 -0700347 hal: HalMirror, in charge of all communications with the HAL layer.
348 lib: LibMirror, in charge of all communications with static and shared
349 native libs.
350 shell: ShellMirror, in charge of all communications with shell.
Keun Soo Yime34754e2016-08-15 11:25:15 -0700351 _product_type: A string, the device product type (e.g., bullhead) if
352 known, ANDROID_PRODUCT_TYPE_UNKNOWN otherwise.
Ang Li93420002016-05-10 19:11:44 -0700353 """
354
Keun Soo Yime34754e2016-08-15 11:25:15 -0700355 def __init__(self, serial="", product_type=ANDROID_PRODUCT_TYPE_UNKNOWN,
356 device_callback_port=5010):
Ang Li93420002016-05-10 19:11:44 -0700357 self.serial = serial
Keun Soo Yime34754e2016-08-15 11:25:15 -0700358 self._product_type = product_type
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700359 self.device_command_port = None
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700360 self.device_callback_port = device_callback_port
Ang Lie014a8b2016-06-28 18:24:52 -0700361 self.log = AndroidDeviceLoggerAdapter(logging.getLogger(),
362 {"serial": self.serial})
363 base_log_path = getattr(logging, "log_path", "/tmp/logs/")
Ang Li7f0e1c72016-06-14 11:23:49 -0700364 self.log_path = os.path.join(base_log_path, "AndroidDevice%s" % serial)
Ang Li93420002016-05-10 19:11:44 -0700365 self.adb_logcat_process = None
366 self.adb_logcat_file_path = None
Ang Lie014a8b2016-06-28 18:24:52 -0700367 self.vts_agent_process = None
Ang Li93420002016-05-10 19:11:44 -0700368 self.adb = adb.AdbProxy(serial)
369 self.fastboot = fastboot.FastbootProxy(serial)
370 if not self.isBootloaderMode:
371 self.rootAdb()
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700372 self.host_command_port = adb.get_available_host_port()
373 self.host_callback_port = adb.get_available_host_port()
Ang Lie014a8b2016-06-28 18:24:52 -0700374 self.adb.reverse_tcp_forward(self.device_callback_port,
375 self.host_callback_port)
Ang Li53bb72b2016-07-19 18:29:37 -0700376 self.hal = None
Keun Soo Yimf5d0bca2016-07-30 23:59:26 -0700377 self.lib = None
378 self.shell = None
Ang Li93420002016-05-10 19:11:44 -0700379
380 def __del__(self):
Ang Li53bb72b2016-07-19 18:29:37 -0700381 self.cleanUp()
382
383 def cleanUp(self):
384 """Cleans up the AndroidDevice object and releases any resources it
385 claimed.
386 """
387 self.stopServices()
Keun Soo Yimcbd8c052016-06-20 15:10:58 -0700388 if self.host_command_port:
389 self.adb.forward("--remove tcp:%s" % self.host_command_port)
Ang Li93420002016-05-10 19:11:44 -0700390
391 @property
392 def isBootloaderMode(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700393 """True if the device is in bootloader mode."""
Ang Li93420002016-05-10 19:11:44 -0700394 return self.serial in list_fastboot_devices()
395
396 @property
397 def isAdbRoot(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700398 """True if adb is running as root for this device."""
399 id_str = self.adb.shell("id -u").decode("utf-8")
400 self.log.info(id_str)
401 return "root" in id_str
Ang Li93420002016-05-10 19:11:44 -0700402
403 @property
404 def model(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700405 """The Android code name for the device."""
Ang Li93420002016-05-10 19:11:44 -0700406 # If device is in bootloader mode, get mode name from fastboot.
407 if self.isBootloaderMode:
408 out = self.fastboot.getvar("product").strip()
409 # "out" is never empty because of the "total time" message fastboot
410 # writes to stderr.
411 lines = out.decode("utf-8").split('\n', 1)
412 if lines:
413 tokens = lines[0].split(' ')
414 if len(tokens) > 1:
415 return tokens[1].lower()
416 return None
417 out = self.adb.shell('getprop | grep ro.build.product')
418 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
419 if model == "sprout":
420 return model
421 else:
422 out = self.adb.shell('getprop | grep ro.product.name')
423 model = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
424 return model
425
426 @property
Tri Vo921bfa02016-09-20 10:25:23 -0700427 def cpu_abi(self):
428 """CPU ABI (Application Binary Interface) of the device."""
429 out = self.adb.shell('getprop | grep "\[ro.product.cpu.abi\]"')
430 if not out:
431 return "unknown"
432
433 cpu_abi = out.decode("utf-8").strip().split('[')[-1][:-1].lower()
434 return cpu_abi
435
436 @property
Tri Vof07f1292016-09-21 17:27:46 -0700437 def is64Bit(self):
438 """True if device is 64 bit."""
439 out = self.adb.shell('uname -m')
440 return "64" in out
441
442 @property
Ang Li93420002016-05-10 19:11:44 -0700443 def isAdbLogcatOn(self):
444 """Whether there is an ongoing adb logcat collection.
445 """
446 if self.adb_logcat_process:
447 return True
448 return False
449
450 def loadConfig(self, config):
451 """Add attributes to the AndroidDevice object based on json config.
452
453 Args:
454 config: A dictionary representing the configs.
455
456 Raises:
457 AndroidDeviceError is raised if the config is trying to overwrite
458 an existing attribute.
459 """
460 for k, v in config.items():
461 if hasattr(self, k):
Ang Li7f0e1c72016-06-14 11:23:49 -0700462 raise AndroidDeviceError(
463 "Attempting to set existing attribute %s on %s" %
464 (k, self.serial))
Ang Li93420002016-05-10 19:11:44 -0700465 setattr(self, k, v)
466
467 def rootAdb(self):
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700468 """Changes adb to root mode for this device."""
Ang Li93420002016-05-10 19:11:44 -0700469 if not self.isAdbRoot:
Keun Soo Yimc2bc9f82016-07-16 15:36:36 -0700470 try:
471 self.adb.root()
Keun Soo Yima5a0dc22016-07-16 17:56:19 -0700472 self.adb.wait_for_device()
473 self.adb.remount()
Keun Soo Yim731e9172016-07-16 17:48:39 -0700474 self.adb.wait_for_device()
475 except adb.AdbError as e:
476 # adb wait-for-device is not always possible in the lab
Keun Soo Yima5a0dc22016-07-16 17:56:19 -0700477 # continue with an assumption it's done by the harness.
Keun Soo Yim731e9172016-07-16 17:48:39 -0700478 logging.exception(e)
Ang Li93420002016-05-10 19:11:44 -0700479
Ang Li93420002016-05-10 19:11:44 -0700480 def startAdbLogcat(self):
481 """Starts a standing adb logcat collection in separate subprocesses and
482 save the logcat in a file.
483 """
484 if self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700485 raise AndroidDeviceError(("Android device %s already has an adb "
Ang Lie2139f12016-05-12 17:39:06 -0700486 "logcat thread going on. Cannot start "
Ang Li7f0e1c72016-06-14 11:23:49 -0700487 "another one.") % self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700488 f_name = "adblog,%s,%s.txt" % (self.model, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700489 utils.create_dir(self.log_path)
490 logcat_file_path = os.path.join(self.log_path, f_name)
491 try:
492 extra_params = self.adb_logcat_param
493 except AttributeError:
494 extra_params = "-b all"
Ang Li7f0e1c72016-06-14 11:23:49 -0700495 cmd = "adb -s %s logcat -v threadtime %s >> %s" % (
Ang Li93420002016-05-10 19:11:44 -0700496 self.serial, extra_params, logcat_file_path)
497 self.adb_logcat_process = utils.start_standing_subprocess(cmd)
498 self.adb_logcat_file_path = logcat_file_path
499
500 def stopAdbLogcat(self):
501 """Stops the adb logcat collection subprocess.
502 """
503 if not self.isAdbLogcatOn:
Ang Li7f0e1c72016-06-14 11:23:49 -0700504 raise AndroidDeviceError(
505 "Android device %s does not have an ongoing adb logcat collection."
506 % self.serial)
Ang Li93420002016-05-10 19:11:44 -0700507 utils.stop_standing_subprocess(self.adb_logcat_process)
508 self.adb_logcat_process = None
509
510 def takeBugReport(self, test_name, begin_time):
511 """Takes a bug report on the device and stores it in a file.
512
513 Args:
514 test_name: Name of the test case that triggered this bug report.
515 begin_time: Logline format timestamp taken when the test started.
516 """
517 br_path = os.path.join(self.log_path, "BugReports")
518 utils.create_dir(br_path)
Ang Li7f0e1c72016-06-14 11:23:49 -0700519 base_name = ",%s,%s.txt" % (begin_time, self.serial)
Ang Li93420002016-05-10 19:11:44 -0700520 test_name_len = utils.MAX_FILENAME_LEN - len(base_name)
521 out_name = test_name[:test_name_len] + base_name
522 full_out_path = os.path.join(br_path, out_name.replace(' ', '\ '))
523 self.log.info("Taking bugreport for %s on %s", test_name, self.serial)
Ang Li7f0e1c72016-06-14 11:23:49 -0700524 self.adb.bugreport(" > %s" % full_out_path)
Ang Li93420002016-05-10 19:11:44 -0700525 self.log.info("Bugreport for %s taken at %s", test_name, full_out_path)
526
Ang Li93420002016-05-10 19:11:44 -0700527 @utils.timeout(15 * 60)
528 def waitForBootCompletion(self):
529 """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED.
530
531 This function times out after 15 minutes.
532 """
Keun Soo Yim731e9172016-07-16 17:48:39 -0700533 try:
534 self.adb.wait_for_device()
535 except adb.AdbError as e:
536 # adb wait-for-device is not always possible in the lab
537 logging.exception(e)
Ang Li93420002016-05-10 19:11:44 -0700538 while True:
539 try:
540 out = self.adb.shell("getprop sys.boot_completed")
541 completed = out.decode('utf-8').strip()
542 if completed == '1':
543 return
544 except adb.AdbError:
545 # adb shell calls may fail during certain period of booting
546 # process, which is normal. Ignoring these errors.
547 pass
548 time.sleep(5)
549
550 def reboot(self):
Ang Li7f0e1c72016-06-14 11:23:49 -0700551 """Reboots the device and wait for device to complete booting.
Ang Li93420002016-05-10 19:11:44 -0700552
553 This is probably going to print some error messages in console. Only
554 use if there's no other option.
555
Ang Li93420002016-05-10 19:11:44 -0700556 Raises:
557 AndroidDeviceError is raised if waiting for completion timed
558 out.
559 """
560 if self.isBootloaderMode:
561 self.fastboot.reboot()
562 return
563 has_adb_log = self.isAdbLogcatOn
Ang Lie014a8b2016-06-28 18:24:52 -0700564 has_vts_agent = True if self.vts_agent_process else False
Ang Li93420002016-05-10 19:11:44 -0700565 if has_adb_log:
566 self.stopAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700567 if has_vts_agent:
568 self.stopVtsAgent()
Ang Li93420002016-05-10 19:11:44 -0700569 self.adb.reboot()
570 self.waitForBootCompletion()
571 self.rootAdb()
Ang Li93420002016-05-10 19:11:44 -0700572 if has_adb_log:
573 self.startAdbLogcat()
Ang Lie014a8b2016-06-28 18:24:52 -0700574 if has_vts_agent:
575 self.startVtsAgent()
Sahil Jain06dd6a22016-06-24 13:47:37 -0700576
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700577 def startServices(self, use_vts_agent):
Ang Li53bb72b2016-07-19 18:29:37 -0700578 """Starts long running services on the android device.
579
580 1. Start adb logcat capture.
581 2. Start VtsAgent.
582 3. Create HalMirror
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700583
584 Args:
585 use_vts_agent: bool, whether to use the VTS agent.
Ang Li53bb72b2016-07-19 18:29:37 -0700586 """
587 try:
588 self.startAdbLogcat()
589 except:
590 self.log.exception("Failed to start adb logcat!")
591 raise
Keun Soo Yim4231b6e2016-07-31 19:01:05 -0700592 if use_vts_agent:
593 self.startVtsAgent()
594 self.device_command_port = int(
595 self.adb.shell("cat /data/local/tmp/vts_tcp_server_port"))
596 logging.info("device_command_port: %s", self.device_command_port)
597 self.adb.tcp_forward(self.host_command_port, self.device_command_port)
598 self.hal = hal_mirror.HalMirror(self.host_command_port,
599 self.host_callback_port)
600 self.lib = lib_mirror.LibMirror(self.host_command_port)
601 self.shell = shell_mirror.ShellMirror(self.host_command_port)
602 else:
603 logging.info("not using VTS agent.")
Ang Li53bb72b2016-07-19 18:29:37 -0700604
605 def stopServices(self):
606 """Stops long running services on the android device.
607 """
608 if self.adb_logcat_process:
609 self.stopAdbLogcat()
610 self.stopVtsAgent()
611 if self.hal:
612 self.hal.CleanUp()
613
Ang Lie014a8b2016-06-28 18:24:52 -0700614 def startVtsAgent(self):
615 """Start HAL agent on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700616
617 This function starts the target side native agent and is persisted
Ang Lie014a8b2016-06-28 18:24:52 -0700618 throughout the test run.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700619 """
Keun Soo Yimab7fb062016-07-13 14:47:19 -0700620 self.log.info("start a VTS agent")
Ang Lie014a8b2016-06-28 18:24:52 -0700621 if self.vts_agent_process:
622 raise AndroidDeviceError("HAL agent is already running on %s." %
623 self.serial)
Keun Soo Yima066dd52016-07-01 15:18:28 -0700624
625 cleanup_commands = [
Keun Soo Yim02da0272016-07-19 07:56:38 -0700626 "rm -f /data/local/tmp/vts_driver_*",
Ang Li53bb72b2016-07-19 18:29:37 -0700627 "rm -f /data/local/tmp/vts_agent_callback*"
628 ]
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700629 kill_commands = ["killall vts_hal_agent32", "killall vts_hal_agent64",
630 "killall fuzzer32", "killall fuzzer64",
631 "killall vts_shell_driver32",
Yuexi Ma674e59d2016-07-19 15:39:54 -0700632 "killall vts_shell_driver64"]
Keun Soo Yima066dd52016-07-01 15:18:28 -0700633 cleanup_commands.extend(kill_commands)
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700634 chmod_commands = [
Keun Soo Yim2eecdfa2016-07-29 11:48:37 -0700635 "chmod 755 %s/32/vts_hal_agent32" % DEFAULT_AGENT_BASE_DIR,
636 "chmod 755 %s/64/vts_hal_agent64" % DEFAULT_AGENT_BASE_DIR,
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700637 "chmod 755 %s/32/fuzzer32" % DEFAULT_AGENT_BASE_DIR,
Keun Soo Yim02da0272016-07-19 07:56:38 -0700638 "chmod 755 %s/64/fuzzer64" % DEFAULT_AGENT_BASE_DIR,
639 "chmod 755 %s/32/vts_shell_driver32" % DEFAULT_AGENT_BASE_DIR,
Ang Li53bb72b2016-07-19 18:29:37 -0700640 "chmod 755 %s/64/vts_shell_driver64" % DEFAULT_AGENT_BASE_DIR
641 ]
Keun Soo Yimbf8f7b42016-07-13 13:58:28 -0700642 cleanup_commands.extend(chmod_commands)
Keun Soo Yima066dd52016-07-01 15:18:28 -0700643 for cmd in cleanup_commands:
Sahil Jain06dd6a22016-06-24 13:47:37 -0700644 try:
645 self.adb.shell(cmd)
Keun Soo Yimab7fb062016-07-13 14:47:19 -0700646 except adb.AdbError as e:
647 self.log.warning(
Ang Li53bb72b2016-07-19 18:29:37 -0700648 "A command to setup the env to start the VTS Agent failed %s",
649 e)
Ang Lie014a8b2016-06-28 18:24:52 -0700650 vts_agent_log_path = os.path.join(self.log_path, "vts_agent.log")
Tri Vo843b57f2016-09-24 14:51:38 -0700651
652 bits = ['64', '32'] if self.is64Bit else ['32']
653 for bitness in bits:
Keun Soo Yimd2aa5b82016-07-30 20:12:19 -0700654 cmd = (
655 'adb -s {s} shell LD_LIBRARY_PATH={path}/{bitness} '
656 '{path}/{bitness}/vts_hal_agent{bitness}'
657 ' {path}/32/fuzzer32 {path}/64/fuzzer64 {path}/spec'
658 ' {path}/32/vts_shell_driver32 {path}/64/vts_shell_driver64 >> {log}'
659 ).format(s=self.serial,
660 bitness=bitness,
661 path=DEFAULT_AGENT_BASE_DIR,
662 log=vts_agent_log_path)
663 try:
664 self.vts_agent_process = utils.start_standing_subprocess(
665 cmd, check_health_delay=1)
666 except utils.VTSUtilsError as e:
667 logging.exception(e)
668 with open(vts_agent_log_path, 'r') as log_file:
669 logging.error("VTS agent output:\n")
670 logging.error(log_file.read())
671 # one common cause is that 64-bit executable is not supported
672 # in low API level devices.
673 if bitness == '32':
674 raise
675 else:
676 logging.error('retrying using a 32-bit binary.')
Sahil Jain06dd6a22016-06-24 13:47:37 -0700677
Ang Lie014a8b2016-06-28 18:24:52 -0700678 def stopVtsAgent(self):
679 """Stop the HAL agent running on the AndroidDevice.
Sahil Jain06dd6a22016-06-24 13:47:37 -0700680 """
Ang Lie014a8b2016-06-28 18:24:52 -0700681 if self.vts_agent_process:
682 utils.stop_standing_subprocess(self.vts_agent_process)
683 self.vts_agent_process = None
Sahil Jain06dd6a22016-06-24 13:47:37 -0700684
Keun Soo Yime34754e2016-08-15 11:25:15 -0700685 @property
686 def product_type(self):
687 """Gets the product type name."""
688 return self._product_type
689
Sahil Jain06dd6a22016-06-24 13:47:37 -0700690
Ang Lie014a8b2016-06-28 18:24:52 -0700691class AndroidDeviceLoggerAdapter(logging.LoggerAdapter):
692 """A wrapper class that attaches a prefix to all log lines from an
693 AndroidDevice object.
694 """
695
696 def process(self, msg, kwargs):
697 """Process every log message written via the wrapped logger object.
698
699 We are adding the prefix "[AndroidDevice|<serial>]" to all log lines.
700
701 Args:
702 msg: string, the original log message.
703 kwargs: dict, the key value pairs that can be used to modify the
704 original log message.
705 """
706 msg = "[AndroidDevice|%s] %s" % (self.extra["serial"], msg)
707 return (msg, kwargs)