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