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