1# Copyright (C) 2022 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15load("@bazel_skylib//lib:paths.bzl", "paths") 16 17# Arch to ABI map 18_arch_abi_map = { 19 "arm": "armeabi-v7a", 20 "arm64": "arm64-v8a", 21 "x86": "x86", 22 "x86_64": "x86_64", 23} 24 25def _proto_convert(actions, name, aapt2, apex_file): 26 """Run 'aapt2 convert' to convert resource files to protobuf format.""" 27 28 root, ext = paths.split_extension(apex_file.basename) 29 output_file = actions.declare_file(paths.join( 30 name, 31 root + ".pb" + ext, 32 )) 33 34 # Arguments 35 args = actions.args() 36 args.add("convert") 37 args.add("--output-format", "proto") 38 args.add(apex_file) 39 args.add("-o", output_file) 40 41 actions.run( 42 inputs = [apex_file], 43 outputs = [output_file], 44 executable = aapt2, 45 arguments = [args], 46 mnemonic = "ApexProtoConvert", 47 ) 48 return output_file 49 50def _base_file(actions, name, zip2zip, arch, secondary_arch, apex_proto_file): 51 """Transforms the apex file to the expected directory structure with all files that will be included in the base module of aab file.""" 52 53 output_file = actions.declare_file(name + "-base.zip") 54 55 # Arguments 56 args = actions.args() 57 args.add("-i", apex_proto_file) 58 args.add("-o", output_file) 59 abi = _arch_abi_map[arch] 60 if secondary_arch: 61 abi += "." + _arch_abi_map[secondary_arch] 62 args.add_all([ 63 "apex_payload.img:apex/%s.img" % abi, 64 "apex_build_info.pb:apex/%s.build_info.pb" % abi, 65 "apex_manifest.json:root/apex_manifest.json", 66 "apex_manifest.pb:root/apex_manifest.pb", 67 "AndroidManifest.xml:manifest/AndroidManifest.xml", 68 "assets/NOTICE.html.gz:assets/NOTICE.html.gz", 69 ]) 70 71 actions.run( 72 inputs = [apex_proto_file], 73 outputs = [output_file], 74 executable = zip2zip, 75 arguments = [args], 76 mnemonic = "ApexBaseFile", 77 ) 78 return output_file 79 80def build_bundle_config(actions, name): 81 """Create bundle_config.json as configuration for running bundletool. 82 83 Args: 84 actions: ctx.actions from a rule, used to declare outputs and actions. 85 name: name of target creating action 86 Returns: 87 The bundle_config.json file 88 """ 89 file_content = { 90 # TODO(b/257459237): Config should collect manifest names and paths of android apps if their manifest name is overridden. 91 "apex_config": {}, 92 "compression": { 93 "uncompressed_glob": [ 94 "apex_payload.img", 95 "apex_manifest.*", 96 ], 97 }, 98 } 99 bundle_config_file = actions.declare_file(paths.join(name, "bundle_config.json")) 100 101 actions.write(bundle_config_file, json.encode(file_content)) 102 103 return bundle_config_file 104 105def _merge_apex_zip_with_config(actions, name, soong_zip, merge_zips, apex_zip, apex_file): 106 # TODO(): Only used as compatibility with mixed builds 107 bundle_config = build_bundle_config(actions, name) 108 apex_config_zip = actions.declare_file(name + ".config") 109 110 args = actions.args() 111 args.add("-o", apex_config_zip) 112 args.add("-C", bundle_config.dirname) 113 args.add("-f", bundle_config) 114 actions.run( 115 inputs = [bundle_config], 116 outputs = [apex_config_zip], 117 executable = soong_zip, 118 arguments = [args], 119 mnemonic = "ApexBaseConfigZip", 120 ) 121 122 merged_zip = actions.declare_file(apex_file.basename + "-base.zip") 123 merge_args = actions.args() 124 merge_args.add(merged_zip) 125 merge_args.add(apex_zip) 126 merge_args.add(apex_config_zip) 127 actions.run( 128 inputs = [apex_config_zip, apex_zip], 129 outputs = [merged_zip], 130 executable = merge_zips, 131 arguments = [merge_args], 132 mnemonic = "ApexMergeBaseFileAndConfig", 133 ) 134 return merged_zip 135 136def apex_zip_files(actions, name, tools, apex_file, arch, secondary_arch): 137 """Create apex zip files used to create an APEX bundle. 138 139 Args: 140 actions: Actions, ctx.actions from a rule, used to declare outputs and actions. 141 name: string, name of the target creating the action 142 tools: struct containing fields with executables: aapt2, zip2zip, soong_zip, merge_zips 143 apex_file: File, APEX file 144 arch: string, the arch of the target configuration of the target requesting the action 145 Returns: 146 A struct with these fields: 147 apex_only: the regular "base" apex zip 148 apex_with_config: a zipfile that's identical to apex_only, but with the addition of bundle_config.json 149 """ 150 apex_proto = _proto_convert(actions, name, tools.aapt2, apex_file) 151 apex_zip = _base_file(actions, name, tools.zip2zip, arch, secondary_arch, apex_proto) 152 merged_zip = _merge_apex_zip_with_config(actions, name, tools.soong_zip, tools.merge_zips, apex_zip, apex_file) 153 154 return struct( 155 apex_only = apex_zip, 156 apex_with_config = merged_zip, 157 ) 158