• 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
17import (
18	"encoding/json"
19	"fmt"
20	"io/ioutil"
21	"os"
22	"path/filepath"
23	"runtime"
24	"strconv"
25	"strings"
26	"sync"
27
28	"github.com/google/blueprint/bootstrap"
29	"github.com/google/blueprint/proptools"
30)
31
32var Bool = proptools.Bool
33var String = proptools.String
34var FutureApiLevel = 10000
35
36// The configuration file name
37const configFileName = "soong.config"
38const productVariablesFileName = "soong.variables"
39
40// A FileConfigurableOptions contains options which can be configured by the
41// config file. These will be included in the config struct.
42type FileConfigurableOptions struct {
43	Mega_device *bool `json:",omitempty"`
44	Host_bionic *bool `json:",omitempty"`
45}
46
47func (f *FileConfigurableOptions) SetDefaultConfig() {
48	*f = FileConfigurableOptions{}
49}
50
51// A Config object represents the entire build configuration for Android.
52type Config struct {
53	*config
54}
55
56func (c Config) BuildDir() string {
57	return c.buildDir
58}
59
60// A DeviceConfig object represents the configuration for a particular device being built.  For
61// now there will only be one of these, but in the future there may be multiple devices being
62// built
63type DeviceConfig struct {
64	*deviceConfig
65}
66
67type VendorConfig interface {
68	// Bool interprets the variable named `name` as a boolean, returning true if, after
69	// lowercasing, it matches one of "1", "y", "yes", "on", or "true". Unset, or any other
70	// value will return false.
71	Bool(name string) bool
72
73	// String returns the string value of `name`. If the variable was not set, it will
74	// return the empty string.
75	String(name string) string
76
77	// IsSet returns whether the variable `name` was set by Make.
78	IsSet(name string) bool
79}
80
81type config struct {
82	FileConfigurableOptions
83	productVariables productVariables
84
85	// Only available on configs created by TestConfig
86	TestProductVariables *productVariables
87
88	PrimaryBuilder           string
89	ConfigFileName           string
90	ProductVariablesFileName string
91
92	Targets              map[OsType][]Target
93	BuildOsVariant       string
94	BuildOsCommonVariant string
95
96	deviceConfig *deviceConfig
97
98	srcDir   string // the path of the root source directory
99	buildDir string // the path of the build output directory
100
101	env       map[string]string
102	envLock   sync.Mutex
103	envDeps   map[string]string
104	envFrozen bool
105
106	inMake bool
107
108	captureBuild      bool // true for tests, saves build parameters for each module
109	ignoreEnvironment bool // true for tests, returns empty from all Getenv calls
110
111	targetOpenJDK9 bool // Target 1.9
112
113	stopBefore bootstrap.StopBefore
114
115	OncePer
116}
117
118type deviceConfig struct {
119	config *config
120	OncePer
121}
122
123type vendorConfig map[string]string
124
125type jsonConfigurable interface {
126	SetDefaultConfig()
127}
128
129func loadConfig(config *config) error {
130	err := loadFromConfigFile(&config.FileConfigurableOptions, config.ConfigFileName)
131	if err != nil {
132		return err
133	}
134
135	return loadFromConfigFile(&config.productVariables, config.ProductVariablesFileName)
136}
137
138// loads configuration options from a JSON file in the cwd.
139func loadFromConfigFile(configurable jsonConfigurable, filename string) error {
140	// Try to open the file
141	configFileReader, err := os.Open(filename)
142	defer configFileReader.Close()
143	if os.IsNotExist(err) {
144		// Need to create a file, so that blueprint & ninja don't get in
145		// a dependency tracking loop.
146		// Make a file-configurable-options with defaults, write it out using
147		// a json writer.
148		configurable.SetDefaultConfig()
149		err = saveToConfigFile(configurable, filename)
150		if err != nil {
151			return err
152		}
153	} else if err != nil {
154		return fmt.Errorf("config file: could not open %s: %s", filename, err.Error())
155	} else {
156		// Make a decoder for it
157		jsonDecoder := json.NewDecoder(configFileReader)
158		err = jsonDecoder.Decode(configurable)
159		if err != nil {
160			return fmt.Errorf("config file: %s did not parse correctly: %s", filename, err.Error())
161		}
162	}
163
164	// No error
165	return nil
166}
167
168// atomically writes the config file in case two copies of soong_build are running simultaneously
169// (for example, docs generation and ninja manifest generation)
170func saveToConfigFile(config jsonConfigurable, filename string) error {
171	data, err := json.MarshalIndent(&config, "", "    ")
172	if err != nil {
173		return fmt.Errorf("cannot marshal config data: %s", err.Error())
174	}
175
176	f, err := ioutil.TempFile(filepath.Dir(filename), "config")
177	if err != nil {
178		return fmt.Errorf("cannot create empty config file %s: %s\n", filename, err.Error())
179	}
180	defer os.Remove(f.Name())
181	defer f.Close()
182
183	_, err = f.Write(data)
184	if err != nil {
185		return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
186	}
187
188	_, err = f.WriteString("\n")
189	if err != nil {
190		return fmt.Errorf("default config file: %s could not be written: %s", filename, err.Error())
191	}
192
193	f.Close()
194	os.Rename(f.Name(), filename)
195
196	return nil
197}
198
199// TestConfig returns a Config object suitable for using for tests
200func TestConfig(buildDir string, env map[string]string) Config {
201	config := &config{
202		productVariables: productVariables{
203			DeviceName:                  stringPtr("test_device"),
204			Platform_sdk_version:        intPtr(26),
205			DeviceSystemSdkVersions:     []string{"14", "15"},
206			Platform_systemsdk_versions: []string{"25", "26"},
207			AAPTConfig:                  []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
208			AAPTPreferredConfig:         stringPtr("xhdpi"),
209			AAPTCharacteristics:         stringPtr("nosdcard"),
210			AAPTPrebuiltDPI:             []string{"xhdpi", "xxhdpi"},
211			UncompressPrivAppDex:        boolPtr(true),
212		},
213
214		buildDir:     buildDir,
215		captureBuild: true,
216		env:          env,
217	}
218	config.deviceConfig = &deviceConfig{
219		config: config,
220	}
221	config.TestProductVariables = &config.productVariables
222
223	if err := config.fromEnv(); err != nil {
224		panic(err)
225	}
226
227	return Config{config}
228}
229
230func TestArchConfigFuchsia(buildDir string, env map[string]string) Config {
231	testConfig := TestConfig(buildDir, env)
232	config := testConfig.config
233
234	config.Targets = map[OsType][]Target{
235		Fuchsia: []Target{
236			{Fuchsia, Arch{ArchType: Arm64, ArchVariant: "", Native: true}},
237		},
238		BuildOs: []Target{
239			{BuildOs, Arch{ArchType: X86_64}},
240		},
241	}
242
243	return testConfig
244}
245
246// TestConfig returns a Config object suitable for using for tests that need to run the arch mutator
247func TestArchConfig(buildDir string, env map[string]string) Config {
248	testConfig := TestConfig(buildDir, env)
249	config := testConfig.config
250
251	config.Targets = map[OsType][]Target{
252		Android: []Target{
253			{Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true, Abi: []string{"arm64-v8a"}}},
254			{Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true, Abi: []string{"armeabi-v7a"}}},
255		},
256		BuildOs: []Target{
257			{BuildOs, Arch{ArchType: X86_64}},
258			{BuildOs, Arch{ArchType: X86}},
259		},
260	}
261
262	config.BuildOsVariant = config.Targets[BuildOs][0].String()
263	config.BuildOsCommonVariant = getCommonTargets(config.Targets[BuildOs])[0].String()
264
265	return testConfig
266}
267
268// New creates a new Config object.  The srcDir argument specifies the path to
269// the root source directory. It also loads the config file, if found.
270func NewConfig(srcDir, buildDir string) (Config, error) {
271	// Make a config with default options
272	config := &config{
273		ConfigFileName:           filepath.Join(buildDir, configFileName),
274		ProductVariablesFileName: filepath.Join(buildDir, productVariablesFileName),
275
276		env: originalEnv,
277
278		srcDir:   srcDir,
279		buildDir: buildDir,
280	}
281
282	config.deviceConfig = &deviceConfig{
283		config: config,
284	}
285
286	// Sanity check the build and source directories. This won't catch strange
287	// configurations with symlinks, but at least checks the obvious cases.
288	absBuildDir, err := filepath.Abs(buildDir)
289	if err != nil {
290		return Config{}, err
291	}
292
293	absSrcDir, err := filepath.Abs(srcDir)
294	if err != nil {
295		return Config{}, err
296	}
297
298	if strings.HasPrefix(absSrcDir, absBuildDir) {
299		return Config{}, fmt.Errorf("Build dir must not contain source directory")
300	}
301
302	// Load any configurable options from the configuration file
303	err = loadConfig(config)
304	if err != nil {
305		return Config{}, err
306	}
307
308	inMakeFile := filepath.Join(buildDir, ".soong.in_make")
309	if _, err := os.Stat(inMakeFile); err == nil {
310		config.inMake = true
311	}
312
313	targets, err := decodeTargetProductVariables(config)
314	if err != nil {
315		return Config{}, err
316	}
317
318	var archConfig []archConfig
319	if Bool(config.Mega_device) {
320		archConfig = getMegaDeviceConfig()
321	} else if config.NdkAbis() {
322		archConfig = getNdkAbisConfig()
323	}
324
325	if archConfig != nil {
326		androidTargets, err := decodeArchSettings(Android, archConfig)
327		if err != nil {
328			return Config{}, err
329		}
330		targets[Android] = androidTargets
331	}
332
333	config.Targets = targets
334	config.BuildOsVariant = targets[BuildOs][0].String()
335	config.BuildOsCommonVariant = getCommonTargets(targets[BuildOs])[0].String()
336
337	if err := config.fromEnv(); err != nil {
338		return Config{}, err
339	}
340
341	return Config{config}, nil
342}
343
344func (c *config) fromEnv() error {
345	switch c.Getenv("EXPERIMENTAL_USE_OPENJDK9") {
346	case "", "1.8":
347		// Nothing, we always use OpenJDK9
348	case "true":
349		// Use OpenJDK9 and target 1.9
350		c.targetOpenJDK9 = true
351	default:
352		return fmt.Errorf(`Invalid value for EXPERIMENTAL_USE_OPENJDK9, should be "", "1.8", or "true"`)
353	}
354
355	return nil
356}
357
358func (c *config) StopBefore() bootstrap.StopBefore {
359	return c.stopBefore
360}
361
362func (c *config) SetStopBefore(stopBefore bootstrap.StopBefore) {
363	c.stopBefore = stopBefore
364}
365
366var _ bootstrap.ConfigStopBefore = (*config)(nil)
367
368func (c *config) BlueprintToolLocation() string {
369	return filepath.Join(c.buildDir, "host", c.PrebuiltOS(), "bin")
370}
371
372var _ bootstrap.ConfigBlueprintToolLocation = (*config)(nil)
373
374func (c *config) HostToolPath(ctx PathContext, tool string) Path {
375	return PathForOutput(ctx, "host", c.PrebuiltOS(), "bin", tool)
376}
377
378// HostSystemTool looks for non-hermetic tools from the system we're running on.
379// Generally shouldn't be used, but useful to find the XCode SDK, etc.
380func (c *config) HostSystemTool(name string) string {
381	for _, dir := range filepath.SplitList(c.Getenv("PATH")) {
382		path := filepath.Join(dir, name)
383		if s, err := os.Stat(path); err != nil {
384			continue
385		} else if m := s.Mode(); !s.IsDir() && m&0111 != 0 {
386			return path
387		}
388	}
389	return name
390}
391
392// PrebuiltOS returns the name of the host OS used in prebuilts directories
393func (c *config) PrebuiltOS() string {
394	switch runtime.GOOS {
395	case "linux":
396		return "linux-x86"
397	case "darwin":
398		return "darwin-x86"
399	default:
400		panic("Unknown GOOS")
401	}
402}
403
404// GoRoot returns the path to the root directory of the Go toolchain.
405func (c *config) GoRoot() string {
406	return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
407}
408
409func (c *config) CpPreserveSymlinksFlags() string {
410	switch runtime.GOOS {
411	case "darwin":
412		return "-R"
413	case "linux":
414		return "-d"
415	default:
416		return ""
417	}
418}
419
420func (c *config) Getenv(key string) string {
421	var val string
422	var exists bool
423	c.envLock.Lock()
424	defer c.envLock.Unlock()
425	if c.envDeps == nil {
426		c.envDeps = make(map[string]string)
427	}
428	if val, exists = c.envDeps[key]; !exists {
429		if c.envFrozen {
430			panic("Cannot access new environment variables after envdeps are frozen")
431		}
432		val, _ = c.env[key]
433		c.envDeps[key] = val
434	}
435	return val
436}
437
438func (c *config) GetenvWithDefault(key string, defaultValue string) string {
439	ret := c.Getenv(key)
440	if ret == "" {
441		return defaultValue
442	}
443	return ret
444}
445
446func (c *config) IsEnvTrue(key string) bool {
447	value := c.Getenv(key)
448	return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
449}
450
451func (c *config) IsEnvFalse(key string) bool {
452	value := c.Getenv(key)
453	return value == "0" || value == "n" || value == "no" || value == "off" || value == "false"
454}
455
456func (c *config) EnvDeps() map[string]string {
457	c.envLock.Lock()
458	defer c.envLock.Unlock()
459	c.envFrozen = true
460	return c.envDeps
461}
462
463func (c *config) EmbeddedInMake() bool {
464	return c.inMake
465}
466
467func (c *config) BuildId() string {
468	return String(c.productVariables.BuildId)
469}
470
471func (c *config) BuildNumberFromFile() string {
472	return String(c.productVariables.BuildNumberFromFile)
473}
474
475// DeviceName returns the name of the current device target
476// TODO: take an AndroidModuleContext to select the device name for multi-device builds
477func (c *config) DeviceName() string {
478	return *c.productVariables.DeviceName
479}
480
481func (c *config) DeviceResourceOverlays() []string {
482	return c.productVariables.DeviceResourceOverlays
483}
484
485func (c *config) ProductResourceOverlays() []string {
486	return c.productVariables.ProductResourceOverlays
487}
488
489func (c *config) PlatformVersionName() string {
490	return String(c.productVariables.Platform_version_name)
491}
492
493func (c *config) PlatformSdkVersionInt() int {
494	return *c.productVariables.Platform_sdk_version
495}
496
497func (c *config) PlatformSdkVersion() string {
498	return strconv.Itoa(c.PlatformSdkVersionInt())
499}
500
501func (c *config) PlatformSdkCodename() string {
502	return String(c.productVariables.Platform_sdk_codename)
503}
504
505func (c *config) PlatformSecurityPatch() string {
506	return String(c.productVariables.Platform_security_patch)
507}
508
509func (c *config) PlatformPreviewSdkVersion() string {
510	return String(c.productVariables.Platform_preview_sdk_version)
511}
512
513func (c *config) PlatformMinSupportedTargetSdkVersion() string {
514	return String(c.productVariables.Platform_min_supported_target_sdk_version)
515}
516
517func (c *config) PlatformBaseOS() string {
518	return String(c.productVariables.Platform_base_os)
519}
520
521func (c *config) MinSupportedSdkVersion() int {
522	return 16
523}
524
525func (c *config) DefaultAppTargetSdkInt() int {
526	if Bool(c.productVariables.Platform_sdk_final) {
527		return c.PlatformSdkVersionInt()
528	} else {
529		return FutureApiLevel
530	}
531}
532
533func (c *config) DefaultAppTargetSdk() string {
534	if Bool(c.productVariables.Platform_sdk_final) {
535		return c.PlatformSdkVersion()
536	} else {
537		return c.PlatformSdkCodename()
538	}
539}
540
541func (c *config) AppsDefaultVersionName() string {
542	return String(c.productVariables.AppsDefaultVersionName)
543}
544
545// Codenames that are active in the current lunch target.
546func (c *config) PlatformVersionActiveCodenames() []string {
547	return c.productVariables.Platform_version_active_codenames
548}
549
550// Codenames that are available in the branch but not included in the current
551// lunch target.
552func (c *config) PlatformVersionFutureCodenames() []string {
553	return c.productVariables.Platform_version_future_codenames
554}
555
556// All possible codenames in the current branch. NB: Not named AllCodenames
557// because "all" has historically meant "active" in make, and still does in
558// build.prop.
559func (c *config) PlatformVersionCombinedCodenames() []string {
560	combined := []string{}
561	combined = append(combined, c.PlatformVersionActiveCodenames()...)
562	combined = append(combined, c.PlatformVersionFutureCodenames()...)
563	return combined
564}
565
566func (c *config) ProductAAPTConfig() []string {
567	return c.productVariables.AAPTConfig
568}
569
570func (c *config) ProductAAPTPreferredConfig() string {
571	return String(c.productVariables.AAPTPreferredConfig)
572}
573
574func (c *config) ProductAAPTCharacteristics() string {
575	return String(c.productVariables.AAPTCharacteristics)
576}
577
578func (c *config) ProductAAPTPrebuiltDPI() []string {
579	return c.productVariables.AAPTPrebuiltDPI
580}
581
582func (c *config) DefaultAppCertificateDir(ctx PathContext) SourcePath {
583	defaultCert := String(c.productVariables.DefaultAppCertificate)
584	if defaultCert != "" {
585		return PathForSource(ctx, filepath.Dir(defaultCert))
586	} else {
587		return PathForSource(ctx, "build/target/product/security")
588	}
589}
590
591func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) {
592	defaultCert := String(c.productVariables.DefaultAppCertificate)
593	if defaultCert != "" {
594		return PathForSource(ctx, defaultCert+".x509.pem"), PathForSource(ctx, defaultCert+".pk8")
595	} else {
596		defaultDir := c.DefaultAppCertificateDir(ctx)
597		return defaultDir.Join(ctx, "testkey.x509.pem"), defaultDir.Join(ctx, "testkey.pk8")
598	}
599}
600
601func (c *config) ApexKeyDir(ctx ModuleContext) SourcePath {
602	// TODO(b/121224311): define another variable such as TARGET_APEX_KEY_OVERRIDE
603	defaultCert := String(c.productVariables.DefaultAppCertificate)
604	if defaultCert == "" || filepath.Dir(defaultCert) == "build/target/product/security" {
605		// When defaultCert is unset or is set to the testkeys path, use the APEX keys
606		// that is under the module dir
607		return pathForModuleSrc(ctx)
608	} else {
609		// If not, APEX keys are under the specified directory
610		return PathForSource(ctx, filepath.Dir(defaultCert))
611	}
612}
613
614func (c *config) AllowMissingDependencies() bool {
615	return Bool(c.productVariables.Allow_missing_dependencies)
616}
617
618func (c *config) UnbundledBuild() bool {
619	return Bool(c.productVariables.Unbundled_build)
620}
621
622func (c *config) UnbundledBuildUsePrebuiltSdks() bool {
623	return Bool(c.productVariables.Unbundled_build) && !Bool(c.productVariables.Unbundled_build_sdks_from_source)
624}
625
626func (c *config) Fuchsia() bool {
627	return Bool(c.productVariables.Fuchsia)
628}
629
630func (c *config) IsPdkBuild() bool {
631	return Bool(c.productVariables.Pdk)
632}
633
634func (c *config) MinimizeJavaDebugInfo() bool {
635	return Bool(c.productVariables.MinimizeJavaDebugInfo) && !Bool(c.productVariables.Eng)
636}
637
638func (c *config) Debuggable() bool {
639	return Bool(c.productVariables.Debuggable)
640}
641
642func (c *config) Eng() bool {
643	return Bool(c.productVariables.Eng)
644}
645
646func (c *config) DevicePrefer32BitApps() bool {
647	return Bool(c.productVariables.DevicePrefer32BitApps)
648}
649
650func (c *config) DevicePrefer32BitExecutables() bool {
651	return Bool(c.productVariables.DevicePrefer32BitExecutables)
652}
653
654func (c *config) DevicePrimaryArchType() ArchType {
655	return c.Targets[Android][0].Arch.ArchType
656}
657
658func (c *config) SkipDeviceInstall() bool {
659	return c.EmbeddedInMake()
660}
661
662func (c *config) SkipMegaDeviceInstall(path string) bool {
663	return Bool(c.Mega_device) &&
664		strings.HasPrefix(path, filepath.Join(c.buildDir, "target", "product"))
665}
666
667func (c *config) SanitizeHost() []string {
668	return append([]string(nil), c.productVariables.SanitizeHost...)
669}
670
671func (c *config) SanitizeDevice() []string {
672	return append([]string(nil), c.productVariables.SanitizeDevice...)
673}
674
675func (c *config) SanitizeDeviceDiag() []string {
676	return append([]string(nil), c.productVariables.SanitizeDeviceDiag...)
677}
678
679func (c *config) SanitizeDeviceArch() []string {
680	return append([]string(nil), c.productVariables.SanitizeDeviceArch...)
681}
682
683func (c *config) EnableCFI() bool {
684	if c.productVariables.EnableCFI == nil {
685		return true
686	} else {
687		return *c.productVariables.EnableCFI
688	}
689}
690
691func (c *config) DisableScudo() bool {
692	return Bool(c.productVariables.DisableScudo)
693}
694
695func (c *config) EnableXOM() bool {
696	if c.productVariables.EnableXOM == nil {
697		return true
698	} else {
699		return Bool(c.productVariables.EnableXOM)
700	}
701}
702
703func (c *config) Android64() bool {
704	for _, t := range c.Targets[Android] {
705		if t.Arch.ArchType.Multilib == "lib64" {
706			return true
707		}
708	}
709
710	return false
711}
712
713func (c *config) UseGoma() bool {
714	return Bool(c.productVariables.UseGoma)
715}
716
717func (c *config) RunErrorProne() bool {
718	return c.IsEnvTrue("RUN_ERROR_PRONE")
719}
720
721// Returns true if -source 1.9 -target 1.9 is being passed to javac
722func (c *config) TargetOpenJDK9() bool {
723	return c.targetOpenJDK9
724}
725
726func (c *config) ClangTidy() bool {
727	return Bool(c.productVariables.ClangTidy)
728}
729
730func (c *config) TidyChecks() string {
731	if c.productVariables.TidyChecks == nil {
732		return ""
733	}
734	return *c.productVariables.TidyChecks
735}
736
737func (c *config) LibartImgHostBaseAddress() string {
738	return "0x60000000"
739}
740
741func (c *config) LibartImgDeviceBaseAddress() string {
742	archType := Common
743	if len(c.Targets[Android]) > 0 {
744		archType = c.Targets[Android][0].Arch.ArchType
745	}
746	switch archType {
747	default:
748		return "0x70000000"
749	case Mips, Mips64:
750		return "0x5C000000"
751	}
752}
753
754func (c *config) ArtUseReadBarrier() bool {
755	return Bool(c.productVariables.ArtUseReadBarrier)
756}
757
758func (c *config) EnforceRROForModule(name string) bool {
759	enforceList := c.productVariables.EnforceRROTargets
760	if enforceList != nil {
761		if len(enforceList) == 1 && (enforceList)[0] == "*" {
762			return true
763		}
764		return InList(name, enforceList)
765	}
766	return false
767}
768
769func (c *config) EnforceRROExcludedOverlay(path string) bool {
770	excluded := c.productVariables.EnforceRROExcludedOverlays
771	if excluded != nil {
772		for _, exclude := range excluded {
773			if strings.HasPrefix(path, exclude) {
774				return true
775			}
776		}
777	}
778	return false
779}
780
781func (c *config) ExportedNamespaces() []string {
782	return append([]string(nil), c.productVariables.NamespacesToExport...)
783}
784
785func (c *config) HostStaticBinaries() bool {
786	return Bool(c.productVariables.HostStaticBinaries)
787}
788
789func (c *config) UncompressPrivAppDex() bool {
790	return Bool(c.productVariables.UncompressPrivAppDex)
791}
792
793func (c *config) ModulesLoadedByPrivilegedModules() []string {
794	return c.productVariables.ModulesLoadedByPrivilegedModules
795}
796
797func (c *config) BootJars() []string {
798	return c.productVariables.BootJars
799}
800
801func (c *config) DexpreoptGlobalConfig() string {
802	return String(c.productVariables.DexpreoptGlobalConfig)
803}
804
805func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {
806	return ExistentPathForSource(ctx, "frameworks", "base").Valid()
807}
808
809func (c *deviceConfig) Arches() []Arch {
810	var arches []Arch
811	for _, target := range c.config.Targets[Android] {
812		arches = append(arches, target.Arch)
813	}
814	return arches
815}
816
817func (c *deviceConfig) BinderBitness() string {
818	is32BitBinder := c.config.productVariables.Binder32bit
819	if is32BitBinder != nil && *is32BitBinder {
820		return "32"
821	}
822	return "64"
823}
824
825func (c *deviceConfig) VendorPath() string {
826	if c.config.productVariables.VendorPath != nil {
827		return *c.config.productVariables.VendorPath
828	}
829	return "vendor"
830}
831
832func (c *deviceConfig) VndkVersion() string {
833	return String(c.config.productVariables.DeviceVndkVersion)
834}
835
836func (c *deviceConfig) PlatformVndkVersion() string {
837	return String(c.config.productVariables.Platform_vndk_version)
838}
839
840func (c *deviceConfig) ExtraVndkVersions() []string {
841	return c.config.productVariables.ExtraVndkVersions
842}
843
844func (c *deviceConfig) VndkUseCoreVariant() bool {
845	return Bool(c.config.productVariables.VndkUseCoreVariant)
846}
847
848func (c *deviceConfig) SystemSdkVersions() []string {
849	return c.config.productVariables.DeviceSystemSdkVersions
850}
851
852func (c *deviceConfig) PlatformSystemSdkVersions() []string {
853	return c.config.productVariables.Platform_systemsdk_versions
854}
855
856func (c *deviceConfig) OdmPath() string {
857	if c.config.productVariables.OdmPath != nil {
858		return *c.config.productVariables.OdmPath
859	}
860	return "odm"
861}
862
863func (c *deviceConfig) ProductPath() string {
864	if c.config.productVariables.ProductPath != nil {
865		return *c.config.productVariables.ProductPath
866	}
867	return "product"
868}
869
870func (c *deviceConfig) ProductServicesPath() string {
871	if c.config.productVariables.ProductServicesPath != nil {
872		return *c.config.productVariables.ProductServicesPath
873	}
874	return "product_services"
875}
876
877func (c *deviceConfig) BtConfigIncludeDir() string {
878	return String(c.config.productVariables.BtConfigIncludeDir)
879}
880
881func (c *deviceConfig) DeviceKernelHeaderDirs() []string {
882	return c.config.productVariables.DeviceKernelHeaders
883}
884
885func (c *deviceConfig) NativeCoverageEnabled() bool {
886	return Bool(c.config.productVariables.NativeCoverage)
887}
888
889func (c *deviceConfig) CoverageEnabledForPath(path string) bool {
890	coverage := false
891	if c.config.productVariables.CoveragePaths != nil {
892		if InList("*", c.config.productVariables.CoveragePaths) || PrefixInList(path, c.config.productVariables.CoveragePaths) {
893			coverage = true
894		}
895	}
896	if coverage && c.config.productVariables.CoverageExcludePaths != nil {
897		if PrefixInList(path, c.config.productVariables.CoverageExcludePaths) {
898			coverage = false
899		}
900	}
901	return coverage
902}
903
904func (c *deviceConfig) PgoAdditionalProfileDirs() []string {
905	return c.config.productVariables.PgoAdditionalProfileDirs
906}
907
908func (c *deviceConfig) VendorSepolicyDirs() []string {
909	return c.config.productVariables.BoardVendorSepolicyDirs
910}
911
912func (c *deviceConfig) OdmSepolicyDirs() []string {
913	return c.config.productVariables.BoardOdmSepolicyDirs
914}
915
916func (c *deviceConfig) PlatPublicSepolicyDirs() []string {
917	return c.config.productVariables.BoardPlatPublicSepolicyDirs
918}
919
920func (c *deviceConfig) PlatPrivateSepolicyDirs() []string {
921	return c.config.productVariables.BoardPlatPrivateSepolicyDirs
922}
923
924func (c *deviceConfig) OverrideManifestPackageNameFor(name string) (manifestName string, overridden bool) {
925	return findOverrideValue(c.config.productVariables.ManifestPackageNameOverrides, name,
926		"invalid override rule %q in PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES should be <module_name>:<manifest_name>")
927}
928
929func (c *deviceConfig) OverrideCertificateFor(name string) (certificatePath string, overridden bool) {
930	return findOverrideValue(c.config.productVariables.CertificateOverrides, name,
931		"invalid override rule %q in PRODUCT_CERTIFICATE_OVERRIDES should be <module_name>:<certificate_module_name>")
932}
933
934func (c *deviceConfig) OverridePackageNameFor(name string) string {
935	newName, overridden := findOverrideValue(
936		c.config.productVariables.PackageNameOverrides,
937		name,
938		"invalid override rule %q in PRODUCT_PACKAGE_NAME_OVERRIDES should be <module_name>:<package_name>")
939	if overridden {
940		return newName
941	}
942	return name
943}
944
945func findOverrideValue(overrides []string, name string, errorMsg string) (newValue string, overridden bool) {
946	if overrides == nil || len(overrides) == 0 {
947		return "", false
948	}
949	for _, o := range overrides {
950		split := strings.Split(o, ":")
951		if len(split) != 2 {
952			// This shouldn't happen as this is first checked in make, but just in case.
953			panic(fmt.Errorf(errorMsg, o))
954		}
955		if matchPattern(split[0], name) {
956			return substPattern(split[0], split[1], name), true
957		}
958	}
959	return "", false
960}
961
962// SecondArchIsTranslated returns true if the primary device arch is X86 or X86_64 and the device also has an arch
963// that is Arm or Arm64.
964func (c *config) SecondArchIsTranslated() bool {
965	deviceTargets := c.Targets[Android]
966	if len(deviceTargets) < 2 {
967		return false
968	}
969
970	arch := deviceTargets[0].Arch
971
972	return (arch.ArchType == X86 || arch.ArchType == X86_64) && hasArmAndroidArch(deviceTargets)
973}
974
975func (c *config) IntegerOverflowDisabledForPath(path string) bool {
976	if c.productVariables.IntegerOverflowExcludePaths == nil {
977		return false
978	}
979	return PrefixInList(path, c.productVariables.IntegerOverflowExcludePaths)
980}
981
982func (c *config) CFIDisabledForPath(path string) bool {
983	if c.productVariables.CFIExcludePaths == nil {
984		return false
985	}
986	return PrefixInList(path, c.productVariables.CFIExcludePaths)
987}
988
989func (c *config) CFIEnabledForPath(path string) bool {
990	if c.productVariables.CFIIncludePaths == nil {
991		return false
992	}
993	return PrefixInList(path, c.productVariables.CFIIncludePaths)
994}
995
996func (c *config) XOMDisabledForPath(path string) bool {
997	if c.productVariables.XOMExcludePaths == nil {
998		return false
999	}
1000	return PrefixInList(path, c.productVariables.XOMExcludePaths)
1001}
1002
1003func (c *config) VendorConfig(name string) VendorConfig {
1004	return vendorConfig(c.productVariables.VendorVars[name])
1005}
1006
1007func (c vendorConfig) Bool(name string) bool {
1008	v := strings.ToLower(c[name])
1009	return v == "1" || v == "y" || v == "yes" || v == "on" || v == "true"
1010}
1011
1012func (c vendorConfig) String(name string) string {
1013	return c[name]
1014}
1015
1016func (c vendorConfig) IsSet(name string) bool {
1017	_, ok := c[name]
1018	return ok
1019}
1020
1021func (c *config) NdkAbis() bool {
1022	return Bool(c.productVariables.Ndk_abis)
1023}
1024
1025func (c *config) ExcludeDraftNdkApis() bool {
1026	return Bool(c.productVariables.Exclude_draft_ndk_apis)
1027}
1028
1029func (c *config) FlattenApex() bool {
1030	return Bool(c.productVariables.FlattenApex)
1031}
1032
1033func (c *config) EnforceSystemCertificate() bool {
1034	return Bool(c.productVariables.EnforceSystemCertificate)
1035}
1036
1037func (c *config) EnforceSystemCertificateWhitelist() []string {
1038	return c.productVariables.EnforceSystemCertificateWhitelist
1039}
1040
1041func (c *config) ProductHiddenAPIStubs() []string {
1042	return c.productVariables.ProductHiddenAPIStubs
1043}
1044
1045func (c *config) ProductHiddenAPIStubsSystem() []string {
1046	return c.productVariables.ProductHiddenAPIStubsSystem
1047}
1048
1049func (c *config) ProductHiddenAPIStubsTest() []string {
1050	return c.productVariables.ProductHiddenAPIStubsTest
1051}
1052
1053func (c *deviceConfig) TargetFSConfigGen() []string {
1054	return c.config.productVariables.TargetFSConfigGen
1055}
1056