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