xref: /aosp_15_r20/external/cronet/build/android/gyp/optimize_resources.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6777b538SAndroid Build Coastguard Worker#
3*6777b538SAndroid Build Coastguard Worker# Copyright 2021 The Chromium Authors
4*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
5*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Workerimport argparse
8*6777b538SAndroid Build Coastguard Workerimport logging
9*6777b538SAndroid Build Coastguard Workerimport os
10*6777b538SAndroid Build Coastguard Workerimport sys
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Workerfrom util import build_utils
13*6777b538SAndroid Build Coastguard Workerimport action_helpers  # build_utils adds //build to sys.path.
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Workerdef _ParseArgs(args):
17*6777b538SAndroid Build Coastguard Worker  """Parses command line options.
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker  Returns:
20*6777b538SAndroid Build Coastguard Worker    An options object as from argparse.ArgumentParser.parse_args()
21*6777b538SAndroid Build Coastguard Worker  """
22*6777b538SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
23*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--aapt2-path',
24*6777b538SAndroid Build Coastguard Worker                      required=True,
25*6777b538SAndroid Build Coastguard Worker                      help='Path to the Android aapt2 tool.')
26*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
27*6777b538SAndroid Build Coastguard Worker      '--short-resource-paths',
28*6777b538SAndroid Build Coastguard Worker      action='store_true',
29*6777b538SAndroid Build Coastguard Worker      help='Whether to shorten resource paths inside the apk or module.')
30*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
31*6777b538SAndroid Build Coastguard Worker      '--strip-resource-names',
32*6777b538SAndroid Build Coastguard Worker      action='store_true',
33*6777b538SAndroid Build Coastguard Worker      help='Whether to strip resource names from the resource table of the apk '
34*6777b538SAndroid Build Coastguard Worker      'or module.')
35*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--proto-path',
36*6777b538SAndroid Build Coastguard Worker                      required=True,
37*6777b538SAndroid Build Coastguard Worker                      help='Input proto format resources APK.')
38*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--resources-config-paths',
39*6777b538SAndroid Build Coastguard Worker                      default='[]',
40*6777b538SAndroid Build Coastguard Worker                      help='GN list of paths to aapt2 resources config files.')
41*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--r-text-in',
42*6777b538SAndroid Build Coastguard Worker                      required=True,
43*6777b538SAndroid Build Coastguard Worker                      help='Path to R.txt. Used to exclude id/ resources.')
44*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
45*6777b538SAndroid Build Coastguard Worker      '--resources-path-map-out-path',
46*6777b538SAndroid Build Coastguard Worker      help='Path to file produced by aapt2 that maps original resource paths '
47*6777b538SAndroid Build Coastguard Worker      'to shortened resource paths inside the apk or module.')
48*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--optimized-proto-path',
49*6777b538SAndroid Build Coastguard Worker                      required=True,
50*6777b538SAndroid Build Coastguard Worker                      help='Output for `aapt2 optimize`.')
51*6777b538SAndroid Build Coastguard Worker  options = parser.parse_args(args)
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker  options.resources_config_paths = action_helpers.parse_gn_list(
54*6777b538SAndroid Build Coastguard Worker      options.resources_config_paths)
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker  if options.resources_path_map_out_path and not options.short_resource_paths:
57*6777b538SAndroid Build Coastguard Worker    parser.error(
58*6777b538SAndroid Build Coastguard Worker        '--resources-path-map-out-path requires --short-resource-paths')
59*6777b538SAndroid Build Coastguard Worker  return options
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Workerdef _CombineResourceConfigs(resources_config_paths, out_config_path):
63*6777b538SAndroid Build Coastguard Worker  with open(out_config_path, 'w') as out_config:
64*6777b538SAndroid Build Coastguard Worker    for config_path in resources_config_paths:
65*6777b538SAndroid Build Coastguard Worker      with open(config_path) as config:
66*6777b538SAndroid Build Coastguard Worker        out_config.write(config.read())
67*6777b538SAndroid Build Coastguard Worker        out_config.write('\n')
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Workerdef _ExtractNonCollapsableResources(rtxt_path):
71*6777b538SAndroid Build Coastguard Worker  """Extract resources that should not be collapsed from the R.txt file
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker  Resources of type ID are references to UI elements/views. They are used by
74*6777b538SAndroid Build Coastguard Worker  UI automation testing frameworks. They are kept in so that they don't break
75*6777b538SAndroid Build Coastguard Worker  tests, even though they may not actually be used during runtime. See
76*6777b538SAndroid Build Coastguard Worker  https://crbug.com/900993
77*6777b538SAndroid Build Coastguard Worker  App icons (aka mipmaps) are sometimes referenced by other apps by name so must
78*6777b538SAndroid Build Coastguard Worker  be keps as well. See https://b/161564466
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker  Args:
81*6777b538SAndroid Build Coastguard Worker    rtxt_path: Path to R.txt file with all the resources
82*6777b538SAndroid Build Coastguard Worker  Returns:
83*6777b538SAndroid Build Coastguard Worker    List of resources in the form of <resource_type>/<resource_name>
84*6777b538SAndroid Build Coastguard Worker  """
85*6777b538SAndroid Build Coastguard Worker  resources = []
86*6777b538SAndroid Build Coastguard Worker  _NO_COLLAPSE_TYPES = ['id', 'mipmap']
87*6777b538SAndroid Build Coastguard Worker  with open(rtxt_path) as rtxt:
88*6777b538SAndroid Build Coastguard Worker    for line in rtxt:
89*6777b538SAndroid Build Coastguard Worker      for resource_type in _NO_COLLAPSE_TYPES:
90*6777b538SAndroid Build Coastguard Worker        if ' {} '.format(resource_type) in line:
91*6777b538SAndroid Build Coastguard Worker          resource_name = line.split()[2]
92*6777b538SAndroid Build Coastguard Worker          resources.append('{}/{}'.format(resource_type, resource_name))
93*6777b538SAndroid Build Coastguard Worker  return resources
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Workerdef _OptimizeApk(output, options, temp_dir, unoptimized_path, r_txt_path):
97*6777b538SAndroid Build Coastguard Worker  """Optimize intermediate .ap_ file with aapt2.
98*6777b538SAndroid Build Coastguard Worker
99*6777b538SAndroid Build Coastguard Worker  Args:
100*6777b538SAndroid Build Coastguard Worker    output: Path to write to.
101*6777b538SAndroid Build Coastguard Worker    options: The command-line options.
102*6777b538SAndroid Build Coastguard Worker    temp_dir: A temporary directory.
103*6777b538SAndroid Build Coastguard Worker    unoptimized_path: path of the apk to optimize.
104*6777b538SAndroid Build Coastguard Worker    r_txt_path: path to the R.txt file of the unoptimized apk.
105*6777b538SAndroid Build Coastguard Worker  """
106*6777b538SAndroid Build Coastguard Worker  optimize_command = [
107*6777b538SAndroid Build Coastguard Worker      options.aapt2_path,
108*6777b538SAndroid Build Coastguard Worker      'optimize',
109*6777b538SAndroid Build Coastguard Worker      unoptimized_path,
110*6777b538SAndroid Build Coastguard Worker      '-o',
111*6777b538SAndroid Build Coastguard Worker      output,
112*6777b538SAndroid Build Coastguard Worker  ]
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker  # Optimize the resources.pb file by obfuscating resource names and only
115*6777b538SAndroid Build Coastguard Worker  # allow usage via R.java constant.
116*6777b538SAndroid Build Coastguard Worker  if options.strip_resource_names:
117*6777b538SAndroid Build Coastguard Worker    no_collapse_resources = _ExtractNonCollapsableResources(r_txt_path)
118*6777b538SAndroid Build Coastguard Worker    gen_config_path = os.path.join(temp_dir, 'aapt2.config')
119*6777b538SAndroid Build Coastguard Worker    if options.resources_config_paths:
120*6777b538SAndroid Build Coastguard Worker      _CombineResourceConfigs(options.resources_config_paths, gen_config_path)
121*6777b538SAndroid Build Coastguard Worker    with open(gen_config_path, 'a') as config:
122*6777b538SAndroid Build Coastguard Worker      for resource in no_collapse_resources:
123*6777b538SAndroid Build Coastguard Worker        config.write('{}#no_collapse\n'.format(resource))
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker    optimize_command += [
126*6777b538SAndroid Build Coastguard Worker        '--collapse-resource-names',
127*6777b538SAndroid Build Coastguard Worker        '--resources-config-path',
128*6777b538SAndroid Build Coastguard Worker        gen_config_path,
129*6777b538SAndroid Build Coastguard Worker    ]
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker  if options.short_resource_paths:
132*6777b538SAndroid Build Coastguard Worker    optimize_command += ['--shorten-resource-paths']
133*6777b538SAndroid Build Coastguard Worker  if options.resources_path_map_out_path:
134*6777b538SAndroid Build Coastguard Worker    optimize_command += [
135*6777b538SAndroid Build Coastguard Worker        '--resource-path-shortening-map', options.resources_path_map_out_path
136*6777b538SAndroid Build Coastguard Worker    ]
137*6777b538SAndroid Build Coastguard Worker
138*6777b538SAndroid Build Coastguard Worker  logging.debug('Running aapt2 optimize')
139*6777b538SAndroid Build Coastguard Worker  build_utils.CheckOutput(optimize_command,
140*6777b538SAndroid Build Coastguard Worker                          print_stdout=False,
141*6777b538SAndroid Build Coastguard Worker                          print_stderr=False)
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Workerdef main(args):
145*6777b538SAndroid Build Coastguard Worker  options = _ParseArgs(args)
146*6777b538SAndroid Build Coastguard Worker  with build_utils.TempDir() as temp_dir:
147*6777b538SAndroid Build Coastguard Worker    _OptimizeApk(options.optimized_proto_path, options, temp_dir,
148*6777b538SAndroid Build Coastguard Worker                 options.proto_path, options.r_text_in)
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker
151*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__':
152*6777b538SAndroid Build Coastguard Worker  main(sys.argv[1:])
153