diff options
37 files changed, 644 insertions, 195 deletions
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go index f3c68c37a..5a5262485 100644 --- a/aconfig/all_aconfig_declarations.go +++ b/aconfig/all_aconfig_declarations.go @@ -129,6 +129,7 @@ func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx and invalidExportedFlags := android.PathForIntermediates(ctx, "invalid_exported_flags.txt") GenerateExportedFlagCheck(ctx, invalidExportedFlags, parsedFlagsFile, this.properties) depsFiles = append(depsFiles, invalidExportedFlags) + ctx.Phony("droidcore", invalidExportedFlags) } } diff --git a/android/Android.bp b/android/Android.bp index 00dc50ac2..97d634fb5 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -12,6 +12,7 @@ bootstrap_go_package { "blueprint-gobtools", "blueprint-metrics", "blueprint-pool", + "blueprint-syncmap", "sbox_proto", "soong", "soong-android_team_proto", @@ -83,6 +84,7 @@ bootstrap_go_package { "nothing.go", "notices.go", "onceper.go", + "otatools_package_cert_zip.go", "override_module.go", "package.go", "package_ctx.go", diff --git a/android/androidmk.go b/android/androidmk.go index 784559312..e32835946 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -435,13 +435,18 @@ func getDistContributions(ctx ConfigAndOtherModuleProviderContext, mod Module) * suffix = *dist.Suffix } - productString := "" - if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product { - productString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct()) + prependProductString := "" + if proptools.Bool(dist.Prepend_artifact_with_product) { + prependProductString = fmt.Sprintf("%s-", ctx.Config().DeviceProduct()) } - if suffix != "" || productString != "" { - dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext + appendProductString := "" + if proptools.Bool(dist.Append_artifact_with_product) { + appendProductString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct()) + } + + if suffix != "" || appendProductString != "" || prependProductString != "" { + dest = prependProductString + strings.TrimSuffix(dest, ext) + suffix + appendProductString + ext } if dist.Dir != nil { @@ -510,6 +515,9 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod Module) { a.EntryMap = make(map[string][]string) base := mod.base() name := base.BaseModuleName() + if bmn, ok := mod.(baseModuleName); ok { + name = bmn.BaseModuleName() + } if a.OverrideName != "" { name = a.OverrideName } diff --git a/android/configurable_properties.go b/android/configurable_properties.go index 2c794a186..bde33e99b 100644 --- a/android/configurable_properties.go +++ b/android/configurable_properties.go @@ -7,7 +7,8 @@ import "github.com/google/blueprint/proptools" // to indicate a "default" case. func CreateSelectOsToBool(cases map[string]*bool) proptools.Configurable[bool] { var resultCases []proptools.ConfigurableCase[bool] - for pattern, value := range cases { + for _, pattern := range SortedKeys(cases) { + value := cases[pattern] if pattern == "" { resultCases = append(resultCases, proptools.NewConfigurableCase( []proptools.ConfigurablePattern{proptools.NewDefaultConfigurablePattern()}, diff --git a/android/module.go b/android/module.go index ecd0f239c..1538861d3 100644 --- a/android/module.go +++ b/android/module.go @@ -45,6 +45,14 @@ type Module interface { // For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go GenerateAndroidBuildActions(ModuleContext) + // CleanupAfterBuildActions is called after ModuleBase.GenerateBuildActions is finished. + // If all interactions with this module are handled via providers instead of direct access + // to the module then it can free memory attached to the module. + // This is a temporary measure to reduce memory usage, eventually blueprint's reference + // to the Module should be dropped after GenerateAndroidBuildActions once all accesses + // can be done through providers. + CleanupAfterBuildActions() + // Add dependencies to the components of a module, i.e. modules that are created // by the module and which are considered to be part of the creating module. // @@ -200,6 +208,12 @@ type Dist struct { // no change to the artifact file name. Append_artifact_with_product *bool `android:"arch_variant"` + // If true, then the artifact file will be prepended with <product name>-. For + // example, if the product is coral and the module is an android_app module + // of name foo, then the artifact would be coral-foo.apk. If false, there is + // no change to the artifact file name. + Prepend_artifact_with_product *bool `android:"arch_variant"` + // A string tag to select the OutputFiles associated with the tag. // // If no tag is specified then it will select the default dist paths provided @@ -2387,8 +2401,12 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) }) } } + + m.module.CleanupAfterBuildActions() } +func (m *ModuleBase) CleanupAfterBuildActions() {} + func SetJarJarPrefixHandler(handler func(ModuleContext)) { if jarJarPrefixHandler != nil { panic("jarJarPrefixHandler already set") diff --git a/android/module_proxy.go b/android/module_proxy.go index 561c4770c..81d90e9a0 100644 --- a/android/module_proxy.go +++ b/android/module_proxy.go @@ -27,6 +27,10 @@ func (m ModuleProxy) GenerateAndroidBuildActions(context ModuleContext) { panic("method is not implemented on ModuleProxy") } +func (m ModuleProxy) CleanupAfterBuildActions() { + panic("method is not implemented on ModuleProxy") +} + func (m ModuleProxy) ComponentDepsMutator(ctx BottomUpMutatorContext) { panic("method is not implemented on ModuleProxy") } diff --git a/android/otatools_package_cert_zip.go b/android/otatools_package_cert_zip.go new file mode 100644 index 000000000..3a654cfe5 --- /dev/null +++ b/android/otatools_package_cert_zip.go @@ -0,0 +1,62 @@ +// Copyright 2025 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 ( + "github.com/google/blueprint" +) + +func init() { + RegisterOtatoolsPackageBuildComponents(InitRegistrationContext) + pctx.HostBinToolVariable("SoongZipCmd", "soong_zip") +} + +func RegisterOtatoolsPackageBuildComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("otatools_package_cert_files", OtatoolsPackageFactory) +} + +type OtatoolsPackage struct { + ModuleBase +} + +func OtatoolsPackageFactory() Module { + module := &OtatoolsPackage{} + InitAndroidModule(module) + return module +} + +var ( + otatoolsPackageCertRule = pctx.AndroidStaticRule("otatools_package_cert_files", blueprint.RuleParams{ + Command: "echo '$out : ' $$(cat $in) > ${out}.d && ${SoongZipCmd} -o $out -l $in", + CommandDeps: []string{"${SoongZipCmd}"}, + Depfile: "${out}.d", + Description: "Zip otatools-package cert files", + }) +) + +func (fg *OtatoolsPackage) GenerateAndroidBuildActions(ctx ModuleContext) { + if ctx.ModuleDir() != "build/make/tools/otatools_package" { + ctx.ModuleErrorf("There can only be one otatools_package_cert_files module in build/make/tools/otatools_package") + return + } + fileListFile := PathForArbitraryOutput(ctx, ".module_paths", "OtaToolsCertFiles.list") + otatoolsPackageCertZip := PathForModuleOut(ctx, "otatools_package_cert_files.zip") + ctx.Build(pctx, BuildParams{ + Rule: otatoolsPackageCertRule, + Input: fileListFile, + Output: otatoolsPackageCertZip, + }) + ctx.SetOutputFiles([]Path{otatoolsPackageCertZip}, "") +} diff --git a/android/packaging.go b/android/packaging.go index bb1fe4e45..bf1840929 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -506,13 +506,11 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont // all packaging specs gathered from the high priority deps. var highPriorities []PackagingSpec - // Name of the dependency which requested the packaging spec. - // If this dep is overridden, the packaging spec will not be installed via this dependency chain. - // (the packaging spec might still be installed if there are some other deps which depend on it). - var depNames []string - // list of module names overridden - var overridden []string + overridden := make(map[string]bool) + + // all installed modules which are not overridden. + modulesToInstall := make(map[string]bool) var arches []ArchType for _, target := range getSupportedTargets(ctx) { @@ -529,6 +527,7 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont return false } + // find all overridden modules and packaging specs ctx.VisitDirectDepsProxy(func(child ModuleProxy) { depTag := ctx.OtherModuleDependencyTag(child) if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() { @@ -556,20 +555,32 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont regularPriorities = append(regularPriorities, ps) } - depNames = append(depNames, child.Name()) - overridden = append(overridden, ps.overrides.ToSlice()...) + for o := range ps.overrides.Iter() { + overridden[o] = true + } + } + }) + + // gather modules to install, skipping overridden modules + ctx.WalkDeps(func(child, parent Module) bool { + owner := ctx.OtherModuleName(child) + if o, ok := child.(OverridableModule); ok { + if overriddenBy := o.GetOverriddenBy(); overriddenBy != "" { + owner = overriddenBy + } + } + if overridden[owner] { + return false } + modulesToInstall[owner] = true + return true }) filterOverridden := func(input []PackagingSpec) []PackagingSpec { - // input minus packaging specs that are overridden + // input minus packaging specs that are not installed var filtered []PackagingSpec - for index, ps := range input { - if ps.owner != "" && InList(ps.owner, overridden) { - continue - } - // The dependency which requested this packaging spec has been overridden. - if InList(depNames[index], overridden) { + for _, ps := range input { + if !modulesToInstall[ps.owner] { continue } filtered = append(filtered, ps) diff --git a/android/raw_files.go b/android/raw_files.go index fd371965c..ebba4d145 100644 --- a/android/raw_files.go +++ b/android/raw_files.go @@ -26,6 +26,7 @@ import ( "testing" "github.com/google/blueprint" + "github.com/google/blueprint/syncmap" "github.com/google/blueprint/proptools" ) @@ -213,10 +214,10 @@ type rawFileInfo struct { var rawFileSetKey OnceKey = NewOnceKey("raw file set") -func getRawFileSet(config Config) *SyncMap[string, rawFileInfo] { +func getRawFileSet(config Config) *syncmap.SyncMap[string, rawFileInfo] { return config.Once(rawFileSetKey, func() any { - return &SyncMap[string, rawFileInfo]{} - }).(*SyncMap[string, rawFileInfo]) + return &syncmap.SyncMap[string, rawFileInfo]{} + }).(*syncmap.SyncMap[string, rawFileInfo]) } // ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use diff --git a/android/test_suites.go b/android/test_suites.go index 9eaf78549..dbcd48c79 100644 --- a/android/test_suites.go +++ b/android/test_suites.go @@ -42,6 +42,12 @@ type TestSuiteInfo struct { var TestSuiteInfoProvider = blueprint.NewProvider[TestSuiteInfo]() +type SupportFilesInfo struct { + SupportFiles InstallPaths +} + +var SupportFilesInfoProvider = blueprint.NewProvider[SupportFilesInfo]() + func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) { files := make(map[string]map[string]InstallPaths) diff --git a/android/util.go b/android/util.go index 7b305b575..4520f400e 100644 --- a/android/util.go +++ b/android/util.go @@ -23,7 +23,6 @@ import ( "runtime" "sort" "strings" - "sync" "github.com/google/blueprint/proptools" ) @@ -646,35 +645,6 @@ func AddToStringSet(set map[string]bool, items []string) { } } -// SyncMap is a wrapper around sync.Map that provides type safety via generics. -type SyncMap[K comparable, V any] struct { - sync.Map -} - -// Load returns the value stored in the map for a key, or the zero value if no -// value is present. -// The ok result indicates whether value was found in the map. -func (m *SyncMap[K, V]) Load(key K) (value V, ok bool) { - v, ok := m.Map.Load(key) - if !ok { - return *new(V), false - } - return v.(V), true -} - -// Store sets the value for a key. -func (m *SyncMap[K, V]) Store(key K, value V) { - m.Map.Store(key, value) -} - -// LoadOrStore returns the existing value for the key if present. -// Otherwise, it stores and returns the given value. -// The loaded result is true if the value was loaded, false if stored. -func (m *SyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) { - v, loaded := m.Map.LoadOrStore(key, value) - return v.(V), loaded -} - // AppendIfNotZero append the given value to the slice if it is not the zero value // for its type. func AppendIfNotZero[T comparable](slice []T, value T) []T { diff --git a/android/variable.go b/android/variable.go index 357d137c7..f00dd138b 100644 --- a/android/variable.go +++ b/android/variable.go @@ -715,6 +715,10 @@ type PartitionVariables struct { ReleaseToolsExtensionDir string `json:",omitempty"` + BoardPartialOtaUpdatePartitionsList []string `json:",omitempty"` + BoardFlashBlockSize string `json:",omitempty"` + BootloaderInUpdatePackage bool `json:",omitempty"` + BoardFastbootInfoFile string `json:",omitempty"` } diff --git a/apex/androidmk.go b/apex/androidmk.go index 3a81ee4e6..0a5644ae3 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -75,7 +75,7 @@ func (a *apexBundle) fullModuleName(apexBundleName string, linkToSystemLib bool, // populated by Soong for unconverted APEXes, or Bazel in mixed mode. Use // apexFile#isBazelPrebuilt to differentiate. func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir string, - apexAndroidMkData android.AndroidMkData) []string { + apexAndroidMkData android.AndroidMkData) (archSpecificModuleNames []string, moduleNames []string) { // apexBundleName comes from the 'name' property or soong module. // apexName comes from 'name' property of apex_manifest. @@ -84,11 +84,12 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st // However, symbol files for apex files are installed under /apex/<apexBundleName> to avoid // conflicts between two apexes with the same apexName. - moduleNames := []string{} - for _, fi := range a.filesInfo { linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() moduleName := a.fullModuleName(apexBundleName, linkToSystemLib, &fi) + if !android.InList(moduleName, moduleNames) { + moduleNames = append(moduleNames, moduleName) + } // This name will be added to LOCAL_REQUIRED_MODULES of the APEX. We need to be // arch-specific otherwise we will end up installing both ABIs even when only @@ -100,8 +101,8 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st case "lib64": aName = aName + ":64" } - if !android.InList(aName, moduleNames) { - moduleNames = append(moduleNames, aName) + if !android.InList(aName, archSpecificModuleNames) { + archSpecificModuleNames = append(archSpecificModuleNames, aName) } if linkToSystemLib { @@ -216,7 +217,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir st fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName) } } - return moduleNames + return } func (a *apexBundle) writeRequiredModules(w io.Writer, moduleNames []string) { @@ -235,9 +236,10 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { return android.AndroidMkData{ // While we do not provide a value for `Extra`, AconfigUpdateAndroidMkData may add some, which we must honor. Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { + archSpecificModuleNames := []string{} moduleNames := []string{} if a.installable() { - moduleNames = a.androidMkForFiles(w, name, moduleDir, data) + archSpecificModuleNames, moduleNames = a.androidMkForFiles(w, name, moduleDir, data) } fmt.Fprintln(w, "\ninclude $(CLEAR_VARS) # apex.apexBundle") @@ -274,7 +276,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { } android.AndroidMkEmitAssignList(w, "LOCAL_OVERRIDES_MODULES", a.overridableProperties.Overrides) - a.writeRequiredModules(w, moduleNames) + a.writeRequiredModules(w, archSpecificModuleNames) // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here. for _, extra := range data.Extra { extra(w, a.outputFile) @@ -296,6 +298,9 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { fmt.Fprintln(w, dist) } + fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).SYMBOLIC_OUTPUT_PATH := $(foreach m,%s,$(ALL_MODULES.$(m).SYMBOLIC_OUTPUT_PATH))\n", strings.Join(moduleNames, " ")) + fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).ELF_SYMBOL_MAPPING_PATH := $(foreach m,%s,$(ALL_MODULES.$(m).ELF_SYMBOL_MAPPING_PATH))\n", strings.Join(moduleNames, " ")) + distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisUsedByModuleFile.String()) distCoverageFiles(w, "ndk_apis_backedby_apex", a.nativeApisBackedByModuleFile.String()) distCoverageFiles(w, "java_apis_used_by_apex", a.javaApisUsedByModuleFile.String()) diff --git a/apex/apex_test.go b/apex/apex_test.go index 36a697487..327e018f4 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -11468,6 +11468,16 @@ func TestInstallationRulesForMultipleApexPrebuilts(t *testing.T) { // 1. The contents of the selected apex_contributions are visible to make // 2. The rest of the apexes in the mainline module family (source or other prebuilt) is hidden from make checkHideFromMake(t, ctx, tc.expectedVisibleModuleName, tc.expectedHiddenModuleNames) + + // Check that source_apex_name is written as LOCAL_MODULE for make packaging + if tc.expectedVisibleModuleName == "prebuilt_com.google.android.foo.v2" { + apex := ctx.ModuleForTests(t, "prebuilt_com.google.android.foo.v2", "android_common_prebuilt_com.android.foo").Module() + entries := android.AndroidMkEntriesForTest(t, ctx, apex)[0] + + expected := "com.google.android.foo" + actual := entries.EntryMap["LOCAL_MODULE"][0] + android.AssertStringEquals(t, "LOCAL_MODULE", expected, actual) + } } } diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 89b0091be..fdd9a75d7 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -15,7 +15,9 @@ package apex import ( + "fmt" "slices" + "sort" "strconv" "strings" @@ -80,6 +82,10 @@ type prebuiltCommon struct { // systemServerDexJars stores the list of dexjars for system server jars in the prebuilt for use when // dexpreopting system server jars that are later in the system server classpath. systemServerDexJars android.Paths + + // Certificate information of any apk packaged inside the prebuilt apex. + // This will be nil if the prebuilt apex does not contain any apk. + apkCertsFile android.WritablePath } type sanitizedPrebuilt interface { @@ -273,6 +279,10 @@ func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries { entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable()) entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...) entries.SetString("LOCAL_APEX_KEY_PATH", p.apexKeysPath.String()) + if p.apkCertsFile != nil { + entries.SetString("LOCAL_APKCERTS_FILE", p.apkCertsFile.String()) + } + }, }, }, @@ -286,6 +296,14 @@ func (p *prebuiltCommon) hasExportedDeps() bool { len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0 } +type appInPrebuiltApexDepTag struct { + blueprint.BaseDependencyTag +} + +func (appInPrebuiltApexDepTag) ExcludeFromVisibilityEnforcement() {} + +var appInPrebuiltApexTag = appInPrebuiltApexDepTag{} + // prebuiltApexContentsDeps adds dependencies onto the prebuilt apex module's contents. func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) { module := ctx.Module() @@ -432,6 +450,12 @@ type PrebuiltProperties struct { ApexFileProperties PrebuiltCommonProperties + + // List of apps that are bundled inside this prebuilt apex. + // This will be used to create the certificate info of those apps for apkcerts.txt + // This dependency will only be used for apkcerts.txt processing. + // Notably, building the prebuilt apex will not build the source app. + Apps []string } func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool { @@ -545,6 +569,9 @@ var ( func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { p.prebuiltApexContentsDeps(ctx) + for _, app := range p.properties.Apps { + ctx.AddDependency(p, appInPrebuiltApexTag, app) + } } var _ ApexTransitionMutator = (*Prebuilt)(nil) @@ -677,11 +704,59 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile) } + p.addApkCertsInfo(ctx) + ctx.SetOutputFiles(android.Paths{p.outputApex}, "") android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{p.apexKeysPath}) } +// `addApkCertsInfo` sets a provider that will be used to create apkcerts.txt +func (p *Prebuilt) addApkCertsInfo(ctx android.ModuleContext) { + formatLine := func(cert java.Certificate, name, partition string) string { + pem := cert.AndroidMkString() + var key string + if cert.Key == nil { + key = "" + } else { + key = cert.Key.String() + } + return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition) + } + + // Determine if this prebuilt_apex contains any .apks + var appInfos java.AppInfos + ctx.VisitDirectDepsProxyWithTag(appInPrebuiltApexTag, func(app android.ModuleProxy) { + if appInfo, ok := android.OtherModuleProvider(ctx, app, java.AppInfoProvider); ok { + appInfos = append(appInfos, *appInfo) + } else { + ctx.ModuleErrorf("App %s does not set AppInfoProvider\n", app.Name()) + } + }) + sort.Slice(appInfos, func(i, j int) bool { + return appInfos[i].InstallApkName < appInfos[j].InstallApkName + }) + + if len(appInfos) == 0 { + return + } + + // Set a provider for use by `android_device`. + // `android_device` will create an apkcerts.txt with the list of installed apps for that device. + android.SetProvider(ctx, java.AppInfosProvider, appInfos) + + // Set a Make variable for legacy apkcerts.txt creation + // p.apkCertsFile will become `LOCAL_APKCERTS_FILE` + var lines []string + for _, appInfo := range appInfos { + lines = append(lines, formatLine(appInfo.Certificate, appInfo.InstallApkName+".apk", p.PartitionTag(ctx.DeviceConfig()))) + } + if len(lines) > 0 { + p.apkCertsFile = android.PathForModuleOut(ctx, "apkcerts.txt") + android.WriteFileRule(ctx, p.apkCertsFile, strings.Join(lines, "\n")) + } +} + func (p *Prebuilt) ProvenanceMetaDataFile() android.Path { return p.provenanceMetaDataFile } @@ -2438,6 +2438,27 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } } +func (c *Module) CleanupAfterBuildActions() { + // Clear as much of Module as possible to reduce memory usage. + c.generators = nil + c.compiler = nil + c.installer = nil + c.features = nil + c.coverage = nil + c.fuzzer = nil + c.sabi = nil + c.lto = nil + c.afdo = nil + c.orderfile = nil + + // TODO: these can be cleared after nativeBinaryInfoProperties and nativeLibInfoProperties are switched to + // using providers. + // c.linker = nil + // c.stl = nil + // c.sanitize = nil + // c.library = nil +} + func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableInterface) *LinkableInfo { info := &LinkableInfo{ StaticExecutable: mod.StaticExecutable(), diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index d1440eaad..46290300c 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -573,9 +573,8 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte func getRequiredMemberOutputFile(ctx android.SdkMemberContext, ccModule *Module) android.Path { var path android.Path - outputFile := ccModule.OutputFile() - if outputFile.Valid() { - path = outputFile.Path() + if info, ok := android.OtherModuleProvider(ctx.SdkModuleContext(), ccModule, LinkableInfoProvider); ok && info.OutputFile.Valid() { + path = info.OutputFile.Path() } else { ctx.SdkModuleContext().ModuleErrorf("member variant %s does not have a valid output file", ccModule) } diff --git a/ci_tests/ci_test_package_zip.go b/ci_tests/ci_test_package_zip.go index d7aaa6686..4cadffddc 100644 --- a/ci_tests/ci_test_package_zip.go +++ b/ci_tests/ci_test_package_zip.go @@ -68,7 +68,7 @@ var ( pctx = android.NewPackageContext("android/soong/ci_tests") // test_package module type should only be used for the following modules. // TODO: remove "_soong" from the module names inside when eliminating the corresponding make modules - moduleNamesAllowed = []string{"continuous_native_tests_soong", "continuous_instrumentation_tests_soong", "platform_tests"} + moduleNamesAllowed = []string{"continuous_instrumentation_tests_soong", "continuous_instrumentation_metric_tests_soong", "continuous_native_tests_soong", "continuous_native_metric_tests_soong", "platform_tests"} ) func (p *testPackageZip) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -150,12 +150,6 @@ func (p *testPackageZip) GenerateAndroidBuildActions(ctx android.ModuleContext) p.output = createOutput(ctx, pctx) ctx.SetOutputFiles(android.Paths{p.output}, "") - - // dist the test output - if ctx.ModuleName() == "platform_tests" { - distedName := ctx.Config().Getenv("TARGET_PRODUCT") + "-tests-FILE_NAME_TAG_PLACEHOLDER.zip" - ctx.DistForGoalWithFilename("platform_tests", p.output, distedName) - } } func createOutput(ctx android.ModuleContext, pctx android.PackageContext) android.ModuleOutPath { diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go index 4f6de82a2..584cc042d 100644 --- a/cmd/soong_ui/main.go +++ b/cmd/soong_ui/main.go @@ -333,7 +333,7 @@ func dumpVar(ctx build.Context, config build.Config, args []string) { varName := flags.Arg(0) if varName == "report_config" { - varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars) + varData, err := build.DumpMakeVars(ctx, config, nil, append(build.BannerVars, "PRODUCT_SOONG_ONLY")) if err != nil { ctx.Fatal(err) } @@ -400,7 +400,7 @@ func dumpVars(ctx build.Context, config build.Config, args []string) { if i := indexList("report_config", allVars); i != -1 { allVars = append(allVars[:i], allVars[i+1:]...) - allVars = append(allVars, build.BannerVars...) + allVars = append(allVars, append(build.BannerVars, "PRODUCT_SOONG_ONLY")...) } if len(allVars) == 0 { diff --git a/filesystem/android_device.go b/filesystem/android_device.go index feb000dc4..9a085a628 100644 --- a/filesystem/android_device.go +++ b/filesystem/android_device.go @@ -90,6 +90,10 @@ type DeviceProperties struct { Releasetools_extension *string `android:"path"` FastbootInfo *string `android:"path"` + Partial_ota_update_partitions []string + Flash_block_size *string + Bootloader_in_update_package *bool + // The kernel version in the build. Will be verified against the actual kernel. // If not provided, will attempt to extract it from the loose kernel or the kernel inside // the boot image. The version is later used to decide whether or not to enable uffd_gc @@ -116,6 +120,7 @@ type androidDevice struct { rootDirForFsConfig string rootDirForFsConfigTimestamp android.Path apkCertsInfo android.Path + targetFilesZip android.Path } func AndroidDeviceFactory() android.Module { @@ -391,6 +396,16 @@ func (a *androidDevice) distFiles(ctx android.ModuleContext) { if a.deviceProps.Android_info != nil { ctx.DistForGoal("droidcore-unbundled", android.PathForModuleSrc(ctx, *a.deviceProps.Android_info)) } + if a.miscInfo != nil { + ctx.DistForGoal("droidcore-unbundled", a.miscInfo) + if a.partitionProps.Super_partition_name != nil { + ctx.DistForGoalWithFilename("dist_files", a.miscInfo, "super_misc_info.txt") + } + } + if a.targetFilesZip != nil { + ctx.DistForGoalWithFilename("target-files-package", a.targetFilesZip, namePrefix+insertBeforeExtension(a.targetFilesZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) + } + } } @@ -579,6 +594,7 @@ func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstal a.copyImagesToTargetZip(ctx, builder, targetFilesDir) a.copyMetadataToTargetZip(ctx, builder, targetFilesDir, allInstalledModules) + a.targetFilesZip = targetFilesZip builder.Command(). BuiltTool("soong_zip"). Text("-d"). @@ -840,14 +856,25 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path { Textf("echo avb_enable=true >> %s", miscInfo). Textf("&& echo avb_building_vbmeta_image=true >> %s", miscInfo). Textf("&& echo avb_avbtool=avbtool >> %s", miscInfo) + + var allChainedVbmetaPartitionTypes []string for _, vbmetaPartitionName := range a.partitionProps.Vbmeta_partitions { img := ctx.GetDirectDepProxyWithTag(vbmetaPartitionName, filesystemDepTag) if provider, ok := android.OtherModuleProvider(ctx, img, vbmetaPartitionProvider); ok { builder.Command().Text("cat").Input(provider.PropFileForMiscInfo).Textf(" >> %s", miscInfo) + if provider.FilesystemPartitionType != "" { // the top-level vbmeta.img + allChainedVbmetaPartitionTypes = append(allChainedVbmetaPartitionTypes, provider.FilesystemPartitionType) + } } else { ctx.ModuleErrorf("vbmeta dep %s does not set vbmetaPartitionProvider\n", vbmetaPartitionName) } } + // Determine the custom vbmeta partitions by removing system and vendor + customVbmetaPartitionTypes := android.RemoveListFromList(allChainedVbmetaPartitionTypes, []string{"system", "vendor"}) + builder.Command().Textf("echo avb_custom_vbmeta_images_partition_list=%s >> %s", + strings.Join(android.SortedUniqueStrings(customVbmetaPartitionTypes), " "), + miscInfo, + ) } if a.partitionProps.Boot_partition_name != nil { @@ -883,6 +910,14 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path { builder.Command().Text("cat").Input(bootImgInfo.PropFileForMiscInfo).Textf(" >> %s", miscInfo) } + builder.Command().Textf("echo blocksize=%s >> %s", proptools.String(a.deviceProps.Flash_block_size), miscInfo) + if proptools.Bool(a.deviceProps.Bootloader_in_update_package) { + builder.Command().Textf("echo bootloader_in_update_package=true >> %s", miscInfo) + } + if len(a.deviceProps.Partial_ota_update_partitions) > 0 { + builder.Command().Textf("echo partial_ota_update_partitions_list=%s >> %s", strings.Join(a.deviceProps.Partial_ota_update_partitions, " "), miscInfo) + } + // Sort and dedup builder.Command().Textf("sort -u %s -o %s", miscInfo, miscInfo) diff --git a/filesystem/android_device_product_out.go b/filesystem/android_device_product_out.go index 7d37f1ee7..aa06337ca 100644 --- a/filesystem/android_device_product_out.go +++ b/filesystem/android_device_product_out.go @@ -167,7 +167,7 @@ func (a *androidDevice) copyFilesToProductOutForSoongOnly(ctx android.ModuleCont } if proptools.String(a.deviceProps.Android_info) != "" { - installPath := android.PathForModuleInPartitionInstall(ctx, "", "android_info.txt") + installPath := android.PathForModuleInPartitionInstall(ctx, "", "android-info.txt") ctx.Build(pctx, android.BuildParams{ Rule: android.Cp, Input: android.PathForModuleSrc(ctx, *a.deviceProps.Android_info), diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go index 5ab0c6899..485eae47c 100644 --- a/filesystem/bootimg.go +++ b/filesystem/bootimg.go @@ -539,6 +539,14 @@ func (b *bootimg) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Pa bootImgType := proptools.String(b.properties.Boot_image_type) addStr("avb_"+bootImgType+"_add_hash_footer_args", b.getAvbHashFooterArgs(ctx)) + if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" { + ramdiskModule := ctx.GetDirectDepWithTag(ramdisk, bootimgRamdiskDep) + fsInfo, _ := android.OtherModuleProvider(ctx, ramdiskModule, FilesystemProvider) + if fsInfo.HasOrIsRecovery { + // Create a dup entry for recovery + addStr("avb_recovery_add_hash_footer_args", strings.ReplaceAll(b.getAvbHashFooterArgs(ctx), bootImgType, "recovery")) + } + } if b.properties.Avb_private_key != nil { addStr("avb_"+bootImgType+"_algorithm", proptools.StringDefault(b.properties.Avb_algorithm, "SHA256_RSA4096")) addStr("avb_"+bootImgType+"_key_path", android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key)).String()) diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index e86ebf4fa..fd1c784ec 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -463,6 +463,9 @@ type FilesystemInfo struct { AvbAlgorithm string AvbHashAlgorithm string AvbKey android.Path + PartitionName string + // HasOrIsRecovery returns true for recovery and for ramdisks with a recovery partition. + HasOrIsRecovery bool } // FullInstallPathInfo contains information about the "full install" paths of all the files @@ -720,6 +723,8 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { HasFsverity: f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) != nil, PropFileForMiscInfo: propFileForMiscInfo, PartitionSize: f.properties.Partition_size, + PartitionName: f.partitionName(), + HasOrIsRecovery: f.hasOrIsRecovery(ctx), } if proptools.Bool(f.properties.Use_avb) { fsInfo.UseAvb = true @@ -1177,10 +1182,6 @@ func (f *filesystem) buildPropFileForMiscInfo(ctx android.ModuleContext) android if proptools.Bool(f.properties.Use_avb) { addStr("avb_"+f.partitionName()+"_hashtree_enable", "true") - if f.properties.Avb_private_key != nil { - key := android.PathForModuleSrc(ctx, *f.properties.Avb_private_key) - addStr("avb_"+f.partitionName()+"_key_path", key.String()) - } addStr("avb_"+f.partitionName()+"_add_hashtree_footer_args", strings.TrimSpace(f.getAvbAddHashtreeFooterArgs(ctx))) } @@ -1307,6 +1308,19 @@ func includeFilesInstalledFiles(ctx android.ModuleContext) (ret []depset.DepSet[ return } +func (f *filesystem) hasOrIsRecovery(ctx android.ModuleContext) bool { + if f.partitionName() == "recovery" { + return true + } + ret := false + ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) { + if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok && fsProvider.PartitionName == "recovery" { + ret = true + } + }) + return ret +} + func (f *filesystem) buildCpioImage( ctx android.ModuleContext, builder *android.RuleBuilder, diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go index bf7f5b64b..e57e45cb6 100644 --- a/filesystem/filesystem_test.go +++ b/filesystem/filesystem_test.go @@ -736,15 +736,14 @@ func TestOverrideModulesInDeps(t *testing.T) { stl: "none", system_shared_libs: [], } - android_filesystem { - name: "myfilesystem", - deps: ["myapp"], + phony { + name: "myapp_phony", + required: ["myapp"], } - android_filesystem { - name: "myfilesystem_overridden", - deps: ["myapp", "myoverrideapp"], + phony { + name: "myoverrideapp_phony", + required: ["myoverrideapp"], } - android_app { name: "myapp", platform_apis: true, @@ -755,15 +754,29 @@ func TestOverrideModulesInDeps(t *testing.T) { base: "myapp", required: ["libbar"], } + android_filesystem { + name: "myfilesystem", + deps: ["myapp"], + } + android_filesystem { + name: "myfilesystem_overridden", + deps: ["myapp", "myoverrideapp"], + } + android_filesystem { + name: "myfilesystem_overridden_indirect", + deps: ["myapp_phony", "myoverrideapp_phony"], + } `) partition := result.ModuleForTests(t, "myfilesystem", "android_common") fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList")) android.AssertStringEquals(t, "filesystem without override app", "app/myapp/myapp.apk\nlib64/libfoo.so\n", fileList) - overriddenPartition := result.ModuleForTests(t, "myfilesystem_overridden", "android_common") - overriddenFileList := android.ContentFromFileRuleForTests(t, result.TestContext, overriddenPartition.Output("fileList")) - android.AssertStringEquals(t, "filesystem with override app", "app/myoverrideapp/myoverrideapp.apk\nlib64/libbar.so\n", overriddenFileList) + for _, overridden := range []string{"myfilesystem_overridden", "myfilesystem_overridden_indirect"} { + overriddenPartition := result.ModuleForTests(t, overridden, "android_common") + overriddenFileList := android.ContentFromFileRuleForTests(t, result.TestContext, overriddenPartition.Output("fileList")) + android.AssertStringEquals(t, "filesystem with "+overridden, "app/myoverrideapp/myoverrideapp.apk\nlib64/libbar.so\n", overriddenFileList) + } } func TestRamdiskPartitionSetsDevNodes(t *testing.T) { diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go index d59a2aec5..e7a39bef7 100644 --- a/filesystem/vbmeta.go +++ b/filesystem/vbmeta.go @@ -55,6 +55,10 @@ type VbmetaProperties struct { // Name of the partition stored in vbmeta desc. Defaults to the name of this module. Partition_name *string + // Type of the `android_filesystem` for which the vbmeta.img is created. + // Examples are system, vendor, product. + Filesystem_partition_type *string + // Set the name of the output. Defaults to <module_name>.img. Stem *string @@ -118,6 +122,9 @@ type vbmetaPartitionInfo struct { // Name of the partition Name string + // Partition type of the correspdonding android_filesystem. + FilesystemPartitionType string + // Rollback index location, non-negative int RollbackIndexLocation int @@ -305,11 +312,12 @@ func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) { }) android.SetProvider(ctx, vbmetaPartitionProvider, vbmetaPartitionInfo{ - Name: v.partitionName(), - RollbackIndexLocation: ril, - PublicKey: extractedPublicKey, - Output: output, - PropFileForMiscInfo: v.buildPropFileForMiscInfo(ctx), + Name: v.partitionName(), + FilesystemPartitionType: proptools.String(v.properties.Filesystem_partition_type), + RollbackIndexLocation: ril, + PublicKey: extractedPublicKey, + Output: output, + PropFileForMiscInfo: v.buildPropFileForMiscInfo(ctx), }) ctx.SetOutputFiles([]android.Path{output}, "") diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index b73fb219f..14aa062fc 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -419,13 +419,16 @@ func (f *filesystemCreator) createDeviceModule( partitionProps.Vbmeta_partitions = vbmetaPartitions deviceProps := &filesystem.DeviceProperties{ - Main_device: proptools.BoolPtr(true), - Ab_ota_updater: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaUpdater), - Ab_ota_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPartitions, - Ab_ota_postinstall_config: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig, - Ramdisk_node_list: proptools.StringPtr(":ramdisk_node_list"), - Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")), - Kernel_version: ctx.Config().ProductVariables().BoardKernelVersion, + Main_device: proptools.BoolPtr(true), + Ab_ota_updater: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaUpdater), + Ab_ota_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPartitions, + Ab_ota_postinstall_config: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig, + Ramdisk_node_list: proptools.StringPtr(":ramdisk_node_list"), + Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")), + Kernel_version: ctx.Config().ProductVariables().BoardKernelVersion, + Partial_ota_update_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardPartialOtaUpdatePartitionsList, + Flash_block_size: proptools.StringPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardFlashBlockSize), + Bootloader_in_update_package: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BootloaderInUpdatePackage), } if bootloader, ok := f.createBootloaderFilegroup(ctx); ok { diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go index 651d2d1a9..2c4d3c817 100644 --- a/fsgen/filesystem_creator_test.go +++ b/fsgen/filesystem_creator_test.go @@ -289,6 +289,10 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { "device/sample/etc/apns-full-conf.xml:product/etc/apns-conf-2.xml", "device/sample/etc/apns-full-conf.xml:system/foo/file.txt", "device/sample/etc/apns-full-conf.xml:system/foo/apns-full-conf.xml", + "device/sample/firmware/firmware.bin:recovery/root/firmware.bin", + "device/sample/firmware/firmware.bin:recovery/root/firmware-2.bin", + "device/sample/firmware/firmware.bin:recovery/root/lib/firmware/firmware.bin", + "device/sample/firmware/firmware.bin:recovery/root/lib/firmware/firmware-2.bin", } config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables = map[string]android.PartitionQualifiedVariablesType{ @@ -309,6 +313,7 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { "frameworks/base/data/keyboards/Vendor_0079_Product_0011.kl": nil, "frameworks/base/data/keyboards/Vendor_0079_Product_18d4.kl": nil, "device/sample/etc/apns-full-conf.xml": nil, + "device/sample/firmware/firmware.bin": nil, }), ).RunTest(t) @@ -324,7 +329,7 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { // check generated prebuilt_* module type install path and install partition generatedModule := result.ModuleForTests(t, "system-frameworks_base_config-etc-0", "android_arm64_armv8-a").Module() - etcModule, _ := generatedModule.(*etc.PrebuiltEtc) + etcModule := generatedModule.(*etc.PrebuiltEtc) android.AssertStringEquals( t, "module expected to have etc install path", @@ -342,7 +347,7 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { // check generated prebuilt_* module specifies correct relative_install_path property generatedModule = result.ModuleForTests(t, "system-frameworks_base_data_keyboards-usr_keylayout_subdir-0", "android_arm64_armv8-a").Module() - etcModule, _ = generatedModule.(*etc.PrebuiltEtc) + etcModule = generatedModule.(*etc.PrebuiltEtc) android.AssertStringEquals( t, "module expected to set correct relative_install_path properties", @@ -490,7 +495,7 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { ) // check generated prebuilt_* module specifies correct install path and relative install path - etcModule, _ = generatedModule1.(*etc.PrebuiltEtc) + etcModule = generatedModule1.(*etc.PrebuiltEtc) android.AssertStringEquals( t, "module expected to have . install path", @@ -520,4 +525,138 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { return "" }), ) + + generatedModule0 = result.ModuleForTests(t, "recovery-device_sample_firmware-0", "android_recovery_arm64_armv8-a").Module() + generatedModule1 = result.ModuleForTests(t, "recovery-device_sample_firmware-1", "android_recovery_common").Module() + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule0.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set empty relative_install_path properties", + "", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module don't set dsts + eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to not set dsts property", + "", + getModuleProp(generatedModule0, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) != 0 { + return dsts[0] + } + } + return "" + }), + ) + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule1.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set empty relative_install_path properties", + "", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module sets correct dsts + eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to set correct dsts property", + "firmware-2.bin", + getModuleProp(generatedModule1, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) == 1 { + return dsts[0] + } + } + return "" + }), + ) + + generatedModule0 = result.ModuleForTests(t, "recovery-device_sample_firmware-lib_firmware-0", "android_recovery_common").Module() + generatedModule1 = result.ModuleForTests(t, "recovery-device_sample_firmware-lib_firmware-1", "android_recovery_common").Module() + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule0.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set correct relative_install_path properties", + "lib/firmware", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module sets correct srcs + eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to not set dsts property", + "", + getModuleProp(generatedModule0, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) != 0 { + return dsts[0] + } + } + return "" + }), + ) + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule1.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set empty relative_install_path properties", + "", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module sets correct srcs + eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to set correct dsts property", + "lib/firmware/firmware-2.bin", + getModuleProp(generatedModule1, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) == 1 { + return dsts[0] + } + } + return "" + }), + ) } diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go index e9dabe44c..c0f114caf 100644 --- a/fsgen/prebuilt_etc_modules_gen.go +++ b/fsgen/prebuilt_etc_modules_gen.go @@ -337,6 +337,10 @@ func createPrebuiltEtcModulesInDirectory(ctx android.LoadHookContext, partition, propsList = append(propsList, &prebuiltInstallInRootProperties{ Install_in_root: proptools.BoolPtr(true), }) + // Discard any previously picked module and force it to prebuilt_{root,any} as + // they are the only modules allowed to specify the `install_in_root` property. + etcInstallPathKey = "" + relDestDirFromInstallDirBase = destDir } // Set appropriate srcs, dsts, and releative_install_path based on diff --git a/fsgen/vbmeta_partitions.go b/fsgen/vbmeta_partitions.go index 11f4bd013..594c40482 100644 --- a/fsgen/vbmeta_partitions.go +++ b/fsgen/vbmeta_partitions.go @@ -76,6 +76,7 @@ func (f *filesystemCreator) createVbmetaPartitions(ctx android.LoadHookContext, var chainedPartitionTypes []string for _, chainedName := range android.SortedKeys(partitionVars.ChainedVbmetaPartitions) { props := partitionVars.ChainedVbmetaPartitions[chainedName] + filesystemPartitionType := chainedName chainedName = "vbmeta_" + chainedName if len(props.Partitions) == 0 { continue @@ -123,13 +124,14 @@ func (f *filesystemCreator) createVbmetaPartitions(ctx android.LoadHookContext, filesystem.VbmetaFactory, ".", // Create in the root directory for now so its easy to get the key &filesystem.VbmetaProperties{ - Partition_name: proptools.StringPtr(chainedName), - Stem: proptools.StringPtr(chainedName + ".img"), - Private_key: proptools.StringPtr(props.Key), - Algorithm: &props.Algorithm, - Rollback_index: rollbackIndex, - Rollback_index_location: &ril, - Partitions: proptools.NewSimpleConfigurable(partitionModules), + Partition_name: proptools.StringPtr(chainedName), + Filesystem_partition_type: proptools.StringPtr(filesystemPartitionType), + Stem: proptools.StringPtr(chainedName + ".img"), + Private_key: proptools.StringPtr(props.Key), + Algorithm: &props.Algorithm, + Rollback_index: rollbackIndex, + Rollback_index_location: &ril, + Partitions: proptools.NewSimpleConfigurable(partitionModules), }, &struct { Name *string }{ diff --git a/java/app_import.go b/java/app_import.go index c0e8171d5..9fb13ba3c 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -338,7 +338,7 @@ func (a *AndroidAppImport) stripEmbeddedJniLibsUnusedArch( for _, target := range ctx.MultiTargets() { supported_abis := target.Arch.Abi for _, arch := range supported_abis { - wantedJniLibSlice = append(wantedJniLibSlice, " -X lib/"+arch+"/*.so") + wantedJniLibSlice = append(wantedJniLibSlice, " -X 'lib/"+arch+"/*.so'") } } wantedJniLibString := strings.Join(wantedJniLibSlice, " ") diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go index bdcfbbba1..f462795aa 100644 --- a/rust/fuzz_test.go +++ b/rust/fuzz_test.go @@ -134,17 +134,24 @@ func TestCCFuzzDepBundling(t *testing.T) { } `) - fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface) - fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface) - fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface) + fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module() + fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module() + fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module() - if !strings.Contains(fuzz_shared_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") { - t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", fuzz_shared_libtest.FuzzSharedLibraries().String()) + fuzzSharedLibraries := func(module android.Module) string { + if info, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok { + return info.FuzzSharedLibraries.String() + } + return "" } - if !strings.Contains(fuzz_static_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") { - t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_static_libtest.FuzzSharedLibraries().String()) + + if libs := fuzzSharedLibraries(fuzz_shared_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") { + t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", libs) + } + if libs := fuzzSharedLibraries(fuzz_static_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") { + t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs) } - if !strings.Contains(fuzz_staticffi_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") { - t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_staticffi_libtest.FuzzSharedLibraries().String()) + if libs := fuzzSharedLibraries(fuzz_staticffi_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") { + t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs) } } diff --git a/scripts/Android.bp b/scripts/Android.bp index c0e13d52f..b6cac32f3 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -254,11 +254,6 @@ python_binary_host { ], } -sh_binary_host { - name: "list_image", - src: "list_image.sh", -} - filegroup { name: "rustfmt.toml", srcs: ["rustfmt.toml"], diff --git a/scripts/list_image.sh b/scripts/list_image.sh deleted file mode 100755 index 0542fa610..000000000 --- a/scripts/list_image.sh +++ /dev/null @@ -1,51 +0,0 @@ -#! /bin/bash - -# Recursively list Android image directory. -set -eu -set -o pipefail - -function die() { format=$1; shift; printf "$format\n" "$@"; exit 1; } - -# Figure out the filer utility. -declare filer= -[[ -z "${ANDROID_HOST_OUT:-}" ]] || filer=${ANDROID_HOST_OUT}/bin/debugfs_static -if [[ "${1:-}" =~ --debugfs_path=(.*) ]]; then - filer=${BASH_REMATCH[1]} - shift -fi -if [[ -z "${filer:-}" ]]; then - maybefiler="$(dirname $0)/debugfs_static" - [[ ! -x "$maybefiler" ]] || filer="$maybefiler" -fi - -(( $# >0 )) || die "%s [--debugfs_path=<path>] IMAGE" "$0" - -[[ -n "${filer:-}" ]] || die "cannot locate 'debugfs' executable: \ ---debugfs_path= is missing, ANDROID_HOST_OUT is not set, \ -and 'debugfs_static' is not colocated with this script" -declare -r image="$1" - -function dolevel() { - printf "%s/\n" "$1" - # Each line of the file output consists of 6 fields separated with '/'. - # The second one contains the file's attributes, and the fifth its name. - $filer -R "ls -l -p $1" "$image" 2>/dev/null |\ - sed -nr 's|^/.*/(.*)/.*/.*/(.+)/.*/$|\2 \1|p' | LANG=C sort | \ - while read name attr; do - [[ "$name" != '.' && "$name" != '..' ]] || continue - path="$1/$name" - # If the second char of the attributes is '4', it is a directory. - if [[ $attr =~ ^.4 ]]; then - dolevel "$path" - else - printf "%s\n" "$path" - fi - done -} - -# The filer always prints its version on stderr, so we are going -# to redirect it to the bit bucket. On the other hand, the filer's -# return code on error is still 0. Let's run it once to without -# redirecting stderr to see that there is at least one entry. -$filer -R "ls -l -p" "$image" | grep -q -m1 -P '^/.*/.*/.*/.*/.+/.*/$' -dolevel . diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go index 2b341288a..e833df293 100644 --- a/tradefed_modules/test_module_config.go +++ b/tradefed_modules/test_module_config.go @@ -1,14 +1,15 @@ package tradefed_modules import ( - "android/soong/android" - "android/soong/tradefed" "encoding/json" "fmt" "io" "slices" "strings" + "android/soong/android" + "android/soong/tradefed" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -178,6 +179,10 @@ func (m *testModuleConfigModule) GenerateAndroidBuildActions(ctx android.ModuleC moduleInfoJSON.TestConfig = []string{m.testConfig.String()} moduleInfoJSON.AutoTestConfig = []string{"true"} moduleInfoJSON.TestModuleConfigBase = proptools.String(m.Base) + + android.SetProvider(ctx, android.SupportFilesInfoProvider, android.SupportFilesInfo{ + SupportFiles: m.supportFiles, + }) } // Ensure at least one test_suite is listed. Ideally it should be general-tests @@ -327,6 +332,9 @@ func (m *testModuleConfigHostModule) DepsMutator(ctx android.BottomUpMutatorCont func (m *testModuleConfigHostModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { m.validateBase(ctx, &testModuleConfigHostTag, "java_test_host", true) m.generateManifestAndConfig(ctx) + android.SetProvider(ctx, android.SupportFilesInfoProvider, android.SupportFilesInfo{ + SupportFiles: m.supportFiles, + }) } // Ensure the base listed is the right type by checking that we get the expected provider data. diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go index cd49ec876..4134cf5de 100644 --- a/ui/build/androidmk_denylist.go +++ b/ui/build/androidmk_denylist.go @@ -15,20 +15,29 @@ package build import ( + "os" + "slices" "strings" ) var androidmk_denylist []string = []string{ + "art/", "bionic/", - "chained_build_config/", + "bootable/", + "build/", "cts/", "dalvik/", "developers/", "development/", "device/common/", + "device/generic/", + "device/google/", "device/google_car/", "device/sample/", + "external/", "frameworks/", + "hardware/google/", + "hardware/interfaces/", "hardware/libhardware/", "hardware/libhardware_legacy/", "hardware/ril/", @@ -45,24 +54,47 @@ var androidmk_denylist []string = []string{ "sdk/", "system/", "test/", + "tools/", "trusty/", - // Add back toolchain/ once defensive Android.mk files are removed - //"toolchain/", - "vendor/google_contexthub/", - "vendor/google_data/", - "vendor/google_elmyra/", - "vendor/google_mhl/", - "vendor/google_pdk/", - "vendor/google_testing/", - "vendor/partner_testing/", - "vendor/partner_tools/", - "vendor/pdk/", + "toolchain/", +} + +var androidmk_allowlist []string = []string{ + "art/Android.mk", + "bootable/deprecated-ota/updater/Android.mk", +} + +func getAllLines(ctx Context, filename string) []string { + bytes, err := os.ReadFile(filename) + if err != nil { + if os.IsNotExist(err) { + return []string{} + } else { + ctx.Fatalf("Could not read %s: %v", filename, err) + } + } + return strings.Split(strings.Trim(string(bytes), " \n"), "\n") } func blockAndroidMks(ctx Context, androidMks []string) { + allowlist_files := []string{ + "vendor/google/build/androidmk/allowlist.txt", + "device/google/clockwork/build/androidmk/allowlist.txt", + "device/google/sdv/androidmk/allowlist.txt", + } + for _, allowlist_file := range allowlist_files { + allowlist := getAllLines(ctx, allowlist_file) + androidmk_allowlist = append(androidmk_allowlist, allowlist...) + } + slices.Sort(androidmk_allowlist) + androidmk_allowlist = slices.Compact(androidmk_allowlist) + + denylist := getAllLines(ctx, "vendor/google/build/androidmk/denylist.txt") + androidmk_denylist = append(androidmk_denylist, denylist...) + for _, mkFile := range androidMks { for _, d := range androidmk_denylist { - if strings.HasPrefix(mkFile, d) { + if strings.HasPrefix(mkFile, d) && !slices.Contains(androidmk_allowlist, mkFile) { ctx.Fatalf("Found blocked Android.mk file: %s. "+ "Please see androidmk_denylist.go for the blocked directories and contact build system team if the file should not be blocked.", mkFile) } @@ -86,6 +118,12 @@ var external_androidmks []string = []string{ // These directories hold the published Android SDK, used in Unbundled Gradle builds. "prebuilts/fullsdk-darwin", "prebuilts/fullsdk-linux", + // wpa_supplicant_8 has been converted to Android.bp and Android.mk files are kept for troubleshooting. + "external/wpa_supplicant_8/", + // Empty Android.mk in package's top directory + "external/proguard/", + "external/swig/", + "toolchain/", } var art_androidmks = []string{ diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go index 16a3db8e6..710be8407 100644 --- a/ui/build/dumpvars.go +++ b/ui/build/dumpvars.go @@ -181,7 +181,12 @@ func Banner(config Config, make_vars map[string]string) string { fmt.Fprintf(b, "%s=%s\n", name, make_vars[name]) } } - fmt.Fprintf(b, "SOONG_ONLY=%t\n", config.soongOnlyRequested) + if config.skipKatiControlledByFlags { + fmt.Fprintf(b, "SOONG_ONLY=%t\n", config.soongOnlyRequested) + } else { // default for this product + fmt.Fprintf(b, "SOONG_ONLY=%t\n", make_vars["PRODUCT_SOONG_ONLY"] == "true") + } + fmt.Fprint(b, "============================================") return b.String() diff --git a/ui/build/finder.go b/ui/build/finder.go index 783b48863..ff8908b29 100644 --- a/ui/build/finder.go +++ b/ui/build/finder.go @@ -84,8 +84,14 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) { // METADATA file of packages "METADATA", }, - // .mk files for product/board configuration. - IncludeSuffixes: []string{".mk"}, + IncludeSuffixes: []string{ + // .mk files for product/board configuration. + ".mk", + // otatools cert files + ".pk8", + ".pem", + ".avbpubkey", + }, } dumpDir := config.FileListDir() f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard), @@ -118,6 +124,18 @@ func findProductAndBoardConfigFiles(entries finder.DirEntries) (dirNames []strin return entries.DirNames, matches } +func findOtaToolsCertFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) { + matches := []string{} + for _, foundName := range entries.FileNames { + if strings.HasSuffix(foundName, ".pk8") || + strings.HasSuffix(foundName, ".pem") || + strings.HasSuffix(foundName, ".avbpubkey") { + matches = append(matches, foundName) + } + } + return entries.DirNames, matches +} + // FindSources searches for source files known to <f> and writes them to the filesystem for // use later. func FindSources(ctx Context, config Config, f *finder.Finder) { @@ -184,6 +202,17 @@ func FindSources(ctx Context, config Config, f *finder.Finder) { ctx.Fatalf("Could not find TEST_MAPPING: %v", err) } + // Recursively look for all otatools cert files. + otatools_cert_files := f.FindMatching("build/make/target/product/security", findOtaToolsCertFiles) + otatools_cert_files = append(otatools_cert_files, f.FindMatching("device", findOtaToolsCertFiles)...) + otatools_cert_files = append(otatools_cert_files, f.FindMatching("external/avb/test/data", findOtaToolsCertFiles)...) + otatools_cert_files = append(otatools_cert_files, f.FindMatching("packages/modules", findOtaToolsCertFiles)...) + otatools_cert_files = append(otatools_cert_files, f.FindMatching("vendor", findOtaToolsCertFiles)...) + err = dumpListToFile(ctx, config, otatools_cert_files, filepath.Join(dumpDir, "OtaToolsCertFiles.list")) + if err != nil { + ctx.Fatalf("Could not find otatools cert files: %v", err) + } + // Recursively look for all Android.bp files androidBps := f.FindNamedAt(".", "Android.bp") if len(androidBps) == 0 { |