1// Copyright (C) 2019 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
15package apex
16
17import (
18	"fmt"
19	"io"
20	"path/filepath"
21	"strconv"
22	"strings"
23
24	"android/soong/android"
25	"android/soong/dexpreopt"
26	"android/soong/java"
27	"android/soong/provenance"
28
29	"github.com/google/blueprint"
30	"github.com/google/blueprint/proptools"
31)
32
33var (
34	extractMatchingApex = pctx.StaticRule(
35		"extractMatchingApex",
36		blueprint.RuleParams{
37			Command: `rm -rf "$out" && ` +
38				`${extract_apks} -o "${out}" -allow-prereleased=${allow-prereleased} ` +
39				`-sdk-version=${sdk-version} -skip-sdk-check=${skip-sdk-check} -abis=${abis} ` +
40				`-screen-densities=all -extract-single ` +
41				`${in}`,
42			CommandDeps: []string{"${extract_apks}"},
43		},
44		"abis", "allow-prereleased", "sdk-version", "skip-sdk-check")
45)
46
47type prebuilt interface {
48	isForceDisabled() bool
49	InstallFilename() string
50}
51
52type prebuiltCommon struct {
53	android.ModuleBase
54	java.Dexpreopter
55	prebuilt android.Prebuilt
56
57	// Properties common to both prebuilt_apex and apex_set.
58	prebuiltCommonProperties *PrebuiltCommonProperties
59
60	installDir      android.InstallPath
61	installFilename string
62	installedFile   android.InstallPath
63	outputApex      android.WritablePath
64
65	// fragment for this apex for apexkeys.txt
66	apexKeysPath android.WritablePath
67
68	// A list of apexFile objects created in prebuiltCommon.initApexFilesForAndroidMk which are used
69	// to create make modules in prebuiltCommon.AndroidMkEntries.
70	apexFilesForAndroidMk []apexFile
71
72	// Installed locations of symlinks for backward compatibility.
73	compatSymlinks android.InstallPaths
74
75	hostRequired        []string
76	requiredModuleNames []string
77}
78
79type sanitizedPrebuilt interface {
80	hasSanitizedSource(sanitizer string) bool
81}
82
83type PrebuiltCommonProperties struct {
84	SelectedApexProperties
85
86	// Canonical name of this APEX. Used to determine the path to the activated APEX on
87	// device (/apex/<apex_name>). If unspecified, follows the name property.
88	Apex_name *string
89
90	// Name of the source APEX that gets shadowed by this prebuilt
91	// e.g. com.mycompany.android.myapex
92	// If unspecified, follows the naming convention that the source apex of
93	// the prebuilt is Name() without "prebuilt_" prefix
94	Source_apex_name *string
95
96	ForceDisable bool `blueprint:"mutated"`
97
98	// whether the extracted apex file is installable.
99	Installable *bool
100
101	// optional name for the installed apex. If unspecified, name of the
102	// module is used as the file name
103	Filename *string
104
105	// names of modules to be overridden. Listed modules can only be other binaries
106	// (in Make or Soong).
107	// This does not completely prevent installation of the overridden binaries, but if both
108	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
109	// from PRODUCT_PACKAGES.
110	Overrides []string
111
112	// List of java libraries that are embedded inside this prebuilt APEX bundle and for which this
113	// APEX bundle will create an APEX variant and provide dex implementation jars for use by
114	// dexpreopt and boot jars package check.
115	Exported_java_libs []string
116
117	// List of bootclasspath fragments inside this prebuilt APEX bundle and for which this APEX
118	// bundle will create an APEX variant.
119	Exported_bootclasspath_fragments []string
120
121	// List of systemserverclasspath fragments inside this prebuilt APEX bundle and for which this
122	// APEX bundle will create an APEX variant.
123	Exported_systemserverclasspath_fragments []string
124
125	// Path to the .prebuilt_info file of the prebuilt apex.
126	// In case of mainline modules, the .prebuilt_info file contains the build_id that was used to
127	// generate the prebuilt.
128	Prebuilt_info *string `android:"path"`
129}
130
131// initPrebuiltCommon initializes the prebuiltCommon structure and performs initialization of the
132// module that is common to Prebuilt and ApexSet.
133func (p *prebuiltCommon) initPrebuiltCommon(module android.Module, properties *PrebuiltCommonProperties) {
134	p.prebuiltCommonProperties = properties
135	android.InitSingleSourcePrebuiltModule(module.(android.PrebuiltInterface), properties, "Selected_apex")
136	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
137}
138
139func (p *prebuiltCommon) ApexVariationName() string {
140	return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.BaseModuleName())
141}
142
143func (p *prebuiltCommon) BaseModuleName() string {
144	return proptools.StringDefault(p.prebuiltCommonProperties.Source_apex_name, p.ModuleBase.BaseModuleName())
145}
146
147func (p *prebuiltCommon) Prebuilt() *android.Prebuilt {
148	return &p.prebuilt
149}
150
151func (p *prebuiltCommon) isForceDisabled() bool {
152	return p.prebuiltCommonProperties.ForceDisable
153}
154
155func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool {
156	forceDisable := false
157
158	// Force disable the prebuilts when we are doing unbundled build. We do unbundled build
159	// to build the prebuilts themselves.
160	forceDisable = forceDisable || ctx.Config().UnbundledBuild()
161
162	// b/137216042 don't use prebuilts when address sanitizer is on, unless the prebuilt has a sanitized source
163	sanitized := ctx.Module().(sanitizedPrebuilt)
164	forceDisable = forceDisable || (android.InList("address", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("address"))
165	forceDisable = forceDisable || (android.InList("hwaddress", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("hwaddress"))
166
167	if forceDisable && p.prebuilt.SourceExists() {
168		p.prebuiltCommonProperties.ForceDisable = true
169		return true
170	}
171	return false
172}
173
174func (p *prebuiltCommon) InstallFilename() string {
175	return proptools.StringDefault(p.prebuiltCommonProperties.Filename, p.BaseModuleName()+imageApexSuffix)
176}
177
178func (p *prebuiltCommon) Name() string {
179	return p.prebuilt.Name(p.ModuleBase.Name())
180}
181
182func (p *prebuiltCommon) Overrides() []string {
183	return p.prebuiltCommonProperties.Overrides
184}
185
186func (p *prebuiltCommon) installable() bool {
187	return proptools.BoolDefault(p.prebuiltCommonProperties.Installable, true)
188}
189
190// To satisfy java.DexpreopterInterface
191func (p *prebuiltCommon) IsInstallable() bool {
192	return p.installable()
193}
194
195// initApexFilesForAndroidMk initializes the prebuiltCommon.requiredModuleNames field with the install only deps of the prebuilt apex
196func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) {
197	// If this apex contains a system server jar, then the dexpreopt artifacts should be added as required
198	for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() {
199		p.requiredModuleNames = append(p.requiredModuleNames, install.FullModuleName())
200		install.PackageFile(ctx)
201	}
202}
203
204// If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex
205func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) {
206	// If this apex does not export anything, return
207	if !p.hasExportedDeps() {
208		return
209	}
210	// If this prebuilt apex has not been selected, return
211	if p.IsHideFromMake() {
212		return
213	}
214	// Use apex_name to determine the api domain of this prebuilt apex
215	apexName := p.ApexVariationName()
216	di, err := android.FindDeapexerProviderForModule(ctx)
217	if err != nil {
218		ctx.ModuleErrorf(err.Error())
219	}
220	dc := dexpreopt.GetGlobalConfig(ctx)
221	systemServerJarList := dc.AllApexSystemServerJars(ctx)
222
223	for i := 0; i < systemServerJarList.Len(); i++ {
224		sscpApex := systemServerJarList.Apex(i)
225		sscpJar := systemServerJarList.Jar(i)
226		if apexName != sscpApex {
227			continue
228		}
229		p.Dexpreopter.DexpreoptPrebuiltApexSystemServerJars(ctx, sscpJar, di)
230	}
231}
232
233func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) {
234	for _, fi := range p.apexFilesForAndroidMk {
235		entries.AddStrings("LOCAL_REQUIRED_MODULES", fi.requiredModuleNames...)
236		entries.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", fi.targetRequiredModuleNames...)
237		entries.AddStrings("LOCAL_HOST_REQUIRED_MODULES", fi.hostRequiredModuleNames...)
238	}
239	entries.AddStrings("LOCAL_REQUIRED_MODULES", p.requiredModuleNames...)
240}
241
242func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries {
243	entriesList := []android.AndroidMkEntries{
244		{
245			Class:         "ETC",
246			OutputFile:    android.OptionalPathForPath(p.outputApex),
247			Include:       "$(BUILD_PREBUILT)",
248			Host_required: p.hostRequired,
249			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
250				func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
251					entries.SetString("LOCAL_MODULE_PATH", p.installDir.String())
252					entries.SetString("LOCAL_MODULE_STEM", p.installFilename)
253					entries.SetPath("LOCAL_SOONG_INSTALLED_MODULE", p.installedFile)
254					entries.SetString("LOCAL_SOONG_INSTALL_PAIRS", p.outputApex.String()+":"+p.installedFile.String())
255					entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", p.compatSymlinks.Strings()...)
256					entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
257					entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...)
258					entries.SetString("LOCAL_APEX_KEY_PATH", p.apexKeysPath.String())
259					p.addRequiredModules(entries)
260				},
261			},
262		},
263	}
264
265	// Add the dexpreopt artifacts to androidmk
266	for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() {
267		entriesList = append(entriesList, install.ToMakeEntries())
268	}
269
270	// Iterate over the apexFilesForAndroidMk list and create an AndroidMkEntries struct for each
271	// file. This provides similar behavior to that provided in apexBundle.AndroidMk() as it makes the
272	// apex specific variants of the exported java modules available for use from within make.
273	apexName := p.BaseModuleName()
274	for _, fi := range p.apexFilesForAndroidMk {
275		entries := p.createEntriesForApexFile(fi, apexName)
276		entriesList = append(entriesList, entries)
277	}
278
279	return entriesList
280}
281
282// createEntriesForApexFile creates an AndroidMkEntries for the supplied apexFile
283func (p *prebuiltCommon) createEntriesForApexFile(fi apexFile, apexName string) android.AndroidMkEntries {
284	moduleName := fi.androidMkModuleName + "." + apexName
285	entries := android.AndroidMkEntries{
286		Class:        fi.class.nameInMake(),
287		OverrideName: moduleName,
288		OutputFile:   android.OptionalPathForPath(fi.builtFile),
289		Include:      "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
290		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
291			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
292				entries.SetString("LOCAL_MODULE_PATH", p.installDir.String())
293				entries.SetString("LOCAL_SOONG_INSTALLED_MODULE", filepath.Join(p.installDir.String(), fi.stem()))
294				entries.SetString("LOCAL_SOONG_INSTALL_PAIRS",
295					fi.builtFile.String()+":"+filepath.Join(p.installDir.String(), fi.stem()))
296
297				// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar  Therefore
298				// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
299				// we will have foo.jar.jar
300				entries.SetString("LOCAL_MODULE_STEM", strings.TrimSuffix(fi.stem(), ".jar"))
301				entries.SetString("LOCAL_SOONG_DEX_JAR", fi.builtFile.String())
302				entries.SetString("LOCAL_DEX_PREOPT", "false")
303			},
304		},
305		ExtraFooters: []android.AndroidMkExtraFootersFunc{
306			func(w io.Writer, name, prefix, moduleDir string) {
307				// m <module_name> will build <module_name>.<apex_name> as well.
308				if fi.androidMkModuleName != moduleName {
309					fmt.Fprintf(w, ".PHONY: %s\n", fi.androidMkModuleName)
310					fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName)
311				}
312			},
313		},
314	}
315	return entries
316}
317
318// prebuiltApexModuleCreator defines the methods that need to be implemented by prebuilt_apex and
319// apex_set in order to create the modules needed to provide access to the prebuilt .apex file.
320type prebuiltApexModuleCreator interface {
321	createPrebuiltApexModules(ctx android.TopDownMutatorContext)
322}
323
324// prebuiltApexModuleCreatorMutator is the mutator responsible for invoking the
325// prebuiltApexModuleCreator's createPrebuiltApexModules method.
326//
327// It is registered as a pre-arch mutator as it must run after the ComponentDepsMutator because it
328// will need to access dependencies added by that (exported modules) but must run before the
329// DepsMutator so that the deapexer module it creates can add dependencies onto itself from the
330// exported modules.
331func prebuiltApexModuleCreatorMutator(ctx android.TopDownMutatorContext) {
332	module := ctx.Module()
333	if creator, ok := module.(prebuiltApexModuleCreator); ok {
334		creator.createPrebuiltApexModules(ctx)
335	}
336}
337
338func (p *prebuiltCommon) hasExportedDeps() bool {
339	return len(p.prebuiltCommonProperties.Exported_java_libs) > 0 ||
340		len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 ||
341		len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0
342}
343
344// prebuiltApexContentsDeps adds dependencies onto the prebuilt apex module's contents.
345func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) {
346	module := ctx.Module()
347
348	for _, dep := range p.prebuiltCommonProperties.Exported_java_libs {
349		prebuiltDep := android.PrebuiltNameFromSource(dep)
350		ctx.AddDependency(module, exportedJavaLibTag, prebuiltDep)
351	}
352
353	for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments {
354		prebuiltDep := android.PrebuiltNameFromSource(dep)
355		ctx.AddDependency(module, exportedBootclasspathFragmentTag, prebuiltDep)
356	}
357
358	for _, dep := range p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments {
359		prebuiltDep := android.PrebuiltNameFromSource(dep)
360		ctx.AddDependency(module, exportedSystemserverclasspathFragmentTag, prebuiltDep)
361	}
362}
363
364// Implements android.DepInInSameApex
365func (p *prebuiltCommon) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
366	tag := ctx.OtherModuleDependencyTag(dep)
367	_, ok := tag.(exportedDependencyTag)
368	return ok
369}
370
371// apexInfoMutator marks any modules for which this apex exports a file as requiring an apex
372// specific variant and checks that they are supported.
373//
374// The apexMutator will ensure that the ApexInfo objects passed to BuildForApex(ApexInfo) are
375// associated with the apex specific variant using the ApexInfoProvider for later retrieval.
376//
377// Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
378// across prebuilt_apex modules. That is because there is no way to determine whether two
379// prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
380// been built from different source at different times or they could have been built with different
381// build options that affect the libraries.
382//
383// While it may be possible to provide sufficient information to determine whether two prebuilt_apex
384// modules were compatible it would be a lot of work and would not provide much benefit for a couple
385// of reasons:
386//   - The number of prebuilt_apex modules that will be exporting files for the same module will be
387//     low as the prebuilt_apex only exports files for the direct dependencies that require it and
388//     very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
389//     few com.android.art* apex files that contain the same contents and could export files for the
390//     same modules but only one of them needs to do so. Contrast that with source apex modules which
391//     need apex specific variants for every module that contributes code to the apex, whether direct
392//     or indirect.
393//   - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
394//     extra copying of files. Contrast that with source apex modules that has to build each variant
395//     from source.
396func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) {
397
398	// Collect direct dependencies into contents.
399	contents := make(map[string]android.ApexMembership)
400
401	// Collect the list of dependencies.
402	var dependencies []android.ApexModule
403	mctx.WalkDeps(func(child, parent android.Module) bool {
404		// If the child is not in the same apex as the parent then exit immediately and do not visit
405		// any of the child's dependencies.
406		if !android.IsDepInSameApex(mctx, parent, child) {
407			return false
408		}
409
410		tag := mctx.OtherModuleDependencyTag(child)
411		depName := mctx.OtherModuleName(child)
412		if exportedTag, ok := tag.(exportedDependencyTag); ok {
413			propertyName := exportedTag.name
414
415			// It is an error if the other module is not a prebuilt.
416			if !android.IsModulePrebuilt(child) {
417				mctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
418				return false
419			}
420
421			// It is an error if the other module is not an ApexModule.
422			if _, ok := child.(android.ApexModule); !ok {
423				mctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
424				return false
425			}
426		}
427
428		// Ignore any modules that do not implement ApexModule as they cannot have an APEX specific
429		// variant.
430		if _, ok := child.(android.ApexModule); !ok {
431			return false
432		}
433
434		// Strip off the prebuilt_ prefix if present before storing content to ensure consistent
435		// behavior whether there is a corresponding source module present or not.
436		depName = android.RemoveOptionalPrebuiltPrefix(depName)
437
438		// Remember if this module was added as a direct dependency.
439		direct := parent == mctx.Module()
440		contents[depName] = contents[depName].Add(direct)
441
442		// Add the module to the list of dependencies that need to have an APEX variant.
443		dependencies = append(dependencies, child.(android.ApexModule))
444
445		return true
446	})
447
448	// Create contents for the prebuilt_apex and store it away for later use.
449	apexContents := android.NewApexContents(contents)
450	android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{
451		Contents: apexContents,
452	})
453
454	// Create an ApexInfo for the prebuilt_apex.
455	apexVariationName := p.ApexVariationName()
456	apexInfo := android.ApexInfo{
457		ApexVariationName: apexVariationName,
458		InApexVariants:    []string{apexVariationName},
459		InApexModules:     []string{p.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix.
460		ApexContents:      []*android.ApexContents{apexContents},
461		ForPrebuiltApex:   true,
462	}
463
464	// Mark the dependencies of this module as requiring a variant for this module.
465	for _, am := range dependencies {
466		am.BuildForApex(apexInfo)
467	}
468}
469
470// prebuiltApexSelectorModule is a private module type that is only created by the prebuilt_apex
471// module. It selects the apex to use and makes it available for use by prebuilt_apex and the
472// deapexer.
473type prebuiltApexSelectorModule struct {
474	android.ModuleBase
475
476	apexFileProperties ApexFileProperties
477
478	inputApex android.Path
479}
480
481func privateApexSelectorModuleFactory() android.Module {
482	module := &prebuiltApexSelectorModule{}
483	module.AddProperties(
484		&module.apexFileProperties,
485	)
486	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
487	return module
488}
489
490func (p *prebuiltApexSelectorModule) Srcs() android.Paths {
491	return android.Paths{p.inputApex}
492}
493
494func (p *prebuiltApexSelectorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
495	p.inputApex = android.SingleSourcePathFromSupplier(ctx, p.apexFileProperties.prebuiltApexSelector, "src")
496}
497
498type Prebuilt struct {
499	prebuiltCommon
500
501	properties PrebuiltProperties
502
503	inputApex android.Path
504
505	provenanceMetaDataFile android.OutputPath
506}
507
508type ApexFileProperties struct {
509	// the path to the prebuilt .apex file to import.
510	//
511	// This cannot be marked as `android:"arch_variant"` because the `prebuilt_apex` is only mutated
512	// for android_common. That is so that it will have the same arch variant as, and so be compatible
513	// with, the source `apex` module type that it replaces.
514	Src  *string `android:"path"`
515	Arch struct {
516		Arm struct {
517			Src *string `android:"path"`
518		}
519		Arm64 struct {
520			Src *string `android:"path"`
521		}
522		Riscv64 struct {
523			Src *string `android:"path"`
524		}
525		X86 struct {
526			Src *string `android:"path"`
527		}
528		X86_64 struct {
529			Src *string `android:"path"`
530		}
531	}
532}
533
534// prebuiltApexSelector selects the correct prebuilt APEX file for the build target.
535//
536// The ctx parameter can be for any module not just the prebuilt module so care must be taken not
537// to use methods on it that are specific to the current module.
538//
539// See the ApexFileProperties.Src property.
540func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) []string {
541	multiTargets := prebuilt.MultiTargets()
542	if len(multiTargets) != 1 {
543		ctx.OtherModuleErrorf(prebuilt, "compile_multilib shouldn't be \"both\" for prebuilt_apex")
544		return nil
545	}
546	var src string
547	switch multiTargets[0].Arch.ArchType {
548	case android.Arm:
549		src = String(p.Arch.Arm.Src)
550	case android.Arm64:
551		src = String(p.Arch.Arm64.Src)
552	case android.Riscv64:
553		src = String(p.Arch.Riscv64.Src)
554		// HACK: fall back to arm64 prebuilts, the riscv64 ones don't exist yet.
555		if src == "" {
556			src = String(p.Arch.Arm64.Src)
557		}
558	case android.X86:
559		src = String(p.Arch.X86.Src)
560	case android.X86_64:
561		src = String(p.Arch.X86_64.Src)
562	}
563	if src == "" {
564		src = String(p.Src)
565	}
566
567	if src == "" {
568		if ctx.Config().AllowMissingDependencies() {
569			ctx.AddMissingDependencies([]string{ctx.OtherModuleName(prebuilt)})
570		} else {
571			ctx.OtherModuleErrorf(prebuilt, "prebuilt_apex does not support %q", multiTargets[0].Arch.String())
572		}
573		// Drop through to return an empty string as the src (instead of nil) to avoid the prebuilt
574		// logic from reporting a more general, less useful message.
575	}
576
577	return []string{src}
578}
579
580type PrebuiltProperties struct {
581	ApexFileProperties
582
583	PrebuiltCommonProperties
584}
585
586func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool {
587	return false
588}
589
590func (p *Prebuilt) OutputFiles(tag string) (android.Paths, error) {
591	switch tag {
592	case "":
593		return android.Paths{p.outputApex}, nil
594	default:
595		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
596	}
597}
598
599// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
600func PrebuiltFactory() android.Module {
601	module := &Prebuilt{}
602	module.AddProperties(&module.properties)
603	module.initPrebuiltCommon(module, &module.properties.PrebuiltCommonProperties)
604
605	return module
606}
607
608func createApexSelectorModule(ctx android.TopDownMutatorContext, name string, apexFileProperties *ApexFileProperties) {
609	props := struct {
610		Name *string
611	}{
612		Name: proptools.StringPtr(name),
613	}
614
615	ctx.CreateModule(privateApexSelectorModuleFactory,
616		&props,
617		apexFileProperties,
618	)
619}
620
621// createDeapexerModuleIfNeeded will create a deapexer module if it is needed.
622//
623// A deapexer module is only needed when the prebuilt apex specifies one or more modules in either
624// the `exported_java_libs` or `exported_bootclasspath_fragments` properties as that indicates that
625// the listed modules need access to files from within the prebuilt .apex file.
626func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutatorContext, deapexerName string, apexFileSource string) {
627	// Only create the deapexer module if it is needed.
628	if !p.hasExportedDeps() {
629		return
630	}
631
632	// Compute the deapexer properties from the transitive dependencies of this module.
633	commonModules := []string{}
634	dexpreoptProfileGuidedModules := []string{}
635	exportedFiles := []string{}
636	ctx.WalkDeps(func(child, parent android.Module) bool {
637		tag := ctx.OtherModuleDependencyTag(child)
638
639		// If the child is not in the same apex as the parent then ignore it and all its children.
640		if !android.IsDepInSameApex(ctx, parent, child) {
641			return false
642		}
643
644		name := java.ModuleStemForDeapexing(child)
645		if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok {
646			commonModules = append(commonModules, name)
647
648			extract := child.(android.RequiredFilesFromPrebuiltApex)
649			requiredFiles := extract.RequiredFilesFromPrebuiltApex(ctx)
650			exportedFiles = append(exportedFiles, requiredFiles...)
651
652			if extract.UseProfileGuidedDexpreopt() {
653				dexpreoptProfileGuidedModules = append(dexpreoptProfileGuidedModules, name)
654			}
655
656			// Visit the dependencies of this module just in case they also require files from the
657			// prebuilt apex.
658			return true
659		}
660
661		return false
662	})
663
664	// Create properties for deapexer module.
665	deapexerProperties := &DeapexerProperties{
666		// Remove any duplicates from the common modules lists as a module may be included via a direct
667		// dependency as well as transitive ones.
668		CommonModules:                 android.SortedUniqueStrings(commonModules),
669		DexpreoptProfileGuidedModules: android.SortedUniqueStrings(dexpreoptProfileGuidedModules),
670	}
671
672	// Populate the exported files property in a fixed order.
673	deapexerProperties.ExportedFiles = android.SortedUniqueStrings(exportedFiles)
674
675	props := struct {
676		Name          *string
677		Selected_apex *string
678	}{
679		Name:          proptools.StringPtr(deapexerName),
680		Selected_apex: proptools.StringPtr(apexFileSource),
681	}
682	ctx.CreateModule(privateDeapexerFactory,
683		&props,
684		deapexerProperties,
685	)
686}
687
688func apexSelectorModuleName(baseModuleName string) string {
689	return baseModuleName + ".apex.selector"
690}
691
692func prebuiltApexExportedModuleName(ctx android.BottomUpMutatorContext, name string) string {
693	// The prebuilt_apex should be depending on prebuilt modules but as this runs after
694	// prebuilt_rename the prebuilt module may or may not be using the prebuilt_ prefixed named. So,
695	// check to see if the prefixed name is in use first, if it is then use that, otherwise assume
696	// the unprefixed name is the one to use. If the unprefixed one turns out to be a source module
697	// and not a renamed prebuilt module then that will be detected and reported as an error when
698	// processing the dependency in ApexInfoMutator().
699	prebuiltName := android.PrebuiltNameFromSource(name)
700	if ctx.OtherModuleExists(prebuiltName) {
701		name = prebuiltName
702	}
703	return name
704}
705
706type exportedDependencyTag struct {
707	blueprint.BaseDependencyTag
708	name string
709}
710
711// Mark this tag so dependencies that use it are excluded from visibility enforcement.
712//
713// This does allow any prebuilt_apex to reference any module which does open up a small window for
714// restricted visibility modules to be referenced from the wrong prebuilt_apex. However, doing so
715// avoids opening up a much bigger window by widening the visibility of modules that need files
716// provided by the prebuilt_apex to include all the possible locations they may be defined, which
717// could include everything below vendor/.
718//
719// A prebuilt_apex that references a module via this tag will have to contain the appropriate files
720// corresponding to that module, otherwise it will fail when attempting to retrieve the files from
721// the .apex file. It will also have to be included in the module's apex_available property too.
722// That makes it highly unlikely that a prebuilt_apex would reference a restricted module
723// incorrectly.
724func (t exportedDependencyTag) ExcludeFromVisibilityEnforcement() {}
725
726func (t exportedDependencyTag) RequiresFilesFromPrebuiltApex() {}
727
728var _ android.RequiresFilesFromPrebuiltApexTag = exportedDependencyTag{}
729
730var (
731	exportedJavaLibTag                       = exportedDependencyTag{name: "exported_java_libs"}
732	exportedBootclasspathFragmentTag         = exportedDependencyTag{name: "exported_bootclasspath_fragments"}
733	exportedSystemserverclasspathFragmentTag = exportedDependencyTag{name: "exported_systemserverclasspath_fragments"}
734)
735
736var _ prebuiltApexModuleCreator = (*Prebuilt)(nil)
737
738// createPrebuiltApexModules creates modules necessary to export files from the prebuilt apex to the
739// build.
740//
741// If this needs to make files from within a `.apex` file available for use by other Soong modules,
742// e.g. make dex implementation jars available for java_import modules listed in exported_java_libs,
743// it does so as follows:
744//
745//  1. It creates a `deapexer` module that actually extracts the files from the `.apex` file and
746//     makes them available for use by other modules, at both Soong and ninja levels.
747//
748//  2. It adds a dependency onto those modules and creates an apex specific variant similar to what
749//     an `apex` module does. That ensures that code which looks for specific apex variant, e.g.
750//     dexpreopt, will work the same way from source and prebuilt.
751//
752//  3. The `deapexer` module adds a dependency from the modules that require the exported files onto
753//     itself so that they can retrieve the file paths to those files.
754//
755// It also creates a child module `selector` that is responsible for selecting the appropriate
756// input apex for both the prebuilt_apex and the deapexer. That is needed for a couple of reasons:
757//
758//  1. To dedup the selection logic so it only runs in one module.
759//
760//  2. To allow the deapexer to be wired up to a different source for the input apex, e.g. an
761//     `apex_set`.
762//
763//     prebuilt_apex
764//     /      |      \
765//     /         |         \
766//     V            V            V
767//     selector  <---  deapexer  <---  exported java lib
768func (p *Prebuilt) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
769	apexSelectorModuleName := apexSelectorModuleName(p.Name())
770	createApexSelectorModule(ctx, apexSelectorModuleName, &p.properties.ApexFileProperties)
771
772	apexFileSource := ":" + apexSelectorModuleName
773	p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(p.Name()), apexFileSource)
774
775	// Add a source reference to retrieve the selected apex from the selector module.
776	p.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
777}
778
779func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
780	p.prebuiltApexContentsDeps(ctx)
781}
782
783func (p *prebuiltCommon) DepsMutator(ctx android.BottomUpMutatorContext) {
784	if p.hasExportedDeps() {
785		// Create a dependency from the prebuilt apex (prebuilt_apex/apex_set) to the internal deapexer module
786		// The deapexer will return a provider that will be bubbled up to the rdeps of apexes (e.g. dex_bootjars)
787		ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.Name()))
788	}
789}
790
791var _ ApexInfoMutator = (*Prebuilt)(nil)
792
793func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
794	p.apexInfoMutator(mctx)
795}
796
797// Set a provider containing information about the jars and .prof provided by the apex
798// Apexes built from prebuilts retrieve this information by visiting its internal deapexer module
799// Used by dex_bootjars to generate the boot image
800func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext) {
801	if !p.hasExportedDeps() {
802		// nothing to do
803		return
804	}
805	if di, err := android.FindDeapexerProviderForModule(ctx); err == nil {
806		javaModuleToDexPath := map[string]android.Path{}
807		for _, commonModule := range di.GetExportedModuleNames() {
808			if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil {
809				javaModuleToDexPath[commonModule] = dex
810			}
811		}
812
813		exports := android.ApexExportsInfo{
814			ApexName:                      p.ApexVariationName(),
815			ProfilePathOnHost:             di.PrebuiltExportPath(java.ProfileInstallPathInApex),
816			LibraryNameToDexJarPathOnHost: javaModuleToDexPath,
817		}
818		android.SetProvider(ctx, android.ApexExportsInfoProvider, exports)
819	} else {
820		ctx.ModuleErrorf(err.Error())
821	}
822}
823
824// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
825// with information about whether source or prebuilt of an apex was used during the build.
826func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) {
827	info := android.PrebuiltInfo{
828		Name:        p.BaseModuleName(),
829		Is_prebuilt: true,
830	}
831	// If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json.
832	if p.prebuiltCommonProperties.Prebuilt_info != nil {
833		info.Prebuilt_info_file_path = android.PathForModuleSrc(ctx, *p.prebuiltCommonProperties.Prebuilt_info).String()
834	}
835	android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
836}
837
838// Uses an object provided by its deps to validate that the contents of bcpf have been added to the global
839// PRODUCT_APEX_BOOT_JARS
840// This validation will only run on the apex which is active for this product/release_config
841func validateApexClasspathFragments(ctx android.ModuleContext) {
842	ctx.VisitDirectDeps(func(m android.Module) {
843		if info, exists := android.OtherModuleProvider(ctx, m, java.ClasspathFragmentValidationInfoProvider); exists {
844			ctx.ModuleErrorf("%s in contents of %s must also be declared in PRODUCT_APEX_BOOT_JARS", info.UnknownJars, info.ClasspathFragmentModuleName)
845		}
846	})
847}
848
849func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
850	// Validate contents of classpath fragments
851	if !p.IsHideFromMake() {
852		validateApexClasspathFragments(ctx)
853	}
854
855	p.apexKeysPath = writeApexKeys(ctx, p)
856	// TODO(jungjw): Check the key validity.
857	p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
858	p.installDir = android.PathForModuleInstall(ctx, "apex")
859	p.installFilename = p.InstallFilename()
860	if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
861		ctx.ModuleErrorf("filename should end in %s for prebuilt_apex", imageApexSuffix)
862	}
863	p.outputApex = android.PathForModuleOut(ctx, p.installFilename)
864	ctx.Build(pctx, android.BuildParams{
865		Rule:   android.Cp,
866		Input:  p.inputApex,
867		Output: p.outputApex,
868	})
869
870	if p.prebuiltCommon.checkForceDisable(ctx) {
871		p.HideFromMake()
872		return
873	}
874
875	// dexpreopt any system server jars if present
876	p.dexpreoptSystemServerJars(ctx)
877
878	// provide info used for generating the boot image
879	p.provideApexExportsInfo(ctx)
880
881	p.providePrebuiltInfo(ctx)
882
883	// Save the files that need to be made available to Make.
884	p.initApexFilesForAndroidMk(ctx)
885
886	// in case that prebuilt_apex replaces source apex (using prefer: prop)
887	p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx)
888	// or that prebuilt_apex overrides other apexes (using overrides: prop)
889	for _, overridden := range p.prebuiltCommonProperties.Overrides {
890		p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx)...)
891	}
892
893	if p.installable() {
894		p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...)
895		p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
896	}
897}
898
899func (p *Prebuilt) ProvenanceMetaDataFile() android.OutputPath {
900	return p.provenanceMetaDataFile
901}
902
903// prebuiltApexExtractorModule is a private module type that is only created by the prebuilt_apex
904// module. It extracts the correct apex to use and makes it available for use by apex_set.
905type prebuiltApexExtractorModule struct {
906	android.ModuleBase
907
908	properties ApexExtractorProperties
909
910	extractedApex android.WritablePath
911}
912
913func privateApexExtractorModuleFactory() android.Module {
914	module := &prebuiltApexExtractorModule{}
915	module.AddProperties(
916		&module.properties,
917	)
918	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
919	return module
920}
921
922func (p *prebuiltApexExtractorModule) Srcs() android.Paths {
923	return android.Paths{p.extractedApex}
924}
925
926func (p *prebuiltApexExtractorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
927	srcsSupplier := func(ctx android.BaseModuleContext, prebuilt android.Module) []string {
928		return p.properties.prebuiltSrcs(ctx)
929	}
930	defaultAllowPrerelease := ctx.Config().IsEnvTrue("SOONG_ALLOW_PRERELEASE_APEXES")
931	apexSet := android.SingleSourcePathFromSupplier(ctx, srcsSupplier, "set")
932	p.extractedApex = android.PathForModuleOut(ctx, "extracted", apexSet.Base())
933	// Filter out NativeBridge archs (b/260115309)
934	abis := java.SupportedAbis(ctx, true)
935	ctx.Build(pctx,
936		android.BuildParams{
937			Rule:        extractMatchingApex,
938			Description: "Extract an apex from an apex set",
939			Inputs:      android.Paths{apexSet},
940			Output:      p.extractedApex,
941			Args: map[string]string{
942				"abis":              strings.Join(abis, ","),
943				"allow-prereleased": strconv.FormatBool(proptools.BoolDefault(p.properties.Prerelease, defaultAllowPrerelease)),
944				"sdk-version":       ctx.Config().PlatformSdkVersion().String(),
945				"skip-sdk-check":    strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")),
946			},
947		})
948}
949
950type ApexSet struct {
951	prebuiltCommon
952
953	properties ApexSetProperties
954}
955
956type ApexExtractorProperties struct {
957	// the .apks file path that contains prebuilt apex files to be extracted.
958	Set *string `android:"path"`
959
960	Sanitized struct {
961		None struct {
962			Set *string `android:"path"`
963		}
964		Address struct {
965			Set *string `android:"path"`
966		}
967		Hwaddress struct {
968			Set *string `android:"path"`
969		}
970	}
971
972	// apexes in this set use prerelease SDK version
973	Prerelease *bool
974}
975
976func (e *ApexExtractorProperties) prebuiltSrcs(ctx android.BaseModuleContext) []string {
977	var srcs []string
978	if e.Set != nil {
979		srcs = append(srcs, *e.Set)
980	}
981
982	sanitizers := ctx.Config().SanitizeDevice()
983
984	if android.InList("address", sanitizers) && e.Sanitized.Address.Set != nil {
985		srcs = append(srcs, *e.Sanitized.Address.Set)
986	} else if android.InList("hwaddress", sanitizers) && e.Sanitized.Hwaddress.Set != nil {
987		srcs = append(srcs, *e.Sanitized.Hwaddress.Set)
988	} else if e.Sanitized.None.Set != nil {
989		srcs = append(srcs, *e.Sanitized.None.Set)
990	}
991
992	return srcs
993}
994
995type ApexSetProperties struct {
996	ApexExtractorProperties
997
998	PrebuiltCommonProperties
999}
1000
1001func (a *ApexSet) hasSanitizedSource(sanitizer string) bool {
1002	if sanitizer == "address" {
1003		return a.properties.Sanitized.Address.Set != nil
1004	}
1005	if sanitizer == "hwaddress" {
1006		return a.properties.Sanitized.Hwaddress.Set != nil
1007	}
1008
1009	return false
1010}
1011
1012func (a *ApexSet) OutputFiles(tag string) (android.Paths, error) {
1013	switch tag {
1014	case "":
1015		return android.Paths{a.outputApex}, nil
1016	default:
1017		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1018	}
1019}
1020
1021// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
1022func apexSetFactory() android.Module {
1023	module := &ApexSet{}
1024	module.AddProperties(&module.properties)
1025	module.initPrebuiltCommon(module, &module.properties.PrebuiltCommonProperties)
1026
1027	return module
1028}
1029
1030func createApexExtractorModule(ctx android.TopDownMutatorContext, name string, apexExtractorProperties *ApexExtractorProperties) {
1031	props := struct {
1032		Name *string
1033	}{
1034		Name: proptools.StringPtr(name),
1035	}
1036
1037	ctx.CreateModule(privateApexExtractorModuleFactory,
1038		&props,
1039		apexExtractorProperties,
1040	)
1041}
1042
1043func apexExtractorModuleName(baseModuleName string) string {
1044	return baseModuleName + ".apex.extractor"
1045}
1046
1047var _ prebuiltApexModuleCreator = (*ApexSet)(nil)
1048
1049// createPrebuiltApexModules creates modules necessary to export files from the apex set to other
1050// modules.
1051//
1052// This effectively does for apex_set what Prebuilt.createPrebuiltApexModules does for a
1053// prebuilt_apex except that instead of creating a selector module which selects one .apex file
1054// from those provided this creates an extractor module which extracts the appropriate .apex file
1055// from the zip file containing them.
1056func (a *ApexSet) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
1057	apexExtractorModuleName := apexExtractorModuleName(a.Name())
1058	createApexExtractorModule(ctx, apexExtractorModuleName, &a.properties.ApexExtractorProperties)
1059
1060	apexFileSource := ":" + apexExtractorModuleName
1061	a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(a.Name()), apexFileSource)
1062
1063	// After passing the arch specific src properties to the creating the apex selector module
1064	a.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
1065}
1066
1067func (a *ApexSet) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
1068	a.prebuiltApexContentsDeps(ctx)
1069}
1070
1071var _ ApexInfoMutator = (*ApexSet)(nil)
1072
1073func (a *ApexSet) ApexInfoMutator(mctx android.TopDownMutatorContext) {
1074	a.apexInfoMutator(mctx)
1075}
1076
1077func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1078	// Validate contents of classpath fragments
1079	if !a.IsHideFromMake() {
1080		validateApexClasspathFragments(ctx)
1081	}
1082
1083	a.apexKeysPath = writeApexKeys(ctx, a)
1084	a.installFilename = a.InstallFilename()
1085	if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) {
1086		ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix)
1087	}
1088
1089	inputApex := android.OptionalPathForModuleSrc(ctx, a.prebuiltCommonProperties.Selected_apex).Path()
1090	a.outputApex = android.PathForModuleOut(ctx, a.installFilename)
1091	ctx.Build(pctx, android.BuildParams{
1092		Rule:   android.Cp,
1093		Input:  inputApex,
1094		Output: a.outputApex,
1095	})
1096
1097	if a.prebuiltCommon.checkForceDisable(ctx) {
1098		a.HideFromMake()
1099		return
1100	}
1101
1102	// dexpreopt any system server jars if present
1103	a.dexpreoptSystemServerJars(ctx)
1104
1105	// provide info used for generating the boot image
1106	a.provideApexExportsInfo(ctx)
1107
1108	a.providePrebuiltInfo(ctx)
1109
1110	// Save the files that need to be made available to Make.
1111	a.initApexFilesForAndroidMk(ctx)
1112
1113	a.installDir = android.PathForModuleInstall(ctx, "apex")
1114	if a.installable() {
1115		a.installedFile = ctx.InstallFile(a.installDir, a.installFilename, a.outputApex)
1116	}
1117
1118	// in case that apex_set replaces source apex (using prefer: prop)
1119	a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
1120	// or that apex_set overrides other apexes (using overrides: prop)
1121	for _, overridden := range a.prebuiltCommonProperties.Overrides {
1122		a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx)...)
1123	}
1124}
1125
1126type systemExtContext struct {
1127	android.ModuleContext
1128}
1129
1130func (*systemExtContext) SystemExtSpecific() bool {
1131	return true
1132}
1133