diff options
Diffstat (limited to 'android')
| -rw-r--r-- | android/Android.bp | 1 | ||||
| -rw-r--r-- | android/apex.go | 198 | ||||
| -rw-r--r-- | android/apex_test.go | 23 | ||||
| -rw-r--r-- | android/build_prop.go | 21 | ||||
| -rw-r--r-- | android/config.go | 8 | ||||
| -rw-r--r-- | android/container.go | 4 | ||||
| -rw-r--r-- | android/module.go | 2 | ||||
| -rw-r--r-- | android/module_context.go | 5 | ||||
| -rw-r--r-- | android/packaging.go | 6 | ||||
| -rw-r--r-- | android/prebuilt_test.go | 5 | ||||
| -rw-r--r-- | android/rule_builder.go | 40 | ||||
| -rw-r--r-- | android/rule_builder_test.go | 64 | ||||
| -rw-r--r-- | android/sbom.go | 18 | ||||
| -rw-r--r-- | android/selects_test.go | 48 | ||||
| -rw-r--r-- | android/test_config.go | 1 | ||||
| -rw-r--r-- | android/variable.go | 33 | ||||
| -rw-r--r-- | android/vendor_api_levels.go | 49 |
17 files changed, 190 insertions, 336 deletions
diff --git a/android/Android.bp b/android/Android.bp index a9a3564ab..dfea8f999 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -111,6 +111,7 @@ bootstrap_go_package { "testing.go", "util.go", "variable.go", + "vendor_api_levels.go", "vintf_fragment.go", "vintf_data.go", "visibility.go", diff --git a/android/apex.go b/android/apex.go index 9277ff31b..db9391204 100644 --- a/android/apex.go +++ b/android/apex.go @@ -16,7 +16,6 @@ package android import ( "fmt" - "reflect" "slices" "sort" "strconv" @@ -62,19 +61,6 @@ type ApexInfo struct { // that are merged together. InApexVariants []string - // List of APEX Soong module names that this module is part of. Note that the list includes - // different variations of the same APEX. For example, if module `foo` is included in the - // apex `com.android.foo`, and also if there is an override_apex module - // `com.mycompany.android.foo` overriding `com.android.foo`, then this list contains both - // `com.android.foo` and `com.mycompany.android.foo`. If the APEX Soong module is a - // prebuilt, the name here doesn't have the `prebuilt_` prefix. - InApexModules []string - - // Pointers to the ApexContents struct each of which is for apexBundle modules that this - // module is part of. The ApexContents gives information about which modules the apexBundle - // has and whether a module became part of the apexBundle via a direct dependency or not. - ApexContents []*ApexContents - // True if this is for a prebuilt_apex. // // If true then this will customize the apex processing to make it suitable for handling @@ -105,7 +91,6 @@ func (i ApexInfo) AddJSONData(d *map[string]interface{}) { (*d)["Apex"] = map[string]interface{}{ "ApexVariationName": i.ApexVariationName, "MinSdkVersion": i.MinSdkVersion, - "InApexModules": i.InApexModules, "InApexVariants": i.InApexVariants, "ForPrebuiltApex": i.ForPrebuiltApex, } @@ -140,15 +125,6 @@ func (i ApexInfo) InApexVariant(apexVariant string) bool { return false } -func (i ApexInfo) InApexModule(apexModuleName string) bool { - for _, a := range i.InApexModules { - if a == apexModuleName { - return true - } - } - return false -} - // To satisfy the comparable interface func (i ApexInfo) Equal(other any) bool { otherApexInfo, ok := other.(ApexInfo) @@ -156,13 +132,11 @@ func (i ApexInfo) Equal(other any) bool { i.MinSdkVersion == otherApexInfo.MinSdkVersion && i.Updatable == otherApexInfo.Updatable && i.UsePlatformApis == otherApexInfo.UsePlatformApis && - reflect.DeepEqual(i.InApexVariants, otherApexInfo.InApexVariants) && - reflect.DeepEqual(i.InApexModules, otherApexInfo.InApexModules) + slices.Equal(i.InApexVariants, otherApexInfo.InApexVariants) } // ApexBundleInfo contains information about the dependencies of an apex type ApexBundleInfo struct { - Contents *ApexContents } var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_info") @@ -220,15 +194,8 @@ type ApexModule interface { // this after apex.apexMutator is run. InAnyApex() bool - // Returns true if this module is directly in any APEX. Call this AFTER apex.apexMutator is - // run. - DirectlyInAnyApex() bool - - // NotInPlatform tells whether or not this module is included in an APEX and therefore - // shouldn't be exposed to the platform (i.e. outside of the APEX) directly. A module is - // considered to be included in an APEX either when there actually is an APEX that - // explicitly has the module as its dependency or the module is not available to the - // platform, which indicates that the module belongs to at least one or more other APEXes. + // NotInPlatform returns true if the module is not available to the platform due to + // apex_available being set and not containing "//apex_available:platform". NotInPlatform() bool // Tests if this module could have APEX variants. Even when a module type implements @@ -285,20 +252,6 @@ type ApexProperties struct { // Default is ["//apex_available:platform"]. Apex_available []string - // See ApexModule.InAnyApex() - InAnyApex bool `blueprint:"mutated"` - - // See ApexModule.DirectlyInAnyApex() - DirectlyInAnyApex bool `blueprint:"mutated"` - - // AnyVariantDirectlyInAnyApex is true in the primary variant of a module if _any_ variant - // of the module is directly in any apex. This includes host, arch, asan, etc. variants. It - // is unused in any variant that is not the primary variant. Ideally this wouldn't be used, - // as it incorrectly mixes arch variants if only one arch is in an apex, but a few places - // depend on it, for example when an ASAN variant is created before the apexMutator. Call - // this after apex.apexMutator is run. - AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"` - // See ApexModule.NotAvailableForPlatform() NotAvailableForPlatform bool `blueprint:"mutated"` @@ -335,16 +288,6 @@ type AlwaysRequireApexVariantTag interface { AlwaysRequireApexVariant() bool } -// Marker interface that identifies dependencies that should inherit the DirectlyInAnyApex state -// from the parent to the child. For example, stubs libraries are marked as DirectlyInAnyApex if -// their implementation is in an apex. -type CopyDirectlyInAnyApexTag interface { - blueprint.DependencyTag - - // Method that differentiates this interface from others. - CopyDirectlyInAnyApex() -} - // Interface that identifies dependencies to skip Apex dependency check type SkipApexAllowedDependenciesCheck interface { // Returns true to skip the Apex dependency check, which limits the allowed dependency in build. @@ -395,40 +338,27 @@ func (m *ApexModuleBase) ApexAvailable() []string { func (m *ApexModuleBase) BuildForApex(apex ApexInfo) { m.apexInfosLock.Lock() defer m.apexInfosLock.Unlock() - for i, v := range m.apexInfos { - if v.ApexVariationName == apex.ApexVariationName { - if len(apex.InApexModules) != 1 { - panic(fmt.Errorf("Newly created apexInfo must be for a single APEX")) - } - // Even when the ApexVariantNames are the same, the given ApexInfo might - // actually be for different APEX. This can happen when an APEX is - // overridden via override_apex. For example, there can be two apexes - // `com.android.foo` (from the `apex` module type) and - // `com.mycompany.android.foo` (from the `override_apex` module type), both - // of which has the same ApexVariantName `com.android.foo`. Add the apex - // name to the list so that it's not lost. - if !InList(apex.InApexModules[0], v.InApexModules) { - m.apexInfos[i].InApexModules = append(m.apexInfos[i].InApexModules, apex.InApexModules[0]) - } - return - } + if slices.ContainsFunc(m.apexInfos, func(existing ApexInfo) bool { + return existing.ApexVariationName == apex.ApexVariationName + }) { + return } m.apexInfos = append(m.apexInfos, apex) } // Implements ApexModule func (m *ApexModuleBase) InAnyApex() bool { - return m.ApexProperties.InAnyApex -} - -// Implements ApexModule -func (m *ApexModuleBase) DirectlyInAnyApex() bool { - return m.ApexProperties.DirectlyInAnyApex + for _, apex_name := range m.ApexProperties.Apex_available { + if apex_name != AvailableToPlatform { + return true + } + } + return false } // Implements ApexModule func (m *ApexModuleBase) NotInPlatform() bool { - return m.ApexProperties.AnyVariantDirectlyInAnyApex || !m.AvailableFor(AvailableToPlatform) + return !m.AvailableFor(AvailableToPlatform) } // Implements ApexModule @@ -585,8 +515,6 @@ func mergeApexVariations(apexInfos []ApexInfo) (merged []ApexInfo, aliases [][2] if index, exists := seen[mergedName]; exists { // Variants having the same mergedName are deduped merged[index].InApexVariants = append(merged[index].InApexVariants, variantName) - merged[index].InApexModules = append(merged[index].InApexModules, apexInfo.InApexModules...) - merged[index].ApexContents = append(merged[index].ApexContents, apexInfo.ApexContents...) merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable // Platform APIs is allowed for this module only when all APEXes containing // the module are with `use_platform_apis: true`. @@ -596,8 +524,6 @@ func mergeApexVariations(apexInfos []ApexInfo) (merged []ApexInfo, aliases [][2] seen[mergedName] = len(merged) apexInfo.ApexVariationName = mergedName apexInfo.InApexVariants = CopyOf(apexInfo.InApexVariants) - apexInfo.InApexModules = CopyOf(apexInfo.InApexModules) - apexInfo.ApexContents = append([]*ApexContents(nil), apexInfo.ApexContents...) apexInfo.TestApexes = CopyOf(apexInfo.TestApexes) merged = append(merged, apexInfo) } @@ -685,15 +611,6 @@ func MutateApexTransition(ctx BaseModuleContext, variation string) { apexInfos, _ = mergeApexVariations(apexInfos) } - var inApex ApexMembership - for _, a := range apexInfos { - for _, apexContents := range a.ApexContents { - inApex = inApex.merge(apexContents.contents[ctx.ModuleName()]) - } - } - base.ApexProperties.InAnyApex = true - base.ApexProperties.DirectlyInAnyApex = inApex == directlyInApex - if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() { // Do not install the module for platform, but still allow it to output // uninstallable AndroidMk entries in certain cases when they have side @@ -783,93 +700,6 @@ func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModul }) } -// UpdateDirectlyInAnyApex uses the final module to store if any variant of this module is directly -// in any APEX, and then copies the final value to all the modules. It also copies the -// DirectlyInAnyApex value to any transitive dependencies with a CopyDirectlyInAnyApexTag -// dependency tag. -func UpdateDirectlyInAnyApex(mctx BottomUpMutatorContext, am ApexModule) { - base := am.apexModuleBase() - // Copy DirectlyInAnyApex and InAnyApex from any transitive dependencies with a - // CopyDirectlyInAnyApexTag dependency tag. - mctx.WalkDeps(func(child, parent Module) bool { - if _, ok := mctx.OtherModuleDependencyTag(child).(CopyDirectlyInAnyApexTag); ok { - depBase := child.(ApexModule).apexModuleBase() - depBase.apexPropertiesLock.Lock() - defer depBase.apexPropertiesLock.Unlock() - depBase.ApexProperties.DirectlyInAnyApex = base.ApexProperties.DirectlyInAnyApex - depBase.ApexProperties.InAnyApex = base.ApexProperties.InAnyApex - return true - } - return false - }) - - if base.ApexProperties.DirectlyInAnyApex { - // Variants of a module are always visited sequentially in order, so it is safe to - // write to another variant of this module. For a BottomUpMutator the - // PrimaryModule() is visited first and FinalModule() is visited last. - mctx.FinalModule().(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex = true - } - - // If this is the FinalModule (last visited module) copy - // AnyVariantDirectlyInAnyApex to all the other variants - if mctx.IsFinalModule(am) { - mctx.VisitAllModuleVariants(func(variant Module) { - variant.(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex = - base.ApexProperties.AnyVariantDirectlyInAnyApex - }) - } -} - -// ApexMembership tells how a module became part of an APEX. -type ApexMembership int - -const ( - notInApex ApexMembership = 0 - indirectlyInApex = iota - directlyInApex -) - -// ApexContents gives an information about member modules of an apexBundle. Each apexBundle has an -// apexContents, and modules in that apex have a provider containing the apexContents of each -// apexBundle they are part of. -type ApexContents struct { - // map from a module name to its membership in this apexBundle - contents map[string]ApexMembership -} - -// NewApexContents creates and initializes an ApexContents that is suitable -// for use with an apex module. -// - contents is a map from a module name to information about its membership within -// the apex. -func NewApexContents(contents map[string]ApexMembership) *ApexContents { - return &ApexContents{ - contents: contents, - } -} - -// Updates an existing membership by adding a new direct (or indirect) membership -func (i ApexMembership) Add(direct bool) ApexMembership { - if direct || i == directlyInApex { - return directlyInApex - } - return indirectlyInApex -} - -// Merges two membership into one. Merging is needed because a module can be a part of an apexBundle -// in many different paths. For example, it could be dependend on by the apexBundle directly, but at -// the same time, there might be an indirect dependency to the module. In that case, the more -// specific dependency (the direct one) is chosen. -func (i ApexMembership) merge(other ApexMembership) ApexMembership { - if other == directlyInApex || i == directlyInApex { - return directlyInApex - } - - if other == indirectlyInApex || i == indirectlyInApex { - return indirectlyInApex - } - return notInApex -} - //////////////////////////////////////////////////////////////////////////////////////////////////// //Below are routines for extra safety checks. // diff --git a/android/apex_test.go b/android/apex_test.go index 347bf7d98..78597b234 100644 --- a/android/apex_test.go +++ b/android/apex_test.go @@ -37,7 +37,6 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "foo", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -46,7 +45,6 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "apex10000", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -61,14 +59,12 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "foo", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, { ApexVariationName: "bar", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"bar"}, - InApexModules: []string{"bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -77,7 +73,6 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "apex10000", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo", "bar"}, - InApexModules: []string{"foo", "bar"}, }}, wantAliases: [][2]string{ {"foo", "apex10000"}, @@ -91,14 +86,12 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "foo", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, { ApexVariationName: "bar", MinSdkVersion: uncheckedFinalApiLevel(30), InApexVariants: []string{"bar"}, - InApexModules: []string{"bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -107,14 +100,12 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "apex10000", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, { ApexVariationName: "apex30", MinSdkVersion: uncheckedFinalApiLevel(30), InApexVariants: []string{"bar"}, - InApexModules: []string{"bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -130,7 +121,6 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "foo", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, { @@ -138,7 +128,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, Updatable: true, InApexVariants: []string{"bar"}, - InApexModules: []string{"bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -148,7 +137,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, Updatable: true, InApexVariants: []string{"foo", "bar"}, - InApexModules: []string{"foo", "bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -164,7 +152,6 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "foo", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, { @@ -172,7 +159,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, Updatable: true, InApexVariants: []string{"bar"}, - InApexModules: []string{"bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, // This one should not be merged in with the others because it is for @@ -182,7 +168,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, Updatable: true, InApexVariants: []string{"baz"}, - InApexModules: []string{"baz"}, ForPrebuiltApex: ForPrebuiltApex, }, }, @@ -192,7 +177,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, Updatable: true, InApexVariants: []string{"foo", "bar"}, - InApexModules: []string{"foo", "bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, { @@ -200,7 +184,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, Updatable: true, InApexVariants: []string{"baz"}, - InApexModules: []string{"baz"}, ForPrebuiltApex: ForPrebuiltApex, }, }, @@ -216,7 +199,6 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "foo", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, { @@ -224,7 +206,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, UsePlatformApis: true, InApexVariants: []string{"bar"}, - InApexModules: []string{"bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -233,7 +214,6 @@ func Test_mergeApexVariations(t *testing.T) { ApexVariationName: "apex10000", MinSdkVersion: FutureApiLevel, InApexVariants: []string{"foo", "bar"}, - InApexModules: []string{"foo", "bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -250,7 +230,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, UsePlatformApis: true, InApexVariants: []string{"foo"}, - InApexModules: []string{"foo"}, ForPrebuiltApex: NotForPrebuiltApex, }, { @@ -258,7 +237,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, UsePlatformApis: true, InApexVariants: []string{"bar"}, - InApexModules: []string{"bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, @@ -268,7 +246,6 @@ func Test_mergeApexVariations(t *testing.T) { MinSdkVersion: FutureApiLevel, UsePlatformApis: true, InApexVariants: []string{"foo", "bar"}, - InApexModules: []string{"foo", "bar"}, ForPrebuiltApex: NotForPrebuiltApex, }, }, diff --git a/android/build_prop.go b/android/build_prop.go index cda56f1e0..2f71bc03f 100644 --- a/android/build_prop.go +++ b/android/build_prop.go @@ -15,6 +15,8 @@ package android import ( + "fmt" + "github.com/google/blueprint/proptools" ) @@ -173,7 +175,16 @@ func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { postProcessCmd.Text(outputFilePath.String()) postProcessCmd.Flags(p.properties.Block_list) - rule.Command().Text("echo").Text(proptools.NinjaAndShellEscape("# end of file")).FlagWithArg(">> ", outputFilePath.String()) + for _, footer := range p.properties.Footer_files { + path := PathForModuleSrc(ctx, footer) + rule.appendText(outputFilePath, "####################################") + rule.appendTextf(outputFilePath, "# Adding footer from %v", footer) + rule.appendTextf(outputFilePath, "# with path %v", path) + rule.appendText(outputFilePath, "####################################") + rule.Command().Text("cat").FlagWithInput("", path).FlagWithArg(">> ", outputFilePath.String()) + } + + rule.appendText(outputFilePath, "# end of file") rule.Build(ctx.ModuleName(), "generating build.prop") @@ -184,6 +195,14 @@ func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { p.outputFilePath = outputFilePath } +func (r *RuleBuilder) appendText(path ModuleOutPath, text string) { + r.Command().Text("echo").Text(proptools.NinjaAndShellEscape(text)).FlagWithArg(">> ", path.String()) +} + +func (r *RuleBuilder) appendTextf(path ModuleOutPath, format string, a ...any) { + r.appendText(path, fmt.Sprintf(format, a...)) +} + func (p *buildPropModule) AndroidMkEntries() []AndroidMkEntries { return []AndroidMkEntries{{ Class: "ETC", diff --git a/android/config.go b/android/config.go index 27d3b87ba..dff3ea5bd 100644 --- a/android/config.go +++ b/android/config.go @@ -285,6 +285,10 @@ func (c Config) ReleaseCreateAconfigStorageFile() bool { return c.config.productVariables.GetBuildFlagBool("RELEASE_CREATE_ACONFIG_STORAGE_FILE") } +func (c Config) ReleaseUseSystemFeatureBuildFlags() bool { + return c.config.productVariables.GetBuildFlagBool("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS") +} + // A DeviceConfig object represents the configuration for a particular device // being built. For now there will only be one of these, but in the future there // may be multiple devices being built. @@ -1834,6 +1838,10 @@ func (c *config) ApexCompressionEnabled() bool { return Bool(c.productVariables.CompressedApex) && !c.UnbundledBuildApps() } +func (c *config) DefaultApexPayloadType() string { + return StringDefault(c.productVariables.DefaultApexPayloadType, "ext4") +} + func (c *config) UseSoongSystemImage() bool { return Bool(c.productVariables.UseSoongSystemImage) } diff --git a/android/container.go b/android/container.go index 2a3777b30..27b17ed99 100644 --- a/android/container.go +++ b/android/container.go @@ -93,7 +93,7 @@ var globallyAllowlistedDependencies = []string{ // TODO(b/363016634): Remove from the allowlist when the module is converted // to java_sdk_library and the java_aconfig_library modules depend on the stub. - "aconfig_storage_reader_java", + "aconfig_storage_stub", // framework-res provides core resources essential for building apps and system UI. // This module is implicitly added as a dependency for java modules even when the @@ -382,7 +382,7 @@ func (c *ContainersInfo) BelongingContainers() []*container { func (c *ContainersInfo) ApexNames() (ret []string) { for _, apex := range c.belongingApexes { - ret = append(ret, apex.InApexModules...) + ret = append(ret, apex.InApexVariants...) } slices.Sort(ret) return ret diff --git a/android/module.go b/android/module.go index 686a90ef0..5437d48ee 100644 --- a/android/module.go +++ b/android/module.go @@ -2455,6 +2455,8 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu return proptools.ConfigurableValueString(v) case "bool": return proptools.ConfigurableValueBool(v == "true") + case "string_list": + return proptools.ConfigurableValueStringList(strings.Split(v, " ")) default: panic("unhandled soong config variable type: " + ty) } diff --git a/android/module_context.go b/android/module_context.go index 20149074e..ae7b54f66 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -831,6 +831,11 @@ func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON { } func (m *moduleContext) SetOutputFiles(outputFiles Paths, tag string) { + for _, outputFile := range outputFiles { + if outputFile == nil { + panic("outputfiles cannot be nil") + } + } if tag == "" { if len(m.outputFiles.DefaultOutputFiles) > 0 { m.ModuleErrorf("Module %s default OutputFiles cannot be overwritten", m.ModuleName()) diff --git a/android/packaging.go b/android/packaging.go index e71d983eb..dcd8844f0 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -410,9 +410,9 @@ func (PackagingItemAlwaysDepTag) IsPackagingItem() bool { return true } -// highPriorityDepTag provides default implementation of HighPriorityPackagingItem interface. type highPriorityDepTag struct { - blueprint.DependencyTag + blueprint.BaseDependencyTag + PackagingItemAlwaysDepTag } // See PackageModule.AddDeps @@ -433,7 +433,7 @@ func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.Dep } depTagToUse := depTag if highPriority { - depTagToUse = highPriorityDepTag{depTag} + depTagToUse = highPriorityDepTag{} } ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep) diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 5e4af0ba5..b90ef3b1c 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -508,11 +508,10 @@ func (p *prebuiltModule) Name() string { } func (p *prebuiltModule) GenerateAndroidBuildActions(ctx ModuleContext) { - var src Path if len(p.properties.Srcs) >= 1 { - src = p.prebuilt.SingleSourcePath(ctx) + src := p.prebuilt.SingleSourcePath(ctx) + ctx.SetOutputFiles(Paths{src}, "") } - ctx.SetOutputFiles(Paths{src}, "") } func (p *prebuiltModule) Prebuilt() *Prebuilt { diff --git a/android/rule_builder.go b/android/rule_builder.go index 403c18418..83f8b9992 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -488,21 +488,15 @@ func (r *RuleBuilder) depFileMergerCmd(depFiles WritablePaths) *RuleBuilderComma Inputs(depFiles.Paths()) } -// BuildWithNinjaVars adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for -// Outputs. This function will not escape Ninja variables, so it may be used to write sandbox manifests using Ninja variables. -func (r *RuleBuilder) BuildWithUnescapedNinjaVars(name string, desc string) { - r.build(name, desc, false) -} - // Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for // Outputs. func (r *RuleBuilder) Build(name string, desc string) { - r.build(name, desc, true) + r.build(name, desc) } var sandboxEnvOnceKey = NewOnceKey("sandbox_environment_variables") -func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString bool) { +func (r *RuleBuilder) build(name string, desc string) { name = ninjaNameEscape(name) if len(r.missingDeps) > 0 { @@ -611,6 +605,7 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b nsjailCmd.WriteString(" -m none:/tmp:tmpfs:size=1073741824") // 1GB, should be enough nsjailCmd.WriteString(" -D nsjail_build_sandbox") nsjailCmd.WriteString(" --disable_rlimits") + nsjailCmd.WriteString(" --skip_setsid") // ABFS relies on process-groups to track file operations nsjailCmd.WriteString(" -q") nsjailCmd.WriteString(" -- ") nsjailCmd.WriteString("/bin/bash -c ") @@ -764,30 +759,7 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b if err != nil { ReportPathErrorf(r.ctx, "sbox manifest failed to marshal: %q", err) } - if ninjaEscapeCommandString { - WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText)) - } else { - // We need to have a rule to write files that is - // defined on the RuleBuilder's pctx in order to - // write Ninja variables in the string. - // The WriteFileRule function above rule can only write - // raw strings because it is defined on the android - // package's pctx, and it can't access variables defined - // in another context. - r.ctx.Build(r.pctx, BuildParams{ - Rule: r.ctx.Rule(r.pctx, "unescapedWriteFile", blueprint.RuleParams{ - Command: `rm -rf ${out} && cat ${out}.rsp > ${out}`, - Rspfile: "${out}.rsp", - RspfileContent: "${content}", - Description: "write file", - }, "content"), - Output: r.sboxManifestPath, - Description: "write sbox manifest " + r.sboxManifestPath.Base(), - Args: map[string]string{ - "content": string(pbText), - }, - }) - } + WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText)) // Generate a new string to use as the command line of the sbox rule. This uses // a RuleBuilderCommand as a convenience method of building the command line, then @@ -881,9 +853,7 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b pool = localPool } - if ninjaEscapeCommandString { - commandString = proptools.NinjaEscape(commandString) - } + commandString = proptools.NinjaEscape(commandString) args_vars := make([]string, len(r.args)) i := 0 diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go index 6a8a964a1..e1a1e08c4 100644 --- a/android/rule_builder_test.go +++ b/android/rule_builder_test.go @@ -475,10 +475,9 @@ type testRuleBuilderModule struct { Srcs []string Flags []string - Restat bool - Sbox bool - Sbox_inputs bool - Unescape_ninja_vars bool + Restat bool + Sbox bool + Sbox_inputs bool } } @@ -498,7 +497,7 @@ func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) { testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, t.properties.Flags, out, outDep, outDir, - manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs, t.properties.Unescape_ninja_vars, + manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs, rspFile, rspFileContents, rspFile2, rspFileContents2) } @@ -523,14 +522,14 @@ func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) { manifestPath := PathForOutput(ctx, "singleton/sbox.textproto") testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, nil, out, outDep, outDir, - manifestPath, true, false, false, false, + manifestPath, true, false, false, rspFile, rspFileContents, rspFile2, rspFileContents2) } func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, validation Path, flags []string, out, outDep, outDir, manifestPath WritablePath, - restat, sbox, sboxInputs, unescapeNinjaVars bool, + restat, sbox, sboxInputs bool, rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) { rule := NewRuleBuilder(pctx_ruleBuilderTest, ctx) @@ -558,11 +557,7 @@ func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, va rule.Restat() } - if unescapeNinjaVars { - rule.BuildWithUnescapedNinjaVars("rule", "desc") - } else { - rule.Build("rule", "desc") - } + rule.Build("rule", "desc") } var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) { @@ -777,48 +772,3 @@ func TestRuleBuilderHashInputs(t *testing.T) { }) } } - -func TestRuleBuilderWithNinjaVarEscaping(t *testing.T) { - bp := ` - rule_builder_test { - name: "foo_sbox_escaped", - flags: ["${cmdFlags}"], - sbox: true, - sbox_inputs: true, - } - rule_builder_test { - name: "foo_sbox_unescaped", - flags: ["${cmdFlags}"], - sbox: true, - sbox_inputs: true, - unescape_ninja_vars: true, - } - ` - result := GroupFixturePreparers( - prepareForRuleBuilderTest, - FixtureWithRootAndroidBp(bp), - ).RunTest(t) - - escapedNinjaMod := result.ModuleForTests("foo_sbox_escaped", "").Output("sbox.textproto") - AssertStringEquals(t, "expected rule", "android/soong/android.rawFileCopy", escapedNinjaMod.Rule.String()) - AssertStringDoesContain( - t, - "", - ContentFromFileRuleForTests(t, result.TestContext, escapedNinjaMod), - "${cmdFlags}", - ) - - unescapedNinjaMod := result.ModuleForTests("foo_sbox_unescaped", "").Rule("unescapedWriteFile") - AssertStringDoesContain( - t, - "", - unescapedNinjaMod.BuildParams.Args["content"], - "${cmdFlags}", - ) - AssertStringDoesNotContain( - t, - "", - unescapedNinjaMod.BuildParams.Args["content"], - "$${cmdFlags}", - ) -} diff --git a/android/sbom.go b/android/sbom.go index 2a5499ed8..f2b9c0ff1 100644 --- a/android/sbom.go +++ b/android/sbom.go @@ -15,9 +15,7 @@ package android import ( - "io" "path/filepath" - "strings" "github.com/google/blueprint" ) @@ -55,21 +53,7 @@ func (this *sbomSingleton) GenerateBuildActions(ctx SingletonContext) { if !ctx.Config().HasDeviceProduct() { return } - // Get all METADATA files and add them as implicit input - metadataFileListFile := PathForArbitraryOutput(ctx, ".module_paths", "METADATA.list") - f, err := ctx.Config().fs.Open(metadataFileListFile.String()) - if err != nil { - panic(err) - } - b, err := io.ReadAll(f) - if err != nil { - panic(err) - } - allMetadataFiles := strings.Split(string(b), "\n") - implicits := []Path{metadataFileListFile} - for _, path := range allMetadataFiles { - implicits = append(implicits, PathForSource(ctx, path)) - } + implicits := []Path{} prodVars := ctx.Config().productVariables buildFingerprintFile := PathForArbitraryOutput(ctx, "target", "product", String(prodVars.DeviceName), "build_fingerprint.txt") implicits = append(implicits, buildFingerprintFile) diff --git a/android/selects_test.go b/android/selects_test.go index 90d7091e0..1397ed8b7 100644 --- a/android/selects_test.go +++ b/android/selects_test.go @@ -1031,6 +1031,54 @@ my_module_type { my_string_list: &[]string{"d2", "e2", "f2", "a1", "b1", "c1"}, }, }, + { + name: "string list variables", + bp: ` +my_module_type { + name: "foo", + my_string_list: ["a"] + select(soong_config_variable("my_namespace", "my_var"), { + any @ my_var: my_var, + default: [], + }), +} +`, + vendorVars: map[string]map[string]string{ + "my_namespace": { + "my_var": "b c", + }, + }, + vendorVarTypes: map[string]map[string]string{ + "my_namespace": { + "my_var": "string_list", + }, + }, + provider: selectsTestProvider{ + my_string_list: &[]string{"a", "b", "c"}, + }, + }, + { + name: "string list variables don't match string matchers", + bp: ` +my_module_type { + name: "foo", + my_string_list: ["a"] + select(soong_config_variable("my_namespace", "my_var"), { + "foo": ["b"], + default: [], + }), +} +`, + vendorVars: map[string]map[string]string{ + "my_namespace": { + "my_var": "b c", + }, + }, + vendorVarTypes: map[string]map[string]string{ + "my_namespace": { + "my_var": "string_list", + }, + }, + expectedError: `Expected all branches of a select on condition soong_config_variable\("my_namespace", "my_var"\) to have type string_list, found string`, + }, } for _, tc := range testCases { diff --git a/android/test_config.go b/android/test_config.go index f2510387f..3609e6b78 100644 --- a/android/test_config.go +++ b/android/test_config.go @@ -45,6 +45,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string Platform_version_active_codenames: []string{"S", "Tiramisu"}, DeviceSystemSdkVersions: []string{"29", "30", "S"}, Platform_systemsdk_versions: []string{"29", "30", "S", "Tiramisu"}, + VendorApiLevel: stringPtr("202404"), AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"}, AAPTPreferredConfig: stringPtr("xhdpi"), AAPTCharacteristics: stringPtr("nosdcard"), diff --git a/android/variable.go b/android/variable.go index 2d43c6da4..36ddc1c81 100644 --- a/android/variable.go +++ b/android/variable.go @@ -408,9 +408,10 @@ type ProductVariables struct { Ndk_abis *bool `json:",omitempty"` - ForceApexSymlinkOptimization *bool `json:",omitempty"` - CompressedApex *bool `json:",omitempty"` - Aml_abis *bool `json:",omitempty"` + ForceApexSymlinkOptimization *bool `json:",omitempty"` + CompressedApex *bool `json:",omitempty"` + DefaultApexPayloadType *string `json:",omitempty"` + Aml_abis *bool `json:",omitempty"` DexpreoptGlobalConfig *string `json:",omitempty"` @@ -609,15 +610,25 @@ type PartitionVariables struct { ProductUseDynamicPartitionSize bool `json:",omitempty"` CopyImagesForTargetFilesZip bool `json:",omitempty"` + VendorSecurityPatch string `json:",omitempty"` + // Boot image stuff - ProductBuildBootImage bool `json:",omitempty"` - ProductBuildInitBootImage bool `json:",omitempty"` - BoardUsesRecoveryAsBoot bool `json:",omitempty"` - BoardPrebuiltBootimage string `json:",omitempty"` - BoardPrebuiltInitBootimage string `json:",omitempty"` - BoardBootimagePartitionSize string `json:",omitempty"` - BoardInitBootimagePartitionSize string `json:",omitempty"` - BoardBootHeaderVersion string `json:",omitempty"` + BuildingRamdiskImage bool `json:",omitempty"` + ProductBuildBootImage bool `json:",omitempty"` + ProductBuildVendorBootImage string `json:",omitempty"` + ProductBuildInitBootImage bool `json:",omitempty"` + BoardUsesRecoveryAsBoot bool `json:",omitempty"` + BoardPrebuiltBootimage string `json:",omitempty"` + BoardPrebuiltInitBootimage string `json:",omitempty"` + BoardBootimagePartitionSize string `json:",omitempty"` + BoardInitBootimagePartitionSize string `json:",omitempty"` + BoardBootHeaderVersion string `json:",omitempty"` + TargetKernelPath string `json:",omitempty"` + BoardUsesGenericKernelImage bool `json:",omitempty"` + BootSecurityPatch string `json:",omitempty"` + InitBootSecurityPatch string `json:",omitempty"` + BoardIncludeDtbInBootimg bool `json:",omitempty"` + InternalKernelCmdline []string `json:",omitempty"` // Avb (android verified boot) stuff BoardAvbEnable bool `json:",omitempty"` diff --git a/android/vendor_api_levels.go b/android/vendor_api_levels.go new file mode 100644 index 000000000..4d364fde6 --- /dev/null +++ b/android/vendor_api_levels.go @@ -0,0 +1,49 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "fmt" + "strconv" +) + +func getSdkVersionOfVendorApiLevel(apiLevel int) (int, bool) { + ok := true + sdkVersion := -1 + switch apiLevel { + case 202404: + sdkVersion = 35 + case 202504: + sdkVersion = 36 + default: + ok = false + } + return sdkVersion, ok +} + +func GetSdkVersionForVendorApiLevel(vendorApiLevel string) (ApiLevel, error) { + vendorApiLevelInt, err := strconv.Atoi(vendorApiLevel) + if err != nil { + return NoneApiLevel, fmt.Errorf("The vendor API level %q must be able to be parsed as an integer", vendorApiLevel) + } + if vendorApiLevelInt < 35 { + return uncheckedFinalApiLevel(vendorApiLevelInt), nil + } + + if sdkInt, ok := getSdkVersionOfVendorApiLevel(vendorApiLevelInt); ok { + return uncheckedFinalApiLevel(sdkInt), nil + } + return NoneApiLevel, fmt.Errorf("Unknown vendor API level %q. Requires updating the map in vendor_api_level.go?", vendorApiLevel) +} |