Home | History | Annotate | Download | only in apex
      1 // Copyright (C) 2018 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 
     15 package apex
     16 
     17 import (
     18 	"fmt"
     19 	"io"
     20 	"path/filepath"
     21 	"runtime"
     22 	"sort"
     23 	"strings"
     24 
     25 	"android/soong/android"
     26 	"android/soong/cc"
     27 	"android/soong/java"
     28 	"android/soong/python"
     29 
     30 	"github.com/google/blueprint"
     31 	"github.com/google/blueprint/bootstrap"
     32 	"github.com/google/blueprint/proptools"
     33 )
     34 
     35 var (
     36 	pctx = android.NewPackageContext("android/apex")
     37 
     38 	// Create a canned fs config file where all files and directories are
     39 	// by default set to (uid/gid/mode) = (1000/1000/0644)
     40 	// TODO(b/113082813) make this configurable using config.fs syntax
     41 	generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
     42 		Command: `echo '/ 1000 1000 0755' > ${out} && ` +
     43 			`echo '/apex_manifest.json 1000 1000 0644' >> ${out} && ` +
     44 			`echo ${ro_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 1000 1000 0644"}' >> ${out} && ` +
     45 			`echo ${exec_paths} | tr ' ' '\n' | awk '{print "/"$$1 " 0 2000 0755"}' >> ${out}`,
     46 		Description: "fs_config ${out}",
     47 	}, "ro_paths", "exec_paths")
     48 
     49 	// TODO(b/113233103): make sure that file_contexts is sane, i.e., validate
     50 	// against the binary policy using sefcontext_compiler -p <policy>.
     51 
     52 	// TODO(b/114327326): automate the generation of file_contexts
     53 	apexRule = pctx.StaticRule("apexRule", blueprint.RuleParams{
     54 		Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
     55 			`(${copy_commands}) && ` +
     56 			`APEXER_TOOL_PATH=${tool_path} ` +
     57 			`${apexer} --force --manifest ${manifest} ` +
     58 			`--file_contexts ${file_contexts} ` +
     59 			`--canned_fs_config ${canned_fs_config} ` +
     60 			`--payload_type image ` +
     61 			`--key ${key} ${opt_flags} ${image_dir} ${out} `,
     62 		CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
     63 			"${mke2fs}", "${resize2fs}", "${sefcontext_compile}",
     64 			"${soong_zip}", "${zipalign}", "${aapt2}"},
     65 		Description: "APEX ${image_dir} => ${out}",
     66 	}, "tool_path", "image_dir", "copy_commands", "manifest", "file_contexts", "canned_fs_config", "key", "opt_flags")
     67 
     68 	zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
     69 		Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
     70 			`(${copy_commands}) && ` +
     71 			`APEXER_TOOL_PATH=${tool_path} ` +
     72 			`${apexer} --force --manifest ${manifest} ` +
     73 			`--payload_type zip ` +
     74 			`${image_dir} ${out} `,
     75 		CommandDeps: []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"},
     76 		Description: "ZipAPEX ${image_dir} => ${out}",
     77 	}, "tool_path", "image_dir", "copy_commands", "manifest")
     78 
     79 	apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule",
     80 		blueprint.RuleParams{
     81 			Command:     `${aapt2} convert --output-format proto $in -o $out`,
     82 			CommandDeps: []string{"${aapt2}"},
     83 		})
     84 
     85 	apexBundleRule = pctx.StaticRule("apexBundleRule", blueprint.RuleParams{
     86 		Command: `${zip2zip} -i $in -o $out ` +
     87 			`apex_payload.img:apex/${abi}.img ` +
     88 			`apex_manifest.json:root/apex_manifest.json ` +
     89 			`AndroidManifest.xml:manifest/AndroidManifest.xml`,
     90 		CommandDeps: []string{"${zip2zip}"},
     91 		Description: "app bundle",
     92 	}, "abi")
     93 )
     94 
     95 var imageApexSuffix = ".apex"
     96 var zipApexSuffix = ".zipapex"
     97 
     98 var imageApexType = "image"
     99 var zipApexType = "zip"
    100 
    101 type dependencyTag struct {
    102 	blueprint.BaseDependencyTag
    103 	name string
    104 }
    105 
    106 var (
    107 	sharedLibTag   = dependencyTag{name: "sharedLib"}
    108 	executableTag  = dependencyTag{name: "executable"}
    109 	javaLibTag     = dependencyTag{name: "javaLib"}
    110 	prebuiltTag    = dependencyTag{name: "prebuilt"}
    111 	keyTag         = dependencyTag{name: "key"}
    112 	certificateTag = dependencyTag{name: "certificate"}
    113 )
    114 
    115 func init() {
    116 	pctx.Import("android/soong/android")
    117 	pctx.Import("android/soong/java")
    118 	pctx.HostBinToolVariable("apexer", "apexer")
    119 	// ART minimal builds (using the master-art manifest) do not have the "frameworks/base"
    120 	// projects, and hence cannot built 'aapt2'. Use the SDK prebuilt instead.
    121 	hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) {
    122 		pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
    123 			if !ctx.Config().FrameworksBaseDirExists(ctx) {
    124 				return filepath.Join(prebuiltDir, runtime.GOOS, "bin", tool)
    125 			} else {
    126 				return pctx.HostBinToolPath(ctx, tool).String()
    127 			}
    128 		})
    129 	}
    130 	hostBinToolVariableWithPrebuilt("aapt2", "prebuilts/sdk/tools", "aapt2")
    131 	pctx.HostBinToolVariable("avbtool", "avbtool")
    132 	pctx.HostBinToolVariable("e2fsdroid", "e2fsdroid")
    133 	pctx.HostBinToolVariable("merge_zips", "merge_zips")
    134 	pctx.HostBinToolVariable("mke2fs", "mke2fs")
    135 	pctx.HostBinToolVariable("resize2fs", "resize2fs")
    136 	pctx.HostBinToolVariable("sefcontext_compile", "sefcontext_compile")
    137 	pctx.HostBinToolVariable("soong_zip", "soong_zip")
    138 	pctx.HostBinToolVariable("zip2zip", "zip2zip")
    139 	pctx.HostBinToolVariable("zipalign", "zipalign")
    140 
    141 	android.RegisterModuleType("apex", apexBundleFactory)
    142 	android.RegisterModuleType("apex_test", testApexBundleFactory)
    143 	android.RegisterModuleType("apex_defaults", defaultsFactory)
    144 	android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
    145 
    146 	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
    147 		ctx.TopDown("apex_deps", apexDepsMutator)
    148 		ctx.BottomUp("apex", apexMutator)
    149 	})
    150 }
    151 
    152 // Mark the direct and transitive dependencies of apex bundles so that they
    153 // can be built for the apex bundles.
    154 func apexDepsMutator(mctx android.TopDownMutatorContext) {
    155 	if a, ok := mctx.Module().(*apexBundle); ok {
    156 		apexBundleName := mctx.ModuleName()
    157 		mctx.WalkDeps(func(child, parent android.Module) bool {
    158 			depName := mctx.OtherModuleName(child)
    159 			// If the parent is apexBundle, this child is directly depended.
    160 			_, directDep := parent.(*apexBundle)
    161 			if a.installable() && !a.testApex {
    162 				// TODO(b/123892969): Workaround for not having any way to annotate test-apexs
    163 				// non-installable apex's cannot be installed and so should not prevent libraries from being
    164 				// installed to the system.
    165 				android.UpdateApexDependency(apexBundleName, depName, directDep)
    166 			}
    167 
    168 			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
    169 				am.BuildForApex(apexBundleName)
    170 				return true
    171 			} else {
    172 				return false
    173 			}
    174 		})
    175 	}
    176 }
    177 
    178 // Create apex variations if a module is included in APEX(s).
    179 func apexMutator(mctx android.BottomUpMutatorContext) {
    180 	if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
    181 		am.CreateApexVariations(mctx)
    182 	} else if _, ok := mctx.Module().(*apexBundle); ok {
    183 		// apex bundle itself is mutated so that it and its modules have same
    184 		// apex variant.
    185 		apexBundleName := mctx.ModuleName()
    186 		mctx.CreateVariations(apexBundleName)
    187 	}
    188 }
    189 
    190 type apexNativeDependencies struct {
    191 	// List of native libraries
    192 	Native_shared_libs []string
    193 	// List of native executables
    194 	Binaries []string
    195 }
    196 type apexMultilibProperties struct {
    197 	// Native dependencies whose compile_multilib is "first"
    198 	First apexNativeDependencies
    199 
    200 	// Native dependencies whose compile_multilib is "both"
    201 	Both apexNativeDependencies
    202 
    203 	// Native dependencies whose compile_multilib is "prefer32"
    204 	Prefer32 apexNativeDependencies
    205 
    206 	// Native dependencies whose compile_multilib is "32"
    207 	Lib32 apexNativeDependencies
    208 
    209 	// Native dependencies whose compile_multilib is "64"
    210 	Lib64 apexNativeDependencies
    211 }
    212 
    213 type apexBundleProperties struct {
    214 	// Json manifest file describing meta info of this APEX bundle. Default:
    215 	// "apex_manifest.json"
    216 	Manifest *string `android:"path"`
    217 
    218 	// AndroidManifest.xml file used for the zip container of this APEX bundle.
    219 	// If unspecified, a default one is automatically generated.
    220 	AndroidManifest *string `android:"path"`
    221 
    222 	// Canonical name of the APEX bundle in the manifest file.
    223 	// If unspecified, defaults to the value of name
    224 	Apex_name *string
    225 
    226 	// Determines the file contexts file for setting security context to each file in this APEX bundle.
    227 	// Specifically, when this is set to <value>, /system/sepolicy/apex/<value>_file_contexts file is
    228 	// used.
    229 	// Default: <name_of_this_module>
    230 	File_contexts *string
    231 
    232 	// List of native shared libs that are embedded inside this APEX bundle
    233 	Native_shared_libs []string
    234 
    235 	// List of native executables that are embedded inside this APEX bundle
    236 	Binaries []string
    237 
    238 	// List of java libraries that are embedded inside this APEX bundle
    239 	Java_libs []string
    240 
    241 	// List of prebuilt files that are embedded inside this APEX bundle
    242 	Prebuilts []string
    243 
    244 	// Name of the apex_key module that provides the private key to sign APEX
    245 	Key *string
    246 
    247 	// The type of APEX to build. Controls what the APEX payload is. Either
    248 	// 'image', 'zip' or 'both'. Default: 'image'.
    249 	Payload_type *string
    250 
    251 	// The name of a certificate in the default certificate directory, blank to use the default product certificate,
    252 	// or an android_app_certificate module name in the form ":module".
    253 	Certificate *string
    254 
    255 	// Whether this APEX is installable to one of the partitions. Default: true.
    256 	Installable *bool
    257 
    258 	// For native libraries and binaries, use the vendor variant instead of the core (platform) variant.
    259 	// Default is false.
    260 	Use_vendor *bool
    261 
    262 	// For telling the apex to ignore special handling for system libraries such as bionic. Default is false.
    263 	Ignore_system_library_special_case *bool
    264 
    265 	Multilib apexMultilibProperties
    266 
    267 	// List of sanitizer names that this APEX is enabled for
    268 	SanitizerNames []string `blueprint:"mutated"`
    269 }
    270 
    271 type apexTargetBundleProperties struct {
    272 	Target struct {
    273 		// Multilib properties only for android.
    274 		Android struct {
    275 			Multilib apexMultilibProperties
    276 		}
    277 		// Multilib properties only for host.
    278 		Host struct {
    279 			Multilib apexMultilibProperties
    280 		}
    281 		// Multilib properties only for host linux_bionic.
    282 		Linux_bionic struct {
    283 			Multilib apexMultilibProperties
    284 		}
    285 		// Multilib properties only for host linux_glibc.
    286 		Linux_glibc struct {
    287 			Multilib apexMultilibProperties
    288 		}
    289 	}
    290 }
    291 
    292 type apexFileClass int
    293 
    294 const (
    295 	etc apexFileClass = iota
    296 	nativeSharedLib
    297 	nativeExecutable
    298 	shBinary
    299 	pyBinary
    300 	goBinary
    301 	javaSharedLib
    302 )
    303 
    304 type apexPackaging int
    305 
    306 const (
    307 	imageApex apexPackaging = iota
    308 	zipApex
    309 	both
    310 )
    311 
    312 func (a apexPackaging) image() bool {
    313 	switch a {
    314 	case imageApex, both:
    315 		return true
    316 	}
    317 	return false
    318 }
    319 
    320 func (a apexPackaging) zip() bool {
    321 	switch a {
    322 	case zipApex, both:
    323 		return true
    324 	}
    325 	return false
    326 }
    327 
    328 func (a apexPackaging) suffix() string {
    329 	switch a {
    330 	case imageApex:
    331 		return imageApexSuffix
    332 	case zipApex:
    333 		return zipApexSuffix
    334 	case both:
    335 		panic(fmt.Errorf("must be either zip or image"))
    336 	default:
    337 		panic(fmt.Errorf("unkonwn APEX type %d", a))
    338 	}
    339 }
    340 
    341 func (a apexPackaging) name() string {
    342 	switch a {
    343 	case imageApex:
    344 		return imageApexType
    345 	case zipApex:
    346 		return zipApexType
    347 	case both:
    348 		panic(fmt.Errorf("must be either zip or image"))
    349 	default:
    350 		panic(fmt.Errorf("unkonwn APEX type %d", a))
    351 	}
    352 }
    353 
    354 func (class apexFileClass) NameInMake() string {
    355 	switch class {
    356 	case etc:
    357 		return "ETC"
    358 	case nativeSharedLib:
    359 		return "SHARED_LIBRARIES"
    360 	case nativeExecutable, shBinary, pyBinary, goBinary:
    361 		return "EXECUTABLES"
    362 	case javaSharedLib:
    363 		return "JAVA_LIBRARIES"
    364 	default:
    365 		panic(fmt.Errorf("unkonwn class %d", class))
    366 	}
    367 }
    368 
    369 type apexFile struct {
    370 	builtFile  android.Path
    371 	moduleName string
    372 	installDir string
    373 	class      apexFileClass
    374 	module     android.Module
    375 	symlinks   []string
    376 }
    377 
    378 type apexBundle struct {
    379 	android.ModuleBase
    380 	android.DefaultableModuleBase
    381 
    382 	properties       apexBundleProperties
    383 	targetProperties apexTargetBundleProperties
    384 
    385 	apexTypes apexPackaging
    386 
    387 	bundleModuleFile android.WritablePath
    388 	outputFiles      map[apexPackaging]android.WritablePath
    389 	installDir       android.OutputPath
    390 
    391 	public_key_file  android.Path
    392 	private_key_file android.Path
    393 
    394 	container_certificate_file android.Path
    395 	container_private_key_file android.Path
    396 
    397 	// list of files to be included in this apex
    398 	filesInfo []apexFile
    399 
    400 	// list of module names that this APEX is depending on
    401 	externalDeps []string
    402 
    403 	flattened bool
    404 
    405 	testApex bool
    406 }
    407 
    408 func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
    409 	native_shared_libs []string, binaries []string, arch string, imageVariation string) {
    410 	// Use *FarVariation* to be able to depend on modules having
    411 	// conflicting variations with this module. This is required since
    412 	// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
    413 	// for native shared libs.
    414 	ctx.AddFarVariationDependencies([]blueprint.Variation{
    415 		{Mutator: "arch", Variation: arch},
    416 		{Mutator: "image", Variation: imageVariation},
    417 		{Mutator: "link", Variation: "shared"},
    418 		{Mutator: "version", Variation: ""}, // "" is the non-stub variant
    419 	}, sharedLibTag, native_shared_libs...)
    420 
    421 	ctx.AddFarVariationDependencies([]blueprint.Variation{
    422 		{Mutator: "arch", Variation: arch},
    423 		{Mutator: "image", Variation: imageVariation},
    424 	}, executableTag, binaries...)
    425 }
    426 
    427 func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
    428 	if ctx.Os().Class == android.Device {
    429 		proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil)
    430 	} else {
    431 		proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Host.Multilib, nil)
    432 		if ctx.Os().Bionic() {
    433 			proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_bionic.Multilib, nil)
    434 		} else {
    435 			proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_glibc.Multilib, nil)
    436 		}
    437 	}
    438 }
    439 
    440 func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
    441 
    442 	targets := ctx.MultiTargets()
    443 	config := ctx.DeviceConfig()
    444 
    445 	a.combineProperties(ctx)
    446 
    447 	has32BitTarget := false
    448 	for _, target := range targets {
    449 		if target.Arch.ArchType.Multilib == "lib32" {
    450 			has32BitTarget = true
    451 		}
    452 	}
    453 	for i, target := range targets {
    454 		// When multilib.* is omitted for native_shared_libs, it implies
    455 		// multilib.both.
    456 		ctx.AddFarVariationDependencies([]blueprint.Variation{
    457 			{Mutator: "arch", Variation: target.String()},
    458 			{Mutator: "image", Variation: a.getImageVariation(config)},
    459 			{Mutator: "link", Variation: "shared"},
    460 		}, sharedLibTag, a.properties.Native_shared_libs...)
    461 
    462 		// Add native modules targetting both ABIs
    463 		addDependenciesForNativeModules(ctx,
    464 			a.properties.Multilib.Both.Native_shared_libs,
    465 			a.properties.Multilib.Both.Binaries, target.String(),
    466 			a.getImageVariation(config))
    467 
    468 		isPrimaryAbi := i == 0
    469 		if isPrimaryAbi {
    470 			// When multilib.* is omitted for binaries, it implies
    471 			// multilib.first.
    472 			ctx.AddFarVariationDependencies([]blueprint.Variation{
    473 				{Mutator: "arch", Variation: target.String()},
    474 				{Mutator: "image", Variation: a.getImageVariation(config)},
    475 			}, executableTag, a.properties.Binaries...)
    476 
    477 			// Add native modules targetting the first ABI
    478 			addDependenciesForNativeModules(ctx,
    479 				a.properties.Multilib.First.Native_shared_libs,
    480 				a.properties.Multilib.First.Binaries, target.String(),
    481 				a.getImageVariation(config))
    482 
    483 			// When multilib.* is omitted for prebuilts, it implies multilib.first.
    484 			ctx.AddFarVariationDependencies([]blueprint.Variation{
    485 				{Mutator: "arch", Variation: target.String()},
    486 			}, prebuiltTag, a.properties.Prebuilts...)
    487 		}
    488 
    489 		switch target.Arch.ArchType.Multilib {
    490 		case "lib32":
    491 			// Add native modules targetting 32-bit ABI
    492 			addDependenciesForNativeModules(ctx,
    493 				a.properties.Multilib.Lib32.Native_shared_libs,
    494 				a.properties.Multilib.Lib32.Binaries, target.String(),
    495 				a.getImageVariation(config))
    496 
    497 			addDependenciesForNativeModules(ctx,
    498 				a.properties.Multilib.Prefer32.Native_shared_libs,
    499 				a.properties.Multilib.Prefer32.Binaries, target.String(),
    500 				a.getImageVariation(config))
    501 		case "lib64":
    502 			// Add native modules targetting 64-bit ABI
    503 			addDependenciesForNativeModules(ctx,
    504 				a.properties.Multilib.Lib64.Native_shared_libs,
    505 				a.properties.Multilib.Lib64.Binaries, target.String(),
    506 				a.getImageVariation(config))
    507 
    508 			if !has32BitTarget {
    509 				addDependenciesForNativeModules(ctx,
    510 					a.properties.Multilib.Prefer32.Native_shared_libs,
    511 					a.properties.Multilib.Prefer32.Binaries, target.String(),
    512 					a.getImageVariation(config))
    513 			}
    514 		}
    515 
    516 	}
    517 
    518 	ctx.AddFarVariationDependencies([]blueprint.Variation{
    519 		{Mutator: "arch", Variation: "android_common"},
    520 	}, javaLibTag, a.properties.Java_libs...)
    521 
    522 	if String(a.properties.Key) == "" {
    523 		ctx.ModuleErrorf("key is missing")
    524 		return
    525 	}
    526 	ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key))
    527 
    528 	cert := android.SrcIsModule(a.getCertString(ctx))
    529 	if cert != "" {
    530 		ctx.AddDependency(ctx.Module(), certificateTag, cert)
    531 	}
    532 }
    533 
    534 func (a *apexBundle) getCertString(ctx android.BaseContext) string {
    535 	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
    536 	if overridden {
    537 		return ":" + certificate
    538 	}
    539 	return String(a.properties.Certificate)
    540 }
    541 
    542 func (a *apexBundle) Srcs() android.Paths {
    543 	if file, ok := a.outputFiles[imageApex]; ok {
    544 		return android.Paths{file}
    545 	} else {
    546 		return nil
    547 	}
    548 }
    549 
    550 func (a *apexBundle) installable() bool {
    551 	return a.properties.Installable == nil || proptools.Bool(a.properties.Installable)
    552 }
    553 
    554 func (a *apexBundle) getImageVariation(config android.DeviceConfig) string {
    555 	if config.VndkVersion() != "" && proptools.Bool(a.properties.Use_vendor) {
    556 		return "vendor"
    557 	} else {
    558 		return "core"
    559 	}
    560 }
    561 
    562 func (a *apexBundle) EnableSanitizer(sanitizerName string) {
    563 	if !android.InList(sanitizerName, a.properties.SanitizerNames) {
    564 		a.properties.SanitizerNames = append(a.properties.SanitizerNames, sanitizerName)
    565 	}
    566 }
    567 
    568 func (a *apexBundle) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool {
    569 	if android.InList(sanitizerName, a.properties.SanitizerNames) {
    570 		return true
    571 	}
    572 
    573 	// Then follow the global setting
    574 	globalSanitizerNames := []string{}
    575 	if a.Host() {
    576 		globalSanitizerNames = ctx.Config().SanitizeHost()
    577 	} else {
    578 		arches := ctx.Config().SanitizeDeviceArch()
    579 		if len(arches) == 0 || android.InList(a.Arch().ArchType.Name, arches) {
    580 			globalSanitizerNames = ctx.Config().SanitizeDevice()
    581 		}
    582 	}
    583 	return android.InList(sanitizerName, globalSanitizerNames)
    584 }
    585 
    586 func getCopyManifestForNativeLibrary(cc *cc.Module, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) {
    587 	// Decide the APEX-local directory by the multilib of the library
    588 	// In the future, we may query this to the module.
    589 	switch cc.Arch().ArchType.Multilib {
    590 	case "lib32":
    591 		dirInApex = "lib"
    592 	case "lib64":
    593 		dirInApex = "lib64"
    594 	}
    595 	dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
    596 	if !cc.Arch().Native {
    597 		dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
    598 	}
    599 	if handleSpecialLibs {
    600 		switch cc.Name() {
    601 		case "libc", "libm", "libdl":
    602 			// Special case for bionic libs. This is to prevent the bionic libs
    603 			// from being included in the search path /apex/com.android.apex/lib.
    604 			// This exclusion is required because bionic libs in the runtime APEX
    605 			// are available via the legacy paths /system/lib/libc.so, etc. By the
    606 			// init process, the bionic libs in the APEX are bind-mounted to the
    607 			// legacy paths and thus will be loaded into the default linker namespace.
    608 			// If the bionic libs are directly in /apex/com.android.apex/lib then
    609 			// the same libs will be again loaded to the runtime linker namespace,
    610 			// which will result double loading of bionic libs that isn't supported.
    611 			dirInApex = filepath.Join(dirInApex, "bionic")
    612 		}
    613 	}
    614 
    615 	fileToCopy = cc.OutputFile().Path()
    616 	return
    617 }
    618 
    619 func getCopyManifestForExecutable(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
    620 	dirInApex = filepath.Join("bin", cc.RelativeInstallPath())
    621 	fileToCopy = cc.OutputFile().Path()
    622 	return
    623 }
    624 
    625 func getCopyManifestForPyBinary(py *python.Module) (fileToCopy android.Path, dirInApex string) {
    626 	dirInApex = "bin"
    627 	fileToCopy = py.HostToolPath().Path()
    628 	return
    629 }
    630 func getCopyManifestForGoBinary(ctx android.ModuleContext, gb bootstrap.GoBinaryTool) (fileToCopy android.Path, dirInApex string) {
    631 	dirInApex = "bin"
    632 	s, err := filepath.Rel(android.PathForOutput(ctx).String(), gb.InstallPath())
    633 	if err != nil {
    634 		ctx.ModuleErrorf("Unable to use compiled binary at %s", gb.InstallPath())
    635 		return
    636 	}
    637 	fileToCopy = android.PathForOutput(ctx, s)
    638 	return
    639 }
    640 
    641 func getCopyManifestForShBinary(sh *android.ShBinary) (fileToCopy android.Path, dirInApex string) {
    642 	dirInApex = filepath.Join("bin", sh.SubDir())
    643 	fileToCopy = sh.OutputFile()
    644 	return
    645 }
    646 
    647 func getCopyManifestForJavaLibrary(java *java.Library) (fileToCopy android.Path, dirInApex string) {
    648 	dirInApex = "javalib"
    649 	fileToCopy = java.DexJarFile()
    650 	return
    651 }
    652 
    653 func getCopyManifestForPrebuiltEtc(prebuilt *android.PrebuiltEtc) (fileToCopy android.Path, dirInApex string) {
    654 	dirInApex = filepath.Join("etc", prebuilt.SubDir())
    655 	fileToCopy = prebuilt.OutputFile()
    656 	return
    657 }
    658 
    659 func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
    660 	filesInfo := []apexFile{}
    661 
    662 	if a.properties.Payload_type == nil || *a.properties.Payload_type == "image" {
    663 		a.apexTypes = imageApex
    664 	} else if *a.properties.Payload_type == "zip" {
    665 		a.apexTypes = zipApex
    666 	} else if *a.properties.Payload_type == "both" {
    667 		a.apexTypes = both
    668 	} else {
    669 		ctx.PropertyErrorf("type", "%q is not one of \"image\", \"zip\", or \"both\".", *a.properties.Payload_type)
    670 		return
    671 	}
    672 
    673 	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
    674 
    675 	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
    676 		if _, ok := parent.(*apexBundle); ok {
    677 			// direct dependencies
    678 			depTag := ctx.OtherModuleDependencyTag(child)
    679 			depName := ctx.OtherModuleName(child)
    680 			switch depTag {
    681 			case sharedLibTag:
    682 				if cc, ok := child.(*cc.Module); ok {
    683 					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
    684 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
    685 					return true
    686 				} else {
    687 					ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
    688 				}
    689 			case executableTag:
    690 				if cc, ok := child.(*cc.Module); ok {
    691 					if !cc.Arch().Native {
    692 						// There is only one 'bin' directory so we shouldn't bother copying in
    693 						// native-bridge'd binaries and only use main ones.
    694 						return true
    695 					}
    696 					fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
    697 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeExecutable, cc, cc.Symlinks()})
    698 					return true
    699 				} else if sh, ok := child.(*android.ShBinary); ok {
    700 					fileToCopy, dirInApex := getCopyManifestForShBinary(sh)
    701 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, shBinary, sh, nil})
    702 				} else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() {
    703 					fileToCopy, dirInApex := getCopyManifestForPyBinary(py)
    704 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, pyBinary, py, nil})
    705 				} else if gb, ok := child.(bootstrap.GoBinaryTool); ok && a.Host() {
    706 					fileToCopy, dirInApex := getCopyManifestForGoBinary(ctx, gb)
    707 					// NB: Since go binaries are static we don't need the module for anything here, which is
    708 					// good since the go tool is a blueprint.Module not an android.Module like we would
    709 					// normally use.
    710 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, goBinary, nil, nil})
    711 				} else {
    712 					ctx.PropertyErrorf("binaries", "%q is neither cc_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName)
    713 				}
    714 			case javaLibTag:
    715 				if java, ok := child.(*java.Library); ok {
    716 					fileToCopy, dirInApex := getCopyManifestForJavaLibrary(java)
    717 					if fileToCopy == nil {
    718 						ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
    719 					} else {
    720 						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, javaSharedLib, java, nil})
    721 					}
    722 					return true
    723 				} else {
    724 					ctx.PropertyErrorf("java_libs", "%q is not a java_library module", depName)
    725 				}
    726 			case prebuiltTag:
    727 				if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
    728 					fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
    729 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, etc, prebuilt, nil})
    730 					return true
    731 				} else {
    732 					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
    733 				}
    734 			case keyTag:
    735 				if key, ok := child.(*apexKey); ok {
    736 					a.private_key_file = key.private_key_file
    737 					a.public_key_file = key.public_key_file
    738 					return false
    739 				} else {
    740 					ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
    741 				}
    742 			case certificateTag:
    743 				if dep, ok := child.(*java.AndroidAppCertificate); ok {
    744 					a.container_certificate_file = dep.Certificate.Pem
    745 					a.container_private_key_file = dep.Certificate.Key
    746 					return false
    747 				} else {
    748 					ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
    749 				}
    750 			}
    751 		} else {
    752 			// indirect dependencies
    753 			if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
    754 				if cc, ok := child.(*cc.Module); ok {
    755 					if !a.Host() && (cc.IsStubs() || cc.HasStubsVariants()) {
    756 						// If the dependency is a stubs lib, don't include it in this APEX,
    757 						// but make sure that the lib is installed on the device.
    758 						// In case no APEX is having the lib, the lib is installed to the system
    759 						// partition.
    760 						//
    761 						// Always include if we are a host-apex however since those won't have any
    762 						// system libraries.
    763 						if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.externalDeps) {
    764 							a.externalDeps = append(a.externalDeps, cc.Name())
    765 						}
    766 						// Don't track further
    767 						return false
    768 					}
    769 					depName := ctx.OtherModuleName(child)
    770 					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
    771 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
    772 					return true
    773 				}
    774 			}
    775 		}
    776 		return false
    777 	})
    778 
    779 	a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
    780 	if a.private_key_file == nil {
    781 		ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.properties.Key))
    782 		return
    783 	}
    784 
    785 	// remove duplicates in filesInfo
    786 	removeDup := func(filesInfo []apexFile) []apexFile {
    787 		encountered := make(map[android.Path]bool)
    788 		result := []apexFile{}
    789 		for _, f := range filesInfo {
    790 			if !encountered[f.builtFile] {
    791 				encountered[f.builtFile] = true
    792 				result = append(result, f)
    793 			}
    794 		}
    795 		return result
    796 	}
    797 	filesInfo = removeDup(filesInfo)
    798 
    799 	// to have consistent build rules
    800 	sort.Slice(filesInfo, func(i, j int) bool {
    801 		return filesInfo[i].builtFile.String() < filesInfo[j].builtFile.String()
    802 	})
    803 
    804 	// prepend the name of this APEX to the module names. These names will be the names of
    805 	// modules that will be defined if the APEX is flattened.
    806 	for i := range filesInfo {
    807 		filesInfo[i].moduleName = ctx.ModuleName() + "." + filesInfo[i].moduleName
    808 	}
    809 
    810 	a.installDir = android.PathForModuleInstall(ctx, "apex")
    811 	a.filesInfo = filesInfo
    812 
    813 	if a.apexTypes.zip() {
    814 		a.buildUnflattenedApex(ctx, zipApex)
    815 	}
    816 	if a.apexTypes.image() {
    817 		// Build rule for unflattened APEX is created even when ctx.Config().FlattenApex()
    818 		// is true. This is to support referencing APEX via ":<module_name" syntax
    819 		// in other modules. It is in AndroidMk where the selection of flattened
    820 		// or unflattened APEX is made.
    821 		a.buildUnflattenedApex(ctx, imageApex)
    822 		a.buildFlattenedApex(ctx)
    823 	}
    824 }
    825 
    826 func (a *apexBundle) buildNoticeFile(ctx android.ModuleContext, apexFileName string) android.OptionalPath {
    827 	noticeFiles := []android.Path{}
    828 	for _, f := range a.filesInfo {
    829 		if f.module != nil {
    830 			notice := f.module.NoticeFile()
    831 			if notice.Valid() {
    832 				noticeFiles = append(noticeFiles, notice.Path())
    833 			}
    834 		}
    835 	}
    836 	// append the notice file specified in the apex module itself
    837 	if a.NoticeFile().Valid() {
    838 		noticeFiles = append(noticeFiles, a.NoticeFile().Path())
    839 	}
    840 
    841 	if len(noticeFiles) == 0 {
    842 		return android.OptionalPath{}
    843 	}
    844 
    845 	return android.OptionalPathForPath(
    846 		android.BuildNoticeOutput(ctx, a.installDir, apexFileName, android.FirstUniquePaths(noticeFiles)))
    847 }
    848 
    849 func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, apexType apexPackaging) {
    850 	cert := String(a.properties.Certificate)
    851 	if cert != "" && android.SrcIsModule(cert) == "" {
    852 		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
    853 		a.container_certificate_file = defaultDir.Join(ctx, cert+".x509.pem")
    854 		a.container_private_key_file = defaultDir.Join(ctx, cert+".pk8")
    855 	} else if cert == "" {
    856 		pem, key := ctx.Config().DefaultAppCertificate(ctx)
    857 		a.container_certificate_file = pem
    858 		a.container_private_key_file = key
    859 	}
    860 
    861 	manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
    862 
    863 	var abis []string
    864 	for _, target := range ctx.MultiTargets() {
    865 		if len(target.Arch.Abi) > 0 {
    866 			abis = append(abis, target.Arch.Abi[0])
    867 		}
    868 	}
    869 
    870 	abis = android.FirstUniqueStrings(abis)
    871 
    872 	suffix := apexType.suffix()
    873 	unsignedOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+".unsigned")
    874 
    875 	filesToCopy := []android.Path{}
    876 	for _, f := range a.filesInfo {
    877 		filesToCopy = append(filesToCopy, f.builtFile)
    878 	}
    879 
    880 	copyCommands := []string{}
    881 	for i, src := range filesToCopy {
    882 		dest := filepath.Join(a.filesInfo[i].installDir, src.Base())
    883 		dest_path := filepath.Join(android.PathForModuleOut(ctx, "image"+suffix).String(), dest)
    884 		copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path))
    885 		copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
    886 		for _, sym := range a.filesInfo[i].symlinks {
    887 			symlinkDest := filepath.Join(filepath.Dir(dest_path), sym)
    888 			copyCommands = append(copyCommands, "ln -s "+filepath.Base(dest)+" "+symlinkDest)
    889 		}
    890 	}
    891 	implicitInputs := append(android.Paths(nil), filesToCopy...)
    892 	implicitInputs = append(implicitInputs, manifest)
    893 
    894 	outHostBinDir := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin").String()
    895 	prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
    896 
    897 	if apexType.image() {
    898 		// files and dirs that will be created in APEX
    899 		var readOnlyPaths []string
    900 		var executablePaths []string // this also includes dirs
    901 		for _, f := range a.filesInfo {
    902 			pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
    903 			if f.installDir == "bin" {
    904 				executablePaths = append(executablePaths, pathInApex)
    905 				for _, s := range f.symlinks {
    906 					executablePaths = append(executablePaths, filepath.Join("bin", s))
    907 				}
    908 			} else {
    909 				readOnlyPaths = append(readOnlyPaths, pathInApex)
    910 			}
    911 			dir := f.installDir
    912 			for !android.InList(dir, executablePaths) && dir != "" {
    913 				executablePaths = append(executablePaths, dir)
    914 				dir, _ = filepath.Split(dir) // move up to the parent
    915 				if len(dir) > 0 {
    916 					// remove trailing slash
    917 					dir = dir[:len(dir)-1]
    918 				}
    919 			}
    920 		}
    921 		sort.Strings(readOnlyPaths)
    922 		sort.Strings(executablePaths)
    923 		cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
    924 		ctx.Build(pctx, android.BuildParams{
    925 			Rule:        generateFsConfig,
    926 			Output:      cannedFsConfig,
    927 			Description: "generate fs config",
    928 			Args: map[string]string{
    929 				"ro_paths":   strings.Join(readOnlyPaths, " "),
    930 				"exec_paths": strings.Join(executablePaths, " "),
    931 			},
    932 		})
    933 
    934 		fcName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName())
    935 		fileContextsPath := "system/sepolicy/apex/" + fcName + "-file_contexts"
    936 		fileContextsOptionalPath := android.ExistentPathForSource(ctx, fileContextsPath)
    937 		if !fileContextsOptionalPath.Valid() {
    938 			ctx.ModuleErrorf("Cannot find file_contexts file: %q", fileContextsPath)
    939 			return
    940 		}
    941 		fileContexts := fileContextsOptionalPath.Path()
    942 
    943 		optFlags := []string{}
    944 
    945 		// Additional implicit inputs.
    946 		implicitInputs = append(implicitInputs, cannedFsConfig, fileContexts, a.private_key_file, a.public_key_file)
    947 		optFlags = append(optFlags, "--pubkey "+a.public_key_file.String())
    948 
    949 		manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
    950 		if overridden {
    951 			optFlags = append(optFlags, "--override_apk_package_name "+manifestPackageName)
    952 		}
    953 
    954 		if a.properties.AndroidManifest != nil {
    955 			androidManifestFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.AndroidManifest))
    956 			implicitInputs = append(implicitInputs, androidManifestFile)
    957 			optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String())
    958 		}
    959 
    960 		targetSdkVersion := ctx.Config().DefaultAppTargetSdk()
    961 		if targetSdkVersion == ctx.Config().PlatformSdkCodename() &&
    962 			ctx.Config().UnbundledBuild() &&
    963 			!ctx.Config().UnbundledBuildUsePrebuiltSdks() &&
    964 			ctx.Config().IsEnvTrue("UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT") {
    965 			apiFingerprint := java.ApiFingerprintPath(ctx)
    966 			targetSdkVersion += fmt.Sprintf(".$$(cat %s)", apiFingerprint.String())
    967 			implicitInputs = append(implicitInputs, apiFingerprint)
    968 		}
    969 		optFlags = append(optFlags, "--target_sdk_version "+targetSdkVersion)
    970 
    971 		noticeFile := a.buildNoticeFile(ctx, ctx.ModuleName()+suffix)
    972 		if noticeFile.Valid() {
    973 			// If there's a NOTICE file, embed it as an asset file in the APEX.
    974 			implicitInputs = append(implicitInputs, noticeFile.Path())
    975 			optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeFile.String()))
    976 		}
    977 
    978 		ctx.Build(pctx, android.BuildParams{
    979 			Rule:        apexRule,
    980 			Implicits:   implicitInputs,
    981 			Output:      unsignedOutputFile,
    982 			Description: "apex (" + apexType.name() + ")",
    983 			Args: map[string]string{
    984 				"tool_path":        outHostBinDir + ":" + prebuiltSdkToolsBinDir,
    985 				"image_dir":        android.PathForModuleOut(ctx, "image"+suffix).String(),
    986 				"copy_commands":    strings.Join(copyCommands, " && "),
    987 				"manifest":         manifest.String(),
    988 				"file_contexts":    fileContexts.String(),
    989 				"canned_fs_config": cannedFsConfig.String(),
    990 				"key":              a.private_key_file.String(),
    991 				"opt_flags":        strings.Join(optFlags, " "),
    992 			},
    993 		})
    994 
    995 		apexProtoFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".pb"+suffix)
    996 		bundleModuleFile := android.PathForModuleOut(ctx, ctx.ModuleName()+suffix+"-base.zip")
    997 		a.bundleModuleFile = bundleModuleFile
    998 
    999 		ctx.Build(pctx, android.BuildParams{
   1000 			Rule:        apexProtoConvertRule,
   1001 			Input:       unsignedOutputFile,
   1002 			Output:      apexProtoFile,
   1003 			Description: "apex proto convert",
   1004 		})
   1005 
   1006 		ctx.Build(pctx, android.BuildParams{
   1007 			Rule:        apexBundleRule,
   1008 			Input:       apexProtoFile,
   1009 			Output:      a.bundleModuleFile,
   1010 			Description: "apex bundle module",
   1011 			Args: map[string]string{
   1012 				"abi": strings.Join(abis, "."),
   1013 			},
   1014 		})
   1015 	} else {
   1016 		ctx.Build(pctx, android.BuildParams{
   1017 			Rule:        zipApexRule,
   1018 			Implicits:   implicitInputs,
   1019 			Output:      unsignedOutputFile,
   1020 			Description: "apex (" + apexType.name() + ")",
   1021 			Args: map[string]string{
   1022 				"tool_path":     outHostBinDir + ":" + prebuiltSdkToolsBinDir,
   1023 				"image_dir":     android.PathForModuleOut(ctx, "image"+suffix).String(),
   1024 				"copy_commands": strings.Join(copyCommands, " && "),
   1025 				"manifest":      manifest.String(),
   1026 			},
   1027 		})
   1028 	}
   1029 
   1030 	a.outputFiles[apexType] = android.PathForModuleOut(ctx, ctx.ModuleName()+suffix)
   1031 	ctx.Build(pctx, android.BuildParams{
   1032 		Rule:        java.Signapk,
   1033 		Description: "signapk",
   1034 		Output:      a.outputFiles[apexType],
   1035 		Input:       unsignedOutputFile,
   1036 		Args: map[string]string{
   1037 			"certificates": a.container_certificate_file.String() + " " + a.container_private_key_file.String(),
   1038 			"flags":        "-a 4096", //alignment
   1039 		},
   1040 	})
   1041 
   1042 	// Install to $OUT/soong/{target,host}/.../apex
   1043 	if a.installable() && (!ctx.Config().FlattenApex() || apexType.zip()) {
   1044 		ctx.InstallFile(a.installDir, ctx.ModuleName()+suffix, a.outputFiles[apexType])
   1045 	}
   1046 }
   1047 
   1048 func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) {
   1049 	if a.installable() {
   1050 		// For flattened APEX, do nothing but make sure that apex_manifest.json and apex_pubkey are also copied along
   1051 		// with other ordinary files.
   1052 		manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
   1053 
   1054 		// rename to apex_manifest.json
   1055 		copiedManifest := android.PathForModuleOut(ctx, "apex_manifest.json")
   1056 		ctx.Build(pctx, android.BuildParams{
   1057 			Rule:   android.Cp,
   1058 			Input:  manifest,
   1059 			Output: copiedManifest,
   1060 		})
   1061 		a.filesInfo = append(a.filesInfo, apexFile{copiedManifest, ctx.ModuleName() + ".apex_manifest.json", ".", etc, nil, nil})
   1062 
   1063 		// rename to apex_pubkey
   1064 		copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
   1065 		ctx.Build(pctx, android.BuildParams{
   1066 			Rule:   android.Cp,
   1067 			Input:  a.public_key_file,
   1068 			Output: copiedPubkey,
   1069 		})
   1070 		a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, ctx.ModuleName() + ".apex_pubkey", ".", etc, nil, nil})
   1071 
   1072 		if ctx.Config().FlattenApex() {
   1073 			for _, fi := range a.filesInfo {
   1074 				dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
   1075 				target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile)
   1076 				for _, sym := range fi.symlinks {
   1077 					ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target)
   1078 				}
   1079 			}
   1080 		}
   1081 	}
   1082 }
   1083 
   1084 func (a *apexBundle) AndroidMk() android.AndroidMkData {
   1085 	writers := []android.AndroidMkData{}
   1086 	if a.apexTypes.image() {
   1087 		writers = append(writers, a.androidMkForType(imageApex))
   1088 	}
   1089 	if a.apexTypes.zip() {
   1090 		writers = append(writers, a.androidMkForType(zipApex))
   1091 	}
   1092 	return android.AndroidMkData{
   1093 		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
   1094 			for _, data := range writers {
   1095 				data.Custom(w, name, prefix, moduleDir, data)
   1096 			}
   1097 		}}
   1098 }
   1099 
   1100 func (a *apexBundle) androidMkForFiles(w io.Writer, name, moduleDir string, apexType apexPackaging) []string {
   1101 	moduleNames := []string{}
   1102 
   1103 	for _, fi := range a.filesInfo {
   1104 		if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
   1105 			continue
   1106 		}
   1107 		if !android.InList(fi.moduleName, moduleNames) {
   1108 			moduleNames = append(moduleNames, fi.moduleName)
   1109 		}
   1110 		fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
   1111 		fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
   1112 		fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
   1113 		// /apex/<name>/{lib|framework|...}
   1114 		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex",
   1115 			proptools.StringDefault(a.properties.Apex_name, name), fi.installDir)
   1116 		if a.flattened && apexType.image() {
   1117 			// /system/apex/<name>/{lib|framework|...}
   1118 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)",
   1119 				a.installDir.RelPathString(), name, fi.installDir))
   1120 			fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
   1121 			if len(fi.symlinks) > 0 {
   1122 				fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " "))
   1123 			}
   1124 
   1125 			if fi.module != nil && fi.module.NoticeFile().Valid() {
   1126 				fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", fi.module.NoticeFile().Path().String())
   1127 			}
   1128 		} else {
   1129 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", pathWhenActivated)
   1130 		}
   1131 		fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String())
   1132 		fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.NameInMake())
   1133 		if fi.module != nil {
   1134 			archStr := fi.module.Target().Arch.ArchType.String()
   1135 			host := false
   1136 			switch fi.module.Target().Os.Class {
   1137 			case android.Host:
   1138 				if archStr != "common" {
   1139 					fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr)
   1140 				}
   1141 				host = true
   1142 			case android.HostCross:
   1143 				if archStr != "common" {
   1144 					fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr)
   1145 				}
   1146 				host = true
   1147 			case android.Device:
   1148 				if archStr != "common" {
   1149 					fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
   1150 				}
   1151 			}
   1152 			if host {
   1153 				makeOs := fi.module.Target().Os.String()
   1154 				if fi.module.Target().Os == android.Linux || fi.module.Target().Os == android.LinuxBionic {
   1155 					makeOs = "linux"
   1156 				}
   1157 				fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", makeOs)
   1158 				fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
   1159 			}
   1160 		}
   1161 		if fi.class == javaSharedLib {
   1162 			javaModule := fi.module.(*java.Library)
   1163 			// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar  Therefore
   1164 			// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
   1165 			// we will have foo.jar.jar
   1166 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".jar"))
   1167 			fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
   1168 			fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
   1169 			fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String())
   1170 			fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
   1171 			fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
   1172 		} else if fi.class == nativeSharedLib || fi.class == nativeExecutable {
   1173 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
   1174 			if cc, ok := fi.module.(*cc.Module); ok && cc.UnstrippedOutputFile() != nil {
   1175 				fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String())
   1176 			}
   1177 			fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
   1178 		} else {
   1179 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
   1180 			fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
   1181 		}
   1182 	}
   1183 	return moduleNames
   1184 }
   1185 
   1186 func (a *apexBundle) androidMkForType(apexType apexPackaging) android.AndroidMkData {
   1187 	return android.AndroidMkData{
   1188 		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
   1189 			moduleNames := []string{}
   1190 			if a.installable() {
   1191 				moduleNames = a.androidMkForFiles(w, name, moduleDir, apexType)
   1192 			}
   1193 
   1194 			if a.flattened && apexType.image() {
   1195 				// Only image APEXes can be flattened.
   1196 				fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
   1197 				fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
   1198 				fmt.Fprintln(w, "LOCAL_MODULE :=", name)
   1199 				if len(moduleNames) > 0 {
   1200 					fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " "))
   1201 				}
   1202 				fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
   1203 			} else {
   1204 				// zip-apex is the less common type so have the name refer to the image-apex
   1205 				// only and use {name}.zip if you want the zip-apex
   1206 				if apexType == zipApex && a.apexTypes == both {
   1207 					name = name + ".zip"
   1208 				}
   1209 				fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
   1210 				fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
   1211 				fmt.Fprintln(w, "LOCAL_MODULE :=", name)
   1212 				fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
   1213 				fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFiles[apexType].String())
   1214 				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString()))
   1215 				fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+apexType.suffix())
   1216 				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
   1217 				if len(moduleNames) > 0 {
   1218 					fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(moduleNames, " "))
   1219 				}
   1220 				if len(a.externalDeps) > 0 {
   1221 					fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.externalDeps, " "))
   1222 				}
   1223 				fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
   1224 
   1225 				if apexType == imageApex {
   1226 					fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String())
   1227 				}
   1228 			}
   1229 		}}
   1230 }
   1231 
   1232 func testApexBundleFactory() android.Module {
   1233 	return ApexBundleFactory( /*testApex*/ true)
   1234 }
   1235 
   1236 func apexBundleFactory() android.Module {
   1237 	return ApexBundleFactory( /*testApex*/ false)
   1238 }
   1239 
   1240 func ApexBundleFactory(testApex bool) android.Module {
   1241 	module := &apexBundle{
   1242 		outputFiles: map[apexPackaging]android.WritablePath{},
   1243 		testApex:    testApex,
   1244 	}
   1245 	module.AddProperties(&module.properties)
   1246 	module.AddProperties(&module.targetProperties)
   1247 	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
   1248 		return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
   1249 	})
   1250 	android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
   1251 	android.InitDefaultableModule(module)
   1252 	return module
   1253 }
   1254 
   1255 //
   1256 // Defaults
   1257 //
   1258 type Defaults struct {
   1259 	android.ModuleBase
   1260 	android.DefaultsModuleBase
   1261 }
   1262 
   1263 func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
   1264 }
   1265 
   1266 func defaultsFactory() android.Module {
   1267 	return DefaultsFactory()
   1268 }
   1269 
   1270 func DefaultsFactory(props ...interface{}) android.Module {
   1271 	module := &Defaults{}
   1272 
   1273 	module.AddProperties(props...)
   1274 	module.AddProperties(
   1275 		&apexBundleProperties{},
   1276 		&apexTargetBundleProperties{},
   1277 	)
   1278 
   1279 	android.InitDefaultsModule(module)
   1280 	return module
   1281 }
   1282 
   1283 //
   1284 // Prebuilt APEX
   1285 //
   1286 type Prebuilt struct {
   1287 	android.ModuleBase
   1288 	prebuilt android.Prebuilt
   1289 
   1290 	properties PrebuiltProperties
   1291 
   1292 	inputApex       android.Path
   1293 	installDir      android.OutputPath
   1294 	installFilename string
   1295 	outputApex      android.WritablePath
   1296 }
   1297 
   1298 type PrebuiltProperties struct {
   1299 	// the path to the prebuilt .apex file to import.
   1300 	Source       string `blueprint:"mutated"`
   1301 	ForceDisable bool   `blueprint:"mutated"`
   1302 
   1303 	Src  *string
   1304 	Arch struct {
   1305 		Arm struct {
   1306 			Src *string
   1307 		}
   1308 		Arm64 struct {
   1309 			Src *string
   1310 		}
   1311 		X86 struct {
   1312 			Src *string
   1313 		}
   1314 		X86_64 struct {
   1315 			Src *string
   1316 		}
   1317 	}
   1318 
   1319 	Installable *bool
   1320 	// Optional name for the installed apex. If unspecified, name of the
   1321 	// module is used as the file name
   1322 	Filename *string
   1323 }
   1324 
   1325 func (p *Prebuilt) installable() bool {
   1326 	return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
   1327 }
   1328 
   1329 func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
   1330 	// If the device is configured to use flattened APEX, force disable the prebuilt because
   1331 	// the prebuilt is a non-flattened one.
   1332 	forceDisable := ctx.Config().FlattenApex()
   1333 
   1334 	// Force disable the prebuilts when we are doing unbundled build. We do unbundled build
   1335 	// to build the prebuilts themselves.
   1336 	forceDisable = forceDisable || ctx.Config().UnbundledBuild()
   1337 
   1338 	// b/137216042 don't use prebuilts when address sanitizer is on
   1339 	forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) ||
   1340 		android.InList("hwaddress", ctx.Config().SanitizeDevice())
   1341 
   1342 	if forceDisable && p.prebuilt.SourceExists() {
   1343 		p.properties.ForceDisable = true
   1344 		return
   1345 	}
   1346 
   1347 	// This is called before prebuilt_select and prebuilt_postdeps mutators
   1348 	// The mutators requires that src to be set correctly for each arch so that
   1349 	// arch variants are disabled when src is not provided for the arch.
   1350 	if len(ctx.MultiTargets()) != 1 {
   1351 		ctx.ModuleErrorf("compile_multilib shouldn't be \"both\" for prebuilt_apex")
   1352 		return
   1353 	}
   1354 	var src string
   1355 	switch ctx.MultiTargets()[0].Arch.ArchType {
   1356 	case android.Arm:
   1357 		src = String(p.properties.Arch.Arm.Src)
   1358 	case android.Arm64:
   1359 		src = String(p.properties.Arch.Arm64.Src)
   1360 	case android.X86:
   1361 		src = String(p.properties.Arch.X86.Src)
   1362 	case android.X86_64:
   1363 		src = String(p.properties.Arch.X86_64.Src)
   1364 	default:
   1365 		ctx.ModuleErrorf("prebuilt_apex does not support %q", ctx.MultiTargets()[0].Arch.String())
   1366 		return
   1367 	}
   1368 	if src == "" {
   1369 		src = String(p.properties.Src)
   1370 	}
   1371 	p.properties.Source = src
   1372 }
   1373 
   1374 func (p *Prebuilt) Srcs() android.Paths {
   1375 	return android.Paths{p.outputApex}
   1376 }
   1377 
   1378 func (p *Prebuilt) InstallFilename() string {
   1379 	return proptools.StringDefault(p.properties.Filename, p.BaseModuleName()+imageApexSuffix)
   1380 }
   1381 
   1382 func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
   1383 	if p.properties.ForceDisable {
   1384 		return
   1385 	}
   1386 
   1387 	// TODO(jungjw): Check the key validity.
   1388 	p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
   1389 	p.installDir = android.PathForModuleInstall(ctx, "apex")
   1390 	p.installFilename = p.InstallFilename()
   1391 	if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
   1392 		ctx.ModuleErrorf("filename should end in %s for prebuilt_apex", imageApexSuffix)
   1393 	}
   1394 	p.outputApex = android.PathForModuleOut(ctx, p.installFilename)
   1395 	ctx.Build(pctx, android.BuildParams{
   1396 		Rule:   android.Cp,
   1397 		Input:  p.inputApex,
   1398 		Output: p.outputApex,
   1399 	})
   1400 	if p.installable() {
   1401 		ctx.InstallFile(p.installDir, p.installFilename, p.inputApex)
   1402 	}
   1403 }
   1404 
   1405 func (p *Prebuilt) Prebuilt() *android.Prebuilt {
   1406 	return &p.prebuilt
   1407 }
   1408 
   1409 func (p *Prebuilt) Name() string {
   1410 	return p.prebuilt.Name(p.ModuleBase.Name())
   1411 }
   1412 
   1413 func (p *Prebuilt) AndroidMk() android.AndroidMkData {
   1414 	return android.AndroidMkData{
   1415 		Class:      "ETC",
   1416 		OutputFile: android.OptionalPathForPath(p.inputApex),
   1417 		Include:    "$(BUILD_PREBUILT)",
   1418 		Extra: []android.AndroidMkExtraFunc{
   1419 			func(w io.Writer, outputFile android.Path) {
   1420 				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", p.installDir.RelPathString()))
   1421 				fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", p.installFilename)
   1422 				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !p.installable())
   1423 			},
   1424 		},
   1425 	}
   1426 }
   1427 
   1428 // prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
   1429 func PrebuiltFactory() android.Module {
   1430 	module := &Prebuilt{}
   1431 	module.AddProperties(&module.properties)
   1432 	android.InitSingleSourcePrebuiltModule(module, &module.properties.Source)
   1433 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
   1434 	return module
   1435 }
   1436