Rename GetIconID to GetIconId
[chromium-blink-merge.git] / build / android / incremental_install.py
blob9020607adff84c62a76a93348aa9e23b25e4aefd
1 #!/usr/bin/env python
3 # Copyright 2015 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.
7 """Install *_incremental.apk targets as well as their dependent files."""
9 import argparse
10 import glob
11 import logging
12 import os
13 import posixpath
14 import sys
15 import time
17 from devil.android import apk_helper
18 from devil.android import device_utils
19 from devil.android import device_errors
20 from devil.utils import reraiser_thread
21 from pylib import constants
24 def main():
25 start_time = time.time()
26 logging.basicConfig(level=logging.INFO,
27 format='%(asctime)s (%(thread)d) %(message)s')
29 parser = argparse.ArgumentParser()
30 parser.add_argument('apk_path',
31 help='The path to the APK to install.')
32 parser.add_argument('--split',
33 action='append',
34 dest='splits',
35 help='A glob matching the apk splits. '
36 'Can be specified multiple times.')
37 parser.add_argument('--lib-dir',
38 help='Path to native libraries directory.')
39 parser.add_argument('-d', '--device', dest='device',
40 help='Target device for apk to install on.')
41 parser.add_argument('--uninstall',
42 action='store_true',
43 default=False,
44 help='Remove the app and all side-loaded files.')
45 parser.add_argument('--no-threading',
46 action='store_true',
47 default=False,
48 help='Do not install and push concurrently')
50 args = parser.parse_args()
52 constants.SetBuildType('Debug')
54 if args.device:
55 # Retries are annoying when commands fail for legitimate reasons. Might want
56 # to enable them if this is ever used on bots though.
57 device = device_utils.DeviceUtils(args.device, default_retries=0)
58 else:
59 devices = device_utils.DeviceUtils.HealthyDevices(default_retries=0)
60 if not devices:
61 raise device_errors.NoDevicesError()
62 elif len(devices) == 1:
63 device = devices[0]
64 else:
65 all_devices = device_utils.DeviceUtils.parallel(devices)
66 msg = ('More than one device available.\n'
67 'Use --device=SERIAL to select a device.\n'
68 'Available devices:\n')
69 descriptions = all_devices.pMap(lambda d: d.build_description).pGet(None)
70 for d, desc in zip(devices, descriptions):
71 msg += ' %s (%s)\n' % (d, desc)
72 raise Exception(msg)
74 apk_package = apk_helper.ApkHelper(args.apk_path).GetPackageName()
75 device_incremental_dir = '/data/local/tmp/incremental-app-%s' % apk_package
77 if args.uninstall:
78 logging.info('Uninstalling .apk')
79 device.Uninstall(apk_package)
80 logging.info('Removing side-loaded files')
81 device.RunShellCommand(['rm', '-rf', device_incremental_dir],
82 check_return=True)
83 return
85 # Install .apk(s) if any of them have changed.
86 def do_install():
87 if args.splits:
88 splits = []
89 for split_glob in args.splits:
90 splits.extend((f for f in glob.glob(split_glob)))
91 device.InstallSplitApk(args.apk_path, splits, reinstall=True,
92 allow_cached_props=True)
93 else:
94 device.Install(args.apk_path, reinstall=True)
96 # Push .so files to the device (if they have changed).
97 def do_push_libs():
98 if args.lib_dir:
99 device_lib_dir = posixpath.join(device_incremental_dir, 'lib')
100 device.PushChangedFiles([(args.lib_dir, device_lib_dir)],
101 delete_device_stale=True)
102 # Concurrency here speeds things up quite a bit, but DeviceUtils hasn't
103 # been designed for multi-threading. Enabling only because this is a
104 # developer-only tool.
105 if args.no_threading:
106 do_install()
107 do_push_libs()
108 else:
109 reraiser_thread.RunAsync((do_install, do_push_libs))
110 logging.info('Took %s seconds' % round(time.time() - start_time, 1))
113 if __name__ == '__main__':
114 sys.exit(main())