xref: /aosp_15_r20/build/soong/android/config.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2015 Google Inc. All rights reserved.
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 android
16
17// This is the primary location to write and read all configuration values and
18// product variables necessary for soong_build's operation.
19
20import (
21	"encoding/json"
22	"fmt"
23	"os"
24	"path/filepath"
25	"runtime"
26	"strconv"
27	"strings"
28	"sync"
29	"unicode"
30
31	"android/soong/shared"
32
33	"github.com/google/blueprint"
34	"github.com/google/blueprint/bootstrap"
35	"github.com/google/blueprint/pathtools"
36	"github.com/google/blueprint/proptools"
37
38	"android/soong/android/soongconfig"
39	"android/soong/remoteexec"
40)
41
42// Bool re-exports proptools.Bool for the android package.
43var Bool = proptools.Bool
44
45// String re-exports proptools.String for the android package.
46var String = proptools.String
47
48// StringDefault re-exports proptools.StringDefault for the android package.
49var StringDefault = proptools.StringDefault
50
51// FutureApiLevelInt is a placeholder constant for unreleased API levels.
52const FutureApiLevelInt = 10000
53
54// PrivateApiLevel represents the api level of SdkSpecPrivate (sdk_version: "")
55// This api_level exists to differentiate user-provided "" from "current" sdk_version
56// The differentiation is necessary to enable different validation rules for these two possible values.
57var PrivateApiLevel = ApiLevel{
58	value:     "current",             // The value is current since aidl expects `current` as the default (TestAidlFlagsWithMinSdkVersion)
59	number:    FutureApiLevelInt + 1, // This is used to differentiate it from FutureApiLevel
60	isPreview: true,
61}
62
63// FutureApiLevel represents unreleased API levels.
64var FutureApiLevel = ApiLevel{
65	value:     "current",
66	number:    FutureApiLevelInt,
67	isPreview: true,
68}
69
70// The product variables file name, containing product config from Kati.
71const productVariablesFileName = "soong.variables"
72
73// A Config object represents the entire build configuration for Android.
74type Config struct {
75	*config
76}
77
78type SoongBuildMode int
79
80type CmdArgs struct {
81	bootstrap.Args
82	RunGoTests     bool
83	OutDir         string
84	SoongOutDir    string
85	SoongVariables string
86
87	ModuleGraphFile   string
88	ModuleActionsFile string
89	DocFile           string
90
91	BuildFromSourceStub bool
92
93	EnsureAllowlistIntegrity bool
94}
95
96// Build modes that soong_build can run as.
97const (
98	// Don't use bazel at all during module analysis.
99	AnalysisNoBazel SoongBuildMode = iota
100
101	// Create a JSON representation of the module graph and exit.
102	GenerateModuleGraph
103
104	// Generate a documentation file for module type definitions and exit.
105	GenerateDocFile
106)
107
108const testKeyDir = "build/make/target/product/security"
109
110// SoongOutDir returns the build output directory for the configuration.
111func (c Config) SoongOutDir() string {
112	return c.soongOutDir
113}
114
115// tempDir returns the path to out/soong/.temp, which is cleared at the beginning of every build.
116func (c Config) tempDir() string {
117	return shared.TempDirForOutDir(c.soongOutDir)
118}
119
120func (c Config) OutDir() string {
121	return c.outDir
122}
123
124func (c Config) RunGoTests() bool {
125	return c.runGoTests
126}
127
128func (c Config) DebugCompilation() bool {
129	return false // Never compile Go code in the main build for debugging
130}
131
132func (c Config) Subninjas() []string {
133	return []string{}
134}
135
136func (c Config) PrimaryBuilderInvocations() []bootstrap.PrimaryBuilderInvocation {
137	return []bootstrap.PrimaryBuilderInvocation{}
138}
139
140// RunningInsideUnitTest returns true if this code is being run as part of a Soong unit test.
141func (c Config) RunningInsideUnitTest() bool {
142	return c.config.TestProductVariables != nil
143}
144
145// DisableHiddenApiChecks returns true if hiddenapi checks have been disabled.
146// For 'eng' target variant hiddenapi checks are disabled by default for performance optimisation,
147// but can be enabled by setting environment variable ENABLE_HIDDENAPI_FLAGS=true.
148// For other target variants hiddenapi check are enabled by default but can be disabled by
149// setting environment variable UNSAFE_DISABLE_HIDDENAPI_FLAGS=true.
150// If both ENABLE_HIDDENAPI_FLAGS=true and UNSAFE_DISABLE_HIDDENAPI_FLAGS=true, then
151// ENABLE_HIDDENAPI_FLAGS=true will be triggered and hiddenapi checks will be considered enabled.
152func (c Config) DisableHiddenApiChecks() bool {
153	return !c.IsEnvTrue("ENABLE_HIDDENAPI_FLAGS") &&
154		(c.IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") ||
155			Bool(c.productVariables.Eng))
156}
157
158// DisableVerifyOverlaps returns true if verify_overlaps is skipped.
159// Mismatch in version of apexes and module SDK is required for mainline prebuilts to work in
160// trunk stable.
161// Thus, verify_overlaps is disabled when RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE is set to false.
162// TODO(b/308174018): Re-enable verify_overlaps for both builr from source/mainline prebuilts.
163func (c Config) DisableVerifyOverlaps() bool {
164	if c.IsEnvFalse("DISABLE_VERIFY_OVERLAPS") && c.ReleaseDisableVerifyOverlaps() {
165		panic("The current release configuration does not support verify_overlaps. DISABLE_VERIFY_OVERLAPS cannot be set to false")
166	}
167	return c.IsEnvTrue("DISABLE_VERIFY_OVERLAPS") || c.ReleaseDisableVerifyOverlaps() || !c.ReleaseDefaultModuleBuildFromSource()
168}
169
170func (c Config) CoverageSuffix() string {
171	if v := c.IsEnvTrue("EMMA_INSTRUMENT"); v {
172		return "coverage."
173	}
174	return ""
175}
176
177// MaxPageSizeSupported returns the max page size supported by the device. This
178// value will define the ELF segment alignment for binaries (executables and
179// shared libraries).
180func (c Config) MaxPageSizeSupported() string {
181	return String(c.config.productVariables.DeviceMaxPageSizeSupported)
182}
183
184// NoBionicPageSizeMacro returns true when AOSP is page size agnostic.
185// This means that the bionic's macro PAGE_SIZE won't be defined.
186// Returns false when AOSP is NOT page size agnostic.
187// This means that bionic's macro PAGE_SIZE is defined.
188func (c Config) NoBionicPageSizeMacro() bool {
189	return Bool(c.config.productVariables.DeviceNoBionicPageSizeMacro)
190}
191
192// The release version passed to aconfig, derived from RELEASE_VERSION
193func (c Config) ReleaseVersion() string {
194	return c.config.productVariables.ReleaseVersion
195}
196
197// The aconfig value set passed to aconfig, derived from RELEASE_VERSION
198func (c Config) ReleaseAconfigValueSets() []string {
199	return c.config.productVariables.ReleaseAconfigValueSets
200}
201
202func (c Config) ReleaseAconfigExtraReleaseConfigs() []string {
203	result := []string{}
204	if val, ok := c.config.productVariables.BuildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"]; ok {
205		if len(val) > 0 {
206			// Remove any duplicates from the list.
207			found := make(map[string]bool)
208			for _, k := range strings.Split(val, " ") {
209				if !found[k] {
210					found[k] = true
211					result = append(result, k)
212				}
213			}
214		}
215	}
216	return result
217}
218
219func (c Config) ReleaseAconfigExtraReleaseConfigsValueSets() map[string][]string {
220	result := make(map[string][]string)
221	for _, rcName := range c.ReleaseAconfigExtraReleaseConfigs() {
222		if value, ok := c.config.productVariables.BuildFlags["RELEASE_ACONFIG_VALUE_SETS_"+rcName]; ok {
223			result[rcName] = strings.Split(value, " ")
224		}
225	}
226	return result
227}
228
229// The flag default permission value passed to aconfig
230// derived from RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION
231func (c Config) ReleaseAconfigFlagDefaultPermission() string {
232	return c.config.productVariables.ReleaseAconfigFlagDefaultPermission
233}
234
235// Enable object size sanitizer
236func (c Config) ReleaseBuildObjectSizeSanitizer() bool {
237	return c.config.productVariables.GetBuildFlagBool("RELEASE_BUILD_OBJECT_SIZE_SANITIZER")
238}
239
240// The flag indicating behavior for the tree wrt building modules or using prebuilts
241// derived from RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE
242func (c Config) ReleaseDefaultModuleBuildFromSource() bool {
243	return c.config.productVariables.ReleaseDefaultModuleBuildFromSource == nil ||
244		Bool(c.config.productVariables.ReleaseDefaultModuleBuildFromSource)
245}
246
247func (c Config) ReleaseDefaultUpdatableModuleVersion() string {
248	if val, exists := c.GetBuildFlag("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION"); exists {
249		return val
250	}
251	panic("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION is missing from build flags.")
252}
253
254func (c Config) ReleaseDisableVerifyOverlaps() bool {
255	return c.config.productVariables.GetBuildFlagBool("RELEASE_DISABLE_VERIFY_OVERLAPS_CHECK")
256}
257
258// Enables flagged apis annotated with READ_WRITE aconfig flags to be included in the stubs
259// and hiddenapi flags so that they are accessible at runtime
260func (c Config) ReleaseExportRuntimeApis() bool {
261	return Bool(c.config.productVariables.ExportRuntimeApis)
262}
263
264// Enables ABI monitoring of NDK libraries
265func (c Config) ReleaseNdkAbiMonitored() bool {
266	return c.config.productVariables.GetBuildFlagBool("RELEASE_NDK_ABI_MONITORED")
267}
268
269// Enable read flag from new storage, for C/C++
270func (c Config) ReleaseReadFromNewStorageCc() bool {
271	return c.config.productVariables.GetBuildFlagBool("RELEASE_READ_FROM_NEW_STORAGE_CC")
272}
273
274func (c Config) ReleaseHiddenApiExportableStubs() bool {
275	return c.config.productVariables.GetBuildFlagBool("RELEASE_HIDDEN_API_EXPORTABLE_STUBS") ||
276		Bool(c.config.productVariables.HiddenapiExportableStubs)
277}
278
279// Enable read flag from new storage
280func (c Config) ReleaseReadFromNewStorage() bool {
281	return c.config.productVariables.GetBuildFlagBool("RELEASE_READ_FROM_NEW_STORAGE")
282}
283
284func (c Config) ReleaseCreateAconfigStorageFile() bool {
285	return c.config.productVariables.GetBuildFlagBool("RELEASE_CREATE_ACONFIG_STORAGE_FILE")
286}
287
288func (c Config) ReleaseUseSystemFeatureBuildFlags() bool {
289	return c.config.productVariables.GetBuildFlagBool("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS")
290}
291
292// A DeviceConfig object represents the configuration for a particular device
293// being built. For now there will only be one of these, but in the future there
294// may be multiple devices being built.
295type DeviceConfig struct {
296	*deviceConfig
297}
298
299// VendorConfig represents the configuration for vendor-specific behavior.
300type VendorConfig soongconfig.SoongConfig
301
302// Definition of general build configuration for soong_build. Some of these
303// product configuration values are read from Kati-generated soong.variables.
304type config struct {
305	// Options configurable with soong.variables
306	productVariables ProductVariables
307
308	// Only available on configs created by TestConfig
309	TestProductVariables *ProductVariables
310
311	ProductVariablesFileName string
312
313	// BuildOS stores the OsType for the OS that the build is running on.
314	BuildOS OsType
315
316	// BuildArch stores the ArchType for the CPU that the build is running on.
317	BuildArch ArchType
318
319	Targets                  map[OsType][]Target
320	BuildOSTarget            Target // the Target for tools run on the build machine
321	BuildOSCommonTarget      Target // the Target for common (java) tools run on the build machine
322	AndroidCommonTarget      Target // the Target for common modules for the Android device
323	AndroidFirstDeviceTarget Target // the first Target for modules for the Android device
324
325	// Flags for Partial Compile, derived from SOONG_PARTIAL_COMPILE.
326	partialCompileFlags partialCompileFlags
327
328	// multilibConflicts for an ArchType is true if there is earlier configured
329	// device architecture with the same multilib value.
330	multilibConflicts map[ArchType]bool
331
332	deviceConfig *deviceConfig
333
334	outDir         string // The output directory (usually out/)
335	soongOutDir    string
336	moduleListFile string // the path to the file which lists blueprint files to parse.
337
338	runGoTests bool
339
340	env       map[string]string
341	envLock   sync.Mutex
342	envDeps   map[string]string
343	envFrozen bool
344
345	// Changes behavior based on whether Kati runs after soong_build, or if soong_build
346	// runs standalone.
347	katiEnabled bool
348
349	captureBuild      bool // true for tests, saves build parameters for each module
350	ignoreEnvironment bool // true for tests, returns empty from all Getenv calls
351
352	fs         pathtools.FileSystem
353	mockBpList string
354
355	BuildMode SoongBuildMode
356
357	// If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error
358	// in tests when a path doesn't exist.
359	TestAllowNonExistentPaths bool
360
361	// The list of files that when changed, must invalidate soong_build to
362	// regenerate build.ninja.
363	ninjaFileDepsSet sync.Map
364
365	OncePer
366
367	// If buildFromSourceStub is true then the Java API stubs are
368	// built from the source Java files, not the signature text files.
369	buildFromSourceStub bool
370
371	// If ensureAllowlistIntegrity is true, then the presence of any allowlisted
372	// modules that aren't mixed-built for at least one variant will cause a build
373	// failure
374	ensureAllowlistIntegrity bool
375}
376
377type partialCompileFlags struct {
378	// Is partial compilation enabled at all?
379	enabled bool
380
381	// Whether to use d8 instead of r8
382	use_d8 bool
383
384	// Add others as needed.
385}
386
387type deviceConfig struct {
388	config *config
389	OncePer
390}
391
392type jsonConfigurable interface {
393	SetDefaultConfig()
394}
395
396// Parse SOONG_PARTIAL_COMPILE.
397//
398// SOONG_PARTIAL_COMPILE determines which features are enabled or disabled in
399// rule generation.  Changing this environment variable causes reanalysis.
400//
401// SOONG_USE_PARTIAL_COMPILE determines whether or not we **use** PARTIAL_COMPILE.
402// Rule generation must support both cases, since changing it does not cause
403// reanalysis.
404//
405// The user-facing documentation shows:
406//
407// - empty or not set: "The current default state"
408// - "true" or "on": enable all stable partial compile features.
409// - "false" or "off": disable partial compile completely.
410//
411// What we actually allow is a comma separated list of tokens, whose first
412// character may be "+" (enable) or "-" (disable).  If neither is present, "+"
413// is assumed.  For example, "on,+use_d8" will enable partial compilation, and
414// additionally set the use_d8 flag (regardless of whether it is opt-in or
415// opt-out).
416//
417// To add a new feature to the list, add the field in the struct
418// `partialCompileFlags` above, and then add the name of the field in the
419// switch statement below.
420var defaultPartialCompileFlags = partialCompileFlags{
421	// Set any opt-out flags here.  Opt-in flags are off by default.
422	enabled: false,
423}
424
425func (c *config) parsePartialCompileFlags(isEngBuild bool) (partialCompileFlags, error) {
426	if !isEngBuild {
427		return partialCompileFlags{}, nil
428	}
429	value := c.Getenv("SOONG_PARTIAL_COMPILE")
430	if value == "" {
431		return defaultPartialCompileFlags, nil
432	}
433
434	ret := defaultPartialCompileFlags
435	tokens := strings.Split(strings.ToLower(value), ",")
436	makeVal := func(state string, defaultValue bool) bool {
437		switch state {
438		case "":
439			return defaultValue
440		case "-":
441			return false
442		case "+":
443			return true
444		}
445		return false
446	}
447	for _, tok := range tokens {
448		var state string
449		if len(tok) == 0 {
450			continue
451		}
452		switch tok[0:1] {
453		case "":
454			// Ignore empty tokens.
455			continue
456		case "-", "+":
457			state = tok[0:1]
458			tok = tok[1:]
459		default:
460			// Treat `feature` as `+feature`.
461			state = "+"
462		}
463		switch tok {
464		case "true":
465			ret = defaultPartialCompileFlags
466			ret.enabled = true
467		case "false":
468			// Set everything to false.
469			ret = partialCompileFlags{}
470		case "enabled":
471			ret.enabled = makeVal(state, defaultPartialCompileFlags.enabled)
472		case "use_d8":
473			ret.use_d8 = makeVal(state, defaultPartialCompileFlags.use_d8)
474		default:
475			return partialCompileFlags{}, fmt.Errorf("Unknown SOONG_PARTIAL_COMPILE value: %v", tok)
476		}
477	}
478	return ret, nil
479}
480
481func loadConfig(config *config) error {
482	return loadFromConfigFile(&config.productVariables, absolutePath(config.ProductVariablesFileName))
483}
484
485// Checks if the string is a valid go identifier. This is equivalent to blueprint's definition
486// of an identifier, so it will match the same identifiers as those that can be used in bp files.
487func isGoIdentifier(ident string) bool {
488	for i, r := range ident {
489		valid := r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) && i > 0
490		if !valid {
491			return false
492		}
493	}
494	return len(ident) > 0
495}
496
497// loadFromConfigFile loads and decodes configuration options from a JSON file
498// in the current working directory.
499func loadFromConfigFile(configurable *ProductVariables, filename string) error {
500	// Try to open the file
501	configFileReader, err := os.Open(filename)
502	defer configFileReader.Close()
503	if os.IsNotExist(err) {
504		// Need to create a file, so that blueprint & ninja don't get in
505		// a dependency tracking loop.
506		// Make a file-configurable-options with defaults, write it out using
507		// a json writer.
508		configurable.SetDefaultConfig()
509		err = saveToConfigFile(configurable, filename)
510		if err != nil {
511			return err
512		}
513	} else if err != nil {
514		return fmt.Errorf("config file: could not open %s: %s", filename, err.Error())
515	} else {
516		// Make a decoder for it
517		jsonDecoder := json.NewDecoder(configFileReader)
518		jsonDecoder.DisallowUnknownFields()
519		err = jsonDecoder.Decode(configurable)
520		if err != nil {
521			return fmt.Errorf("config file: %s did not parse correctly: %s", filename, err.Error())
522		}
523	}
524
525	if Bool(configurable.GcovCoverage) && Bool(configurable.ClangCoverage) {
526		return fmt.Errorf("GcovCoverage and ClangCoverage cannot both be set")
527	}
528
529	configurable.Native_coverage = proptools.BoolPtr(
530		Bool(configurable.GcovCoverage) ||
531			Bool(configurable.ClangCoverage))
532
533	// The go scanner's definition of identifiers is c-style identifiers, but allowing unicode's
534	// definition of letters and digits. This is the same scanner that blueprint uses, so it
535	// will allow the same identifiers as are valid in bp files.
536	for namespace := range configurable.VendorVars {
537		if !isGoIdentifier(namespace) {
538			return fmt.Errorf("soong config namespaces must be valid identifiers: %q", namespace)
539		}
540		for variable := range configurable.VendorVars[namespace] {
541			if !isGoIdentifier(variable) {
542				return fmt.Errorf("soong config variables must be valid identifiers: %q", variable)
543			}
544		}
545	}
546
547	// when Platform_sdk_final is true (or PLATFORM_VERSION_CODENAME is REL), use Platform_sdk_version;
548	// if false (pre-released version, for example), use Platform_sdk_codename.
549	if Bool(configurable.Platform_sdk_final) {
550		if configurable.Platform_sdk_version != nil {
551			configurable.Platform_sdk_version_or_codename =
552				proptools.StringPtr(strconv.Itoa(*(configurable.Platform_sdk_version)))
553		} else {
554			return fmt.Errorf("Platform_sdk_version cannot be pointed by a NULL pointer")
555		}
556	} else {
557		configurable.Platform_sdk_version_or_codename =
558			proptools.StringPtr(String(configurable.Platform_sdk_codename))
559	}
560
561	return nil
562}
563
564// atomically writes the config file in case two copies of soong_build are running simultaneously
565// (for example, docs generation and ninja manifest generation)
566func saveToConfigFile(config *ProductVariables, filename string) error {
567	data, err := json.MarshalIndent(&config, "", "    ")
568	if err != nil {
569		return fmt.Errorf("cannot marshal config data: %s", err.Error())
570	}
571
572	f, err := os.CreateTemp(filepath.Dir(filename), "config")
573	if err != nil {
574		return fmt.Errorf("cannot create empty config file %s: %s", filename, err.Error())
575	}
576	defer os.Remove(f.Name())
577	defer f.Close()
578
579	_, err = f.Write(data)
580	if err != nil {
581		return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
582	}
583
584	_, err = f.WriteString("\n")
585	if err != nil {
586		return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
587	}
588
589	f.Close()
590	os.Rename(f.Name(), filename)
591
592	return nil
593}
594
595// NullConfig returns a mostly empty Config for use by standalone tools like dexpreopt_gen that
596// use the android package.
597func NullConfig(outDir, soongOutDir string) Config {
598	return Config{
599		config: &config{
600			outDir:      outDir,
601			soongOutDir: soongOutDir,
602			fs:          pathtools.OsFs,
603		},
604	}
605}
606
607// NewConfig creates a new Config object. The srcDir argument specifies the path
608// to the root source directory. It also loads the config file, if found.
609func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) {
610	// Make a config with default options.
611	config := &config{
612		ProductVariablesFileName: cmdArgs.SoongVariables,
613
614		env: availableEnv,
615
616		outDir:            cmdArgs.OutDir,
617		soongOutDir:       cmdArgs.SoongOutDir,
618		runGoTests:        cmdArgs.RunGoTests,
619		multilibConflicts: make(map[ArchType]bool),
620
621		moduleListFile: cmdArgs.ModuleListFile,
622		fs:             pathtools.NewOsFs(absSrcDir),
623
624		buildFromSourceStub: cmdArgs.BuildFromSourceStub,
625	}
626	variant, ok := os.LookupEnv("TARGET_BUILD_VARIANT")
627	isEngBuild := !ok || variant == "eng"
628
629	config.deviceConfig = &deviceConfig{
630		config: config,
631	}
632
633	// Soundness check of the build and source directories. This won't catch strange
634	// configurations with symlinks, but at least checks the obvious case.
635	absBuildDir, err := filepath.Abs(cmdArgs.SoongOutDir)
636	if err != nil {
637		return Config{}, err
638	}
639
640	absSrcDir, err := filepath.Abs(".")
641	if err != nil {
642		return Config{}, err
643	}
644
645	if strings.HasPrefix(absSrcDir, absBuildDir) {
646		return Config{}, fmt.Errorf("Build dir must not contain source directory")
647	}
648
649	// Load any configurable options from the configuration file
650	err = loadConfig(config)
651	if err != nil {
652		return Config{}, err
653	}
654
655	KatiEnabledMarkerFile := filepath.Join(cmdArgs.SoongOutDir, ".soong.kati_enabled")
656	if _, err := os.Stat(absolutePath(KatiEnabledMarkerFile)); err == nil {
657		config.katiEnabled = true
658	}
659
660	determineBuildOS(config)
661
662	// Sets up the map of target OSes to the finer grained compilation targets
663	// that are configured from the product variables.
664	targets, err := decodeTargetProductVariables(config)
665	if err != nil {
666		return Config{}, err
667	}
668
669	config.partialCompileFlags, err = config.parsePartialCompileFlags(isEngBuild)
670	if err != nil {
671		return Config{}, err
672	}
673
674	// Make the CommonOS OsType available for all products.
675	targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]}
676
677	var archConfig []archConfig
678	if config.NdkAbis() {
679		archConfig = getNdkAbisConfig()
680	} else if config.AmlAbis() {
681		archConfig = getAmlAbisConfig()
682	}
683
684	if archConfig != nil {
685		androidTargets, err := decodeAndroidArchSettings(archConfig)
686		if err != nil {
687			return Config{}, err
688		}
689		targets[Android] = androidTargets
690	}
691
692	multilib := make(map[string]bool)
693	for _, target := range targets[Android] {
694		if seen := multilib[target.Arch.ArchType.Multilib]; seen {
695			config.multilibConflicts[target.Arch.ArchType] = true
696		}
697		multilib[target.Arch.ArchType.Multilib] = true
698	}
699
700	// Map of OS to compilation targets.
701	config.Targets = targets
702
703	// Compilation targets for host tools.
704	config.BuildOSTarget = config.Targets[config.BuildOS][0]
705	config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
706
707	// Compilation targets for Android.
708	if len(config.Targets[Android]) > 0 {
709		config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
710		config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
711	}
712
713	setBuildMode := func(arg string, mode SoongBuildMode) {
714		if arg != "" {
715			if config.BuildMode != AnalysisNoBazel {
716				fmt.Fprintf(os.Stderr, "buildMode is already set, illegal argument: %s", arg)
717				os.Exit(1)
718			}
719			config.BuildMode = mode
720		}
721	}
722	setBuildMode(cmdArgs.ModuleGraphFile, GenerateModuleGraph)
723	setBuildMode(cmdArgs.DocFile, GenerateDocFile)
724
725	config.productVariables.Build_from_text_stub = boolPtr(config.BuildFromTextStub())
726
727	return Config{config}, err
728}
729
730// mockFileSystem replaces all reads with accesses to the provided map of
731// filenames to contents stored as a byte slice.
732func (c *config) mockFileSystem(bp string, fs map[string][]byte) {
733	mockFS := map[string][]byte{}
734
735	if _, exists := mockFS["Android.bp"]; !exists {
736		mockFS["Android.bp"] = []byte(bp)
737	}
738
739	for k, v := range fs {
740		mockFS[k] = v
741	}
742
743	// no module list file specified; find every file named Blueprints or Android.bp
744	pathsToParse := []string{}
745	for candidate := range mockFS {
746		base := filepath.Base(candidate)
747		if base == "Android.bp" {
748			pathsToParse = append(pathsToParse, candidate)
749		}
750	}
751	if len(pathsToParse) < 1 {
752		panic(fmt.Sprintf("No Blueprint or Android.bp files found in mock filesystem: %v\n", mockFS))
753	}
754	mockFS[blueprint.MockModuleListFile] = []byte(strings.Join(pathsToParse, "\n"))
755
756	c.fs = pathtools.MockFs(mockFS)
757	c.mockBpList = blueprint.MockModuleListFile
758}
759
760func (c *config) SetAllowMissingDependencies() {
761	c.productVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
762}
763
764// BlueprintToolLocation returns the directory containing build system tools
765// from Blueprint, like soong_zip and merge_zips.
766func (c *config) HostToolDir() string {
767	if c.KatiEnabled() {
768		return filepath.Join(c.outDir, "host", c.PrebuiltOS(), "bin")
769	} else {
770		return filepath.Join(c.soongOutDir, "host", c.PrebuiltOS(), "bin")
771	}
772}
773
774func (c *config) HostToolPath(ctx PathContext, tool string) Path {
775	path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", tool)
776	return path
777}
778
779func (c *config) HostJNIToolPath(ctx PathContext, lib string) Path {
780	ext := ".so"
781	if runtime.GOOS == "darwin" {
782		ext = ".dylib"
783	}
784	path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "lib64", lib+ext)
785	return path
786}
787
788func (c *config) HostJavaToolPath(ctx PathContext, tool string) Path {
789	path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "framework", tool)
790	return path
791}
792
793func (c *config) HostCcSharedLibPath(ctx PathContext, lib string) Path {
794	libDir := "lib"
795	if ctx.Config().BuildArch.Multilib == "lib64" {
796		libDir = "lib64"
797	}
798	return pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, libDir, lib+".so")
799}
800
801// PrebuiltOS returns the name of the host OS used in prebuilts directories.
802func (c *config) PrebuiltOS() string {
803	switch runtime.GOOS {
804	case "linux":
805		return "linux-x86"
806	case "darwin":
807		return "darwin-x86"
808	default:
809		panic("Unknown GOOS")
810	}
811}
812
813// GoRoot returns the path to the root directory of the Go toolchain.
814func (c *config) GoRoot() string {
815	return fmt.Sprintf("prebuilts/go/%s", c.PrebuiltOS())
816}
817
818// PrebuiltBuildTool returns the path to a tool in the prebuilts directory containing
819// checked-in tools, like Kati, Ninja or Toybox, for the current host OS.
820func (c *config) PrebuiltBuildTool(ctx PathContext, tool string) Path {
821	return PathForSource(ctx, "prebuilts/build-tools", c.PrebuiltOS(), "bin", tool)
822}
823
824// CpPreserveSymlinksFlags returns the host-specific flag for the cp(1) command
825// to preserve symlinks.
826func (c *config) CpPreserveSymlinksFlags() string {
827	switch runtime.GOOS {
828	case "darwin":
829		return "-R"
830	case "linux":
831		return "-d"
832	default:
833		return ""
834	}
835}
836
837func (c *config) Getenv(key string) string {
838	var val string
839	var exists bool
840	c.envLock.Lock()
841	defer c.envLock.Unlock()
842	if c.envDeps == nil {
843		c.envDeps = make(map[string]string)
844	}
845	if val, exists = c.envDeps[key]; !exists {
846		if c.envFrozen {
847			panic("Cannot access new environment variables after envdeps are frozen")
848		}
849		val, _ = c.env[key]
850		c.envDeps[key] = val
851	}
852	return val
853}
854
855func (c *config) GetenvWithDefault(key string, defaultValue string) string {
856	ret := c.Getenv(key)
857	if ret == "" {
858		return defaultValue
859	}
860	return ret
861}
862
863func (c *config) IsEnvTrue(key string) bool {
864	value := strings.ToLower(c.Getenv(key))
865	return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
866}
867
868func (c *config) IsEnvFalse(key string) bool {
869	value := strings.ToLower(c.Getenv(key))
870	return value == "0" || value == "n" || value == "no" || value == "off" || value == "false"
871}
872
873func (c *config) TargetsJava21() bool {
874	return c.productVariables.GetBuildFlagBool("RELEASE_TARGET_JAVA_21")
875}
876
877// EnvDeps returns the environment variables this build depends on. The first
878// call to this function blocks future reads from the environment.
879func (c *config) EnvDeps() map[string]string {
880	c.envLock.Lock()
881	defer c.envLock.Unlock()
882	c.envFrozen = true
883	return c.envDeps
884}
885
886func (c *config) KatiEnabled() bool {
887	return c.katiEnabled
888}
889
890func (c *config) ProductVariables() ProductVariables {
891	return c.productVariables
892}
893
894func (c *config) BuildId() string {
895	return String(c.productVariables.BuildId)
896}
897
898func (c *config) DisplayBuildNumber() bool {
899	return Bool(c.productVariables.DisplayBuildNumber)
900}
901
902// BuildFingerprintFile returns the path to a text file containing metadata
903// representing the current build's fingerprint.
904//
905// Rules that want to reference the build fingerprint should read from this file
906// without depending on it. They will run whenever their other dependencies
907// require them to run and get the current build fingerprint. This ensures they
908// don't rebuild on every incremental build when the build number changes.
909func (c *config) BuildFingerprintFile(ctx PathContext) Path {
910	return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildFingerprintFile))
911}
912
913// BuildNumberFile returns the path to a text file containing metadata
914// representing the current build's number.
915//
916// Rules that want to reference the build number should read from this file
917// without depending on it. They will run whenever their other dependencies
918// require them to run and get the current build number. This ensures they don't
919// rebuild on every incremental build when the build number changes.
920func (c *config) BuildNumberFile(ctx PathContext) Path {
921	return PathForOutput(ctx, String(c.productVariables.BuildNumberFile))
922}
923
924// BuildHostnameFile returns the path to a text file containing metadata
925// representing the current build's host name.
926func (c *config) BuildHostnameFile(ctx PathContext) Path {
927	return PathForOutput(ctx, String(c.productVariables.BuildHostnameFile))
928}
929
930// BuildThumbprintFile returns the path to a text file containing metadata
931// representing the current build's thumbprint.
932//
933// Rules that want to reference the build thumbprint should read from this file
934// without depending on it. They will run whenever their other dependencies
935// require them to run and get the current build thumbprint. This ensures they
936// don't rebuild on every incremental build when the build thumbprint changes.
937func (c *config) BuildThumbprintFile(ctx PathContext) Path {
938	return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildThumbprintFile))
939}
940
941// DeviceName returns the name of the current device target.
942// TODO: take an AndroidModuleContext to select the device name for multi-device builds
943func (c *config) DeviceName() string {
944	return *c.productVariables.DeviceName
945}
946
947// DeviceProduct returns the current product target. There could be multiple of
948// these per device type.
949//
950// NOTE: Do not base conditional logic on this value. It may break product inheritance.
951func (c *config) DeviceProduct() string {
952	return *c.productVariables.DeviceProduct
953}
954
955// HasDeviceProduct returns if the build has a product. A build will not
956// necessarily have a product when --skip-config is passed to soong, like it is
957// in prebuilts/build-tools/build-prebuilts.sh
958func (c *config) HasDeviceProduct() bool {
959	return c.productVariables.DeviceProduct != nil
960}
961
962func (c *config) DeviceAbi() []string {
963	return c.productVariables.DeviceAbi
964}
965
966func (c *config) DeviceResourceOverlays() []string {
967	return c.productVariables.DeviceResourceOverlays
968}
969
970func (c *config) ProductResourceOverlays() []string {
971	return c.productVariables.ProductResourceOverlays
972}
973
974func (c *config) PlatformDisplayVersionName() string {
975	return String(c.productVariables.Platform_display_version_name)
976}
977
978func (c *config) PlatformVersionName() string {
979	return String(c.productVariables.Platform_version_name)
980}
981
982func (c *config) PlatformSdkVersion() ApiLevel {
983	return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
984}
985
986func (c *config) RawPlatformSdkVersion() *int {
987	return c.productVariables.Platform_sdk_version
988}
989
990func (c *config) PlatformSdkFinal() bool {
991	return Bool(c.productVariables.Platform_sdk_final)
992}
993
994func (c *config) PlatformSdkCodename() string {
995	return String(c.productVariables.Platform_sdk_codename)
996}
997
998func (c *config) PlatformSdkExtensionVersion() int {
999	return *c.productVariables.Platform_sdk_extension_version
1000}
1001
1002func (c *config) PlatformBaseSdkExtensionVersion() int {
1003	return *c.productVariables.Platform_base_sdk_extension_version
1004}
1005
1006func (c *config) PlatformSecurityPatch() string {
1007	return String(c.productVariables.Platform_security_patch)
1008}
1009
1010func (c *config) PlatformPreviewSdkVersion() string {
1011	return String(c.productVariables.Platform_preview_sdk_version)
1012}
1013
1014func (c *config) PlatformMinSupportedTargetSdkVersion() string {
1015	var val, ok = c.productVariables.BuildFlags["RELEASE_PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION"]
1016	if !ok {
1017		return ""
1018	}
1019	return val
1020}
1021
1022func (c *config) PlatformBaseOS() string {
1023	return String(c.productVariables.Platform_base_os)
1024}
1025
1026func (c *config) PlatformVersionLastStable() string {
1027	return String(c.productVariables.Platform_version_last_stable)
1028}
1029
1030func (c *config) PlatformVersionKnownCodenames() string {
1031	return String(c.productVariables.Platform_version_known_codenames)
1032}
1033
1034func (c *config) MinSupportedSdkVersion() ApiLevel {
1035	return uncheckedFinalApiLevel(21)
1036}
1037
1038func (c *config) FinalApiLevels() []ApiLevel {
1039	var levels []ApiLevel
1040	for i := 1; i <= c.PlatformSdkVersion().FinalOrFutureInt(); i++ {
1041		levels = append(levels, uncheckedFinalApiLevel(i))
1042	}
1043	return levels
1044}
1045
1046func (c *config) PreviewApiLevels() []ApiLevel {
1047	var levels []ApiLevel
1048	i := 0
1049	for _, codename := range c.PlatformVersionActiveCodenames() {
1050		if codename == "REL" {
1051			continue
1052		}
1053
1054		levels = append(levels, ApiLevel{
1055			value:     codename,
1056			number:    i,
1057			isPreview: true,
1058		})
1059		i++
1060	}
1061	return levels
1062}
1063
1064func (c *config) LatestPreviewApiLevel() ApiLevel {
1065	level := NoneApiLevel
1066	for _, l := range c.PreviewApiLevels() {
1067		if l.GreaterThan(level) {
1068			level = l
1069		}
1070	}
1071	return level
1072}
1073
1074func (c *config) AllSupportedApiLevels() []ApiLevel {
1075	var levels []ApiLevel
1076	levels = append(levels, c.FinalApiLevels()...)
1077	return append(levels, c.PreviewApiLevels()...)
1078}
1079
1080// DefaultAppTargetSdk returns the API level that platform apps are targeting.
1081// This converts a codename to the exact ApiLevel it represents.
1082func (c *config) DefaultAppTargetSdk(ctx EarlyModuleContext) ApiLevel {
1083	if Bool(c.productVariables.Platform_sdk_final) {
1084		return c.PlatformSdkVersion()
1085	}
1086	codename := c.PlatformSdkCodename()
1087	hostOnlyBuild := c.productVariables.DeviceArch == nil
1088	if codename == "" {
1089		// There are some host-only builds (those are invoked by build-prebuilts.sh) which
1090		// don't set platform sdk codename. Platform sdk codename makes sense only when we
1091		// are building the platform. So we don't enforce the below panic for the host-only
1092		// builds.
1093		if hostOnlyBuild {
1094			return NoneApiLevel
1095		}
1096		panic("Platform_sdk_codename must be set")
1097	}
1098	if codename == "REL" {
1099		panic("Platform_sdk_codename should not be REL when Platform_sdk_final is true")
1100	}
1101	return ApiLevelOrPanic(ctx, codename)
1102}
1103
1104func (c *config) PartialCompileFlags() partialCompileFlags {
1105	return c.partialCompileFlags
1106}
1107
1108func (c *config) AppsDefaultVersionName() string {
1109	return String(c.productVariables.AppsDefaultVersionName)
1110}
1111
1112// Codenames that are active in the current lunch target.
1113func (c *config) PlatformVersionActiveCodenames() []string {
1114	return c.productVariables.Platform_version_active_codenames
1115}
1116
1117// All unreleased codenames.
1118func (c *config) PlatformVersionAllPreviewCodenames() []string {
1119	return c.productVariables.Platform_version_all_preview_codenames
1120}
1121
1122func (c *config) ProductAAPTConfig() []string {
1123	return c.productVariables.AAPTConfig
1124}
1125
1126func (c *config) ProductAAPTPreferredConfig() string {
1127	return String(c.productVariables.AAPTPreferredConfig)
1128}
1129
1130func (c *config) ProductAAPTCharacteristics() string {
1131	return String(c.productVariables.AAPTCharacteristics)
1132}
1133
1134func (c *config) ProductAAPTPrebuiltDPI() []string {
1135	return c.productVariables.AAPTPrebuiltDPI
1136}
1137
1138func (c *config) DefaultAppCertificateDir(ctx PathContext) SourcePath {
1139	defaultCert := String(c.productVariables.DefaultAppCertificate)
1140	if defaultCert != "" {
1141		return PathForSource(ctx, filepath.Dir(defaultCert))
1142	}
1143	return PathForSource(ctx, testKeyDir)
1144}
1145
1146func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) {
1147	defaultCert := String(c.productVariables.DefaultAppCertificate)
1148	if defaultCert != "" {
1149		return PathForSource(ctx, defaultCert+".x509.pem"), PathForSource(ctx, defaultCert+".pk8")
1150	}
1151	defaultDir := c.DefaultAppCertificateDir(ctx)
1152	return defaultDir.Join(ctx, "testkey.x509.pem"), defaultDir.Join(ctx, "testkey.pk8")
1153}
1154
1155func (c *config) ExtraOtaKeys(ctx PathContext, recovery bool) []SourcePath {
1156	var otaKeys []string
1157	if recovery {
1158		otaKeys = c.productVariables.ExtraOtaRecoveryKeys
1159	} else {
1160		otaKeys = c.productVariables.ExtraOtaKeys
1161	}
1162
1163	otaPaths := make([]SourcePath, len(otaKeys))
1164	for i, key := range otaKeys {
1165		otaPaths[i] = PathForSource(ctx, key+".x509.pem")
1166	}
1167
1168	return otaPaths
1169}
1170
1171func (c *config) BuildKeys() string {
1172	defaultCert := String(c.productVariables.DefaultAppCertificate)
1173	if defaultCert == "" || defaultCert == filepath.Join(testKeyDir, "testkey") {
1174		return "test-keys"
1175	}
1176	return "dev-keys"
1177}
1178
1179func (c *config) ApexKeyDir(ctx ModuleContext) SourcePath {
1180	// TODO(b/121224311): define another variable such as TARGET_APEX_KEY_OVERRIDE
1181	defaultCert := String(c.productVariables.DefaultAppCertificate)
1182	if defaultCert == "" || filepath.Dir(defaultCert) == testKeyDir {
1183		// When defaultCert is unset or is set to the testkeys path, use the APEX keys
1184		// that is under the module dir
1185		return pathForModuleSrc(ctx)
1186	}
1187	// If not, APEX keys are under the specified directory
1188	return PathForSource(ctx, filepath.Dir(defaultCert))
1189}
1190
1191// Certificate for the NetworkStack sepolicy context
1192func (c *config) MainlineSepolicyDevCertificatesDir(ctx ModuleContext) SourcePath {
1193	cert := String(c.productVariables.MainlineSepolicyDevCertificates)
1194	if cert != "" {
1195		return PathForSource(ctx, cert)
1196	}
1197	return c.DefaultAppCertificateDir(ctx)
1198}
1199
1200// AllowMissingDependencies configures Blueprint/Soong to not fail when modules
1201// are configured to depend on non-existent modules. Note that this does not
1202// affect missing input dependencies at the Ninja level.
1203func (c *config) AllowMissingDependencies() bool {
1204	return Bool(c.productVariables.Allow_missing_dependencies)
1205}
1206
1207// Returns true if a full platform source tree cannot be assumed.
1208func (c *config) UnbundledBuild() bool {
1209	return Bool(c.productVariables.Unbundled_build)
1210}
1211
1212// Returns true if building apps that aren't bundled with the platform.
1213// UnbundledBuild() is always true when this is true.
1214func (c *config) UnbundledBuildApps() bool {
1215	return len(c.productVariables.Unbundled_build_apps) > 0
1216}
1217
1218// Returns true if building image that aren't bundled with the platform.
1219// UnbundledBuild() is always true when this is true.
1220func (c *config) UnbundledBuildImage() bool {
1221	return Bool(c.productVariables.Unbundled_build_image)
1222}
1223
1224// Returns true if building modules against prebuilt SDKs.
1225func (c *config) AlwaysUsePrebuiltSdks() bool {
1226	return Bool(c.productVariables.Always_use_prebuilt_sdks)
1227}
1228
1229func (c *config) MinimizeJavaDebugInfo() bool {
1230	return Bool(c.productVariables.MinimizeJavaDebugInfo) && !Bool(c.productVariables.Eng)
1231}
1232
1233func (c *config) Debuggable() bool {
1234	return Bool(c.productVariables.Debuggable)
1235}
1236
1237func (c *config) Eng() bool {
1238	return Bool(c.productVariables.Eng)
1239}
1240
1241func (c *config) BuildType() string {
1242	return String(c.productVariables.BuildType)
1243}
1244
1245// DevicePrimaryArchType returns the ArchType for the first configured device architecture, or
1246// Common if there are no device architectures.
1247func (c *config) DevicePrimaryArchType() ArchType {
1248	if androidTargets := c.Targets[Android]; len(androidTargets) > 0 {
1249		return androidTargets[0].Arch.ArchType
1250	}
1251	return Common
1252}
1253
1254func (c *config) SanitizeHost() []string {
1255	return append([]string(nil), c.productVariables.SanitizeHost...)
1256}
1257
1258func (c *config) SanitizeDevice() []string {
1259	return append([]string(nil), c.productVariables.SanitizeDevice...)
1260}
1261
1262func (c *config) SanitizeDeviceDiag() []string {
1263	return append([]string(nil), c.productVariables.SanitizeDeviceDiag...)
1264}
1265
1266func (c *config) SanitizeDeviceArch() []string {
1267	return append([]string(nil), c.productVariables.SanitizeDeviceArch...)
1268}
1269
1270func (c *config) EnableCFI() bool {
1271	if c.productVariables.EnableCFI == nil {
1272		return true
1273	}
1274	return *c.productVariables.EnableCFI
1275}
1276
1277func (c *config) DisableScudo() bool {
1278	return Bool(c.productVariables.DisableScudo)
1279}
1280
1281func (c *config) Android64() bool {
1282	for _, t := range c.Targets[Android] {
1283		if t.Arch.ArchType.Multilib == "lib64" {
1284			return true
1285		}
1286	}
1287
1288	return false
1289}
1290
1291func (c *config) UseGoma() bool {
1292	return Bool(c.productVariables.UseGoma)
1293}
1294
1295func (c *config) UseABFS() bool {
1296	return Bool(c.productVariables.UseABFS)
1297}
1298
1299func (c *config) UseRBE() bool {
1300	return Bool(c.productVariables.UseRBE)
1301}
1302
1303func (c *config) UseRBEJAVAC() bool {
1304	return Bool(c.productVariables.UseRBEJAVAC)
1305}
1306
1307func (c *config) UseRBER8() bool {
1308	return Bool(c.productVariables.UseRBER8)
1309}
1310
1311func (c *config) UseRBED8() bool {
1312	return Bool(c.productVariables.UseRBED8)
1313}
1314
1315func (c *config) UseRemoteBuild() bool {
1316	return c.UseGoma() || c.UseRBE()
1317}
1318
1319func (c *config) RunErrorProne() bool {
1320	return c.IsEnvTrue("RUN_ERROR_PRONE")
1321}
1322
1323// XrefCorpusName returns the Kythe cross-reference corpus name.
1324func (c *config) XrefCorpusName() string {
1325	return c.Getenv("XREF_CORPUS")
1326}
1327
1328// XrefCuEncoding returns the compilation unit encoding to use for Kythe code
1329// xrefs. Can be 'json' (default), 'proto' or 'all'.
1330func (c *config) XrefCuEncoding() string {
1331	if enc := c.Getenv("KYTHE_KZIP_ENCODING"); enc != "" {
1332		return enc
1333	}
1334	return "json"
1335}
1336
1337// XrefCuJavaSourceMax returns the maximum number of the Java source files
1338// in a single compilation unit
1339const xrefJavaSourceFileMaxDefault = "1000"
1340
1341func (c Config) XrefCuJavaSourceMax() string {
1342	v := c.Getenv("KYTHE_JAVA_SOURCE_BATCH_SIZE")
1343	if v == "" {
1344		return xrefJavaSourceFileMaxDefault
1345	}
1346	if _, err := strconv.ParseUint(v, 0, 0); err != nil {
1347		fmt.Fprintf(os.Stderr,
1348			"bad KYTHE_JAVA_SOURCE_BATCH_SIZE value: %s, will use %s",
1349			err, xrefJavaSourceFileMaxDefault)
1350		return xrefJavaSourceFileMaxDefault
1351	}
1352	return v
1353
1354}
1355
1356func (c *config) EmitXrefRules() bool {
1357	return c.XrefCorpusName() != ""
1358}
1359
1360func (c *config) ClangTidy() bool {
1361	return Bool(c.productVariables.ClangTidy)
1362}
1363
1364func (c *config) TidyChecks() string {
1365	if c.productVariables.TidyChecks == nil {
1366		return ""
1367	}
1368	return *c.productVariables.TidyChecks
1369}
1370
1371func (c *config) LibartImgHostBaseAddress() string {
1372	return "0x70000000"
1373}
1374
1375func (c *config) LibartImgDeviceBaseAddress() string {
1376	return "0x70000000"
1377}
1378
1379func (c *config) ArtUseReadBarrier() bool {
1380	return Bool(c.productVariables.ArtUseReadBarrier)
1381}
1382
1383// Enforce Runtime Resource Overlays for a module. RROs supersede static RROs,
1384// but some modules still depend on it.
1385//
1386// More info: https://source.android.com/devices/architecture/rros
1387func (c *config) EnforceRROForModule(name string) bool {
1388	enforceList := c.productVariables.EnforceRROTargets
1389
1390	if len(enforceList) > 0 {
1391		if InList("*", enforceList) {
1392			return true
1393		}
1394		return InList(name, enforceList)
1395	}
1396	return false
1397}
1398
1399func (c *config) EnforceRROExcludedOverlay(path string) bool {
1400	excluded := c.productVariables.EnforceRROExcludedOverlays
1401	if len(excluded) > 0 {
1402		return HasAnyPrefix(path, excluded)
1403	}
1404	return false
1405}
1406
1407func (c *config) EnforceRROGlobally() bool {
1408	enforceList := c.productVariables.EnforceRROTargets
1409	return InList("*", enforceList)
1410}
1411
1412func (c *config) ExportedNamespaces() []string {
1413	return append([]string(nil), c.productVariables.NamespacesToExport...)
1414}
1415
1416func (c *config) SourceRootDirs() []string {
1417	return c.productVariables.SourceRootDirs
1418}
1419
1420func (c *config) HostStaticBinaries() bool {
1421	return Bool(c.productVariables.HostStaticBinaries)
1422}
1423
1424func (c *config) UncompressPrivAppDex() bool {
1425	return Bool(c.productVariables.UncompressPrivAppDex)
1426}
1427
1428func (c *config) ModulesLoadedByPrivilegedModules() []string {
1429	return c.productVariables.ModulesLoadedByPrivilegedModules
1430}
1431
1432// DexpreoptGlobalConfigPath returns the path to the dexpreopt.config file in
1433// the output directory, if it was created during the product configuration
1434// phase by Kati.
1435func (c *config) DexpreoptGlobalConfigPath(ctx PathContext) OptionalPath {
1436	if c.productVariables.DexpreoptGlobalConfig == nil {
1437		return OptionalPathForPath(nil)
1438	}
1439	return OptionalPathForPath(
1440		pathForBuildToolDep(ctx, *c.productVariables.DexpreoptGlobalConfig))
1441}
1442
1443// DexpreoptGlobalConfig returns the raw byte contents of the dexpreopt global
1444// configuration. Since the configuration file was created by Kati during
1445// product configuration (externally of soong_build), it's not tracked, so we
1446// also manually add a Ninja file dependency on the configuration file to the
1447// rule that creates the main build.ninja file. This ensures that build.ninja is
1448// regenerated correctly if dexpreopt.config changes.
1449func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) {
1450	path := c.DexpreoptGlobalConfigPath(ctx)
1451	if !path.Valid() {
1452		return nil, nil
1453	}
1454	ctx.AddNinjaFileDeps(path.String())
1455	return os.ReadFile(absolutePath(path.String()))
1456}
1457
1458func (c *deviceConfig) WithDexpreopt() bool {
1459	return c.config.productVariables.WithDexpreopt
1460}
1461
1462func (c *config) FrameworksBaseDirExists(ctx PathGlobContext) bool {
1463	return ExistentPathForSource(ctx, "frameworks", "base", "Android.bp").Valid()
1464}
1465
1466func (c *config) HasMultilibConflict(arch ArchType) bool {
1467	return c.multilibConflicts[arch]
1468}
1469
1470func (c *config) PrebuiltHiddenApiDir(_ PathContext) string {
1471	return String(c.productVariables.PrebuiltHiddenApiDir)
1472}
1473
1474func (c *config) VendorApiLevel() string {
1475	return String(c.productVariables.VendorApiLevel)
1476}
1477
1478func (c *config) PrevVendorApiLevel() string {
1479	vendorApiLevel, err := strconv.Atoi(c.VendorApiLevel())
1480	if err != nil {
1481		panic(fmt.Errorf("Cannot parse vendor API level %s to an integer: %s",
1482			c.VendorApiLevel(), err))
1483	}
1484	// The version before trunk stable is 34.
1485	if vendorApiLevel == 202404 {
1486		return "34"
1487	}
1488	if vendorApiLevel >= 1 && vendorApiLevel <= 34 {
1489		return strconv.Itoa(vendorApiLevel - 1)
1490	}
1491	if vendorApiLevel < 202404 || vendorApiLevel%100 != 4 {
1492		panic("Unknown vendor API level " + c.VendorApiLevel())
1493	}
1494	return strconv.Itoa(vendorApiLevel - 100)
1495}
1496
1497func IsTrunkStableVendorApiLevel(level string) bool {
1498	levelInt, err := strconv.Atoi(level)
1499	return err == nil && levelInt >= 202404
1500}
1501
1502func (c *config) VendorApiLevelFrozen() bool {
1503	return c.productVariables.GetBuildFlagBool("RELEASE_BOARD_API_LEVEL_FROZEN")
1504}
1505
1506func (c *deviceConfig) Arches() []Arch {
1507	var arches []Arch
1508	for _, target := range c.config.Targets[Android] {
1509		arches = append(arches, target.Arch)
1510	}
1511	return arches
1512}
1513
1514func (c *deviceConfig) BinderBitness() string {
1515	is32BitBinder := c.config.productVariables.Binder32bit
1516	if is32BitBinder != nil && *is32BitBinder {
1517		return "32"
1518	}
1519	return "64"
1520}
1521
1522func (c *deviceConfig) RecoveryPath() string {
1523	if c.config.productVariables.RecoveryPath != nil {
1524		return *c.config.productVariables.RecoveryPath
1525	}
1526	return "recovery"
1527}
1528
1529func (c *deviceConfig) VendorPath() string {
1530	if c.config.productVariables.VendorPath != nil {
1531		return *c.config.productVariables.VendorPath
1532	}
1533	return "vendor"
1534}
1535
1536func (c *deviceConfig) VendorDlkmPath() string {
1537	if c.config.productVariables.VendorDlkmPath != nil {
1538		return *c.config.productVariables.VendorDlkmPath
1539	}
1540	return "vendor_dlkm"
1541}
1542
1543func (c *deviceConfig) BuildingVendorImage() bool {
1544	return proptools.Bool(c.config.productVariables.BuildingVendorImage)
1545}
1546
1547func (c *deviceConfig) CurrentApiLevelForVendorModules() string {
1548	return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current")
1549}
1550
1551func (c *deviceConfig) ExtraVndkVersions() []string {
1552	return c.config.productVariables.ExtraVndkVersions
1553}
1554
1555func (c *deviceConfig) SystemSdkVersions() []string {
1556	return c.config.productVariables.DeviceSystemSdkVersions
1557}
1558
1559func (c *deviceConfig) PlatformSystemSdkVersions() []string {
1560	return c.config.productVariables.Platform_systemsdk_versions
1561}
1562
1563func (c *deviceConfig) OdmPath() string {
1564	if c.config.productVariables.OdmPath != nil {
1565		return *c.config.productVariables.OdmPath
1566	}
1567	return "odm"
1568}
1569
1570func (c *deviceConfig) BuildingOdmImage() bool {
1571	return proptools.Bool(c.config.productVariables.BuildingOdmImage)
1572}
1573
1574func (c *deviceConfig) OdmDlkmPath() string {
1575	if c.config.productVariables.OdmDlkmPath != nil {
1576		return *c.config.productVariables.OdmDlkmPath
1577	}
1578	return "odm_dlkm"
1579}
1580
1581func (c *deviceConfig) ProductPath() string {
1582	if c.config.productVariables.ProductPath != nil {
1583		return *c.config.productVariables.ProductPath
1584	}
1585	return "product"
1586}
1587
1588func (c *deviceConfig) BuildingProductImage() bool {
1589	return proptools.Bool(c.config.productVariables.BuildingProductImage)
1590}
1591
1592func (c *deviceConfig) SystemExtPath() string {
1593	if c.config.productVariables.SystemExtPath != nil {
1594		return *c.config.productVariables.SystemExtPath
1595	}
1596	return "system_ext"
1597}
1598
1599func (c *deviceConfig) SystemDlkmPath() string {
1600	if c.config.productVariables.SystemDlkmPath != nil {
1601		return *c.config.productVariables.SystemDlkmPath
1602	}
1603	return "system_dlkm"
1604}
1605
1606func (c *deviceConfig) OemPath() string {
1607	if c.config.productVariables.OemPath != nil {
1608		return *c.config.productVariables.OemPath
1609	}
1610	return "oem"
1611}
1612
1613func (c *deviceConfig) UserdataPath() string {
1614	if c.config.productVariables.UserdataPath != nil {
1615		return *c.config.productVariables.UserdataPath
1616	}
1617	return "data"
1618}
1619
1620func (c *deviceConfig) BuildingUserdataImage() bool {
1621	return proptools.Bool(c.config.productVariables.BuildingUserdataImage)
1622}
1623
1624func (c *deviceConfig) BuildingRecoveryImage() bool {
1625	return proptools.Bool(c.config.productVariables.BuildingRecoveryImage)
1626}
1627
1628func (c *deviceConfig) BtConfigIncludeDir() string {
1629	return String(c.config.productVariables.BtConfigIncludeDir)
1630}
1631
1632func (c *deviceConfig) DeviceKernelHeaderDirs() []string {
1633	return c.config.productVariables.DeviceKernelHeaders
1634}
1635
1636// JavaCoverageEnabledForPath returns whether Java code coverage is enabled for
1637// path. Coverage is enabled by default when the product variable
1638// JavaCoveragePaths is empty. If JavaCoveragePaths is not empty, coverage is
1639// enabled for any path which is part of this variable (and not part of the
1640// JavaCoverageExcludePaths product variable). Value "*" in JavaCoveragePaths
1641// represents any path.
1642func (c *deviceConfig) JavaCoverageEnabledForPath(path string) bool {
1643	coverage := false
1644	if len(c.config.productVariables.JavaCoveragePaths) == 0 ||
1645		InList("*", c.config.productVariables.JavaCoveragePaths) ||
1646		HasAnyPrefix(path, c.config.productVariables.JavaCoveragePaths) {
1647		coverage = true
1648	}
1649	if coverage && len(c.config.productVariables.JavaCoverageExcludePaths) > 0 {
1650		if HasAnyPrefix(path, c.config.productVariables.JavaCoverageExcludePaths) {
1651			coverage = false
1652		}
1653	}
1654	return coverage
1655}
1656
1657// Returns true if gcov or clang coverage is enabled.
1658func (c *deviceConfig) NativeCoverageEnabled() bool {
1659	return Bool(c.config.productVariables.GcovCoverage) ||
1660		Bool(c.config.productVariables.ClangCoverage)
1661}
1662
1663func (c *deviceConfig) ClangCoverageEnabled() bool {
1664	return Bool(c.config.productVariables.ClangCoverage)
1665}
1666
1667func (c *deviceConfig) ClangCoverageContinuousMode() bool {
1668	return Bool(c.config.productVariables.ClangCoverageContinuousMode)
1669}
1670
1671func (c *deviceConfig) GcovCoverageEnabled() bool {
1672	return Bool(c.config.productVariables.GcovCoverage)
1673}
1674
1675// NativeCoverageEnabledForPath returns whether (GCOV- or Clang-based) native
1676// code coverage is enabled for path. By default, coverage is not enabled for a
1677// given path unless it is part of the NativeCoveragePaths product variable (and
1678// not part of the NativeCoverageExcludePaths product variable). Value "*" in
1679// NativeCoveragePaths represents any path.
1680func (c *deviceConfig) NativeCoverageEnabledForPath(path string) bool {
1681	coverage := false
1682	if len(c.config.productVariables.NativeCoveragePaths) > 0 {
1683		if InList("*", c.config.productVariables.NativeCoveragePaths) || HasAnyPrefix(path, c.config.productVariables.NativeCoveragePaths) {
1684			coverage = true
1685		}
1686	}
1687	if coverage && len(c.config.productVariables.NativeCoverageExcludePaths) > 0 {
1688		if HasAnyPrefix(path, c.config.productVariables.NativeCoverageExcludePaths) {
1689			coverage = false
1690		}
1691	}
1692	return coverage
1693}
1694
1695func (c *deviceConfig) PgoAdditionalProfileDirs() []string {
1696	return c.config.productVariables.PgoAdditionalProfileDirs
1697}
1698
1699// AfdoProfile returns fully qualified path associated to the given module name
1700func (c *deviceConfig) AfdoProfile(name string) (string, error) {
1701	for _, afdoProfile := range c.config.productVariables.AfdoProfiles {
1702		split := strings.Split(afdoProfile, ":")
1703		if len(split) != 3 {
1704			return "", fmt.Errorf("AFDO_PROFILES has invalid value: %s. "+
1705				"The expected format is <module>:<fully-qualified-path-to-fdo_profile>", afdoProfile)
1706		}
1707		if split[0] == name {
1708			return strings.Join([]string{split[1], split[2]}, ":"), nil
1709		}
1710	}
1711	return "", nil
1712}
1713
1714func (c *deviceConfig) VendorSepolicyDirs() []string {
1715	return c.config.productVariables.BoardVendorSepolicyDirs
1716}
1717
1718func (c *deviceConfig) OdmSepolicyDirs() []string {
1719	return c.config.productVariables.BoardOdmSepolicyDirs
1720}
1721
1722func (c *deviceConfig) SystemExtPublicSepolicyDirs() []string {
1723	return c.config.productVariables.SystemExtPublicSepolicyDirs
1724}
1725
1726func (c *deviceConfig) SystemExtPrivateSepolicyDirs() []string {
1727	return c.config.productVariables.SystemExtPrivateSepolicyDirs
1728}
1729
1730func (c *deviceConfig) SepolicyM4Defs() []string {
1731	return c.config.productVariables.BoardSepolicyM4Defs
1732}
1733
1734func (c *deviceConfig) OverrideManifestPackageNameFor(name string) (manifestName string, overridden bool) {
1735	return findOverrideValue(c.config.productVariables.ManifestPackageNameOverrides, name,
1736		"invalid override rule %q in PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES should be <module_name>:<manifest_name>")
1737}
1738
1739func (c *deviceConfig) OverrideCertificateFor(name string) (certificatePath string, overridden bool) {
1740	return findOverrideValue(c.config.productVariables.CertificateOverrides, name,
1741		"invalid override rule %q in PRODUCT_CERTIFICATE_OVERRIDES should be <module_name>:<certificate_module_name>")
1742}
1743
1744func (c *deviceConfig) OverridePackageNameFor(name string) string {
1745	newName, overridden := findOverrideValue(
1746		c.config.productVariables.PackageNameOverrides,
1747		name,
1748		"invalid override rule %q in PRODUCT_PACKAGE_NAME_OVERRIDES should be <module_name>:<package_name>")
1749	if overridden {
1750		return newName
1751	}
1752	return name
1753}
1754
1755func findOverrideValue(overrides []string, name string, errorMsg string) (newValue string, overridden bool) {
1756	if overrides == nil || len(overrides) == 0 {
1757		return "", false
1758	}
1759	for _, o := range overrides {
1760		split := strings.Split(o, ":")
1761		if len(split) != 2 {
1762			// This shouldn't happen as this is first checked in make, but just in case.
1763			panic(fmt.Errorf(errorMsg, o))
1764		}
1765		if matchPattern(split[0], name) {
1766			return substPattern(split[0], split[1], name), true
1767		}
1768	}
1769	return "", false
1770}
1771
1772func (c *deviceConfig) ApexGlobalMinSdkVersionOverride() string {
1773	return String(c.config.productVariables.ApexGlobalMinSdkVersionOverride)
1774}
1775
1776func (c *config) IntegerOverflowDisabledForPath(path string) bool {
1777	if len(c.productVariables.IntegerOverflowExcludePaths) == 0 {
1778		return false
1779	}
1780	return HasAnyPrefix(path, c.productVariables.IntegerOverflowExcludePaths)
1781}
1782
1783func (c *config) CFIDisabledForPath(path string) bool {
1784	if len(c.productVariables.CFIExcludePaths) == 0 {
1785		return false
1786	}
1787	return HasAnyPrefix(path, c.productVariables.CFIExcludePaths)
1788}
1789
1790func (c *config) CFIEnabledForPath(path string) bool {
1791	if len(c.productVariables.CFIIncludePaths) == 0 {
1792		return false
1793	}
1794	return HasAnyPrefix(path, c.productVariables.CFIIncludePaths) && !c.CFIDisabledForPath(path)
1795}
1796
1797func (c *config) MemtagHeapDisabledForPath(path string) bool {
1798	if len(c.productVariables.MemtagHeapExcludePaths) == 0 {
1799		return false
1800	}
1801	return HasAnyPrefix(path, c.productVariables.MemtagHeapExcludePaths)
1802}
1803
1804func (c *config) MemtagHeapAsyncEnabledForPath(path string) bool {
1805	if len(c.productVariables.MemtagHeapAsyncIncludePaths) == 0 {
1806		return false
1807	}
1808	return HasAnyPrefix(path, c.productVariables.MemtagHeapAsyncIncludePaths) && !c.MemtagHeapDisabledForPath(path)
1809}
1810
1811func (c *config) MemtagHeapSyncEnabledForPath(path string) bool {
1812	if len(c.productVariables.MemtagHeapSyncIncludePaths) == 0 {
1813		return false
1814	}
1815	return HasAnyPrefix(path, c.productVariables.MemtagHeapSyncIncludePaths) && !c.MemtagHeapDisabledForPath(path)
1816}
1817
1818func (c *config) HWASanDisabledForPath(path string) bool {
1819	if len(c.productVariables.HWASanExcludePaths) == 0 {
1820		return false
1821	}
1822	return HasAnyPrefix(path, c.productVariables.HWASanExcludePaths)
1823}
1824
1825func (c *config) HWASanEnabledForPath(path string) bool {
1826	if len(c.productVariables.HWASanIncludePaths) == 0 {
1827		return false
1828	}
1829	return HasAnyPrefix(path, c.productVariables.HWASanIncludePaths) && !c.HWASanDisabledForPath(path)
1830}
1831
1832func (c *config) VendorConfig(name string) VendorConfig {
1833	return soongconfig.Config(c.productVariables.VendorVars[name])
1834}
1835
1836func (c *config) NdkAbis() bool {
1837	return Bool(c.productVariables.Ndk_abis)
1838}
1839
1840func (c *config) AmlAbis() bool {
1841	return Bool(c.productVariables.Aml_abis)
1842}
1843
1844func (c *config) ForceApexSymlinkOptimization() bool {
1845	return Bool(c.productVariables.ForceApexSymlinkOptimization)
1846}
1847
1848func (c *config) ApexCompressionEnabled() bool {
1849	return Bool(c.productVariables.CompressedApex) && !c.UnbundledBuildApps()
1850}
1851
1852func (c *config) DefaultApexPayloadType() string {
1853	return StringDefault(c.productVariables.DefaultApexPayloadType, "ext4")
1854}
1855
1856func (c *config) UseSoongSystemImage() bool {
1857	return Bool(c.productVariables.UseSoongSystemImage)
1858}
1859
1860func (c *config) SoongDefinedSystemImage() string {
1861	if c.UseSoongSystemImage() {
1862		return String(c.productVariables.ProductSoongDefinedSystemImage)
1863	}
1864	return ""
1865}
1866
1867func (c *config) EnforceSystemCertificate() bool {
1868	return Bool(c.productVariables.EnforceSystemCertificate)
1869}
1870
1871func (c *config) EnforceSystemCertificateAllowList() []string {
1872	return c.productVariables.EnforceSystemCertificateAllowList
1873}
1874
1875func (c *config) EnforceProductPartitionInterface() bool {
1876	return Bool(c.productVariables.EnforceProductPartitionInterface)
1877}
1878
1879func (c *config) ProductHiddenAPIStubs() []string {
1880	return c.productVariables.ProductHiddenAPIStubs
1881}
1882
1883func (c *config) ProductHiddenAPIStubsSystem() []string {
1884	return c.productVariables.ProductHiddenAPIStubsSystem
1885}
1886
1887func (c *config) ProductHiddenAPIStubsTest() []string {
1888	return c.productVariables.ProductHiddenAPIStubsTest
1889}
1890
1891func (c *deviceConfig) TargetFSConfigGen() []string {
1892	return c.config.productVariables.TargetFSConfigGen
1893}
1894
1895func (c *config) ProductPublicSepolicyDirs() []string {
1896	return c.productVariables.ProductPublicSepolicyDirs
1897}
1898
1899func (c *config) ProductPrivateSepolicyDirs() []string {
1900	return c.productVariables.ProductPrivateSepolicyDirs
1901}
1902
1903func (c *config) TargetMultitreeUpdateMeta() bool {
1904	return c.productVariables.MultitreeUpdateMeta
1905}
1906
1907func (c *deviceConfig) DeviceArch() string {
1908	return String(c.config.productVariables.DeviceArch)
1909}
1910
1911func (c *deviceConfig) DeviceArchVariant() string {
1912	return String(c.config.productVariables.DeviceArchVariant)
1913}
1914
1915func (c *deviceConfig) DeviceSecondaryArch() string {
1916	return String(c.config.productVariables.DeviceSecondaryArch)
1917}
1918
1919func (c *deviceConfig) DeviceSecondaryArchVariant() string {
1920	return String(c.config.productVariables.DeviceSecondaryArchVariant)
1921}
1922
1923func (c *deviceConfig) BoardUsesRecoveryAsBoot() bool {
1924	return Bool(c.config.productVariables.BoardUsesRecoveryAsBoot)
1925}
1926
1927func (c *deviceConfig) BoardKernelBinaries() []string {
1928	return c.config.productVariables.BoardKernelBinaries
1929}
1930
1931func (c *deviceConfig) BoardKernelModuleInterfaceVersions() []string {
1932	return c.config.productVariables.BoardKernelModuleInterfaceVersions
1933}
1934
1935func (c *deviceConfig) BoardMoveRecoveryResourcesToVendorBoot() bool {
1936	return Bool(c.config.productVariables.BoardMoveRecoveryResourcesToVendorBoot)
1937}
1938
1939func (c *deviceConfig) PlatformSepolicyVersion() string {
1940	return String(c.config.productVariables.PlatformSepolicyVersion)
1941}
1942
1943func (c *deviceConfig) PlatformSepolicyCompatVersions() []string {
1944	return c.config.productVariables.PlatformSepolicyCompatVersions
1945}
1946
1947func (c *deviceConfig) BoardSepolicyVers() string {
1948	if ver := String(c.config.productVariables.BoardSepolicyVers); ver != "" {
1949		return ver
1950	}
1951	return c.PlatformSepolicyVersion()
1952}
1953
1954func (c *deviceConfig) SystemExtSepolicyPrebuiltApiDir() string {
1955	return String(c.config.productVariables.SystemExtSepolicyPrebuiltApiDir)
1956}
1957
1958func (c *deviceConfig) ProductSepolicyPrebuiltApiDir() string {
1959	return String(c.config.productVariables.ProductSepolicyPrebuiltApiDir)
1960}
1961
1962func (c *deviceConfig) IsPartnerTrebleSepolicyTestEnabled() bool {
1963	return c.SystemExtSepolicyPrebuiltApiDir() != "" || c.ProductSepolicyPrebuiltApiDir() != ""
1964}
1965
1966func createDirsMap(previous map[string]bool, dirs []string) (map[string]bool, error) {
1967	var ret = make(map[string]bool)
1968	for _, dir := range dirs {
1969		clean := filepath.Clean(dir)
1970		if previous[clean] || ret[clean] {
1971			return nil, fmt.Errorf("Duplicate entry %s", dir)
1972		}
1973		ret[clean] = true
1974	}
1975	return ret, nil
1976}
1977
1978func (c *deviceConfig) createDirsMapOnce(onceKey OnceKey, previous map[string]bool, dirs []string) map[string]bool {
1979	dirMap := c.Once(onceKey, func() interface{} {
1980		ret, err := createDirsMap(previous, dirs)
1981		if err != nil {
1982			panic(fmt.Errorf("%s: %w", onceKey.key, err))
1983		}
1984		return ret
1985	})
1986	if dirMap == nil {
1987		return nil
1988	}
1989	return dirMap.(map[string]bool)
1990}
1991
1992func (c *deviceConfig) ShippingApiLevel() ApiLevel {
1993	if c.config.productVariables.Shipping_api_level == nil {
1994		return NoneApiLevel
1995	}
1996	apiLevel, _ := strconv.Atoi(*c.config.productVariables.Shipping_api_level)
1997	return uncheckedFinalApiLevel(apiLevel)
1998}
1999
2000func (c *deviceConfig) BuildBrokenPluginValidation() []string {
2001	return c.config.productVariables.BuildBrokenPluginValidation
2002}
2003
2004func (c *deviceConfig) BuildBrokenClangAsFlags() bool {
2005	return c.config.productVariables.BuildBrokenClangAsFlags
2006}
2007
2008func (c *deviceConfig) BuildBrokenClangCFlags() bool {
2009	return c.config.productVariables.BuildBrokenClangCFlags
2010}
2011
2012func (c *deviceConfig) BuildBrokenClangProperty() bool {
2013	return c.config.productVariables.BuildBrokenClangProperty
2014}
2015
2016func (c *deviceConfig) BuildBrokenEnforceSyspropOwner() bool {
2017	return c.config.productVariables.BuildBrokenEnforceSyspropOwner
2018}
2019
2020func (c *deviceConfig) BuildBrokenTrebleSyspropNeverallow() bool {
2021	return c.config.productVariables.BuildBrokenTrebleSyspropNeverallow
2022}
2023
2024func (c *deviceConfig) BuildDebugfsRestrictionsEnabled() bool {
2025	return c.config.productVariables.BuildDebugfsRestrictionsEnabled
2026}
2027
2028func (c *deviceConfig) BuildBrokenVendorPropertyNamespace() bool {
2029	return c.config.productVariables.BuildBrokenVendorPropertyNamespace
2030}
2031
2032func (c *deviceConfig) BuildBrokenInputDir(name string) bool {
2033	return InList(name, c.config.productVariables.BuildBrokenInputDirModules)
2034}
2035
2036func (c *deviceConfig) BuildBrokenDontCheckSystemSdk() bool {
2037	return c.config.productVariables.BuildBrokenDontCheckSystemSdk
2038}
2039
2040func (c *deviceConfig) BuildBrokenDupSysprop() bool {
2041	return c.config.productVariables.BuildBrokenDupSysprop
2042}
2043
2044func (c *config) BuildWarningBadOptionalUsesLibsAllowlist() []string {
2045	return c.productVariables.BuildWarningBadOptionalUsesLibsAllowlist
2046}
2047
2048func (c *deviceConfig) GenruleSandboxing() bool {
2049	return Bool(c.config.productVariables.GenruleSandboxing)
2050}
2051
2052func (c *deviceConfig) RequiresInsecureExecmemForSwiftshader() bool {
2053	return c.config.productVariables.RequiresInsecureExecmemForSwiftshader
2054}
2055
2056func (c *deviceConfig) Release_aidl_use_unfrozen() bool {
2057	return Bool(c.config.productVariables.Release_aidl_use_unfrozen)
2058}
2059
2060func (c *config) SelinuxIgnoreNeverallows() bool {
2061	return c.productVariables.SelinuxIgnoreNeverallows
2062}
2063
2064func (c *deviceConfig) SepolicyFreezeTestExtraDirs() []string {
2065	return c.config.productVariables.SepolicyFreezeTestExtraDirs
2066}
2067
2068func (c *deviceConfig) SepolicyFreezeTestExtraPrebuiltDirs() []string {
2069	return c.config.productVariables.SepolicyFreezeTestExtraPrebuiltDirs
2070}
2071
2072func (c *deviceConfig) GenerateAidlNdkPlatformBackend() bool {
2073	return c.config.productVariables.GenerateAidlNdkPlatformBackend
2074}
2075
2076func (c *deviceConfig) AconfigContainerValidation() string {
2077	return c.config.productVariables.AconfigContainerValidation
2078}
2079
2080func (c *config) IgnorePrefer32OnDevice() bool {
2081	return c.productVariables.IgnorePrefer32OnDevice
2082}
2083
2084func (c *config) BootJars() []string {
2085	return c.Once(earlyBootJarsKey, func() interface{} {
2086		list := c.productVariables.BootJars.CopyOfJars()
2087		return append(list, c.productVariables.ApexBootJars.CopyOfJars()...)
2088	}).([]string)
2089}
2090
2091func (c *config) NonApexBootJars() ConfiguredJarList {
2092	return c.productVariables.BootJars
2093}
2094
2095func (c *config) ApexBootJars() ConfiguredJarList {
2096	return c.productVariables.ApexBootJars
2097}
2098
2099func (c *config) RBEWrapper() string {
2100	return c.GetenvWithDefault("RBE_WRAPPER", remoteexec.DefaultWrapperPath)
2101}
2102
2103// UseHostMusl returns true if the host target has been configured to build against musl libc.
2104func (c *config) UseHostMusl() bool {
2105	return Bool(c.productVariables.HostMusl)
2106}
2107
2108// ApiSurfaces directory returns the source path inside the api_surfaces repo
2109// (relative to workspace root).
2110func (c *config) ApiSurfacesDir(s ApiSurface, version string) string {
2111	return filepath.Join(
2112		"build",
2113		"bazel",
2114		"api_surfaces",
2115		s.String(),
2116		version)
2117}
2118
2119func (c *config) JavaCoverageEnabled() bool {
2120	return c.IsEnvTrue("EMMA_INSTRUMENT") || c.IsEnvTrue("EMMA_INSTRUMENT_STATIC") || c.IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK")
2121}
2122
2123func (c *deviceConfig) BuildFromSourceStub() bool {
2124	return Bool(c.config.productVariables.BuildFromSourceStub)
2125}
2126
2127func (c *config) BuildFromTextStub() bool {
2128	// TODO: b/302320354 - Remove the coverage build specific logic once the
2129	// robust solution for handling native properties in from-text stub build
2130	// is implemented.
2131	return !c.buildFromSourceStub &&
2132		!c.JavaCoverageEnabled() &&
2133		!c.deviceConfig.BuildFromSourceStub()
2134}
2135
2136func (c *config) SetBuildFromTextStub(b bool) {
2137	c.buildFromSourceStub = !b
2138	c.productVariables.Build_from_text_stub = boolPtr(b)
2139}
2140
2141func (c *deviceConfig) CheckVendorSeappViolations() bool {
2142	return Bool(c.config.productVariables.CheckVendorSeappViolations)
2143}
2144
2145func (c *config) GetBuildFlag(name string) (string, bool) {
2146	val, ok := c.productVariables.BuildFlags[name]
2147	return val, ok
2148}
2149
2150func (c *config) UseOptimizedResourceShrinkingByDefault() bool {
2151	return c.productVariables.GetBuildFlagBool("RELEASE_USE_OPTIMIZED_RESOURCE_SHRINKING_BY_DEFAULT")
2152}
2153
2154func (c *config) UseResourceProcessorByDefault() bool {
2155	return c.productVariables.GetBuildFlagBool("RELEASE_USE_RESOURCE_PROCESSOR_BY_DEFAULT")
2156}
2157
2158func (c *config) UseTransitiveJarsInClasspath() bool {
2159	return c.productVariables.GetBuildFlagBool("RELEASE_USE_TRANSITIVE_JARS_IN_CLASSPATH")
2160}
2161
2162func (c *config) UseDexV41() bool {
2163	return c.productVariables.GetBuildFlagBool("RELEASE_USE_DEX_V41")
2164}
2165
2166var (
2167	mainlineApexContributionBuildFlagsToApexNames = map[string]string{
2168		"RELEASE_APEX_CONTRIBUTIONS_ADBD":                    "com.android.adbd",
2169		"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES":              "com.android.adservices",
2170		"RELEASE_APEX_CONTRIBUTIONS_APPSEARCH":               "com.android.appsearch",
2171		"RELEASE_APEX_CONTRIBUTIONS_ART":                     "com.android.art",
2172		"RELEASE_APEX_CONTRIBUTIONS_BLUETOOTH":               "com.android.btservices",
2173		"RELEASE_APEX_CONTRIBUTIONS_CAPTIVEPORTALLOGIN":      "",
2174		"RELEASE_APEX_CONTRIBUTIONS_CELLBROADCAST":           "com.android.cellbroadcast",
2175		"RELEASE_APEX_CONTRIBUTIONS_CONFIGINFRASTRUCTURE":    "com.android.configinfrastructure",
2176		"RELEASE_APEX_CONTRIBUTIONS_CONNECTIVITY":            "com.android.tethering",
2177		"RELEASE_APEX_CONTRIBUTIONS_CONSCRYPT":               "com.android.conscrypt",
2178		"RELEASE_APEX_CONTRIBUTIONS_CRASHRECOVERY":           "",
2179		"RELEASE_APEX_CONTRIBUTIONS_DEVICELOCK":              "com.android.devicelock",
2180		"RELEASE_APEX_CONTRIBUTIONS_DOCUMENTSUIGOOGLE":       "",
2181		"RELEASE_APEX_CONTRIBUTIONS_EXTSERVICES":             "com.android.extservices",
2182		"RELEASE_APEX_CONTRIBUTIONS_HEALTHFITNESS":           "com.android.healthfitness",
2183		"RELEASE_APEX_CONTRIBUTIONS_IPSEC":                   "com.android.ipsec",
2184		"RELEASE_APEX_CONTRIBUTIONS_MEDIA":                   "com.android.media",
2185		"RELEASE_APEX_CONTRIBUTIONS_MEDIAPROVIDER":           "com.android.mediaprovider",
2186		"RELEASE_APEX_CONTRIBUTIONS_MODULE_METADATA":         "",
2187		"RELEASE_APEX_CONTRIBUTIONS_NETWORKSTACKGOOGLE":      "",
2188		"RELEASE_APEX_CONTRIBUTIONS_NEURALNETWORKS":          "com.android.neuralnetworks",
2189		"RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION": "com.android.ondevicepersonalization",
2190		"RELEASE_APEX_CONTRIBUTIONS_PERMISSION":              "com.android.permission",
2191		"RELEASE_APEX_CONTRIBUTIONS_PRIMARY_LIBS":            "",
2192		"RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING":   "com.android.rkpd",
2193		"RELEASE_APEX_CONTRIBUTIONS_RESOLV":                  "com.android.resolv",
2194		"RELEASE_APEX_CONTRIBUTIONS_SCHEDULING":              "com.android.scheduling",
2195		"RELEASE_APEX_CONTRIBUTIONS_SDKEXTENSIONS":           "com.android.sdkext",
2196		"RELEASE_APEX_CONTRIBUTIONS_SWCODEC":                 "com.android.media.swcodec",
2197		"RELEASE_APEX_CONTRIBUTIONS_STATSD":                  "com.android.os.statsd",
2198		"RELEASE_APEX_CONTRIBUTIONS_TELEMETRY_TVP":           "",
2199		"RELEASE_APEX_CONTRIBUTIONS_TZDATA":                  "com.android.tzdata",
2200		"RELEASE_APEX_CONTRIBUTIONS_UWB":                     "com.android.uwb",
2201		"RELEASE_APEX_CONTRIBUTIONS_WIFI":                    "com.android.wifi",
2202	}
2203)
2204
2205// Returns the list of _selected_ apex_contributions
2206// Each mainline module will have one entry in the list
2207func (c *config) AllApexContributions() []string {
2208	ret := []string{}
2209	for _, f := range SortedKeys(mainlineApexContributionBuildFlagsToApexNames) {
2210		if val, exists := c.GetBuildFlag(f); exists && val != "" {
2211			ret = append(ret, val)
2212		}
2213	}
2214	return ret
2215}
2216
2217func (c *config) AllMainlineApexNames() []string {
2218	return SortedStringValues(mainlineApexContributionBuildFlagsToApexNames)
2219}
2220
2221func (c *config) BuildIgnoreApexContributionContents() *bool {
2222	return c.productVariables.BuildIgnoreApexContributionContents
2223}
2224
2225func (c *config) ProductLocales() []string {
2226	return c.productVariables.ProductLocales
2227}
2228
2229func (c *config) ProductDefaultWifiChannels() []string {
2230	return c.productVariables.ProductDefaultWifiChannels
2231}
2232
2233func (c *config) BoardUseVbmetaDigestInFingerprint() bool {
2234	return Bool(c.productVariables.BoardUseVbmetaDigestInFingerprint)
2235}
2236
2237func (c *config) OemProperties() []string {
2238	return c.productVariables.OemProperties
2239}
2240
2241func (c *config) UseDebugArt() bool {
2242	if c.productVariables.ArtTargetIncludeDebugBuild != nil {
2243		return Bool(c.productVariables.ArtTargetIncludeDebugBuild)
2244	}
2245
2246	return Bool(c.productVariables.Eng)
2247}
2248
2249func (c *config) SystemPropFiles(ctx PathContext) Paths {
2250	return PathsForSource(ctx, c.productVariables.SystemPropFiles)
2251}
2252
2253func (c *config) SystemExtPropFiles(ctx PathContext) Paths {
2254	return PathsForSource(ctx, c.productVariables.SystemExtPropFiles)
2255}
2256
2257func (c *config) ProductPropFiles(ctx PathContext) Paths {
2258	return PathsForSource(ctx, c.productVariables.ProductPropFiles)
2259}
2260
2261func (c *config) OdmPropFiles(ctx PathContext) Paths {
2262	return PathsForSource(ctx, c.productVariables.OdmPropFiles)
2263}
2264
2265func (c *config) VendorPropFiles(ctx PathContext) Paths {
2266	return PathsForSource(ctx, c.productVariables.VendorPropFiles)
2267}
2268
2269func (c *config) ExtraAllowedDepsTxt() string {
2270	return String(c.productVariables.ExtraAllowedDepsTxt)
2271}
2272
2273func (c *config) EnableUffdGc() string {
2274	return String(c.productVariables.EnableUffdGc)
2275}
2276
2277func (c *config) DeviceFrameworkCompatibilityMatrixFile() []string {
2278	return c.productVariables.DeviceFrameworkCompatibilityMatrixFile
2279}
2280
2281func (c *config) DeviceProductCompatibilityMatrixFile() []string {
2282	return c.productVariables.DeviceProductCompatibilityMatrixFile
2283}
2284
2285func (c *config) BoardAvbEnable() bool {
2286	return Bool(c.productVariables.BoardAvbEnable)
2287}
2288
2289func (c *config) BoardAvbSystemAddHashtreeFooterArgs() []string {
2290	return c.productVariables.BoardAvbSystemAddHashtreeFooterArgs
2291}
2292
2293// Returns true if RELEASE_INSTALL_APEX_SYSTEMSERVER_DEXPREOPT_SAME_PARTITION is set to true.
2294// If true, dexpreopt files of apex system server jars will be installed in the same partition as the parent apex.
2295// If false, all these files will be installed in /system partition.
2296func (c Config) InstallApexSystemServerDexpreoptSamePartition() bool {
2297	return c.config.productVariables.GetBuildFlagBool("RELEASE_INSTALL_APEX_SYSTEMSERVER_DEXPREOPT_SAME_PARTITION")
2298}
2299
2300func (c *config) DeviceMatrixFile() []string {
2301	return c.productVariables.DeviceMatrixFile
2302}
2303
2304func (c *config) ProductManifestFiles() []string {
2305	return c.productVariables.ProductManifestFiles
2306}
2307
2308func (c *config) SystemManifestFile() []string {
2309	return c.productVariables.SystemManifestFile
2310}
2311
2312func (c *config) SystemExtManifestFiles() []string {
2313	return c.productVariables.SystemExtManifestFiles
2314}
2315
2316func (c *config) DeviceManifestFiles() []string {
2317	return c.productVariables.DeviceManifestFiles
2318}
2319
2320func (c *config) OdmManifestFiles() []string {
2321	return c.productVariables.OdmManifestFiles
2322}
2323