1# Copyright 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import os
6
7from devil import devil_env
8from devil.android import device_denylist
9from devil.android import device_errors
10from devil.android import device_utils
11
12
13def AddEnvironmentArguments(parser):
14  """Adds environment-specific arguments to the provided parser.
15
16  After adding these arguments, you must pass the user-specified values when
17  initializing devil. See the InitializeEnvironment() to determine how to do so.
18
19  Args:
20    parser: an instance of argparse.ArgumentParser
21  """
22  parser.add_argument(
23      '--adb-path', type=os.path.realpath, help='Path to the adb binary')
24
25
26def InitializeEnvironment(args):
27  """Initializes devil based on the args added by AddEnvironmentArguments().
28
29  This initializes devil, and configures it to use the adb binary specified by
30  the '--adb-path' flag (if provided by the user, otherwise this defaults to
31  devil's copy of adb). Although this is one possible way to initialize devil,
32  you should check if your project has prefered ways to initialize devil (ex.
33  the chromium project uses devil_chromium.Initialize() to have different
34  defaults for dependencies).
35
36  This method requires having previously called AddEnvironmentArguments() on the
37  relevant argparse.ArgumentParser.
38
39  Note: you should only initialize devil once, and subsequent calls to any
40  method wrapping devil_env.config.Initialize() will have no effect.
41
42  Args:
43    args: the parsed args returned by an argparse.ArgumentParser
44  """
45  devil_dynamic_config = devil_env.EmptyConfig()
46  if args.adb_path:
47    devil_dynamic_config['dependencies'].update(
48        devil_env.LocalConfigItem('adb', devil_env.GetPlatform(),
49                                  args.adb_path))
50
51  devil_env.config.Initialize(configs=[devil_dynamic_config])
52
53
54def AddDeviceArguments(parser):
55  """Adds device and denylist arguments to the provided parser.
56
57  Args:
58    parser: an instance of argparse.ArgumentParser
59  """
60  parser.add_argument(
61      '-d',
62      '--device',
63      dest='devices',
64      action='append',
65      default=[],
66      help='Serial number of the Android device to use. (default: use all)')
67
68  parser.add_argument('--denylist-file',
69                      help='Device denylist JSON file.')
70
71
72def GetDevices(requested_devices, denylist_file):
73  """Gets a list of healthy devices matching the given parameters."""
74  if not isinstance(denylist_file, device_denylist.Denylist):
75    denylist_file = (device_denylist.Denylist(denylist_file)
76                     if denylist_file else None)
77
78  devices = device_utils.DeviceUtils.HealthyDevices(denylist_file)
79  if not devices:
80    raise device_errors.NoDevicesError()
81  elif requested_devices:
82    requested = set(requested_devices)
83    available = set(str(d) for d in devices)
84    missing = requested.difference(available)
85    if missing:
86      raise device_errors.DeviceUnreachableError(next(iter(missing)))
87    return sorted(
88        device_utils.DeviceUtils(d) for d in available.intersection(requested))
89  else:
90    return devices
91