|  | #!/usr/bin/env python | 
|  | # | 
|  | # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | """Utility script to install APKs from the command line quickly.""" | 
|  |  | 
|  | import argparse | 
|  | import glob | 
|  | import logging | 
|  | import os | 
|  | import sys | 
|  |  | 
|  | from pylib import constants | 
|  | from pylib.device import device_blacklist | 
|  | from pylib.device import device_errors | 
|  | from pylib.device import device_utils | 
|  | from pylib.utils import apk_helper | 
|  | from pylib.utils import run_tests_helper | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | parser = argparse.ArgumentParser() | 
|  |  | 
|  | apk_group = parser.add_mutually_exclusive_group(required=True) | 
|  | apk_group.add_argument('--apk', dest='apk_name', | 
|  | help='DEPRECATED The name of the apk containing the' | 
|  | ' application (with the .apk extension).') | 
|  | apk_group.add_argument('apk_path', nargs='?', | 
|  | help='The path to the APK to install.') | 
|  |  | 
|  | # TODO(jbudorick): Remove once no clients pass --apk_package | 
|  | parser.add_argument('--apk_package', help='DEPRECATED unused') | 
|  | parser.add_argument('--split', | 
|  | action='append', | 
|  | dest='splits', | 
|  | help='A glob matching the apk splits. ' | 
|  | 'Can be specified multiple times.') | 
|  | parser.add_argument('--keep_data', | 
|  | action='store_true', | 
|  | default=False, | 
|  | help='Keep the package data when installing ' | 
|  | 'the application.') | 
|  | parser.add_argument('--debug', action='store_const', const='Debug', | 
|  | dest='build_type', | 
|  | default=os.environ.get('BUILDTYPE', 'Debug'), | 
|  | help='If set, run test suites under out/Debug. ' | 
|  | 'Default is env var BUILDTYPE or Debug') | 
|  | parser.add_argument('--release', action='store_const', const='Release', | 
|  | dest='build_type', | 
|  | help='If set, run test suites under out/Release. ' | 
|  | 'Default is env var BUILDTYPE or Debug.') | 
|  | parser.add_argument('-d', '--device', dest='device', | 
|  | help='Target device for apk to install on.') | 
|  | parser.add_argument('-v', '--verbose', action='count', | 
|  | help='Enable verbose logging.') | 
|  |  | 
|  | args = parser.parse_args() | 
|  |  | 
|  | run_tests_helper.SetLogLevel(args.verbose) | 
|  | constants.SetBuildType(args.build_type) | 
|  |  | 
|  | apk = args.apk_path or args.apk_name | 
|  | if not apk.endswith('.apk'): | 
|  | apk += '.apk' | 
|  | if not os.path.exists(apk): | 
|  | apk = os.path.join(constants.GetOutDirectory(), 'apks', apk) | 
|  | if not os.path.exists(apk): | 
|  | parser.error('%s not found.' % apk) | 
|  |  | 
|  | if args.splits: | 
|  | splits = [] | 
|  | base_apk_package = apk_helper.ApkHelper(apk).GetPackageName() | 
|  | for split_glob in args.splits: | 
|  | apks = [f for f in glob.glob(split_glob) if f.endswith('.apk')] | 
|  | if not apks: | 
|  | logging.warning('No apks matched for %s.' % split_glob) | 
|  | for f in apks: | 
|  | helper = apk_helper.ApkHelper(f) | 
|  | if (helper.GetPackageName() == base_apk_package | 
|  | and helper.GetSplitName()): | 
|  | splits.append(f) | 
|  |  | 
|  | devices = device_utils.DeviceUtils.HealthyDevices() | 
|  |  | 
|  | if args.device: | 
|  | devices = [d for d in devices if d == args.device] | 
|  | if not devices: | 
|  | raise device_errors.DeviceUnreachableError(args.device) | 
|  | elif not devices: | 
|  | raise device_errors.NoDevicesError() | 
|  |  | 
|  | def blacklisting_install(device): | 
|  | try: | 
|  | if args.splits: | 
|  | device.InstallSplitApk(apk, splits, reinstall=args.keep_data) | 
|  | else: | 
|  | device.Install(apk, reinstall=args.keep_data) | 
|  | except device_errors.CommandFailedError: | 
|  | logging.exception('Failed to install %s', args.apk_name) | 
|  | device_blacklist.ExtendBlacklist([str(device)]) | 
|  | logging.warning('Blacklisting %s', str(device)) | 
|  | except device_errors.CommandTimeoutError: | 
|  | logging.exception('Timed out while installing %s', args.apk_name) | 
|  | device_blacklist.ExtendBlacklist([str(device)]) | 
|  | logging.warning('Blacklisting %s', str(device)) | 
|  |  | 
|  | device_utils.DeviceUtils.parallel(devices).pMap(blacklisting_install) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(main()) | 
|  |  |