Allow selection of adb command.
This is useful for ndk-gdb.py on Windows. Change-Id: I2a2b6b50ae00bcfc530c555f06c945b4f53f9999
This commit is contained in:
@@ -48,11 +48,11 @@ class ShellError(RuntimeError):
|
|||||||
self.exit_code = exit_code
|
self.exit_code = exit_code
|
||||||
|
|
||||||
|
|
||||||
def get_devices():
|
def get_devices(adb_path='adb'):
|
||||||
with open(os.devnull, 'wb') as devnull:
|
with open(os.devnull, 'wb') as devnull:
|
||||||
subprocess.check_call(['adb', 'start-server'], stdout=devnull,
|
subprocess.check_call([adb_path, 'start-server'], stdout=devnull,
|
||||||
stderr=devnull)
|
stderr=devnull)
|
||||||
out = subprocess.check_output(['adb', 'devices']).splitlines()
|
out = subprocess.check_output([adb_path, 'devices']).splitlines()
|
||||||
|
|
||||||
# The first line of `adb devices` just says "List of attached devices", so
|
# The first line of `adb devices` just says "List of attached devices", so
|
||||||
# skip that.
|
# skip that.
|
||||||
@@ -68,21 +68,21 @@ def get_devices():
|
|||||||
return devices
|
return devices
|
||||||
|
|
||||||
|
|
||||||
def _get_unique_device(product=None):
|
def _get_unique_device(product=None, adb_path='adb'):
|
||||||
devices = get_devices()
|
devices = get_devices(adb_path=adb_path)
|
||||||
if len(devices) != 1:
|
if len(devices) != 1:
|
||||||
raise NoUniqueDeviceError()
|
raise NoUniqueDeviceError()
|
||||||
return AndroidDevice(devices[0], product)
|
return AndroidDevice(devices[0], product, adb_path)
|
||||||
|
|
||||||
|
|
||||||
def _get_device_by_serial(serial, product=None):
|
def _get_device_by_serial(serial, product=None, adb_path='adb'):
|
||||||
for device in get_devices():
|
for device in get_devices(adb_path=adb_path):
|
||||||
if device == serial:
|
if device == serial:
|
||||||
return AndroidDevice(serial, product)
|
return AndroidDevice(serial, product, adb_path)
|
||||||
raise DeviceNotFoundError(serial)
|
raise DeviceNotFoundError(serial)
|
||||||
|
|
||||||
|
|
||||||
def get_device(serial=None, product=None):
|
def get_device(serial=None, product=None, adb_path='adb'):
|
||||||
"""Get a uniquely identified AndroidDevice if one is available.
|
"""Get a uniquely identified AndroidDevice if one is available.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -104,29 +104,29 @@ def get_device(serial=None, product=None):
|
|||||||
3) The single device connnected to the system.
|
3) The single device connnected to the system.
|
||||||
"""
|
"""
|
||||||
if serial is not None:
|
if serial is not None:
|
||||||
return _get_device_by_serial(serial, product)
|
return _get_device_by_serial(serial, product, adb_path)
|
||||||
|
|
||||||
android_serial = os.getenv('ANDROID_SERIAL')
|
android_serial = os.getenv('ANDROID_SERIAL')
|
||||||
if android_serial is not None:
|
if android_serial is not None:
|
||||||
return _get_device_by_serial(android_serial, product)
|
return _get_device_by_serial(android_serial, product, adb_path)
|
||||||
|
|
||||||
return _get_unique_device(product)
|
return _get_unique_device(product, adb_path=adb_path)
|
||||||
|
|
||||||
|
|
||||||
def _get_device_by_type(flag):
|
def _get_device_by_type(flag, adb_path):
|
||||||
with open(os.devnull, 'wb') as devnull:
|
with open(os.devnull, 'wb') as devnull:
|
||||||
subprocess.check_call(['adb', 'start-server'], stdout=devnull,
|
subprocess.check_call([adb_path, 'start-server'], stdout=devnull,
|
||||||
stderr=devnull)
|
stderr=devnull)
|
||||||
try:
|
try:
|
||||||
serial = subprocess.check_output(['adb', flag, 'get-serialno']).strip()
|
serial = subprocess.check_output([adb_path, flag, 'get-serialno']).strip()
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
raise RuntimeError('adb unexpectedly returned nonzero')
|
raise RuntimeError('adb unexpectedly returned nonzero')
|
||||||
if serial == 'unknown':
|
if serial == 'unknown':
|
||||||
raise NoUniqueDeviceError()
|
raise NoUniqueDeviceError()
|
||||||
return _get_device_by_serial(serial)
|
return _get_device_by_serial(serial, adb_path=adb_path)
|
||||||
|
|
||||||
|
|
||||||
def get_usb_device():
|
def get_usb_device(adb_path='adb'):
|
||||||
"""Get the unique USB-connected AndroidDevice if it is available.
|
"""Get the unique USB-connected AndroidDevice if it is available.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -136,10 +136,10 @@ def get_usb_device():
|
|||||||
Returns:
|
Returns:
|
||||||
An AndroidDevice associated with the unique USB-connected device.
|
An AndroidDevice associated with the unique USB-connected device.
|
||||||
"""
|
"""
|
||||||
return _get_device_by_type('-d')
|
return _get_device_by_type('-d', adb_path=adb_path)
|
||||||
|
|
||||||
|
|
||||||
def get_emulator_device():
|
def get_emulator_device(adb_path='adb'):
|
||||||
"""Get the unique emulator AndroidDevice if it is available.
|
"""Get the unique emulator AndroidDevice if it is available.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@@ -149,7 +149,7 @@ def get_emulator_device():
|
|||||||
Returns:
|
Returns:
|
||||||
An AndroidDevice associated with the unique running emulator.
|
An AndroidDevice associated with the unique running emulator.
|
||||||
"""
|
"""
|
||||||
return _get_device_by_type('-e')
|
return _get_device_by_type('-e', adb_path=adb_path)
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
@@ -248,10 +248,11 @@ class AndroidDevice(object):
|
|||||||
# Feature name strings.
|
# Feature name strings.
|
||||||
SHELL_PROTOCOL_FEATURE = 'shell_v2'
|
SHELL_PROTOCOL_FEATURE = 'shell_v2'
|
||||||
|
|
||||||
def __init__(self, serial, product=None):
|
def __init__(self, serial, product=None, adb_path='adb'):
|
||||||
self.serial = serial
|
self.serial = serial
|
||||||
self.product = product
|
self.product = product
|
||||||
self.adb_cmd = ['adb']
|
self.adb_cmd = [adb_path]
|
||||||
|
|
||||||
if self.serial is not None:
|
if self.serial is not None:
|
||||||
self.adb_cmd.extend(['-s', serial])
|
self.adb_cmd.extend(['-s', serial])
|
||||||
if self.product is not None:
|
if self.product is not None:
|
||||||
|
|||||||
@@ -21,49 +21,57 @@ import argparse
|
|||||||
import atexit
|
import atexit
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
class ArgumentParser(argparse.ArgumentParser):
|
class ArgumentParser(argparse.ArgumentParser):
|
||||||
"""ArgumentParser subclass that provides adb device selection."""
|
"""ArgumentParser subclass that provides adb device selection."""
|
||||||
|
|
||||||
class DeviceAction(argparse.Action):
|
|
||||||
def __call__(self, parser, namespace, values, option_string=None):
|
|
||||||
if option_string is None:
|
|
||||||
raise RuntimeError("DeviceAction called without option_string")
|
|
||||||
elif option_string == "-a":
|
|
||||||
# Handled in parse_args
|
|
||||||
return
|
|
||||||
elif option_string == "-d":
|
|
||||||
namespace.device = adb.get_usb_device()
|
|
||||||
elif option_string == "-e":
|
|
||||||
namespace.device = adb.get_emulator_device()
|
|
||||||
elif option_string == "-s":
|
|
||||||
namespace.device = adb.get_device(values[0])
|
|
||||||
else:
|
|
||||||
raise RuntimeError("Unexpected flag {}".format(option_string))
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ArgumentParser, self).__init__()
|
super(ArgumentParser, self).__init__()
|
||||||
|
self.add_argument(
|
||||||
|
"--adb", dest="adb_path",
|
||||||
|
help="Use specific adb command")
|
||||||
|
|
||||||
group = self.add_argument_group(title="device selection")
|
group = self.add_argument_group(title="device selection")
|
||||||
group = group.add_mutually_exclusive_group()
|
group = group.add_mutually_exclusive_group()
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"-a", nargs=0, action=self.DeviceAction,
|
"-a", action="store_const", dest="device", const="-a",
|
||||||
help="directs commands to all interfaces")
|
help="directs commands to all interfaces")
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"-d", nargs=0, action=self.DeviceAction,
|
"-d", action="store_const", dest="device", const="-d",
|
||||||
help="directs commands to the only connected USB device")
|
help="directs commands to the only connected USB device")
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"-e", nargs=0, action=self.DeviceAction,
|
"-e", action="store_const", dest="device", const="-e",
|
||||||
help="directs commands to the only connected emulator")
|
help="directs commands to the only connected emulator")
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"-s", nargs=1, metavar="SERIAL", action=self.DeviceAction,
|
"-s", metavar="SERIAL", action="store", dest="serial",
|
||||||
help="directs commands to device/emulator with the given serial")
|
help="directs commands to device/emulator with the given serial")
|
||||||
|
|
||||||
def parse_args(self, args=None, namespace=None):
|
def parse_args(self, args=None, namespace=None):
|
||||||
result = super(ArgumentParser, self).parse_args(args, namespace)
|
result = super(ArgumentParser, self).parse_args(args, namespace)
|
||||||
# Default to -a behavior if no flags are given.
|
|
||||||
if "device" not in result:
|
adb_path = result.adb_path or "adb"
|
||||||
result.device = adb.get_device()
|
|
||||||
|
# Try to run the specified adb command
|
||||||
|
try:
|
||||||
|
subprocess.check_output([adb_path, "version"],
|
||||||
|
stderr=subprocess.STDOUT)
|
||||||
|
except (OSError, subprocess.CalledProcessError):
|
||||||
|
msg = "ERROR: Unable to run adb executable (tried '{}')."
|
||||||
|
if not result.adb_path:
|
||||||
|
msg += "\n Try specifying its location with --adb."
|
||||||
|
sys.exit(msg.format(adb_path))
|
||||||
|
|
||||||
|
if result.device == "-a":
|
||||||
|
result.device = adb.get_device(adb_path=adb_path)
|
||||||
|
elif result.device == "-d":
|
||||||
|
result.device = adb.get_usb_device(adb_path=adb_path)
|
||||||
|
elif result.device == "-e":
|
||||||
|
result.device = adb.get_emulator_device(adb_path=adb_path)
|
||||||
|
else:
|
||||||
|
result.device = adb.get_device(result.serial, adb_path=adb_path)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user