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