1# Lint as: python2, python3 2# Copyright 2022 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6# TODO(rkuroiwa): Rename this file to adb_utils.py to align with other utility 7# modules. Also when class Adb is instantiated, the user is likely to call the 8# instance "adb" which would collide with this file name (unless they always 9# use "import adb as someothername". 10 11import logging 12import re 13 14from autotest_lib.server import utils 15 16 17class Adb: 18 """Class for running adb commands.""" 19 20 def __init__(self): 21 self._install_paths = set() 22 23 def add_path(self, path): 24 """Adds path for executing commands. 25 26 Path to ADB and AAPT may have to be added it if is not in the path. 27 Use this method to add it to the path before using run(). 28 """ 29 self._install_paths.add(path) 30 31 def get_paths(self): 32 return self._install_paths 33 34 def run(self, host, *args, **kwargs): 35 """Runs an ADB command on the host. 36 37 @param host: DUT to issue the adb command. 38 @param args: Extra args passed to the adb command. 39 @param kwargs: Extra arguments passed to utils.run(). 40 """ 41 additional_option = _tradefed_options(host) 42 kwargs['args'] = additional_option + kwargs.get('args', ()) 43 44 # _install_paths should include the directory with adb. 45 # utils.run() will append these to paths. 46 kwargs['extra_paths'] = (kwargs.get('extra_paths', []) + 47 list(self._install_paths)) 48 result = utils.run('adb', **kwargs) 49 logging.info('adb %s:\n%s', ' '.join(kwargs.get('args')), 50 result.stdout + result.stderr) 51 return result 52 53 54def get_adb_target(host): 55 """Get the adb target format. 56 57 This method is slightly different from host.host_port as we need to 58 explicitly specify the port so the serial name of adb target would 59 match. 60 61 @param host: a DUT accessible via adb. 62 @return a string for specifying the host using adb command. 63 """ 64 port = 22 if host.port is None else host.port 65 if re.search(r':.*:', host.hostname): 66 # Add [] for raw IPv6 addresses, stripped for ssh. 67 # In the Python >= 3.3 future, 'import ipaddress' will parse 68 # addresses. 69 return '[{}]:{}'.format(host.hostname, port) 70 return '{}:{}'.format(host.hostname, port) 71 72 73def get_adb_targets(hosts): 74 """Get a list of adb targets.""" 75 return [get_adb_target(host) for host in hosts] 76 77 78def _tradefed_options(host): 79 """ADB arguments for tradefed. 80 81 These arguments are specific to using adb with tradefed. 82 83 @param host: DUT that want to connect to. (None if the adb command is 84 intended to run in the server. eg. keygen) 85 @return a tuple of arguments for adb command. 86 """ 87 if host: 88 host_port = get_adb_target(host) 89 ret = ('-s', host_port) 90 return ret 91 # As of N, tradefed could not specify which adb socket to use, which use 92 # tcp:localhost:5037 by default. 93 return ('-H', 'localhost', '-P', '5037') 94