blob: bc55bf88b456dfe35123647c6739395e470fe3b8 [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001#!/usr/bin/env python
2#
3# Copyright (c) 2012 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Utility script to install APKs from the command line quickly."""
8
9import argparse
10import glob
11import logging
12import os
13import sys
14
15import devil_chromium
16from devil import devil_env
17from devil.android import apk_helper
18from devil.android import device_blacklist
19from devil.android import device_errors
20from devil.android import device_utils
21from devil.utils import run_tests_helper
22from pylib import constants
23
24
25def main():
26 parser = argparse.ArgumentParser()
27
28 apk_group = parser.add_mutually_exclusive_group(required=True)
29 apk_group.add_argument('--apk', dest='apk_name',
30 help='DEPRECATED The name of the apk containing the'
31 ' application (with the .apk extension).')
32 apk_group.add_argument('apk_path', nargs='?',
33 help='The path to the APK to install.')
34
35 # TODO(jbudorick): Remove once no clients pass --apk_package
36 parser.add_argument('--apk_package', help='DEPRECATED unused')
37 parser.add_argument('--split',
38 action='append',
39 dest='splits',
40 help='A glob matching the apk splits. '
41 'Can be specified multiple times.')
42 parser.add_argument('--keep_data',
43 action='store_true',
44 default=False,
45 help='Keep the package data when installing '
46 'the application.')
47 parser.add_argument('--debug', action='store_const', const='Debug',
48 dest='build_type',
49 default=os.environ.get('BUILDTYPE', 'Debug'),
50 help='If set, run test suites under out/Debug. '
51 'Default is env var BUILDTYPE or Debug')
52 parser.add_argument('--release', action='store_const', const='Release',
53 dest='build_type',
54 help='If set, run test suites under out/Release. '
55 'Default is env var BUILDTYPE or Debug.')
56 parser.add_argument('-d', '--device', dest='devices', action='append',
57 default=[],
58 help='Target device for apk to install on. Enter multiple'
59 ' times for multiple devices.')
60 parser.add_argument('--adb-path',
61 help='Absolute path to the adb binary to use.')
62 parser.add_argument('--blacklist-file', help='Device blacklist JSON file.')
63 parser.add_argument('-v', '--verbose', action='count',
64 help='Enable verbose logging.')
65 parser.add_argument('--downgrade', action='store_true',
66 help='If set, allows downgrading of apk.')
67 parser.add_argument('--timeout', type=int,
68 default=device_utils.DeviceUtils.INSTALL_DEFAULT_TIMEOUT,
69 help='Seconds to wait for APK installation. '
70 '(default: %(default)s)')
71
72 args = parser.parse_args()
73
74 run_tests_helper.SetLogLevel(args.verbose)
75 constants.SetBuildType(args.build_type)
76
77 devil_custom_deps = None
78 if args.adb_path:
79 devil_custom_deps = {
80 'adb': {
81 devil_env.GetPlatform(): [args.adb_path],
82 },
83 }
84
85 devil_chromium.Initialize(
86 output_directory=constants.GetOutDirectory(),
87 custom_deps=devil_custom_deps)
88
89 apk = args.apk_path or args.apk_name
90 if not apk.endswith('.apk'):
91 apk += '.apk'
92 if not os.path.exists(apk):
93 apk = os.path.join(constants.GetOutDirectory(), 'apks', apk)
94 if not os.path.exists(apk):
95 parser.error('%s not found.' % apk)
96
97 if args.splits:
98 splits = []
99 base_apk_package = apk_helper.ApkHelper(apk).GetPackageName()
100 for split_glob in args.splits:
101 apks = [f for f in glob.glob(split_glob) if f.endswith('.apk')]
102 if not apks:
103 logging.warning('No apks matched for %s.', split_glob)
104 for f in apks:
105 helper = apk_helper.ApkHelper(f)
106 if (helper.GetPackageName() == base_apk_package
107 and helper.GetSplitName()):
108 splits.append(f)
109
110 blacklist = (device_blacklist.Blacklist(args.blacklist_file)
111 if args.blacklist_file
112 else None)
113 devices = device_utils.DeviceUtils.HealthyDevices(blacklist=blacklist,
114 device_arg=args.devices)
115
116 def blacklisting_install(device):
117 try:
118 if args.splits:
119 device.InstallSplitApk(apk, splits, reinstall=args.keep_data,
120 allow_downgrade=args.downgrade)
121 else:
122 device.Install(apk, reinstall=args.keep_data,
123 allow_downgrade=args.downgrade,
124 timeout=args.timeout)
125 except device_errors.CommandFailedError:
126 logging.exception('Failed to install %s', args.apk_name)
127 if blacklist:
128 blacklist.Extend([str(device)], reason='install_failure')
129 logging.warning('Blacklisting %s', str(device))
130 except device_errors.CommandTimeoutError:
131 logging.exception('Timed out while installing %s', args.apk_name)
132 if blacklist:
133 blacklist.Extend([str(device)], reason='install_timeout')
134 logging.warning('Blacklisting %s', str(device))
135
136 device_utils.DeviceUtils.parallel(devices).pMap(blacklisting_install)
137
138
139if __name__ == '__main__':
140 sys.exit(main())
141