diff options
126 files changed, 2150 insertions, 672 deletions
diff --git a/Android.bp b/Android.bp index 337545bce..713459112 100644 --- a/Android.bp +++ b/Android.bp @@ -176,6 +176,12 @@ build_prop { footer_files: [ ":applied_backported_fixes", ], + dist: { + targets: [ + "droidcore-unbundled", + "sdk", + ], + }, // Currently, only microdroid, Ravenwood, and cf system image can refer to system-build.prop visibility: [ "//build/soong/fsgen", @@ -191,6 +197,10 @@ build_prop { system_ext_specific: true, product_config: ":product_config", relative_install_path: "etc", // system_ext/etc/build.prop + dist: { + targets: ["droidcore-unbundled"], + dest: "build.prop-system_ext", + }, visibility: [ "//build/make/target/product/gsi", "//build/soong/fsgen", @@ -203,6 +213,10 @@ build_prop { product_specific: true, product_config: ":product_config", relative_install_path: "etc", // product/etc/build.prop + dist: { + targets: ["droidcore-unbundled"], + dest: "build.prop-product", + }, visibility: [ "//build/make/target/product/gsi", "//build/soong/fsgen", @@ -215,6 +229,10 @@ build_prop { device_specific: true, product_config: ":product_config", relative_install_path: "etc", // odm/etc/build.prop + dist: { + targets: ["droidcore-unbundled"], + dest: "build.prop-odm", + }, visibility: ["//build/soong/fsgen"], } @@ -251,6 +269,10 @@ build_prop { ramdisk: true, product_config: ":product_config", relative_install_path: "etc/ramdisk", // ramdisk/system/etc/ramdisk/build.prop + dist: { + targets: ["droidcore-unbundled"], + dest: "build.prop-ramdisk", + }, visibility: ["//visibility:private"], } diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go index 3d07e16dc..f3c68c37a 100644 --- a/aconfig/all_aconfig_declarations.go +++ b/aconfig/all_aconfig_declarations.go @@ -95,11 +95,44 @@ func GenerateFinalizedFlagsForApiSurface(ctx android.ModuleContext, outputPath a }) } +func GenerateExportedFlagCheck(ctx android.ModuleContext, outputPath android.WritablePath, + parsedFlagsFile android.Path, apiSurface ApiSurfaceContributorProperties) { + + apiSignatureFiles := android.Paths{} + for _, apiSignatureFile := range apiSurface.Api_signature_files.GetOrDefault(ctx, nil) { + if path := android.PathForModuleSrc(ctx, apiSignatureFile); path != nil { + apiSignatureFiles = append(apiSignatureFiles, path) + } + } + finalizedFlagsFile := android.PathForModuleSrc(ctx, apiSurface.Finalized_flags_file) + + ctx.Build(pctx, android.BuildParams{ + Rule: ExportedFlagCheckRule, + Inputs: append(apiSignatureFiles, finalizedFlagsFile, parsedFlagsFile), + Output: outputPath, + Args: map[string]string{ + "api_signature_files": android.JoinPathsWithPrefix(apiSignatureFiles, "--api-signature-file "), + "finalized_flags_file": "--finalized-flags-file " + finalizedFlagsFile.String(), + "parsed_flags_file": "--parsed-flags-file " + parsedFlagsFile.String(), + }, + }) +} + func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) { parsedFlagsFile := android.PathForIntermediates(ctx, "all_aconfig_declarations.pb") this.finalizedFlags = android.PathForIntermediates(ctx, "finalized-flags.txt") GenerateFinalizedFlagsForApiSurface(ctx, this.finalizedFlags, parsedFlagsFile, this.properties) - ctx.Phony("all_aconfig_declarations", this.finalizedFlags) + + depsFiles := android.Paths{this.finalizedFlags} + if checkExportedFlag, ok := ctx.Config().GetBuildFlag("RELEASE_EXPORTED_FLAG_CHECK"); ok { + if checkExportedFlag == "true" { + invalidExportedFlags := android.PathForIntermediates(ctx, "invalid_exported_flags.txt") + GenerateExportedFlagCheck(ctx, invalidExportedFlags, parsedFlagsFile, this.properties) + depsFiles = append(depsFiles, invalidExportedFlags) + } + } + + ctx.Phony("all_aconfig_declarations", depsFiles...) android.SetProvider(ctx, allAconfigDeclarationsInfoProvider, allAconfigDeclarationsInfo{ parsedFlagsFile: parsedFlagsFile, @@ -111,7 +144,7 @@ func (this *allAconfigDeclarationsSingleton) GenerateSingletonBuildActions(ctx a // Find all of the aconfig_declarations modules var packages = make(map[string]int) var cacheFiles android.Paths - ctx.VisitAllModules(func(module android.Module) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { decl, ok := android.OtherModuleProvider(ctx, module, android.AconfigReleaseDeclarationsProviderKey) if !ok { return diff --git a/aconfig/build_flags/build_flags_singleton.go b/aconfig/build_flags/build_flags_singleton.go index e375d9c70..3a06e72d6 100644 --- a/aconfig/build_flags/build_flags_singleton.go +++ b/aconfig/build_flags/build_flags_singleton.go @@ -15,8 +15,9 @@ package build_flags import ( - "android/soong/android" "fmt" + + "android/soong/android" ) // A singleton module that collects all of the build flags declared in the @@ -42,7 +43,7 @@ func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android. var flagsFiles android.Paths // Find all of the release_config_contribution modules var contributionDirs android.Paths - ctx.VisitAllModules(func(module android.Module) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { decl, ok := android.OtherModuleProvider(ctx, module, BuildFlagDeclarationsProviderKey) if ok { flagsFiles = append(flagsFiles, decl.IntermediateCacheOutputPath) diff --git a/aconfig/init.go b/aconfig/init.go index b2fe5a309..d8d547022 100644 --- a/aconfig/init.go +++ b/aconfig/init.go @@ -77,6 +77,13 @@ var ( "${record-finalized-flags}", }, }, "api_signature_files", "finalized_flags_file", "parsed_flags_file") + ExportedFlagCheckRule = pctx.AndroidStaticRule("ExportedFlagCheckRule", + blueprint.RuleParams{ + Command: `${exported-flag-check} ${parsed_flags_file} ${finalized_flags_file} ${api_signature_files} > ${out}`, + CommandDeps: []string{ + "${exported-flag-check}", + }, + }, "api_signature_files", "finalized_flags_file", "parsed_flags_file") CreateStorageRule = pctx.AndroidStaticRule("aconfig_create_storage", blueprint.RuleParams{ @@ -124,6 +131,7 @@ func init() { pctx.HostBinToolVariable("aconfig", "aconfig") pctx.HostBinToolVariable("soong_zip", "soong_zip") pctx.HostBinToolVariable("record-finalized-flags", "record-finalized-flags") + pctx.HostBinToolVariable("exported-flag-check", "exported-flag-check") } func RegisterBuildComponents(ctx android.RegistrationContext) { diff --git a/android/Android.bp b/android/Android.bp index 1cc7ffe1d..4b75148fc 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -97,6 +97,7 @@ bootstrap_go_package { "product_packages_file.go", "proto.go", "provider.go", + "provider_keys.go", "raw_files.go", "recovery_build_prop.go", "register.go", @@ -170,3 +171,7 @@ bootstrap_go_package { // Used by plugins visibility: ["//visibility:public"], } + +otatools_package_filegroup { + name: "otatools_package_filegroup", +} diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go index 7185a8941..bb73f0bdd 100644 --- a/android/aconfig_providers.go +++ b/android/aconfig_providers.go @@ -248,7 +248,7 @@ func getContainer(m Module) string { // Please only access the module's internal data through providers. func getContainerUsingProviders(ctx OtherModuleProviderContext, m Module) string { container := "system" - commonInfo, _ := OtherModuleProvider(ctx, m, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, m, CommonModuleInfoProvider) if commonInfo.Vendor || commonInfo.Proprietary || commonInfo.SocSpecific { container = "vendor" } else if commonInfo.ProductSpecific { diff --git a/android/all_teams.go b/android/all_teams.go index 8b55adebd..18a050f5d 100644 --- a/android/all_teams.go +++ b/android/all_teams.go @@ -116,7 +116,7 @@ func (t *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) { testOnly: testModInfo.TestOnly, topLevelTestTarget: testModInfo.TopLevelTarget, kind: ctx.ModuleType(module), - teamName: OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).Team, + teamName: OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).Team, } t.teams_for_mods[module.Name()] = entry diff --git a/android/androidmk.go b/android/androidmk.go index e4366fad2..784559312 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -528,6 +528,14 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod Module) { fmt.Fprintf(&a.header, "\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s\n", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod)) + // Add the TestSuites from the provider to LOCAL_SOONG_PROVIDER_TEST_SUITES. + // LOCAL_SOONG_PROVIDER_TEST_SUITES will be compared against LOCAL_COMPATIBILITY_SUITES + // in make and enforced they're the same, to ensure we've successfully translated all + // LOCAL_COMPATIBILITY_SUITES usages to the provider. + if testSuiteInfo, ok := OtherModuleProvider(ctx, mod, TestSuiteInfoProvider); ok { + a.AddStrings("LOCAL_SOONG_PROVIDER_TEST_SUITES", testSuiteInfo.TestSuites...) + } + // Collect make variable assignment entries. a.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) a.SetString("LOCAL_MODULE", name+a.SubName) @@ -880,14 +888,14 @@ func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distCo } } - commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider) if commonInfo.SkipAndroidMkProcessing { continue } if info, ok := OtherModuleProvider(ctx, mod, AndroidMkInfoProvider); ok { // Deep copy the provider info since we need to modify the info later info := deepCopyAndroidMkProviderInfo(info) - info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) + info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo) if info.PrimaryInfo.disabled() { continue } @@ -1312,7 +1320,7 @@ var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]() // Please only access the module's internal data through providers. func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod Module, providerInfo *AndroidMkProviderInfo) error { - commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider) if commonInfo.SkipAndroidMkProcessing { return nil } @@ -1323,11 +1331,11 @@ func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, modu aconfigUpdateAndroidMkInfos(ctx, mod, &info) // Any new or special cases here need review to verify correct propagation of license information. - info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) + info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo) info.PrimaryInfo.write(w) if len(info.ExtraInfo) > 0 { for _, ei := range info.ExtraInfo { - ei.fillInEntries(ctx, mod, &commonInfo) + ei.fillInEntries(ctx, mod, commonInfo) ei.write(w) } } @@ -1476,12 +1484,17 @@ func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module, comm a.Host_required = append(a.Host_required, commonInfo.HostRequiredModuleNames...) a.Target_required = append(a.Target_required, commonInfo.TargetRequiredModuleNames...) - for _, distString := range a.GetDistForGoals(ctx, mod, commonInfo) { - a.HeaderStrings = append(a.HeaderStrings, distString) - } - + a.HeaderStrings = append(a.HeaderStrings, a.GetDistForGoals(ctx, mod, commonInfo)...) a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s", ctx.ModuleType(mod), commonInfo.BaseModuleName, ctx.ModuleSubDir(mod))) + // Add the TestSuites from the provider to LOCAL_SOONG_PROVIDER_TEST_SUITES. + // LOCAL_SOONG_PROVIDER_TEST_SUITES will be compared against LOCAL_COMPATIBILITY_SUITES + // in make and enforced they're the same, to ensure we've successfully translated all + // LOCAL_COMPATIBILITY_SUITES usages to the provider. + if testSuiteInfo, ok := OtherModuleProvider(ctx, mod, TestSuiteInfoProvider); ok { + helperInfo.AddStrings("LOCAL_SOONG_PROVIDER_TEST_SUITES", testSuiteInfo.TestSuites...) + } + // Collect make variable assignment entries. helperInfo.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) helperInfo.SetString("LOCAL_MODULE", name+a.SubName) diff --git a/android/apex.go b/android/apex.go index 39de6de33..57baff5cf 100644 --- a/android/apex.go +++ b/android/apex.go @@ -695,7 +695,7 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion // Function called while walking an APEX's payload dependencies. // // Return true if the `to` module should be visited, false otherwise. -type PayloadDepsCallback func(ctx BaseModuleContext, from Module, to ApexModule, externalDep bool) bool +type PayloadDepsCallback func(ctx BaseModuleContext, from, to ModuleProxy, externalDep bool) bool type WalkPayloadDepsFunc func(ctx BaseModuleContext, do PayloadDepsCallback) // ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks @@ -723,7 +723,7 @@ func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayl return } - walk(ctx, func(ctx BaseModuleContext, from Module, to ApexModule, externalDep bool) bool { + walk(ctx, func(ctx BaseModuleContext, from, to ModuleProxy, externalDep bool) bool { if externalDep { // external deps are outside the payload boundary, which is "stable" // interface. We don't have to check min_sdk_version for external @@ -733,7 +733,7 @@ func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayl if !IsDepInSameApex(ctx, from, to) { return false } - if info, ok := OtherModuleProvider(ctx, to, CommonModuleInfoKey); ok && info.ModuleWithMinSdkVersionCheck { + if info, ok := OtherModuleProvider(ctx, to, CommonModuleInfoProvider); ok && info.ModuleWithMinSdkVersionCheck { if info.MinSdkVersion.ApiLevel == nil || !info.MinSdkVersion.ApiLevel.Specified() { // This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version // to trigger the check. @@ -765,7 +765,7 @@ type MinSdkVersionFromValueContext interface { // implementing this interface should provide an implementation. A module supports an sdk // version when the module's min_sdk_version is equal to or less than the given sdk version. func ShouldSupportSdkVersion(ctx BaseModuleContext, module Module, sdkVersion ApiLevel) error { - info, ok := OtherModuleProvider(ctx, module, CommonModuleInfoKey) + info, ok := OtherModuleProvider(ctx, module, CommonModuleInfoProvider) if !ok || info.MinSdkVersionSupported.IsNone() { return fmt.Errorf("min_sdk_version is not specified") } diff --git a/android/api_levels.go b/android/api_levels.go index c042eebee..c83fae878 100644 --- a/android/api_levels.go +++ b/android/api_levels.go @@ -19,6 +19,8 @@ import ( "fmt" "strconv" "strings" + + "github.com/google/blueprint/gobtools" ) func init() { @@ -52,6 +54,34 @@ type ApiLevel struct { isPreview bool } +type apiLevelGob struct { + Value string + Number int + IsPreview bool +} + +func (a *ApiLevel) ToGob() *apiLevelGob { + return &apiLevelGob{ + Value: a.value, + Number: a.number, + IsPreview: a.isPreview, + } +} + +func (a *ApiLevel) FromGob(data *apiLevelGob) { + a.value = data.Value + a.number = data.Number + a.isPreview = data.IsPreview +} + +func (a ApiLevel) GobEncode() ([]byte, error) { + return gobtools.CustomGobEncode[apiLevelGob](&a) +} + +func (a *ApiLevel) GobDecode(data []byte) error { + return gobtools.CustomGobDecode[apiLevelGob](data, a) +} + func (this ApiLevel) FinalInt() int { if this.IsInvalid() { panic(fmt.Errorf("%v is not a recognized api_level\n", this)) diff --git a/android/base_module_context.go b/android/base_module_context.go index d2404fd3e..5cb9e71cf 100644 --- a/android/base_module_context.go +++ b/android/base_module_context.go @@ -410,7 +410,7 @@ func (b *baseModuleContext) validateAndroidModuleProxy( return &aModule } - if !OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).Enabled { + if !OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).Enabled { if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) { if b.Config().AllowMissingDependencies() { b.AddMissingDependencies([]string{b.OtherModuleName(aModule)}) @@ -440,7 +440,7 @@ func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.Dep func (b *baseModuleContext) getDirectDepsProxyInternal(name string, tag blueprint.DependencyTag) []ModuleProxy { var deps []ModuleProxy b.VisitDirectDepsProxy(func(module ModuleProxy) { - if OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).BaseModuleName == name { + if OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).BaseModuleName == name { returnedTag := b.OtherModuleDependencyTag(module) if tag == nil || returnedTag == tag { deps = append(deps, module) diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go index a6dbb8d17..16a385300 100644 --- a/android/compliance_metadata.go +++ b/android/compliance_metadata.go @@ -18,7 +18,9 @@ import ( "bytes" "encoding/csv" "fmt" + "path/filepath" "slices" + "sort" "strconv" "strings" @@ -127,27 +129,37 @@ var ( // dependencies, built/installed files, etc. It is a wrapper on a map[string]string with some utility // methods to get/set properties' values. type ComplianceMetadataInfo struct { - properties map[string]string + properties map[string]string + filesContained []string + prebuiltFilesCopied []string } type complianceMetadataInfoGob struct { - Properties map[string]string + Properties map[string]string + FilesContained []string + PrebuiltFilesCopied []string } func NewComplianceMetadataInfo() *ComplianceMetadataInfo { return &ComplianceMetadataInfo{ - properties: map[string]string{}, + properties: map[string]string{}, + filesContained: make([]string, 0), + prebuiltFilesCopied: make([]string, 0), } } func (m *ComplianceMetadataInfo) ToGob() *complianceMetadataInfoGob { return &complianceMetadataInfoGob{ - Properties: m.properties, + Properties: m.properties, + FilesContained: m.filesContained, + PrebuiltFilesCopied: m.prebuiltFilesCopied, } } func (m *ComplianceMetadataInfo) FromGob(data *complianceMetadataInfoGob) { m.properties = data.Properties + m.filesContained = data.FilesContained + m.prebuiltFilesCopied = data.PrebuiltFilesCopied } func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) { @@ -169,6 +181,22 @@ func (c *ComplianceMetadataInfo) SetListValue(propertyName string, value []strin c.SetStringValue(propertyName, strings.TrimSpace(strings.Join(value, " "))) } +func (c *ComplianceMetadataInfo) SetFilesContained(files []string) { + c.filesContained = files +} + +func (c *ComplianceMetadataInfo) GetFilesContained() []string { + return c.filesContained +} + +func (c *ComplianceMetadataInfo) SetPrebuiltFilesCopied(files []string) { + c.prebuiltFilesCopied = files +} + +func (c *ComplianceMetadataInfo) GetPrebuiltFilesCopied() []string { + return c.prebuiltFilesCopied +} + func (c *ComplianceMetadataInfo) getStringValue(propertyName string) string { if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) { panic(fmt.Errorf("Unknown metadata property: %s.", propertyName)) @@ -276,7 +304,7 @@ func (c *complianceMetadataSingleton) GenerateBuildActions(ctx SingletonContext) rowId := -1 ctx.VisitAllModuleProxies(func(module ModuleProxy) { - commonInfo, _ := OtherModuleProvider(ctx, module, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider) if !commonInfo.Enabled { return } @@ -316,9 +344,42 @@ func (c *complianceMetadataSingleton) GenerateBuildActions(ctx SingletonContext) makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv") makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv") + productOutPath := filepath.Join(ctx.Config().OutDir(), "target", "product", String(ctx.Config().productVariables.DeviceName)) if !ctx.Config().KatiEnabled() { - WriteFileRule(ctx, makeMetadataCsv, "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text") - WriteFileRule(ctx, makeModulesCsv, "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files") + ctx.VisitAllModuleProxies(func(module ModuleProxy) { + // In soong-only build the installed file list is from android_device module + if androidDeviceInfo, ok := OtherModuleProvider(ctx, module, AndroidDeviceInfoProvider); ok && androidDeviceInfo.Main_device { + if metadataInfo, ok := OtherModuleProvider(ctx, module, ComplianceMetadataProvider); ok { + if len(metadataInfo.filesContained) > 0 || len(metadataInfo.prebuiltFilesCopied) > 0 { + allFiles := make([]string, 0, len(metadataInfo.filesContained)+len(metadataInfo.prebuiltFilesCopied)) + allFiles = append(allFiles, metadataInfo.filesContained...) + prebuiltFilesSrcDest := make(map[string]string) + for _, srcDestPair := range metadataInfo.prebuiltFilesCopied { + prebuiltFilePath := filepath.Join(productOutPath, strings.Split(srcDestPair, ":")[1]) + allFiles = append(allFiles, prebuiltFilePath) + prebuiltFilesSrcDest[prebuiltFilePath] = srcDestPair + } + sort.Strings(allFiles) + + csvHeaders := "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text" + csvContent := make([]string, 0, len(allFiles)+1) + csvContent = append(csvContent, csvHeaders) + for _, file := range allFiles { + if _, ok := prebuiltFilesSrcDest[file]; ok { + srcDestPair := prebuiltFilesSrcDest[file] + csvContent = append(csvContent, file+",,,,"+srcDestPair+",,,,,") + } else { + csvContent = append(csvContent, file+",,Y,,,,,,,") + } + } + + WriteFileRuleVerbatim(ctx, makeMetadataCsv, strings.Join(csvContent, "\n")) + WriteFileRuleVerbatim(ctx, makeModulesCsv, "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files") + } + return + } + } + }) } // Import metadata from Make and Soong to sqlite3 database diff --git a/android/config.go b/android/config.go index 696e7727f..d47f0d44a 100644 --- a/android/config.go +++ b/android/config.go @@ -200,6 +200,11 @@ func (c Config) ReleaseAconfigValueSets() []string { return c.config.productVariables.ReleaseAconfigValueSets } +// If native modules should have symbols stripped by default. Default false, enabled for build tools +func (c Config) StripByDefault() bool { + return proptools.Bool(c.config.productVariables.StripByDefault) +} + func (c Config) ReleaseAconfigExtraReleaseConfigs() []string { result := []string{} if val, ok := c.config.productVariables.BuildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"]; ok { @@ -233,11 +238,6 @@ func (c Config) ReleaseAconfigFlagDefaultPermission() string { return c.config.productVariables.ReleaseAconfigFlagDefaultPermission } -// Enable object size sanitizer -func (c Config) ReleaseBuildObjectSizeSanitizer() bool { - return c.config.productVariables.GetBuildFlagBool("RELEASE_BUILD_OBJECT_SIZE_SANITIZER") -} - // The flag indicating behavior for the tree wrt building modules or using prebuilts // derived from RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE func (c Config) ReleaseDefaultModuleBuildFromSource() bool { @@ -385,24 +385,28 @@ type config struct { } type partialCompileFlags struct { - // Is partial compilation enabled at all? - Enabled bool - // Whether to use d8 instead of r8 Use_d8 bool + // Whether to disable stub validation. This is slightly more surgical + // than DISABLE_STUB_VALIDATION, in that it only applies to partial + // compile builds. + Disable_stub_validation bool + + // Whether to disable api lint. + Disable_api_lint bool + // Add others as needed. } // These are the flags when `SOONG_PARTIAL_COMPILE` is empty or not set. -var defaultPartialCompileFlags = partialCompileFlags{ - Enabled: false, -} +var defaultPartialCompileFlags = partialCompileFlags{} // These are the flags when `SOONG_PARTIAL_COMPILE=true`. var enabledPartialCompileFlags = partialCompileFlags{ - Enabled: true, - Use_d8: true, + Use_d8: true, + Disable_stub_validation: false, + Disable_api_lint: false, } type deviceConfig struct { @@ -477,13 +481,29 @@ func (c *config) parsePartialCompileFlags(isEngBuild bool) (partialCompileFlags, state = "+" } switch tok { + case "all": + // Turn on **all** of the flags. + ret = partialCompileFlags{ + Use_d8: true, + Disable_stub_validation: true, + Disable_api_lint: true, + } case "true": ret = enabledPartialCompileFlags case "false": // Set everything to false. ret = partialCompileFlags{} - case "enabled": - ret.Enabled = makeVal(state, defaultPartialCompileFlags.Enabled) + + case "api_lint", "enable_api_lint": + ret.Disable_api_lint = !makeVal(state, !defaultPartialCompileFlags.Disable_api_lint) + case "disable_api_lint": + ret.Disable_api_lint = makeVal(state, defaultPartialCompileFlags.Disable_api_lint) + + case "stub_validation", "enable_stub_validation": + ret.Disable_stub_validation = !makeVal(state, !defaultPartialCompileFlags.Disable_stub_validation) + case "disable_stub_validation": + ret.Disable_stub_validation = makeVal(state, defaultPartialCompileFlags.Disable_stub_validation) + case "use_d8": ret.Use_d8 = makeVal(state, defaultPartialCompileFlags.Use_d8) default: diff --git a/android/config_test.go b/android/config_test.go index 3d8686041..d1b26c12a 100644 --- a/android/config_test.go +++ b/android/config_test.go @@ -213,13 +213,18 @@ func TestConfiguredJarList(t *testing.T) { }) } -func (p partialCompileFlags) updateEnabled(value bool) partialCompileFlags { - p.Enabled = value +func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags { + p.Use_d8 = value return p } -func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags { - p.Use_d8 = value +func (p partialCompileFlags) updateDisableApiLint(value bool) partialCompileFlags { + p.Disable_api_lint = value + return p +} + +func (p partialCompileFlags) updateDisableStubValidation(value bool) partialCompileFlags { + p.Disable_stub_validation = value return p } @@ -241,10 +246,29 @@ func TestPartialCompile(t *testing.T) { {"false", true, partialCompileFlags{}}, {"true", true, enabledPartialCompileFlags}, {"true", false, partialCompileFlags{}}, + {"all", true, partialCompileFlags{}.updateUseD8(true).updateDisableApiLint(true).updateDisableStubValidation(true)}, + + // This verifies both use_d8 and the processing order. {"true,use_d8", true, enabledPartialCompileFlags.updateUseD8(true)}, {"true,-use_d8", true, enabledPartialCompileFlags.updateUseD8(false)}, {"use_d8,false", true, partialCompileFlags{}}, {"false,+use_d8", true, partialCompileFlags{}.updateUseD8(true)}, + + // disable_api_lint can be specified with any of 3 options. + {"false,-api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)}, + {"false,-enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)}, + {"false,+disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)}, + {"false,+api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)}, + {"false,+enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)}, + {"false,-disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)}, + + // disable_stub_validation can be specified with any of 3 options. + {"false,-stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)}, + {"false,-enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)}, + {"false,+disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)}, + {"false,+stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)}, + {"false,+enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)}, + {"false,-disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)}, } for _, test := range tests { diff --git a/android/container.go b/android/container.go index a5aab79bb..547fe816c 100644 --- a/android/container.go +++ b/android/container.go @@ -39,7 +39,7 @@ type StubsAvailableModule interface { // Returns true if the dependency module is a stubs module var depIsStubsModule exceptionHandleFunc = func(mctx ModuleContext, _ Module, dep ModuleProxy) bool { - return OtherModuleProviderOrDefault(mctx, dep, CommonModuleInfoKey).IsStubsModule + return OtherModulePointerProviderOrDefault(mctx, dep, CommonModuleInfoProvider).IsStubsModule } // Returns true if the dependency module belongs to any of the apexes. @@ -474,7 +474,7 @@ func checkContainerViolations(ctx ModuleContext) { if _, ok := ctx.Module().(InstallableModule); ok { containersInfo, _ := getContainerModuleInfo(ctx, ctx.Module()) ctx.VisitDirectDepsProxy(func(dep ModuleProxy) { - if !OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoKey).Enabled { + if !OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoProvider).Enabled { return } diff --git a/android/filegroup.go b/android/filegroup.go index 4fad52aaa..9bcfd0a83 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -33,6 +33,7 @@ var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx Registrati func RegisterFilegroupBuildComponents(ctx RegistrationContext) { ctx.RegisterModuleType("filegroup", FileGroupFactory) ctx.RegisterModuleType("filegroup_defaults", FileGroupDefaultsFactory) + ctx.RegisterModuleType("otatools_package_filegroup", OtatoolsFileGroupFactory) } type fileGroupProperties struct { @@ -163,3 +164,54 @@ func (fg *fileGroup) IDEInfo(ctx BaseModuleContext, dpInfo *IdeInfo) { } } } + +type OtatoolsFileGroup struct { + ModuleBase +} + +func OtatoolsFileGroupFactory() Module { + module := &OtatoolsFileGroup{} + InitAndroidModule(module) + AddLoadHook(module, func(ctx LoadHookContext) { + module.createOTAToolsPackagefilegroup(ctx) + }) + return module +} + +func (fg *OtatoolsFileGroup) GenerateAndroidBuildActions(ctx ModuleContext) { +} + +// Create the filegroup to collect cert files for otatools.zip. +func (fg *OtatoolsFileGroup) createOTAToolsPackagefilegroup(ctx LoadHookContext) { + ctx.CreateModuleInDirectory( + FileGroupFactory, + ".", + &struct { + Name *string + Srcs []string + Visibility []string + }{ + Name: proptools.StringPtr("soong_generated_otatools_package_filegroup"), + Srcs: []string{ + "build/make/target/product/security/**/*.x509.pem", + "build/make/target/product/security/**/*.pk8", + "device/**/*.pk8", + "device/**/verifiedboot*", + "device/**/*.pem", + "device/**/oem*.prop", + "device/**/*.avbpubkey", + "external/avb/test/data/**/testkey_*.pem", + "external/avb/test/data/**/atx_metadata.bin", + "packages/modules/**/*.x509.pem", + "packages/modules/**/*.pk8", + "packages/modules/**/*.key.pem", + "vendor/**/*.pk8", + "vendor/**/verifiedboot*", + "vendor/**/*.pem", + "vendor/**/oem*.prop", + "vendor/**/*.avbpubkey", + }, + Visibility: []string{"//build/make/tools/otatools_package"}, + }, + ) +} diff --git a/android/gen_notice.go b/android/gen_notice.go index 482b1e006..45f90f47c 100644 --- a/android/gen_notice.go +++ b/android/gen_notice.go @@ -60,7 +60,7 @@ func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) { for _, name := range gm.For { mods := ctx.ModuleVariantsFromName(m, name) for _, mod := range mods { - if !OtherModuleProviderOrDefault(ctx, mod, CommonModuleInfoKey).Enabled { // don't depend on variants without build rules + if !OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider).Enabled { // don't depend on variants without build rules continue } modules = append(modules, mod) diff --git a/android/init.go b/android/init.go index d3a13d0ed..af50323d3 100644 --- a/android/init.go +++ b/android/init.go @@ -17,6 +17,7 @@ package android import "encoding/gob" func init() { + gob.Register(applicableLicensesPropertyImpl{}) gob.Register(extraFilesZip{}) gob.Register(InstallPath{}) gob.Register(ModuleGenPath{}) diff --git a/android/license_metadata.go b/android/license_metadata.go index d15dfa841..0b880dd8a 100644 --- a/android/license_metadata.go +++ b/android/license_metadata.go @@ -65,7 +65,7 @@ func buildLicenseMetadata(ctx *moduleContext, licenseMetadataFile WritablePath) var allDepMetadataDepSets []depset.DepSet[Path] ctx.VisitDirectDepsProxy(func(dep ModuleProxy) { - if !OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoKey).Enabled { + if !OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider).Enabled { return } diff --git a/android/licenses.go b/android/licenses.go index 55f46ae23..387792144 100644 --- a/android/licenses.go +++ b/android/licenses.go @@ -22,6 +22,7 @@ import ( "sync" "github.com/google/blueprint" + "github.com/google/blueprint/gobtools" ) // Adds cross-cutting licenses dependency to propagate license metadata through the build system. @@ -67,6 +68,31 @@ type applicableLicensesPropertyImpl struct { licensesProperty *[]string } +type applicableLicensesPropertyImplGob struct { + Name string + LicensesProperty []string +} + +func (a *applicableLicensesPropertyImpl) ToGob() *applicableLicensesPropertyImplGob { + return &applicableLicensesPropertyImplGob{ + Name: a.name, + LicensesProperty: *a.licensesProperty, + } +} + +func (a *applicableLicensesPropertyImpl) FromGob(data *applicableLicensesPropertyImplGob) { + a.name = data.Name + a.licensesProperty = &data.LicensesProperty +} + +func (a applicableLicensesPropertyImpl) GobEncode() ([]byte, error) { + return gobtools.CustomGobEncode[applicableLicensesPropertyImplGob](&a) +} + +func (a *applicableLicensesPropertyImpl) GobDecode(data []byte) error { + return gobtools.CustomGobDecode[applicableLicensesPropertyImplGob](data, a) +} + func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty { return applicableLicensesPropertyImpl{ name: name, diff --git a/android/logtags.go b/android/logtags.go index 88d36ec72..074f402e7 100644 --- a/android/logtags.go +++ b/android/logtags.go @@ -43,7 +43,7 @@ func MergedLogtagsPath(ctx PathContext) OutputPath { func (l *logtagsSingleton) GenerateBuildActions(ctx SingletonContext) { var allLogtags Paths ctx.VisitAllModuleProxies(func(module ModuleProxy) { - if !OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ExportedToMake { + if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ExportedToMake { return } if logtagsInfo, ok := OtherModuleProvider(ctx, module, LogtagsProviderKey); ok { diff --git a/android/makevars.go b/android/makevars.go index 692b27ec6..7017e7db0 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -259,7 +259,7 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { singletonDists.lock.Unlock() ctx.VisitAllModuleProxies(func(m ModuleProxy) { - commonInfo, _ := OtherModuleProvider(ctx, m, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, m, CommonModuleInfoProvider) if provider, ok := OtherModuleProvider(ctx, m, ModuleMakeVarsInfoProvider); ok && commonInfo.Enabled { mctx := &makeVarsContext{ diff --git a/android/module.go b/android/module.go index 713751a71..a3fe837a5 100644 --- a/android/module.go +++ b/android/module.go @@ -520,6 +520,11 @@ type baseProperties struct { // names of other modules to install on target if this module is installed Target_required []string `android:"arch_variant"` + + // If this is a soong config module, this property will be set to the name of the original + // module type. This is used by neverallow to ensure you can't bypass a ModuleType() matcher + // just by creating a soong config module type. + Soong_config_base_module_type *string `blueprint:"mutated"` } type distProperties struct { @@ -997,11 +1002,19 @@ func (m *ModuleBase) baseDepsMutator(ctx BottomUpMutatorContext) { pv := ctx.Config().productVariables fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil if fullManifest { - addRequiredDeps(ctx) addVintfFragmentDeps(ctx) } } +// required property can be overridden too; handle it separately +func (m *ModuleBase) baseOverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) { + pv := ctx.Config().productVariables + fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil + if fullManifest { + addRequiredDeps(ctx) + } +} + // addRequiredDeps adds required, target_required, and host_required as dependencies. func addRequiredDeps(ctx BottomUpMutatorContext) { addDep := func(target Target, depName string) { @@ -1483,7 +1496,7 @@ func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]depset.DepSet[Inst // Installation is still handled by Make, so anything hidden from Make is not // installable. info := OtherModuleProviderOrDefault(ctx, dep, InstallFilesProvider) - commonInfo := OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoKey) + commonInfo := OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider) if !commonInfo.HideFromMake && !commonInfo.SkipInstall { installDeps = append(installDeps, info.TransitiveInstallFiles) } @@ -1500,7 +1513,7 @@ func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]depset.DepSet[Inst // should also install the output files of the given dependency and dependency tag. func isInstallDepNeeded(ctx ModuleContext, dep ModuleProxy) bool { // Don't add a dependency from the platform to a library provided by an apex. - if OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoKey).UninstallableApexPlatformVariant { + if OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider).UninstallableApexPlatformVariant { return false } // Only install modules if the dependency tag is an InstallDepNeeded tag. @@ -1669,9 +1682,10 @@ func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) { if len(ctx.installFiles) > 0 { name := namespacePrefix + ctx.ModuleName() + "-install" - ctx.Phony(name, ctx.installFiles.Paths()...) + installFiles := ctx.installFiles.Paths() + ctx.Phony(name, installFiles...) info.InstallTarget = PathForPhony(ctx, name) - deps = append(deps, info.InstallTarget) + deps = append(deps, installFiles...) } // A module's -checkbuild phony targets should @@ -1681,13 +1695,13 @@ func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) { if (!ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, m)) && !ctx.uncheckedModule && ctx.checkbuildTarget != nil { name := namespacePrefix + ctx.ModuleName() + "-checkbuild" ctx.Phony(name, ctx.checkbuildTarget) - deps = append(deps, PathForPhony(ctx, name)) + deps = append(deps, ctx.checkbuildTarget) } if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 { name := namespacePrefix + ctx.ModuleName() + "-outputs" ctx.Phony(name, outputFiles...) - deps = append(deps, PathForPhony(ctx, name)) + deps = append(deps, outputFiles...) } if len(deps) > 0 { @@ -1914,6 +1928,7 @@ type CommonModuleInfo struct { Dists []Dist ExportedToMake bool Team string + PartitionTag string } type ApiLevelOrPlatform struct { @@ -1921,7 +1936,7 @@ type ApiLevelOrPlatform struct { IsPlatform bool } -var CommonModuleInfoKey = blueprint.NewProvider[CommonModuleInfo]() +var CommonModuleInfoProvider = blueprint.NewProvider[*CommonModuleInfo]() type PrebuiltModuleInfo struct { SourceExists bool @@ -2281,6 +2296,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) Dists: m.Dists(), ExportedToMake: m.ExportedToMake(), Team: m.Team(), + PartitionTag: m.PartitionTag(ctx.DeviceConfig()), } if mm, ok := m.module.(interface { MinSdkVersion(ctx EarlyModuleContext) ApiLevel @@ -2328,7 +2344,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) if mm, ok := m.module.(interface{ BaseModuleName() string }); ok { commonData.BaseModuleName = mm.BaseModuleName() } - SetProvider(ctx, CommonModuleInfoKey, commonData) + SetProvider(ctx, CommonModuleInfoProvider, &commonData) if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil { SetProvider(ctx, PrebuiltModuleInfoProvider, PrebuiltModuleInfo{ SourceExists: p.Prebuilt().SourceExists(), @@ -2646,6 +2662,8 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu return proptools.ConfigurableValueBool(ctx.Config().UseDebugArt()) case "selinux_ignore_neverallows": return proptools.ConfigurableValueBool(ctx.Config().SelinuxIgnoreNeverallows()) + case "always_use_prebuilt_sdks": + return proptools.ConfigurableValueBool(ctx.Config().AlwaysUsePrebuiltSdks()) default: // TODO(b/323382414): Might add these on a case-by-case basis ctx.OtherModulePropertyErrorf(m, property, fmt.Sprintf("TODO(b/323382414): Product variable %q is not yet supported in selects", variable)) diff --git a/android/neverallow.go b/android/neverallow.go index 8995a0ffe..5c90501d7 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -60,7 +60,8 @@ func init() { AddNeverAllowRules(createCcStubsRule()) AddNeverAllowRules(createProhibitHeaderOnlyRule()) AddNeverAllowRules(createLimitNdkExportRule()...) - AddNeverAllowRules(createLimitDirgroupRule()...) + AddNeverAllowRules(createLimitDirgroupRules()...) + AddNeverAllowRules(createLimitGenruleRules()...) AddNeverAllowRules(createFilesystemIsAutoGeneratedRule()) AddNeverAllowRules(createKotlinPluginRule()...) AddNeverAllowRules(createPrebuiltEtcBpDefineRule()) @@ -251,6 +252,7 @@ func createInstallInRootAllowingRules() []Rule { NotModuleType("prebuilt_system"). NotModuleType("prebuilt_first_stage_ramdisk"). NotModuleType("prebuilt_res"). + NotModuleType("prebuilt_any"). Because("install_in_root is only for init_first_stage or librecovery_ui_ext."), } } @@ -287,45 +289,49 @@ func createLimitNdkExportRule() []Rule { } } -func createLimitDirgroupRule() []Rule { - reason := "dirgroup module and dir_srcs / keep_gendir property of genrule is allowed only to Trusty build rule." +func createLimitDirgroupRules() []Rule { + reason := "The dirgroup module can only be used with Trusty visibility" + scriptsDirsList := []string{"//trusty/vendor/google/aosp/scripts", "//trusty/vendor/google/proprietary/scripts"} return []Rule{ NeverAllow(). ModuleType("dirgroup"). - WithMatcher("visibility", NotInList([]string{"//trusty/vendor/google/aosp/scripts", "//trusty/vendor/google/proprietary/scripts"})).Because(reason), + WithMatcher("visibility", NotInList(scriptsDirsList)).Because(reason), NeverAllow(). ModuleType("dirgroup"). - WithoutMatcher("visibility", InAllowedList([]string{"//trusty/vendor/google/aosp/scripts", "//trusty/vendor/google/proprietary/scripts"})).Because(reason), + WithoutMatcher("visibility", InAllowedList(scriptsDirsList)).Because(reason), + } +} + +func createLimitGenruleRules() []Rule { + dirSrcsReason := "The `dir_srcs` property in a `genrule` module can only be used by Trusty" + keepGendirReason := "The `keep_gendir` property in a `genrule` module can only be used by Trusty" + allowedModuleNameList := []string{ + // Trusty TEE target names + "trusty_tee_package_goog", + "trusty_tee_package", + // Trusty vm target names + "trusty_desktop_vm_arm64.bin", + "trusty_desktop_vm_x86_64.elf", + "trusty_desktop_test_vm_arm64.bin", + "trusty_desktop_test_vm_x86_64.elf", + "trusty_test_vm_arm64.bin", + "trusty_test_vm_x86_64.elf", + "trusty_test_vm_os_arm64.bin", + "trusty_test_vm_os_x86_64.elf", + "trusty_security_vm_arm64.bin", + "trusty_security_vm_x86_64.elf", + "trusty_widevine_vm_arm64.bin", + "trusty_widevine_vm_x86_64.elf", + } + return []Rule{ NeverAllow(). ModuleType("genrule"). - // Trusty TEE target names - Without("name", "trusty_tee_package_goog"). - Without("name", "trusty_tee_package"). - // Trusty vm target names - Without("name", "trusty_test_vm_arm64.bin"). - Without("name", "trusty_test_vm_x86_64.elf"). - Without("name", "trusty_test_vm_os_arm64.bin"). - Without("name", "trusty_test_vm_os_x86_64.elf"). - Without("name", "trusty_security_vm_arm64.bin"). - Without("name", "trusty_security_vm_x86_64.elf"). - Without("name", "trusty_widevine_vm_arm64.bin"). - Without("name", "trusty_widevine_vm_x86_64.elf"). - WithMatcher("dir_srcs", isSetMatcherInstance).Because(reason), + WithoutMatcher("name", InAllowedList(allowedModuleNameList)). + WithMatcher("dir_srcs", isSetMatcherInstance).Because(dirSrcsReason), NeverAllow(). ModuleType("genrule"). - // Trusty TEE target names - Without("name", "trusty_tee_package_goog"). - Without("name", "trusty_tee_package"). - // Trusty vm target names - Without("name", "trusty_test_vm_arm64.bin"). - Without("name", "trusty_test_vm_x86_64.elf"). - Without("name", "trusty_test_vm_os_arm64.bin"). - Without("name", "trusty_test_vm_os_x86_64.elf"). - Without("name", "trusty_security_vm_arm64.bin"). - Without("name", "trusty_security_vm_x86_64.elf"). - Without("name", "trusty_widevine_vm_arm64.bin"). - Without("name", "trusty_widevine_vm_x86_64.elf"). - With("keep_gendir", "true").Because(reason), + WithoutMatcher("name", InAllowedList(allowedModuleNameList)). + With("keep_gendir", "true").Because(keepGendirReason), } } @@ -363,6 +369,7 @@ func createKotlinPluginRule() []Rule { func createPrebuiltEtcBpDefineRule() Rule { return NeverAllow(). ModuleType( + "prebuilt_any", "prebuilt_usr_srec", "prebuilt_priv_app", "prebuilt_rfs", @@ -378,6 +385,9 @@ func createPrebuiltEtcBpDefineRule() Rule { "prebuilt_sbin", "prebuilt_system", "prebuilt_first_stage_ramdisk", + "prebuilt_radio", + "prebuilt_gpu", + "prebuilt_vendor_overlay", ). DefinedInBpFile(). Because("module type not allowed to be defined in bp file") @@ -409,7 +419,8 @@ func neverallowMutator(ctx BottomUpMutatorContext) { continue } - if !n.appliesToModuleType(ctx.ModuleType()) { + modType := proptools.StringDefault(m.base().baseProperties.Soong_config_base_module_type, ctx.ModuleType()) + if !n.appliesToModuleType(modType) { continue } diff --git a/android/neverallow_test.go b/android/neverallow_test.go index c74d5ff58..3ccc883af 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -388,6 +388,30 @@ var neverallowTests = []struct { `module type not allowed to be defined in bp file`, }, }, + // Test the a neverallowed module type can't be smuggled through a soong config module type + { + name: `smuggling module types through soong config modules`, + fs: map[string][]byte{ + "a/b/Android.bp": []byte(` + soong_config_bool_variable { + name: "my_var", + } + soong_config_module_type { + name: "smuggled_prebuilt_usr_srec", + module_type: "prebuilt_usr_srec", + config_namespace: "ANDROID", + variables: ["my_var"], + properties: ["enabled"], + } + smuggled_prebuilt_usr_srec { + name: "foo", + } + `), + }, + expectedErrors: []string{ + `module type not allowed to be defined in bp file`, + }, + }, } var prepareForNeverAllowTest = GroupFixturePreparers( @@ -399,6 +423,7 @@ var prepareForNeverAllowTest = GroupFixturePreparers( ctx.RegisterModuleType("filesystem", newMockFilesystemModule) ctx.RegisterModuleType("prebuilt_usr_srec", newMockPrebuiltUsrSrecModule) }), + PrepareForTestWithSoongConfigModuleBuildComponents, ) func TestNeverallow(t *testing.T) { diff --git a/android/override_module.go b/android/override_module.go index 50ddc9b35..96620ef7a 100644 --- a/android/override_module.go +++ b/android/override_module.go @@ -367,6 +367,7 @@ func checkPrebuiltReplacesOverride(ctx BottomUpMutatorContext, b OverridableModu } func overridableModuleDepsMutator(ctx BottomUpMutatorContext) { + ctx.Module().base().baseOverridablePropertiesDepsMutator(ctx) if b, ok := ctx.Module().(OverridableModule); ok && b.Enabled(ctx) { b.OverridablePropertiesDepsMutator(ctx) } diff --git a/android/package.go b/android/package.go index 42f17b1d5..52bddf9d9 100644 --- a/android/package.go +++ b/android/package.go @@ -62,7 +62,7 @@ func (p *packageModule) DepsMutator(ctx BottomUpMutatorContext) { } func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) { - ctx.SetProvider(CommonModuleInfoKey, CommonModuleInfo{ + ctx.SetProvider(CommonModuleInfoProvider, &CommonModuleInfo{ Enabled: true, PrimaryLicensesProperty: p.primaryLicensesProperty, }) diff --git a/android/packaging.go b/android/packaging.go index 6146f02c9..bb1fe4e45 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -89,6 +89,8 @@ type packagingSpecGob struct { ArchType ArchType Overrides []string Owner string + RequiresFullInstall bool + FullInstallPath InstallPath Variation string } @@ -113,6 +115,8 @@ func (p *PackagingSpec) ToGob() *packagingSpecGob { ArchType: p.archType, Overrides: p.overrides.ToSlice(), Owner: p.owner, + RequiresFullInstall: p.requiresFullInstall, + FullInstallPath: p.fullInstallPath, Variation: p.variation, } } @@ -129,6 +133,8 @@ func (p *PackagingSpec) FromGob(data *packagingSpecGob) { p.archType = data.ArchType p.overrides = uniquelist.Make(data.Overrides) p.owner = data.Owner + p.requiresFullInstall = data.RequiresFullInstall + p.fullInstallPath = data.FullInstallPath p.variation = data.Variation } diff --git a/android/paths.go b/android/paths.go index 9c0c9a273..977473fbd 100644 --- a/android/paths.go +++ b/android/paths.go @@ -683,7 +683,7 @@ func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag if module == nil { return nil, missingDependencyError{[]string{moduleName}} } - if !OtherModuleProviderOrDefault(ctx, *module, CommonModuleInfoKey).Enabled { + if !OtherModulePointerProviderOrDefault(ctx, *module, CommonModuleInfoProvider).Enabled { return nil, missingDependencyError{[]string{moduleName}} } diff --git a/android/prebuilt.go b/android/prebuilt.go index 4a94c0bcb..1ff009bf5 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -358,7 +358,7 @@ func IsModulePreferred(module Module) bool { } func IsModulePreferredProxy(ctx OtherModuleProviderContext, module ModuleProxy) bool { - if OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt { + if OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt { // A source module that has been replaced by a prebuilt counterpart. return false } @@ -397,7 +397,7 @@ func GetEmbeddedPrebuilt(module Module) *Prebuilt { // the right module. This function is only safe to call after all TransitionMutators // have run, e.g. in GenerateAndroidBuildActions. func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module { - if !OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt { + if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt { return module } if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok { @@ -607,11 +607,6 @@ func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoM if !moduleInFamily.ExportedToMake() { continue } - // Skip for the top-level java_sdk_library_(_import). This has some special cases that need to be addressed first. - // This does not run into non-determinism because PrebuiltPostDepsMutator also has the special case - if sdkLibrary, ok := moduleInFamily.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { - continue - } if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil && p.properties.UsePrebuilt { if selectedPrebuilt == nil { selectedPrebuilt = moduleInFamily @@ -638,26 +633,10 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { if p := GetEmbeddedPrebuilt(m); p != nil { bmn, _ := m.(baseModuleName) name := bmn.BaseModuleName() - psi := PrebuiltSelectionInfoMap{} - ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) { - psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider) - }) if p.properties.UsePrebuilt { if p.properties.SourceExists { ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool { - if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { - // Do not replace deps to the top-level prebuilt java_sdk_library hook. - // This hook has been special-cased in #isSelected to be _always_ active, even in next builds - // for dexpreopt and hiddenapi processing. - // If we do not special-case this here, rdeps referring to a java_sdk_library in next builds via libs - // will get prebuilt stubs - // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions - if psi.IsSelected(name) { - return false - } - } - if t, ok := tag.(ReplaceSourceWithPrebuilt); ok { return t.ReplaceSourceWithPrebuilt() } @@ -679,23 +658,13 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { // java_sdk_library_import is a macro that creates // 1. top-level "impl" library // 2. stub libraries (suffixed with .stubs...) -// -// the impl of java_sdk_library_import is a "hook" for hiddenapi and dexpreopt processing. It does not have an impl jar, but acts as a shim -// to provide the jar deapxed from the prebuilt apex -// -// isSelected uses `all_apex_contributions` to supersede source vs prebuilts selection of the stub libraries. It does not supersede the -// selection of the top-level "impl" library so that this hook can work -// -// TODO (b/308174306) - Fix this when we need to support multiple prebuilts in main func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool { if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { sln := proptools.String(sdkLibrary.SdkLibraryName()) // This is the top-level library - // Do not supersede the existing prebuilts vs source selection mechanisms - // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions if bmn, ok := m.(baseModuleName); ok && sln == bmn.BaseModuleName() { - return false + return psi.IsSelected(m.Name()) } // Stub library created by java_sdk_library_import diff --git a/android/provider.go b/android/provider.go index d005daf55..aae93ef88 100644 --- a/android/provider.go +++ b/android/provider.go @@ -41,6 +41,14 @@ func OtherModuleProviderOrDefault[K any](ctx OtherModuleProviderContext, module return value } +func OtherModulePointerProviderOrDefault[K *T, T any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) K { + if value, ok := OtherModuleProvider(ctx, module, provider); ok { + return value + } + var val T + return &val +} + // ModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext // for use in ModuleProvider. type ModuleProviderContext interface { diff --git a/android/provider_keys.go b/android/provider_keys.go new file mode 100644 index 000000000..60b383f53 --- /dev/null +++ b/android/provider_keys.go @@ -0,0 +1,24 @@ +// 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" + +// Providers of package filesystem +type AndroidDeviceInfo struct { + Main_device bool +} + +var AndroidDeviceInfoProvider = blueprint.NewProvider[AndroidDeviceInfo]() diff --git a/android/rule_builder.go b/android/rule_builder.go index db56c3f29..01fe6d8ea 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -660,12 +660,17 @@ func (r *RuleBuilder) build(name string, desc string) { } for _, c := range r.commands { for _, tool := range c.packagedTools { - command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ - From: proto.String(tool.srcPath.String()), - To: proto.String(sboxPathForPackagedToolRel(tool)), - Executable: proto.Bool(tool.executable), - }) - tools = append(tools, tool.srcPath) + if tool.srcPath != nil { + command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ + From: proto.String(tool.srcPath.String()), + To: proto.String(sboxPathForPackagedToolRel(tool)), + Executable: proto.Bool(tool.executable), + }) + tools = append(tools, tool.srcPath) + } else if tool.SymlinkTarget() == "" { + // We ignore symlinks for now, could be added later if needed + panic("Expected tool packagingSpec to either be a file or symlink") + } } } } @@ -1187,7 +1192,11 @@ func (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand { // Textf adds the specified formatted text to the command line. The text should not contain input or output paths or // the rule will not have them listed in its dependencies or outputs. func (c *RuleBuilderCommand) Textf(format string, a ...interface{}) *RuleBuilderCommand { - return c.Text(fmt.Sprintf(format, a...)) + if c.buf.Len() > 0 { + c.buf.WriteByte(' ') + } + fmt.Fprintf(&c.buf, format, a...) + return c } // Flag adds the specified raw text to the command line. The text should not contain input or output paths or the diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go index e0b1d7cbe..a61c9d33d 100644 --- a/android/soong_config_modules.go +++ b/android/soong_config_modules.go @@ -506,6 +506,10 @@ func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfi conditionalProps := proptools.CloneEmptyProperties(conditionalFactoryProps) props = append(props, conditionalProps.Interface()) + if m, ok := module.(Module); ok { + m.base().baseProperties.Soong_config_base_module_type = &moduleType.BaseModuleType + } + // Regular Soong operation wraps the existing module factory with a // conditional on Soong config variables by reading the product // config variables from Make. diff --git a/android/test_suites.go b/android/test_suites.go index 39317ec62..9eaf78549 100644 --- a/android/test_suites.go +++ b/android/test_suites.go @@ -29,10 +29,7 @@ func testSuiteFilesFactory() Singleton { return &testSuiteFiles{} } -type testSuiteFiles struct { - robolectric []Path - ravenwood []Path -} +type testSuiteFiles struct{} type TestSuiteModule interface { Module @@ -61,51 +58,22 @@ func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) { } }) - t.robolectric = robolectricTestSuite(ctx, files["robolectric-tests"]) - ctx.Phony("robolectric-tests", t.robolectric...) - - t.ravenwood = ravenwoodTestSuite(ctx, files["ravenwood-tests"]) - ctx.Phony("ravenwood-tests", t.ravenwood...) - ctx.DistForGoal("robolectric-tests", t.robolectric...) - ctx.DistForGoal("ravenwood-tests", t.ravenwood...) -} - -func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path { - var installedPaths InstallPaths - for _, module := range SortedKeys(files) { - installedPaths = append(installedPaths, files[module]...) - } - - outputFile := pathForPackaging(ctx, "robolectric-tests.zip") - rule := NewRuleBuilder(pctx, ctx) - rule.Command().BuiltTool("soong_zip"). - FlagWithOutput("-o ", outputFile). - FlagWithArg("-P ", "host/testcases"). - FlagWithArg("-C ", pathForTestCases(ctx).String()). - FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()). - Flag("-sha256") // necessary to save cas_uploader's time - - testList := buildTestList(ctx, "robolectric-tests_list", installedPaths) - testListZipOutputFile := pathForPackaging(ctx, "robolectric-tests_list.zip") - - rule.Command().BuiltTool("soong_zip"). - FlagWithOutput("-o ", testListZipOutputFile). - FlagWithArg("-C ", pathForPackaging(ctx).String()). - FlagWithInput("-f ", testList). - Flag("-sha256") - - rule.Build("robolectric_tests_zip", "robolectric-tests.zip") + robolectricZip, robolectrictListZip := buildTestSuite(ctx, "robolectric-tests", files["robolectric-tests"]) + ctx.Phony("robolectric-tests", robolectricZip, robolectrictListZip) + ctx.DistForGoal("robolectric-tests", robolectricZip, robolectrictListZip) - return []Path{outputFile, testListZipOutputFile} + ravenwoodZip, ravenwoodListZip := buildTestSuite(ctx, "ravenwood-tests", files["ravenwood-tests"]) + ctx.Phony("ravenwood-tests", ravenwoodZip, ravenwoodListZip) + ctx.DistForGoal("ravenwood-tests", ravenwoodZip, ravenwoodListZip) } -func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path { +func buildTestSuite(ctx SingletonContext, suiteName string, files map[string]InstallPaths) (Path, Path) { var installedPaths InstallPaths for _, module := range SortedKeys(files) { installedPaths = append(installedPaths, files[module]...) } - outputFile := pathForPackaging(ctx, "ravenwood-tests.zip") + outputFile := pathForPackaging(ctx, suiteName+".zip") rule := NewRuleBuilder(pctx, ctx) rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", outputFile). @@ -114,8 +82,8 @@ func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []P FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()). Flag("-sha256") // necessary to save cas_uploader's time - testList := buildTestList(ctx, "ravenwood-tests_list", installedPaths) - testListZipOutputFile := pathForPackaging(ctx, "ravenwood-tests_list.zip") + testList := buildTestList(ctx, suiteName+"_list", installedPaths) + testListZipOutputFile := pathForPackaging(ctx, suiteName+"_list.zip") rule.Command().BuiltTool("soong_zip"). FlagWithOutput("-o ", testListZipOutputFile). @@ -123,9 +91,9 @@ func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []P FlagWithInput("-f ", testList). Flag("-sha256") - rule.Build("ravenwood_tests_zip", "ravenwood-tests.zip") + rule.Build(strings.ReplaceAll(suiteName, "-", "_")+"_zip", suiteName+".zip") - return []Path{outputFile, testListZipOutputFile} + return outputFile, testListZipOutputFile } func buildTestList(ctx SingletonContext, listFile string, installedPaths InstallPaths) Path { diff --git a/android/testing.go b/android/testing.go index 1962fdea5..d2949ec8e 100644 --- a/android/testing.go +++ b/android/testing.go @@ -1197,11 +1197,11 @@ func AndroidMkInfoForTest(t *testing.T, ctx *TestContext, mod Module) *AndroidMk info := OtherModuleProviderOrDefault(ctx, mod, AndroidMkInfoProvider) aconfigUpdateAndroidMkInfos(ctx, mod, info) - commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) - info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) + commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider) + info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo) if len(info.ExtraInfo) > 0 { for _, ei := range info.ExtraInfo { - ei.fillInEntries(ctx, mod, &commonInfo) + ei.fillInEntries(ctx, mod, commonInfo) } } diff --git a/android/variable.go b/android/variable.go index 5bc0b297e..3d5a6ae12 100644 --- a/android/variable.go +++ b/android/variable.go @@ -65,12 +65,6 @@ type variableProperties struct { Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` } `android:"arch_variant"` - // similar to `Unbundled_build`, but `Always_use_prebuilt_sdks` means that it uses prebuilt - // sdk specifically. - Always_use_prebuilt_sdks struct { - Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` - } `android:"arch_variant"` - Malloc_low_memory struct { Cflags []string `android:"arch_variant"` Shared_libs []string `android:"arch_variant"` @@ -216,6 +210,7 @@ type ProductVariables struct { Platform_display_version_name *string `json:",omitempty"` Platform_version_name *string `json:",omitempty"` Platform_sdk_version *int `json:",omitempty"` + Platform_sdk_minor_version *int `json:",omitempty"` Platform_sdk_codename *string `json:",omitempty"` Platform_sdk_version_or_codename *string `json:",omitempty"` Platform_sdk_final *bool `json:",omitempty"` @@ -553,6 +548,8 @@ type ProductVariables struct { OdmManifestFiles []string `json:",omitempty"` UseSoongNoticeXML *bool `json:",omitempty"` + + StripByDefault *bool `json:",omitempty"` } type PartitionQualifiedVariablesType struct { @@ -653,6 +650,7 @@ type PartitionVariables struct { ProductUseDynamicPartitions bool `json:",omitempty"` ProductRetrofitDynamicPartitions bool `json:",omitempty"` ProductBuildSuperPartition bool `json:",omitempty"` + BuildingSuperEmptyImage bool `json:",omitempty"` BoardSuperPartitionSize string `json:",omitempty"` BoardSuperPartitionMetadataDevice string `json:",omitempty"` BoardSuperPartitionBlockDevices []string `json:",omitempty"` diff --git a/apex/apex.go b/apex/apex.go index 196f389d2..c6566e13b 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -550,6 +550,9 @@ type apexBundle struct { // Required modules, filled out during GenerateAndroidBuildActions and used in AndroidMk required []string + + // appinfo of the apk-in-apex of this module + appInfos java.AppInfos } // apexFileClass represents a type of file that can be included in APEX. @@ -1499,7 +1502,7 @@ func apexFileForJavaModule(ctx android.ModuleContext, module android.Module, jav func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module android.Module, javaInfo *java.JavaInfo, dexImplementationJar android.Path) apexFile { dirInApex := "javalib" - commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider) af := newApexFile(ctx, dexImplementationJar, commonInfo.BaseModuleName, dirInApex, javaSharedLib, module) af.jacocoReportClassesFile = javaInfo.JacocoReportClassesFile if lintInfo, ok := android.OtherModuleProvider(ctx, module, java.LintProvider); ok { @@ -1604,35 +1607,8 @@ func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path // to the child modules. Returning false makes the visit to continue in the sibling or the parent // modules. This is used in check* functions below. func (a *apexBundle) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) { - ctx.WalkDeps(func(child, parent android.Module) bool { - am, ok := child.(android.ApexModule) - if !ok || !am.CanHaveApexVariants() { - return false - } - - // Filter-out unwanted depedendencies - depTag := ctx.OtherModuleDependencyTag(child) - if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { - return false - } - if dt, ok := depTag.(*dependencyTag); ok && !dt.payload { - return false - } - if depTag == android.RequiredDepTag { - return false - } - - externalDep := !android.IsDepInSameApex(ctx, parent, child) - - // Visit actually - return do(ctx, parent, am, externalDep) - }) -} - -func (a *apexBundle) WalkPayloadDepsProxy(ctx android.BaseModuleContext, - do func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool) { ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { - if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).CanHaveApexVariants { + if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).CanHaveApexVariants { return false } // Filter-out unwanted depedendencies @@ -1845,7 +1821,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { return false } - commonInfo := android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider) if !commonInfo.Enabled { return false } @@ -1863,7 +1839,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, if ch.IsStubs { ctx.PropertyErrorf(propertyName, "%q is a stub. Remove it from the list.", depName) } - fi := apexFileForNativeLibrary(ctx, child, &commonInfo, ch, vctx.handleSpecialLibs) + fi := apexFileForNativeLibrary(ctx, child, commonInfo, ch, vctx.handleSpecialLibs) fi.isJniLib = isJniLib vctx.filesInfo = append(vctx.filesInfo, fi) // Collect the list of stub-providing libs except: @@ -1880,11 +1856,11 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, case executableTag: if ccInfo, ok := android.OtherModuleProvider(ctx, child, cc.CcInfoProvider); ok { - vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, child, &commonInfo, ccInfo)) + vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, child, commonInfo, ccInfo)) return true // track transitive dependencies } if _, ok := android.OtherModuleProvider(ctx, child, rust.RustInfoProvider); ok { - vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, child, &commonInfo)) + vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, child, commonInfo)) return true // track transitive dependencies } else { ctx.PropertyErrorf("binaries", @@ -1892,7 +1868,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } case shBinaryTag: if csh, ok := android.OtherModuleProvider(ctx, child, sh.ShBinaryInfoProvider); ok { - vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, child, &commonInfo, &csh)) + vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, child, commonInfo, &csh)) } else { ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName) } @@ -1931,6 +1907,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } case androidAppTag: if appInfo, ok := android.OtherModuleProvider(ctx, child, java.AppInfoProvider); ok { + a.appInfos = append(a.appInfos, *appInfo) if appInfo.AppSet { appDir := "app" if appInfo.Privileged { @@ -1945,7 +1922,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, af.certificate = java.PresignedCertificate vctx.filesInfo = append(vctx.filesInfo, af) } else { - vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, child, &commonInfo, appInfo)...) + vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, child, commonInfo, appInfo)...) if !appInfo.Prebuilt && !appInfo.TestHelperApp { return true // track transitive dependencies } @@ -1992,7 +1969,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } case testTag: if ccInfo, ok := android.OtherModuleProvider(ctx, child, cc.CcInfoProvider); ok { - af := apexFileForExecutable(ctx, child, &commonInfo, ccInfo) + af := apexFileForExecutable(ctx, child, commonInfo, ccInfo) af.class = nativeTest vctx.filesInfo = append(vctx.filesInfo, af) return true // track transitive dependencies @@ -2029,7 +2006,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, // tags used below are private (e.g. `cc.sharedDepTag`). if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) { if ch, ok := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider); ok { - af := apexFileForNativeLibrary(ctx, child, &commonInfo, ch, vctx.handleSpecialLibs) + af := apexFileForNativeLibrary(ctx, child, commonInfo, ch, vctx.handleSpecialLibs) af.transitiveDep = true if ch.IsStubs || ch.HasStubsVariants { @@ -2091,7 +2068,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } linkableInfo := android.OtherModuleProviderOrDefault(ctx, child, cc.LinkableInfoProvider) - af := apexFileForNativeLibrary(ctx, child, &commonInfo, linkableInfo, vctx.handleSpecialLibs) + af := apexFileForNativeLibrary(ctx, child, commonInfo, linkableInfo, vctx.handleSpecialLibs) af.transitiveDep = true vctx.filesInfo = append(vctx.filesInfo, af) return true // track transitive dependencies @@ -2123,7 +2100,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, javaInfo := android.OtherModuleProviderOrDefault(ctx, child, java.JavaInfoProvider) af := apexFileForJavaModule(ctx, child, javaInfo) vctx.filesInfo = append(vctx.filesInfo, af) - if profileAf := apexFileForJavaModuleProfile(ctx, &commonInfo, javaInfo); profileAf != nil { + if profileAf := apexFileForJavaModuleProfile(ctx, commonInfo, javaInfo); profileAf != nil { vctx.filesInfo = append(vctx.filesInfo, *profileAf) } return true // track transitive dependencies @@ -2139,7 +2116,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName) } else if android.IsVintfDepTag(depTag) { if vf, ok := android.OtherModuleProvider(ctx, child, android.VintfFragmentInfoProvider); ok { - apexFile := apexFileForVintfFragment(ctx, child, &commonInfo, &vf) + apexFile := apexFileForVintfFragment(ctx, child, commonInfo, &vf) vctx.filesInfo = append(vctx.filesInfo, apexFile) } } @@ -2267,6 +2244,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { }) android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{a.apexKeysPath}) + + android.SetProvider(ctx, java.AppInfosProvider, a.appInfos) } // Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file @@ -2551,7 +2530,7 @@ func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext librariesDirectlyInApex[ctx.OtherModuleName(dep)] = true }) - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool { if info, ok := android.OtherModuleProvider(ctx, to, cc.LinkableInfoProvider); ok { // If `to` is not actually in the same APEX as `from` then it does not need // apex_available and neither do any of its dependencies. @@ -2665,7 +2644,7 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { return } - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool { // As soon as the dependency graph crosses the APEX boundary, don't go further. if externalDep { return false diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go index dabec4930..797f47b09 100644 --- a/apex/apex_singleton.go +++ b/apex/apex_singleton.go @@ -164,7 +164,7 @@ func (a *apexPrebuiltInfo) GenerateBuildActions(ctx android.SingletonContext) { prebuiltInfo, exists := android.OtherModuleProvider(ctx, m, android.PrebuiltInfoProvider) // Use prebuiltInfoProvider to filter out non apex soong modules. // Use HideFromMake to filter out the unselected variants of a specific apex. - if exists && !android.OtherModuleProviderOrDefault(ctx, m, android.CommonModuleInfoKey).HideFromMake { + if exists && !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).HideFromMake { prebuiltInfos = append(prebuiltInfos, prebuiltInfo) } }) diff --git a/apex/apex_test.go b/apex/apex_test.go index a0a42a149..36a697487 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -11667,7 +11667,7 @@ func TestAconfifDeclarationsValidation(t *testing.T) { // Arguments passed to aconfig to retrieve the state of the flags defined in the // textproto files - aconfigFlagArgs := m.Output("released-flagged-apis-exportable.txt").Args["flags_path"] + aconfigFlagArgs := m.Output("released-flags-exportable.pb").Args["flags_path"] // "bar-lib" is a static_lib of "foo" and is passed to metalava as classpath. Thus the // cache file provided by the associated aconfig_declarations module "bar" should be passed diff --git a/apex/builder.go b/apex/builder.go index 2fc4902fb..23c2ed8aa 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -1102,7 +1102,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { } depInfos := android.DepNameToDepInfoMap{} - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool { if from.Name() == to.Name() { // This can happen for cc.reuseObjTag. We are not interested in tracking this. // As soon as the dependency graph crosses the APEX boundary, don't go further. @@ -1111,7 +1111,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { // Skip dependencies that are only available to APEXes; they are developed with updatability // in mind and don't need manual approval. - if android.OtherModuleProviderOrDefault(ctx, to, android.CommonModuleInfoKey).NotAvailableForPlatform { + if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform { return !externalDep } @@ -1129,7 +1129,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { depInfos[to.Name()] = info } else { toMinSdkVersion := "(no version)" - if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoKey); ok && + if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoProvider); ok && !info.MinSdkVersion.IsPlatform && info.MinSdkVersion.ApiLevel != nil { toMinSdkVersion = info.MinSdkVersion.ApiLevel.String() } diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go index 26f2aa879..d78a907fb 100644 --- a/bloaty/bloaty.go +++ b/bloaty/bloaty.go @@ -84,8 +84,8 @@ func fileSizesSingleton() android.Singleton { func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) { var deps android.Paths - ctx.VisitAllModules(func(m android.Module) { - if !m.ExportedToMake() { + ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { + if !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).ExportedToMake { return } filePaths, ok := android.OtherModuleProvider(ctx, m, fileSizeMeasurerKey) diff --git a/cc/afdo.go b/cc/afdo.go index 8d8341eb4..9be39185c 100644 --- a/cc/afdo.go +++ b/cc/afdo.go @@ -105,6 +105,11 @@ func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags { // The flags are prepended to allow overriding. profileUseFlag := fmt.Sprintf(afdoFlagsFormat, fdoProfilePath) flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...) + // Salvage stale profile by fuzzy matching and use the remapped location for sample profile query. + flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile=true"}, flags.Local.CFlags...) + flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile-max-callsites=2000"}, flags.Local.CFlags...) + // Salvage stale profile by fuzzy matching renamed functions. + flags.Local.CFlags = append([]string{"-mllvm", "--salvage-unused-profile=true"}, flags.Local.CFlags...) flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...) // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt diff --git a/cc/api_level.go b/cc/api_level.go index deca72366..fa8dfaf2f 100644 --- a/cc/api_level.go +++ b/cc/api_level.go @@ -31,11 +31,7 @@ func MinApiForArch(ctx android.EarlyModuleContext, case android.Arm64, android.X86_64: return android.FirstLp64Version case android.Riscv64: - apiLevel, err := android.ApiLevelFromUser(ctx, "VanillaIceCream") - if err != nil { - panic(err) - } - return apiLevel + return android.FutureApiLevel default: panic(fmt.Errorf("Unknown arch %q", arch)) } diff --git a/cc/binary.go b/cc/binary.go index 627d5e560..608251afc 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -551,6 +551,10 @@ func (binary *binaryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON binary.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON) } +func (binary *binaryDecorator) testSuiteInfo(ctx ModuleContext) { + // not a test +} + var _ overridable = (*binaryDecorator)(nil) func init() { @@ -81,12 +81,13 @@ type LinkerInfo struct { HeaderLibs []string ImplementationModuleName *string - BinaryDecoratorInfo *BinaryDecoratorInfo - LibraryDecoratorInfo *LibraryDecoratorInfo - TestBinaryInfo *TestBinaryInfo - BenchmarkDecoratorInfo *BenchmarkDecoratorInfo - ObjectLinkerInfo *ObjectLinkerInfo - StubDecoratorInfo *StubDecoratorInfo + BinaryDecoratorInfo *BinaryDecoratorInfo + LibraryDecoratorInfo *LibraryDecoratorInfo + TestBinaryInfo *TestBinaryInfo + BenchmarkDecoratorInfo *BenchmarkDecoratorInfo + ObjectLinkerInfo *ObjectLinkerInfo + StubDecoratorInfo *StubDecoratorInfo + PrebuiltLibraryLinkerInfo *PrebuiltLibraryLinkerInfo } type BinaryDecoratorInfo struct{} @@ -96,6 +97,7 @@ type LibraryDecoratorInfo struct { // Location of the static library in the sysroot. Empty if the library is // not included in the NDK. NdkSysrootPath android.Path + VndkFileName string } type SnapshotInfo struct { @@ -120,6 +122,10 @@ type ObjectLinkerInfo struct { NdkSysrootPath android.Path } +type PrebuiltLibraryLinkerInfo struct { + VndkFileName string +} + type LibraryInfo struct { BuildStubs bool } @@ -128,6 +134,13 @@ type InstallerInfo struct { StubDecoratorInfo *StubDecoratorInfo } +type LocalOrGlobalFlagsInfo struct { + CommonFlags []string // Flags that apply to C, C++, and assembly source files + CFlags []string // Flags that apply to C and C++ source files + ConlyFlags []string // Flags that apply to C source files + CppFlags []string // Flags that apply to C++ source files +} + // Common info about the cc module. type CcInfo struct { IsPrebuilt bool @@ -148,6 +161,7 @@ type LinkableInfo struct { StaticExecutable bool Static bool Shared bool + Header bool HasStubsVariants bool StubsVersion string IsStubs bool @@ -195,7 +209,11 @@ type LinkableInfo struct { APIListCoverageXMLPath android.ModuleOutPath // FuzzSharedLibraries returns the shared library dependencies for this module. // Expects that IsFuzzModule returns true. - FuzzSharedLibraries android.RuleBuilderInstalls + FuzzSharedLibraries android.RuleBuilderInstalls + IsVndkPrebuiltLibrary bool + HasLLNDKStubs bool + IsLLNDKMovedToApex bool + ImplementationModuleName string } var LinkableInfoProvider = blueprint.NewProvider[*LinkableInfo]() @@ -779,6 +797,8 @@ type linker interface { defaultDistFiles() []android.Path moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) + + testSuiteInfo(ctx ModuleContext) } // specifiedDeps is a tuple struct representing dependencies of a linked binary owned by the linker. @@ -2356,9 +2376,11 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { case *binaryDecorator: ccInfo.LinkerInfo.BinaryDecoratorInfo = &BinaryDecoratorInfo{} case *libraryDecorator: + lk := c.linker.(*libraryDecorator) ccInfo.LinkerInfo.LibraryDecoratorInfo = &LibraryDecoratorInfo{ - InjectBsslHash: Bool(c.linker.(*libraryDecorator).Properties.Inject_bssl_hash), - NdkSysrootPath: c.linker.(*libraryDecorator).ndkSysrootPath, + InjectBsslHash: Bool(lk.Properties.Inject_bssl_hash), + NdkSysrootPath: lk.ndkSysrootPath, + VndkFileName: lk.getLibNameHelper(c.BaseModuleName(), true, false) + ".so", } case *testBinary: ccInfo.LinkerInfo.TestBinaryInfo = &TestBinaryInfo{ @@ -2372,6 +2394,11 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } case *stubDecorator: ccInfo.LinkerInfo.StubDecoratorInfo = &StubDecoratorInfo{} + case *prebuiltLibraryLinker: + ccInfo.LinkerInfo.PrebuiltLibraryLinkerInfo = &PrebuiltLibraryLinkerInfo{ + VndkFileName: c.linker.(*prebuiltLibraryLinker).getLibNameHelper( + c.BaseModuleName(), true, false) + ".so", + } } if s, ok := c.linker.(SnapshotInterface); ok { @@ -2383,6 +2410,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { name := v.ImplementationModuleName(ctx.OtherModuleName(c)) ccInfo.LinkerInfo.ImplementationModuleName = &name } + + c.linker.testSuiteInfo(ctx) } if c.library != nil { ccInfo.LibraryInfo = &LibraryInfo{ @@ -2441,12 +2470,17 @@ func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableIn Multilib: mod.Multilib(), ImplementationModuleNameForMake: mod.ImplementationModuleNameForMake(), Symlinks: mod.Symlinks(), + Header: mod.Header(), + IsVndkPrebuiltLibrary: mod.IsVndkPrebuiltLibrary(), } vi := mod.VersionedInterface() if vi != nil { info.IsStubsImplementationRequired = vi.IsStubsImplementationRequired() info.APIListCoverageXMLPath = vi.GetAPIListCoverageXMLPath() + info.HasLLNDKStubs = vi.HasLLNDKStubs() + info.IsLLNDKMovedToApex = vi.IsLLNDKMovedToApex() + info.ImplementationModuleName = vi.ImplementationModuleName(mod.BaseModuleName()) } if !mod.PreventInstall() && fuzz.IsValid(ctx, mod.FuzzModuleStruct()) && mod.IsFuzzModule() { @@ -3388,7 +3422,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) if commonInfo.Target.Os != ctx.Os() { ctx.ModuleErrorf("OS mismatch between %q (%s) and %q (%s)", ctx.ModuleName(), ctx.Os().Name, depName, dep.Target().Os.Name) return @@ -3642,7 +3676,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { c.sabi.Properties.ReexportedSystemIncludes, depExporterInfo.SystemIncludeDirs.Strings()...) } - makeLibName := MakeLibName(ccInfo, linkableInfo, &commonInfo, commonInfo.BaseModuleName) + libDepTag.makeSuffix + makeLibName := MakeLibName(ccInfo, linkableInfo, commonInfo, commonInfo.BaseModuleName) + libDepTag.makeSuffix switch { case libDepTag.header(): c.Properties.AndroidMkHeaderLibs = append( @@ -3669,7 +3703,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { switch depTag { case runtimeDepTag: c.Properties.AndroidMkRuntimeLibs = append( - c.Properties.AndroidMkRuntimeLibs, MakeLibName(ccInfo, linkableInfo, &commonInfo, + c.Properties.AndroidMkRuntimeLibs, MakeLibName(ccInfo, linkableInfo, commonInfo, commonInfo.BaseModuleName)+libDepTag.makeSuffix) case objDepTag: depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path()) @@ -3745,7 +3779,7 @@ func ShouldUseStubForApex(ctx android.ModuleContext, parent android.Module, dep // platform APIs, use stubs only when it is from an APEX (and not from // platform) However, for host, ramdisk, vendor_ramdisk, recovery or // bootstrap modules, always link to non-stub variant - isNotInPlatform := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey).NotInPlatform + isNotInPlatform := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider).NotInPlatform useStubs = isNotInPlatform && !bootstrap } else { diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go index 0dcf2cfd4..45b15809f 100644 --- a/cc/config/arm64_device.go +++ b/cc/config/arm64_device.go @@ -44,7 +44,7 @@ var ( // On ARMv9 and later, Pointer Authentication Codes (PAC) are mandatory, // so -fstack-protector is unnecessary. "armv9-a": []string{ - "-march=armv8.2-a+dotprod", + "-march=armv9-a", "-mbranch-protection=standard", "-fno-stack-protector", }, diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go index ddc86c299..d2f88ef34 100644 --- a/cc/config/x86_linux_bionic_host.go +++ b/cc/config/x86_linux_bionic_host.go @@ -28,7 +28,7 @@ var ( "-fno-omit-frame-pointer", "-U_FORTIFY_SOURCE", - "-D_FORTIFY_SOURCE=2", + "-D_FORTIFY_SOURCE=3", "-fstack-protector-strong", // From x86_64_device diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go index c070050b7..c3f25aa21 100644 --- a/cc/config/x86_linux_host.go +++ b/cc/config/x86_linux_host.go @@ -29,7 +29,7 @@ var ( "-fno-omit-frame-pointer", "-U_FORTIFY_SOURCE", - "-D_FORTIFY_SOURCE=2", + "-D_FORTIFY_SOURCE=3", "-fstack-protector", "--gcc-toolchain=${LinuxGccRoot}", diff --git a/cc/fuzz.go b/cc/fuzz.go index 325354b16..79874fc80 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -486,7 +486,7 @@ func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) sharedLibsInstallDirPrefix = "lib/vendor" } - commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider) isHost := commonInfo.Target.Os.Class == android.Host hostOrTargetString := "target" if commonInfo.Target.HostCross { diff --git a/cc/genrule_test.go b/cc/genrule_test.go index 438eb9880..4e700a2cd 100644 --- a/cc/genrule_test.go +++ b/cc/genrule_test.go @@ -17,6 +17,7 @@ package cc import ( "reflect" "slices" + "strings" "testing" "android/soong/android" @@ -254,3 +255,42 @@ func TestMultilibGenruleOut(t *testing.T) { gen_64bit, ) } + +// Test that a genrule can depend on a tool with symlinks. The symlinks are ignored, but +// at least it doesn't cause errors. +func TestGenruleToolWithSymlinks(t *testing.T) { + bp := ` + genrule { + name: "gen", + tools: ["tool_with_symlinks"], + cmd: "$(location tool_with_symlinks) $(in) $(out)", + out: ["out"], + } + + cc_binary_host { + name: "tool_with_symlinks", + symlinks: ["symlink1", "symlink2"], + } + ` + ctx := PrepareForIntegrationTestWithCc. + ExtendWithErrorHandler(android.FixtureExpectsNoErrors). + RunTestWithBp(t, bp) + gen := ctx.ModuleForTests(t, "gen", "").Output("out") + toolFound := false + symlinkFound := false + for _, dep := range gen.RuleParams.CommandDeps { + if strings.HasSuffix(dep, "/tool_with_symlinks") { + toolFound = true + } + if strings.HasSuffix(dep, "/symlink1") || strings.HasSuffix(dep, "/symlink2") { + symlinkFound = true + } + } + if !toolFound { + t.Errorf("Tool not found") + } + // We may want to change genrules to include symlinks later + if symlinkFound { + t.Errorf("Symlinks found") + } +} diff --git a/cc/library.go b/cc/library.go index 8a2b6bdbd..5299771ca 100644 --- a/cc/library.go +++ b/cc/library.go @@ -606,10 +606,22 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa panic(err) } + llndkFlag := "--llndk" + if ctx.baseModuleName() == "libbinder_ndk" && ctx.inProduct() { + // This is a special case only for the libbinder_ndk. As the product partition is in the + // framework side along with system and system_ext partitions in Treble, libbinder_ndk + // provides different binder interfaces between product and vendor modules. + // In libbinder_ndk, 'llndk' annotation is for the vendor APIs; while 'systemapi' + // annotation is for the product APIs. + // Use '--systemapi' flag for building the llndk stub of product variant for the + // libbinder_ndk. + llndkFlag = "--systemapi" + } + // This is the vendor variant of an LLNDK library, build the LLNDK stubs. nativeAbiResult := ParseNativeAbiDefinition(ctx, String(library.Properties.Llndk.Symbol_file), - nativeClampedApiLevel(ctx, version), "--llndk") + nativeClampedApiLevel(ctx, version), llndkFlag) objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, sharedFlags) if !Bool(library.Properties.Llndk.Unversioned) { library.versionScriptPath = android.OptionalPathForPath( @@ -1066,6 +1078,10 @@ func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSO library.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON) } +func (library *libraryDecorator) testSuiteInfo(ctx ModuleContext) { + // not a test +} + func (library *libraryDecorator) linkStatic(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { diff --git a/cc/llndk_library.go b/cc/llndk_library.go index 8ca3ca184..b119fdac1 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -82,11 +82,10 @@ type movedToApexLlndkLibraries struct { func (s *movedToApexLlndkLibraries) GenerateBuildActions(ctx android.SingletonContext) { // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to generate the linker config. movedToApexLlndkLibrariesMap := make(map[string]bool) - ctx.VisitAllModules(func(module android.Module) { - if library := moduleVersionedInterface(module); library != nil && library.HasLLNDKStubs() { - if library.IsLLNDKMovedToApex() { - name := library.ImplementationModuleName(module.(*Module).BaseModuleName()) - movedToApexLlndkLibrariesMap[name] = true + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if library, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider); ok { + if library.HasLLNDKStubs && library.IsLLNDKMovedToApex { + movedToApexLlndkLibrariesMap[library.ImplementationModuleName] = true } } }) @@ -151,14 +150,16 @@ func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.Modu etc.SetCommonPrebuiltEtcInfo(ctx, txt) } -func getVndkFileName(m *Module) (string, error) { - if library, ok := m.linker.(*libraryDecorator); ok { - return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil - } - if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok { - return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil +func getVndkFileName(info *LinkerInfo) (string, error) { + if info != nil { + if info.LibraryDecoratorInfo != nil { + return info.LibraryDecoratorInfo.VndkFileName, nil + } + if info.PrebuiltLibraryLinkerInfo != nil { + return info.PrebuiltLibraryLinkerInfo.VndkFileName, nil + } } - return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker) + return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", info) } func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { @@ -167,9 +168,17 @@ func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.Si return } - ctx.VisitAllModules(func(m android.Module) { - if c, ok := m.(*Module); ok && c.VendorProperties.IsLLNDK && !c.Header() && !c.IsVndkPrebuiltLibrary() { - filename, err := getVndkFileName(c) + ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { + ccInfo, ok := android.OtherModuleProvider(ctx, m, CcInfoProvider) + if !ok { + return + } + linkableInfo, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider) + if !ok { + return + } + if linkableInfo.IsLlndk && !linkableInfo.Header && !linkableInfo.IsVndkPrebuiltLibrary { + filename, err := getVndkFileName(ccInfo.LinkerInfo) if err != nil { ctx.ModuleErrorf(m, "%s", err) } diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go index a9f26a40e..b96a779cb 100644 --- a/cc/ndk_abi.go +++ b/cc/ndk_abi.go @@ -40,7 +40,7 @@ type ndkAbiDumpSingleton struct{} func (n *ndkAbiDumpSingleton) GenerateBuildActions(ctx android.SingletonContext) { var depPaths android.Paths ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } @@ -78,7 +78,7 @@ type ndkAbiDiffSingleton struct{} func (n *ndkAbiDiffSingleton) GenerateBuildActions(ctx android.SingletonContext) { var depPaths android.Paths ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index 34f6195a5..16778627f 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -212,7 +212,7 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { var licensePaths android.Paths ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } diff --git a/cc/object.go b/cc/object.go index 95a8beb52..ea3ed6151 100644 --- a/cc/object.go +++ b/cc/object.go @@ -250,3 +250,7 @@ func (object *objectLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *an object.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON) moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"} } + +func (object *objectLinker) testSuiteInfo(ctx ModuleContext) { + // not a test +} diff --git a/cc/sanitize.go b/cc/sanitize.go index db99a5327..f0b0308ae 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -79,7 +79,7 @@ var ( minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined", "-fno-sanitize-recover=integer,undefined"} - memtagStackCommonFlags = []string{"-march=armv8-a+memtag"} + memtagStackCommonFlags = []string{"-Xclang -target-feature -Xclang +mte"} memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"} hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"} @@ -1422,6 +1422,7 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { sanitizers = append(sanitizers, "bool", "integer-divide-by-zero", + "object-size", "return", "returns-nonnull-attribute", "shift-exponent", @@ -1438,10 +1439,6 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { //"shift-base", //"signed-integer-overflow", ) - - if mctx.Config().ReleaseBuildObjectSizeSanitizer() { - sanitizers = append(sanitizers, "object-size") - } } sanitizers = append(sanitizers, sanProps.Misc_undefined...) } diff --git a/cc/strip.go b/cc/strip.go index a950df898..42c9137b7 100644 --- a/cc/strip.go +++ b/cc/strip.go @@ -23,8 +23,9 @@ import ( // StripProperties defines the type of stripping applied to the module. type StripProperties struct { Strip struct { - // Device and host modules default to stripping enabled leaving mini debuginfo. - // This can be disabled by setting none to true. + // Device modules default to stripping enabled leaving mini debuginfo. + // Host modules default to stripping disabled, but can be enabled by setting any other + // strip boolean property. None *bool `android:"arch_variant"` // all forces stripping everything, including the mini debug info. @@ -50,7 +51,12 @@ type Stripper struct { // NeedsStrip determines if stripping is required for a module. func (stripper *Stripper) NeedsStrip(actx android.ModuleContext) bool { forceDisable := Bool(stripper.StripProperties.Strip.None) - return !forceDisable + // Strip is enabled by default for device variants. + defaultEnable := actx.Device() || actx.Config().StripByDefault() + forceEnable := Bool(stripper.StripProperties.Strip.All) || + Bool(stripper.StripProperties.Strip.Keep_symbols) || + Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame) + return !forceDisable && (forceEnable || defaultEnable) } func (stripper *Stripper) strip(actx android.ModuleContext, in android.Path, out android.ModuleOutPath, diff --git a/cc/test.go b/cc/test.go index d2c4b28e8..9c276b81a 100644 --- a/cc/test.go +++ b/cc/test.go @@ -274,6 +274,12 @@ func (test *testDecorator) moduleInfoJSON(ctx android.ModuleContext, moduleInfoJ } } +func (test *testDecorator) testSuiteInfo(ctx ModuleContext) { + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: test.InstallerProperties.Test_suites, + }) +} + func NewTestInstaller() *baseInstaller { return NewBaseInstaller("nativetest", "nativetest64", InstallInData) } @@ -342,6 +348,10 @@ func (test *testBinary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *androi } +func (test *testBinary) testSuiteInfo(ctx ModuleContext) { + test.testDecorator.testSuiteInfo(ctx) +} + func (test *testBinary) installerProps() []interface{} { return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...) } @@ -455,6 +465,9 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { if standaloneTestDep.SkipInstall() { continue } + if standaloneTestDep.Partition() == "data" { + continue + } test.binaryDecorator.baseInstaller.installStandaloneTestDep(ctx, standaloneTestDep) } } @@ -575,6 +588,10 @@ func (test *testLibrary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *andro test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON) } +func (test *testLibrary) testSuiteInfo(ctx ModuleContext) { + test.testDecorator.testSuiteInfo(ctx) +} + func (test *testLibrary) installerProps() []interface{} { return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...) } @@ -692,6 +709,12 @@ func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInf } } +func (benchmark *benchmarkDecorator) testSuiteInfo(ctx ModuleContext) { + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: benchmark.Properties.Test_suites, + }) +} + func NewBenchmark(hod android.HostOrDeviceSupported) *Module { module, binary := newBinary(hod) module.multilib = android.MultilibBoth diff --git a/cc/tidy.go b/cc/tidy.go index 8e7f899a2..bf273e986 100644 --- a/cc/tidy.go +++ b/cc/tidy.go @@ -220,7 +220,7 @@ func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Mo // (1) Collect all obj/tidy files into OS-specific groups. ctx.VisitAllModuleVariantProxies(module, func(variant android.ModuleProxy) { - osName := android.OtherModuleProviderOrDefault(ctx, variant, android.CommonModuleInfoKey).Target.Os.Name + osName := android.OtherModulePointerProviderOrDefault(ctx, variant, android.CommonModuleInfoProvider).Target.Os.Name info := android.OtherModuleProviderOrDefault(ctx, variant, CcObjectInfoProvider) addToOSGroup(osName, info.ObjFiles, allObjFileGroups, subsetObjFileGroups) addToOSGroup(osName, info.TidyFiles, allTidyFileGroups, subsetTidyFileGroups) diff --git a/ci_tests/ci_test_package_zip.go b/ci_tests/ci_test_package_zip.go index 0db3f9f67..95249aa10 100644 --- a/ci_tests/ci_test_package_zip.go +++ b/ci_tests/ci_test_package_zip.go @@ -20,6 +20,7 @@ import ( "strings" "android/soong/android" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -139,6 +140,9 @@ func TestPackageZipFactory() android.Module { } func (p *testPackageZip) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Never install this test package, it's for disting only + p.SkipInstall() + if !android.InList(ctx.ModuleName(), moduleNamesAllowed) { ctx.ModuleErrorf("%s is not allowed to use module type test_package") } @@ -149,7 +153,7 @@ func (p *testPackageZip) GenerateAndroidBuildActions(ctx android.ModuleContext) // dist the test output if ctx.ModuleName() == "platform_tests" { - distedName := ctx.Config().Getenv("TARGET_PRODUCT") + "-tests-" + ctx.Config().BuildId() + ".zip" + distedName := ctx.Config().Getenv("TARGET_PRODUCT") + "-tests-FILE_NAME_TAG_PLACEHOLDER.zip" ctx.DistForGoalWithFilename("platform_tests", p.output, distedName) } } @@ -166,6 +170,9 @@ func createOutput(ctx android.ModuleContext, pctx android.PackageContext) androi builder.Command().Text("mkdir").Flag("-p").Output(stagingDir) builder.Temporary(stagingDir) ctx.WalkDeps(func(child, parent android.Module) bool { + if !child.Enabled(ctx) { + return false + } if android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == testPackageZipDepTag { // handle direct deps extendBuilderCommand(ctx, child, builder, stagingDir, productOut, arch, secondArch) @@ -214,7 +221,13 @@ func extendBuilderCommand(ctx android.ModuleContext, m android.Module, builder * ctx.ModuleErrorf("Module %s doesn't set InstallFilesProvider", m.Name()) } - for _, installedFile := range installedFilesInfo.InstallFiles { + for _, spec := range installedFilesInfo.PackagingSpecs { + if spec.SrcPath() == nil { + // Probably a symlink + continue + } + installedFile := spec.FullInstallPath() + ext := installedFile.Ext() // there are additional installed files for some app-class modules, we only need the .apk, .odex and .vdex files in the test package excludeInstalledFile := ext != ".apk" && ext != ".odex" && ext != ".vdex" @@ -236,23 +249,26 @@ func extendBuilderCommand(ctx android.ModuleContext, m android.Module, builder * if strings.HasPrefix(f, "out") { continue } - f = strings.ReplaceAll(f, "system/", "DATA/") + if strings.HasPrefix(f, "system/") { + f = strings.Replace(f, "system/", "DATA/", 1) + } f = strings.ReplaceAll(f, filepath.Join("testcases", name, arch), filepath.Join("DATA", class, name)) f = strings.ReplaceAll(f, filepath.Join("testcases", name, secondArch), filepath.Join("DATA", class, name)) - f = strings.ReplaceAll(f, "testcases", filepath.Join("DATA", class)) - f = strings.ReplaceAll(f, "data/", "DATA/") + if strings.HasPrefix(f, "testcases") { + f = strings.Replace(f, "testcases", filepath.Join("DATA", class), 1) + } + if strings.HasPrefix(f, "data/") { + f = strings.Replace(f, "data/", "DATA/", 1) + } f = strings.ReplaceAll(f, "DATA_other", "system_other") f = strings.ReplaceAll(f, "system_other/DATA", "system_other/system") dir := filepath.Dir(f) - // ignore the additional installed files from test - if strings.Contains(dir, "DATA/native_tests") || strings.Count(dir, "DATA") > 1 { - continue - } - tempOut := android.PathForModuleOut(ctx, "STAGING", f) builder.Command().Text("mkdir").Flag("-p").Text(filepath.Join(stagingDir.String(), dir)) - builder.Command().Text("cp").Flag("-Rf").Input(installedFile).Output(tempOut) + // Copy srcPath instead of installedFile because some rules like target-files.zip + // are non-hermetic and would be affected if we built the installed files. + builder.Command().Text("cp").Flag("-Rf").Input(spec.SrcPath()).Output(tempOut) builder.Temporary(tempOut) } } diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go index c89facf05..2c5718063 100644 --- a/cmd/merge_zips/merge_zips.go +++ b/cmd/merge_zips/merge_zips.go @@ -212,8 +212,6 @@ func (oz *OutputZip) addZipEntryFromFile(name string, path string) error { Name: name, Method: zip.Store, UncompressedSize64: uint64(len(buf)), - CompressedSize64: uint64(len(buf)), - CRC32: crc32.ChecksumIEEE(buf), } fh.SetMode(0700) fh.SetModTime(jar.DefaultTime) @@ -227,9 +225,7 @@ func (oz *OutputZip) addEmptyEntry(entry string) error { fh := &zip.FileHeader{ Name: entry, Method: zip.Store, - UncompressedSize64: 0, - CompressedSize64: 0, - CRC32: crc32.ChecksumIEEE(emptyBuf), + UncompressedSize64: uint64(len(emptyBuf)), } fh.SetMode(0700) fh.SetModTime(jar.DefaultTime) diff --git a/cmd/merge_zips/merge_zips_test.go b/cmd/merge_zips/merge_zips_test.go index b7491cf4c..17228c4e0 100644 --- a/cmd/merge_zips/merge_zips_test.go +++ b/cmd/merge_zips/merge_zips_test.go @@ -19,7 +19,6 @@ import ( "fmt" "hash/crc32" "os" - "path/filepath" "strconv" "strings" "testing" @@ -35,35 +34,33 @@ type testZipEntry struct { data []byte method uint16 timestamp time.Time - extra []byte } var ( - A = testZipEntry{"A", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime, nil} - a = testZipEntry{"a", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime, nil} - a2 = testZipEntry{"a", 0755, []byte("FOO2"), zip.Deflate, jar.DefaultTime, nil} - a3 = testZipEntry{"a", 0755, []byte("Foo3"), zip.Deflate, jar.DefaultTime, nil} - bDir = testZipEntry{"b/", os.ModeDir | 0755, nil, zip.Deflate, jar.DefaultTime, nil} - bbDir = testZipEntry{"b/b/", os.ModeDir | 0755, nil, zip.Deflate, jar.DefaultTime, nil} - bbb = testZipEntry{"b/b/b", 0755, nil, zip.Deflate, jar.DefaultTime, nil} - ba = testZipEntry{"b/a", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime, nil} - bc = testZipEntry{"b/c", 0755, []byte("bar"), zip.Deflate, jar.DefaultTime, nil} - bd = testZipEntry{"b/d", 0700, []byte("baz"), zip.Deflate, jar.DefaultTime, nil} - be = testZipEntry{"b/e", 0700, []byte(""), zip.Deflate, jar.DefaultTime, nil} - - withTimestamp = testZipEntry{"timestamped", 0755, nil, zip.Store, jar.DefaultTime.Add(time.Hour), nil} - withoutTimestamp = testZipEntry{"timestamped", 0755, nil, zip.Store, jar.DefaultTime, nil} - - service1a = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\n"), zip.Store, jar.DefaultTime, nil} - service1b = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass3\n"), zip.Deflate, jar.DefaultTime, nil} - service1combined = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\nclass3\n"), zip.Store, jar.DefaultTime, nil} - service2 = testZipEntry{"META-INF/services/service2", 0755, []byte("class1\nclass2\n"), zip.Deflate, jar.DefaultTime, nil} - - metainfDir = testZipEntry{jar.MetaDir, os.ModeDir | 0755, nil, zip.Store, jar.DefaultTime, []byte{0xfe, 0xca, 0, 0}} - manifestFile = testZipEntry{jar.ManifestFile, 0644, []byte("Manifest-Version: 1.0\nmanifest"), zip.Store, jar.DefaultTime, nil} - manifestFile2 = testZipEntry{jar.ManifestFile, 0644, []byte("manifest2"), zip.Deflate, jar.DefaultTime, nil} - - pyMainFile = testZipEntry{"__main__.py", 0700, []byte("pyMain"), zip.Store, jar.DefaultTime, nil} + A = testZipEntry{"A", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime} + a = testZipEntry{"a", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime} + a2 = testZipEntry{"a", 0755, []byte("FOO2"), zip.Deflate, jar.DefaultTime} + a3 = testZipEntry{"a", 0755, []byte("Foo3"), zip.Deflate, jar.DefaultTime} + bDir = testZipEntry{"b/", os.ModeDir | 0755, nil, zip.Deflate, jar.DefaultTime} + bbDir = testZipEntry{"b/b/", os.ModeDir | 0755, nil, zip.Deflate, jar.DefaultTime} + bbb = testZipEntry{"b/b/b", 0755, nil, zip.Deflate, jar.DefaultTime} + ba = testZipEntry{"b/a", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime} + bc = testZipEntry{"b/c", 0755, []byte("bar"), zip.Deflate, jar.DefaultTime} + bd = testZipEntry{"b/d", 0700, []byte("baz"), zip.Deflate, jar.DefaultTime} + be = testZipEntry{"b/e", 0700, []byte(""), zip.Deflate, jar.DefaultTime} + + withTimestamp = testZipEntry{"timestamped", 0755, nil, zip.Store, jar.DefaultTime.Add(time.Hour)} + withoutTimestamp = testZipEntry{"timestamped", 0755, nil, zip.Store, jar.DefaultTime} + + service1a = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\n"), zip.Store, jar.DefaultTime} + service1b = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass3\n"), zip.Deflate, jar.DefaultTime} + service1combined = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\nclass3\n"), zip.Store, jar.DefaultTime} + service2 = testZipEntry{"META-INF/services/service2", 0755, []byte("class1\nclass2\n"), zip.Deflate, jar.DefaultTime} + + metainfDir = testZipEntry{jar.MetaDir, os.ModeDir | 0755, nil, zip.Deflate, jar.DefaultTime} + manifestFile = testZipEntry{jar.ManifestFile, 0755, []byte("manifest"), zip.Deflate, jar.DefaultTime} + manifestFile2 = testZipEntry{jar.ManifestFile, 0755, []byte("manifest2"), zip.Deflate, jar.DefaultTime} + moduleInfoFile = testZipEntry{jar.ModuleInfoClass, 0755, []byte("module-info"), zip.Deflate, jar.DefaultTime} ) type testInputZip struct { @@ -111,8 +108,6 @@ func TestMergeZips(t *testing.T) { ignoreDuplicates bool stripDirEntries bool zipsToNotStrip map[string]bool - manifest string - pyMain string out []testZipEntry err string @@ -299,16 +294,6 @@ func TestMergeZips(t *testing.T) { }, par: true, }, - { - name: "manifest", - manifest: "Manifest-Version: 1.0\nmanifest", - out: []testZipEntry{metainfDir, manifestFile}, - }, - { - name: "pyMain", - pyMain: "pyMain", - out: []testZipEntry{pyMainFile}, - }, } for _, test := range testCases { @@ -323,25 +308,7 @@ func TestMergeZips(t *testing.T) { out := &bytes.Buffer{} writer := zip.NewWriter(out) - manifestFile := "" - if test.manifest != "" { - manifestFile = filepath.Join(t.TempDir(), "manifest.txt") - err := os.WriteFile(manifestFile, []byte(test.manifest), 0666) - if err != nil { - t.Fatal(err) - } - } - - pyMainFile := "" - if test.pyMain != "" { - pyMainFile = filepath.Join(t.TempDir(), "pymain.txt") - err := os.WriteFile(pyMainFile, []byte(test.pyMain), 0666) - if err != nil { - t.Fatal(err) - } - } - - err := mergeZips(inputZips, writer, manifestFile, pyMainFile, + err := mergeZips(inputZips, writer, "", "", test.sort, test.jar, test.par, test.stripDirEntries, test.ignoreDuplicates, test.stripFiles, test.stripDirs, test.zipsToNotStrip) @@ -385,7 +352,6 @@ func testZipEntriesToBuf(entries []testZipEntry) []byte { fh.SetModTime(e.timestamp) fh.UncompressedSize64 = uint64(len(e.data)) fh.CRC32 = crc32.ChecksumIEEE(e.data) - fh.Extra = e.extra if fh.Method == zip.Store { fh.CompressedSize64 = fh.UncompressedSize64 } @@ -431,35 +397,35 @@ func dumpZip(buf []byte) string { var ret string for _, f := range zr.File { - ret += fmt.Sprintf("%v: %v %v %v %08x %s\n", f.Name, f.Mode(), f.UncompressedSize64, f.CompressedSize64, f.CRC32, f.ModTime()) + ret += fmt.Sprintf("%v: %v %v %08x %s\n", f.Name, f.Mode(), f.UncompressedSize64, f.CRC32, f.ModTime()) } return ret } -type DummyInputZip struct { +type DummyInpuZip struct { isOpen bool } -func (diz *DummyInputZip) Name() string { +func (diz *DummyInpuZip) Name() string { return "dummy" } -func (diz *DummyInputZip) Open() error { +func (diz *DummyInpuZip) Open() error { diz.isOpen = true return nil } -func (diz *DummyInputZip) Close() error { +func (diz *DummyInpuZip) Close() error { diz.isOpen = false return nil } -func (DummyInputZip) Entries() []*zip.File { +func (DummyInpuZip) Entries() []*zip.File { panic("implement me") } -func (diz *DummyInputZip) IsOpen() bool { +func (diz *DummyInpuZip) IsOpen() bool { return diz.isOpen } @@ -469,7 +435,7 @@ func TestInputZipsManager(t *testing.T) { izm := NewInputZipsManager(20, 10) managedZips := make([]InputZip, nInputZips) for i := 0; i < nInputZips; i++ { - managedZips[i] = izm.Manage(&DummyInputZip{}) + managedZips[i] = izm.Manage(&DummyInpuZip{}) } t.Run("InputZipsManager", func(t *testing.T) { diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp index ea3f52bd2..dbc192238 100644 --- a/dexpreopt/Android.bp +++ b/dexpreopt/Android.bp @@ -9,6 +9,7 @@ bootstrap_go_package { "class_loader_context.go", "config.go", "dexpreopt.go", + "dexpreopt_tools_zip.go", "system_server_zip.go", "testing.go", ], diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go index af1d33da6..7f50912b5 100644 --- a/dexpreopt/class_loader_context.go +++ b/dexpreopt/class_loader_context.go @@ -291,6 +291,11 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont // For prebuilts, library should have the same name as the source module. lib = android.RemoveOptionalPrebuiltPrefix(lib) + // Bootclasspath libraries should not be added to CLC. + if android.InList(lib, ctx.Config().BootJars()) { + return nil + } + devicePath := UnknownInstallLibraryPath if installPath == nil { if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) { diff --git a/dexpreopt/config.go b/dexpreopt/config.go index f3c2b2cbc..e57384fd7 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -464,8 +464,8 @@ func (d dex2oatDependencyTag) AllowDisabledModuleDependency(target android.Modul func (d dex2oatDependencyTag) AllowDisabledModuleDependencyProxy( ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool { - return android.OtherModuleProviderOrDefault( - ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt + return android.OtherModulePointerProviderOrDefault( + ctx, target, android.CommonModuleInfoProvider).ReplacedByPrebuilt } // Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that diff --git a/dexpreopt/dexpreopt_tools_zip.go b/dexpreopt/dexpreopt_tools_zip.go new file mode 100644 index 000000000..c7cf12830 --- /dev/null +++ b/dexpreopt/dexpreopt_tools_zip.go @@ -0,0 +1,62 @@ +package dexpreopt + +import "android/soong/android" + +func init() { + android.InitRegistrationContext.RegisterSingletonType("dexpreopt_tools_zip_singleton", dexpreoptToolsZipSingletonFactory) +} + +func dexpreoptToolsZipSingletonFactory() android.Singleton { + return &dexpreoptToolsZipSingleton{} +} + +type dexpreoptToolsZipSingleton struct{} + +func (s *dexpreoptToolsZipSingleton) GenerateBuildActions(ctx android.SingletonContext) { + // The mac build doesn't build dex2oat, so create the zip file only if the build OS is linux. + if !ctx.Config().BuildOS.Linux() { + return + } + global := GetGlobalConfig(ctx) + if global.DisablePreopt { + return + } + config := GetCachedGlobalSoongConfig(ctx) + if config == nil { + return + } + + deps := android.Paths{ + ctx.Config().HostToolPath(ctx, "dexpreopt_gen"), + ctx.Config().HostToolPath(ctx, "dexdump"), + ctx.Config().HostToolPath(ctx, "oatdump"), + config.Profman, + config.Dex2oat, + config.Aapt, + config.SoongZip, + config.Zip2zip, + config.ManifestCheck, + config.ConstructContext, + config.UffdGcFlag, + } + + out := android.PathForOutput(ctx, "dexpreopt_tools.zip") + builder := android.NewRuleBuilder(pctx, ctx) + + cmd := builder.Command().BuiltTool("soong_zip"). + Flag("-d"). + FlagWithOutput("-o ", out). + Flag("-j") + + for _, dep := range deps { + cmd.FlagWithInput("-f ", dep) + } + + // This reads through a symlink to include the file it points to. This isn't great for + // build reproducibility, will need to be revisited later. + cmd.Textf("-f $(realpath %s)", config.Dex2oat) + + builder.Build("dexpreopt_tools_zip", "building dexpreopt_tools.zip") + + ctx.DistForGoal("droidcore", out) +} diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index fad8f0779..3b0c0329d 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -65,6 +65,7 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory) ctx.RegisterModuleType("prebuilt_overlay", PrebuiltOverlayFactory) ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory) + ctx.RegisterModuleType("prebuilt_gpu", PrebuiltGPUFactory) ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory) ctx.RegisterModuleType("prebuilt_rfsa", PrebuiltRFSAFactory) ctx.RegisterModuleType("prebuilt_renderscript_bitcode", PrebuiltRenderScriptBitcodeFactory) @@ -73,12 +74,14 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_bin", PrebuiltBinaryFactory) ctx.RegisterModuleType("prebuilt_wallpaper", PrebuiltWallpaperFactory) ctx.RegisterModuleType("prebuilt_priv_app", PrebuiltPrivAppFactory) + ctx.RegisterModuleType("prebuilt_radio", PrebuiltRadioFactory) ctx.RegisterModuleType("prebuilt_rfs", PrebuiltRfsFactory) ctx.RegisterModuleType("prebuilt_framework", PrebuiltFrameworkFactory) ctx.RegisterModuleType("prebuilt_res", PrebuiltResFactory) ctx.RegisterModuleType("prebuilt_wlc_upt", PrebuiltWlcUptFactory) ctx.RegisterModuleType("prebuilt_odm", PrebuiltOdmFactory) ctx.RegisterModuleType("prebuilt_vendor_dlkm", PrebuiltVendorDlkmFactory) + ctx.RegisterModuleType("prebuilt_vendor_overlay", PrebuiltVendorOverlayFactory) ctx.RegisterModuleType("prebuilt_bt_firmware", PrebuiltBtFirmwareFactory) ctx.RegisterModuleType("prebuilt_tvservice", PrebuiltTvServiceFactory) ctx.RegisterModuleType("prebuilt_optee", PrebuiltOpteeFactory) @@ -87,6 +90,7 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_sbin", PrebuiltSbinFactory) ctx.RegisterModuleType("prebuilt_system", PrebuiltSystemFactory) ctx.RegisterModuleType("prebuilt_first_stage_ramdisk", PrebuiltFirstStageRamdiskFactory) + ctx.RegisterModuleType("prebuilt_any", PrebuiltAnyFactory) ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory) @@ -113,12 +117,6 @@ type PrebuiltEtcProperties struct { // set. May use globs in filenames. Srcs proptools.Configurable[[]string] `android:"path,arch_variant"` - // Destination files of this prebuilt. Requires srcs to be used and causes srcs not to implicitly - // set filename_from_src. This can be used to install each source file to a different directory - // and/or change filenames when files are installed. Must be exactly one entry per source file, - // which means care must be taken if srcs has globs. - Dsts proptools.Configurable[[]string] `android:"path,arch_variant"` - // Optional name for the installed file. If unspecified, name of the module is used as the file // name. Only available when using a single source (src). Filename *string `android:"arch_variant"` @@ -157,6 +155,20 @@ type PrebuiltEtcProperties struct { Oem_specific *bool `android:"arch_variant"` } +// Dsts is useful in that it allows prebuilt_* modules to easily map the source files to the +// install path within the partition. Dsts values are allowed to contain filepath separator +// so that the source files can be installed in subdirectories within the partition. +// However, this functionality should not be supported for prebuilt_root module type, as it +// allows the module to install to any arbitrary location. Thus, this property is defined in +// a separate struct so that it's not available to be set in prebuilt_root module type. +type PrebuiltDstsProperties struct { + // Destination files of this prebuilt. Requires srcs to be used and causes srcs not to implicitly + // set filename_from_src. This can be used to install each source file to a different directory + // and/or change filenames when files are installed. Must be exactly one entry per source file, + // which means care must be taken if srcs has globs. + Dsts proptools.Configurable[[]string] `android:"path,arch_variant"` +} + type prebuiltSubdirProperties struct { // Optional subdirectory under which this file is installed into, cannot be specified with // relative_install_path, prefer relative_install_path. @@ -192,6 +204,8 @@ type PrebuiltEtc struct { properties PrebuiltEtcProperties + dstsProperties PrebuiltDstsProperties + // rootProperties is used to return the value of the InstallInRoot() method. Currently, only // prebuilt_avb and prebuilt_root modules use this. rootProperties prebuiltRootProperties @@ -382,7 +396,7 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { if srcProperty.IsPresent() && len(srcsProperty) > 0 { ctx.PropertyErrorf("src", "src is set. Cannot set srcs") } - dstsProperty := p.properties.Dsts.GetOrDefault(ctx, nil) + dstsProperty := p.dstsProperties.Dsts.GetOrDefault(ctx, nil) if len(dstsProperty) > 0 && len(srcsProperty) == 0 { ctx.PropertyErrorf("dsts", "dsts is set. Must use srcs") } @@ -610,6 +624,7 @@ func InitPrebuiltEtcModule(p *PrebuiltEtc, dirBase string) { p.AddProperties(&p.properties) p.AddProperties(&p.subdirProperties) p.AddProperties(&p.rootProperties) + p.AddProperties(&p.dstsProperties) } func InitPrebuiltRootModule(p *PrebuiltEtc) { @@ -621,6 +636,7 @@ func InitPrebuiltRootModule(p *PrebuiltEtc) { func InitPrebuiltAvbModule(p *PrebuiltEtc) { p.installDirBase = "avb" p.AddProperties(&p.properties) + p.AddProperties(&p.dstsProperties) p.rootProperties.Install_in_root = proptools.BoolPtr(true) } @@ -664,6 +680,20 @@ func PrebuiltEtcHostFactory() android.Module { return module } +// prebuilt_any is a special module where the module can define the subdirectory that the files +// are installed to. This is only used for converting the PRODUCT_COPY_FILES entries to Soong +// modules, and should never be defined in the bp files. If none of the existing prebuilt_* +// modules allow installing the file at the desired location, introduce a new prebuilt_* module +// type instead. +func PrebuiltAnyFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, ".") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + // prebuilt_etc_host is for a host prebuilt artifact that is installed in // <partition>/etc/<sub_dir> directory. func PrebuiltEtcCaCertsFactory() android.Module { @@ -831,6 +861,15 @@ func PrebuiltFirmwareFactory() android.Module { return module } +// prebuilt_gpu is for a prebuilt artifact in <partition>/gpu directory. +func PrebuiltGPUFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "gpu") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + return module +} + // prebuilt_dsp installs a DSP related file to <partition>/etc/dsp directory for system image. // If soc_specific property is set to true, the DSP related file is installed to the // vendor <partition>/dsp directory for vendor image. @@ -921,6 +960,16 @@ func PrebuiltPrivAppFactory() android.Module { return module } +// prebuilt_radio installs files in <partition>/radio directory. +func PrebuiltRadioFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "radio") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + // prebuilt_rfs installs files in <partition>/rfs directory. func PrebuiltRfsFactory() android.Module { module := &PrebuiltEtc{} @@ -1031,6 +1080,16 @@ func PrebuiltVendorFactory() android.Module { return module } +// prebuilt_vendor_overlay is for a prebuilt artifact in <partition>/vendor_overlay directory. +func PrebuiltVendorOverlayFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "vendor_overlay") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + // prebuilt_sbin installs files in <partition>/sbin directory. func PrebuiltSbinFactory() android.Module { module := &PrebuiltEtc{} diff --git a/filesystem/android_device.go b/filesystem/android_device.go index 005dc3439..3f6348dbf 100644 --- a/filesystem/android_device.go +++ b/filesystem/android_device.go @@ -19,6 +19,7 @@ import ( "fmt" "path/filepath" "slices" + "sort" "strings" "sync/atomic" @@ -106,11 +107,15 @@ type androidDevice struct { allImagesZip android.Path - proguardDictZip android.Path - proguardDictMapping android.Path - proguardUsageZip android.Path - kernelConfig android.Path - kernelVersion android.Path + proguardDictZip android.Path + proguardDictMapping android.Path + proguardUsageZip android.Path + kernelConfig android.Path + kernelVersion android.Path + miscInfo android.Path + rootDirForFsConfig string + rootDirForFsConfigTimestamp android.Path + apkCertsInfo android.Path } func AndroidDeviceFactory() android.Module { @@ -185,7 +190,9 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) { allInstalledModules := a.allInstalledModules(ctx) - a.kernelConfig, a.kernelVersion = a.extractKernelVersionAndConfigs(ctx) + a.apkCertsInfo = a.buildApkCertsInfo(ctx, allInstalledModules) + a.kernelVersion, a.kernelConfig = a.extractKernelVersionAndConfigs(ctx) + a.miscInfo = a.addMiscInfo(ctx) a.buildTargetFilesZip(ctx, allInstalledModules) a.buildProguardZips(ctx, allInstalledModules) @@ -274,6 +281,39 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.setVbmetaPhonyTargets(ctx) a.distFiles(ctx) + + android.SetProvider(ctx, android.AndroidDeviceInfoProvider, android.AndroidDeviceInfo{ + Main_device: android.Bool(a.deviceProps.Main_device), + }) + + if proptools.String(a.partitionProps.Super_partition_name) != "" { + buildComplianceMetadata(ctx, superPartitionDepTag, filesystemDepTag) + } else { + buildComplianceMetadata(ctx, filesystemDepTag) + } +} + +func buildComplianceMetadata(ctx android.ModuleContext, tags ...blueprint.DependencyTag) { + // Collect metadata from deps + filesContained := make([]string, 0) + prebuiltFilesCopied := make([]string, 0) + for _, tag := range tags { + ctx.VisitDirectDepsProxyWithTag(tag, func(m android.ModuleProxy) { + if complianceMetadataInfo, ok := android.OtherModuleProvider(ctx, m, android.ComplianceMetadataProvider); ok { + filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...) + prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...) + } + }) + } + // Merge to module's ComplianceMetadataInfo + complianceMetadataInfo := ctx.ComplianceMetadataInfo() + filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...) + sort.Strings(filesContained) + complianceMetadataInfo.SetFilesContained(filesContained) + + prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...) + sort.Strings(prebuiltFilesCopied) + complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied) } // Returns a list of modules that are installed, which are collected from the dependency @@ -313,18 +353,32 @@ func insertBeforeExtension(file, insertion string) string { return strings.TrimSuffix(file, ext) + insertion + ext } +func (a *androidDevice) distInstalledFiles(ctx android.ModuleContext) { + distInstalledFilesJsonAndTxt := func(installedFiles InstalledFilesStruct) { + if installedFiles.Json != nil { + ctx.DistForGoal("droidcore-unbundled", installedFiles.Json) + } + if installedFiles.Txt != nil { + ctx.DistForGoal("droidcore-unbundled", installedFiles.Txt) + } + } + + fsInfoMap := a.getFsInfos(ctx) + for _, partition := range android.SortedKeys(fsInfoMap) { + // installed-files-*{.txt | .json} is not disted for userdata partition + if partition == "userdata" { + continue + } + fsInfo := fsInfoMap[partition] + for _, installedFiles := range fsInfo.InstalledFilesDepSet.ToList() { + distInstalledFilesJsonAndTxt(installedFiles) + } + } +} + func (a *androidDevice) distFiles(ctx android.ModuleContext) { if !ctx.Config().KatiEnabled() && proptools.Bool(a.deviceProps.Main_device) { - fsInfoMap := a.getFsInfos(ctx) - for _, partition := range android.SortedKeys(fsInfoMap) { - fsInfo := fsInfoMap[partition] - if fsInfo.InstalledFiles.Json != nil { - ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Json) - } - if fsInfo.InstalledFiles.Txt != nil { - ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Txt) - } - } + a.distInstalledFiles(ctx) namePrefix := "" if ctx.Config().HasDeviceProduct() { @@ -333,6 +387,10 @@ func (a *androidDevice) distFiles(ctx android.ModuleContext) { ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictZip, namePrefix+insertBeforeExtension(a.proguardDictZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictMapping, namePrefix+insertBeforeExtension(a.proguardDictMapping.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardUsageZip, namePrefix+insertBeforeExtension(a.proguardUsageZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) + + if a.deviceProps.Android_info != nil { + ctx.DistForGoal("droidcore-unbundled", android.PathForModuleSrc(ctx, *a.deviceProps.Android_info)) + } } } @@ -470,6 +528,17 @@ func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstal if toCopy.destSubdir == "SYSTEM" { // Create the ROOT partition in target_files.zip builder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s/ROOT", toCopy.fsInfo.RootDir, targetFilesDir.String()) + // Add a duplicate rule to assemble the ROOT/ directory in separate intermediates. + // The output timestamp will be an input to a separate fs_config call. + a.rootDirForFsConfig = android.PathForModuleOut(ctx, "root_dir_for_fs_config").String() + rootDirBuilder := android.NewRuleBuilder(pctx, ctx) + rootDirForFsConfigTimestamp := android.PathForModuleOut(ctx, "root_dir_for_fs_config.timestamp") + rootDirBuilder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s", toCopy.fsInfo.RootDir, a.rootDirForFsConfig). + Implicit(toCopy.fsInfo.Output). + Text("&& touch"). + Output(rootDirForFsConfigTimestamp) + rootDirBuilder.Build("assemble_root_dir_for_fs_config", "Assemble ROOT/ for fs_config") + a.rootDirForFsConfigTimestamp = rootDirForFsConfigTimestamp } } // Copy cmdline, kernel etc. files of boot images @@ -554,6 +623,10 @@ func (a *androidDevice) copyImagesToTargetZip(ctx android.ModuleContext, builder builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].MapFile).Textf(" %s/IMAGES/", targetFilesDir.String()) } } + // super_empty.img + if info.SuperEmptyImage != nil { + builder.Command().Textf("cp ").Input(info.SuperEmptyImage).Textf(" %s/IMAGES/", targetFilesDir.String()) + } } else { ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name()) } @@ -608,11 +681,17 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build } if partition == "system" { // Create root_filesystem_config from the assembled ROOT/ intermediates directory - a.generateFilesystemConfigForTargetFiles(ctx, builder, targetFilesDir.String(), targetFilesDir.String()+"/ROOT", "root_filesystem_config.txt") + a.generateFilesystemConfigForTargetFiles(ctx, builder, a.rootDirForFsConfigTimestamp, targetFilesDir.String(), a.rootDirForFsConfig, "root_filesystem_config.txt") } if partition == "vendor_ramdisk" { // Create vendor_boot_filesystem_config from the assembled VENDOR_BOOT/RAMDISK intermediates directory - a.generateFilesystemConfigForTargetFiles(ctx, builder, targetFilesDir.String(), targetFilesDir.String()+"/VENDOR_BOOT/RAMDISK", "vendor_boot_filesystem_config.txt") + vendorRamdiskStagingDir := targetFilesDir.String() + "/VENDOR_BOOT/RAMDISK" + vendorRamdiskFsConfigOut := targetFilesDir.String() + "/META/vendor_boot_filesystem_config.txt" + fsConfigBin := ctx.Config().HostToolPath(ctx, "fs_config") + builder.Command().Textf( + `(cd %s; find . -type d | sed 's,$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,,' | %s -C -D %s -R \"\" > %s`, + vendorRamdiskStagingDir, fsConfigBin, vendorRamdiskStagingDir, vendorRamdiskFsConfigOut). + Implicit(fsConfigBin) } } // Copy ramdisk_node_list @@ -632,6 +711,9 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build } installedApexKeys = android.SortedUniquePaths(installedApexKeys) // Sort by keypath to match make builder.Command().Text("cat").Inputs(installedApexKeys).Textf(" >> %s/META/apexkeys.txt", targetFilesDir.String()) + // apkcerts.txt + builder.Command().Textf("cp").Input(a.apkCertsInfo).Textf(" %s/META/", targetFilesDir.String()) + // Copy fastboot-info.txt if fastbootInfo := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.FastbootInfo)); fastbootInfo != nil { // TODO (b/399788523): Autogenerate fastboot-info.txt if there is no source fastboot-info.txt @@ -646,6 +728,12 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build if a.kernelVersion != nil { builder.Command().Textf("cp").Input(a.kernelVersion).Textf(" %s/META/", targetFilesDir.String()) } + // misc_info.txt + if a.miscInfo != nil { + builder.Command().Textf("cp").Input(a.miscInfo).Textf(" %s/META/", targetFilesDir.String()) + } + // apex_info.pb, care_map.pb, vbmeta_digest.txt + a.addImgToTargetFiles(ctx, builder, targetFilesDir.String()) if a.partitionProps.Super_partition_name != nil { superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag) @@ -660,17 +748,96 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build } +// A partial implementation of make's $PRODUCT_OUT/misc_info.txt +// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5894?q=misc_info.txt%20f:build%2Fmake%2Fcore%2FMakefile&ss=android%2Fplatform%2Fsuperproject%2Fmain +// This file is subsequently used by add_img_to_target_files to create additioanl metadata files like apex_info.pb +// TODO (b/399788119): Complete the migration of misc_info.txt +func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path { + builder := android.NewRuleBuilder(pctx, ctx) + miscInfo := android.PathForModuleOut(ctx, "misc_info.txt") + builder.Command(). + Textf("rm -f %s", miscInfo). + Textf("&& echo recovery_api_version=%s >> %s", ctx.Config().VendorConfig("recovery").String("recovery_api_version"), miscInfo). + Textf("&& echo fstab_version=%s >> %s", ctx.Config().VendorConfig("recovery").String("recovery_fstab_version"), miscInfo). + ImplicitOutput(miscInfo) + + if a.partitionProps.Recovery_partition_name == nil { + builder.Command().Textf("echo no_recovery=true >> %s", miscInfo) + } + fsInfos := a.getFsInfos(ctx) + for _, partition := range android.SortedKeys(fsInfos) { + if fsInfos[partition].UseAvb { + builder.Command().Textf("echo 'avb_%s_hashtree_enable=true' >> %s", partition, miscInfo) + } + } + if len(a.partitionProps.Vbmeta_partitions) > 0 { + builder.Command(). + Textf("echo avb_enable=true >> %s", miscInfo). + Textf("&& echo avb_building_vbmeta_image=true >> %s", miscInfo). + Textf("&& echo avb_avbtool=avbtool >> %s", miscInfo) + } + if a.partitionProps.Boot_partition_name != nil { + builder.Command().Textf("echo boot_images=boot.img >> %s", miscInfo) + } + + if a.partitionProps.Super_partition_name != nil { + superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag) + if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok { + // cat dynamic_partition_info.txt + builder.Command().Text("cat").Input(info.DynamicPartitionsInfo).Textf(" >> %s", miscInfo) + } else { + ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name()) + } + } + bootImgNames := []*string{ + a.partitionProps.Boot_partition_name, + a.partitionProps.Init_boot_partition_name, + a.partitionProps.Vendor_boot_partition_name, + } + for _, bootImgName := range bootImgNames { + if bootImgName == nil { + continue + } + + bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(bootImgName), filesystemDepTag) + bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider) + // cat avb_ metadata of the boot images + builder.Command().Text("cat").Input(bootImgInfo.PropFileForMiscInfo).Textf(" >> %s", miscInfo) + } + + builder.Build("misc_info", "Building misc_info") + + return miscInfo +} + +// addImgToTargetFiles invokes `add_img_to_target_files` and creates the following files in META/ +// - apex_info.pb +// - care_map.pb +// - vbmeta_digest.txt +func (a *androidDevice) addImgToTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir string) { + mkbootimg := ctx.Config().HostToolPath(ctx, "mkbootimg") + builder.Command(). + Textf("PATH=%s:$PATH", ctx.Config().HostToolDir()). + Textf("MKBOOTIMG=%s", mkbootimg). + Implicit(mkbootimg). + BuiltTool("add_img_to_target_files"). + Flag("-a -v -p"). + Flag(ctx.Config().HostToolDir()). + Text(targetFilesDir) +} + type ApexKeyPathInfo struct { ApexKeyPath android.Path } var ApexKeyPathInfoProvider = blueprint.NewProvider[ApexKeyPathInfo]() -func (a *androidDevice) generateFilesystemConfigForTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir, stagingDir, filename string) { +func (a *androidDevice) generateFilesystemConfigForTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, stagingDirTimestamp android.Path, targetFilesDir, stagingDir, filename string) { fsConfigOut := android.PathForModuleOut(ctx, filename) ctx.Build(pctx, android.BuildParams{ - Rule: fsConfigRule, - Output: fsConfigOut, + Rule: fsConfigRule, + Implicit: stagingDirTimestamp, + Output: fsConfigOut, Args: map[string]string{ "rootDir": stagingDir, "prefix": "", @@ -757,11 +924,12 @@ func (a *androidDevice) extractKernelVersionAndConfigs(ctx android.ModuleContext Flag("--tools lz4:"+lz4tool.String()).Implicit(lz4tool). FlagWithInput("--input ", kernel). FlagWithOutput("--output-release ", extractedVersionFile). - FlagWithOutput("--output-configs ", extractedConfigsFile) + FlagWithOutput("--output-configs ", extractedConfigsFile). + Textf(`&& printf "\n" >> %s`, extractedVersionFile) if specifiedVersion := proptools.String(a.deviceProps.Kernel_version); specifiedVersion != "" { specifiedVersionFile := android.PathForModuleOut(ctx, "specified_kernel_version.txt") - android.WriteFileRuleVerbatim(ctx, specifiedVersionFile, specifiedVersion) + android.WriteFileRule(ctx, specifiedVersionFile, specifiedVersion) builder.Command().Text("diff -q"). Input(specifiedVersionFile). Input(extractedVersionFile). @@ -785,3 +953,51 @@ func (a *androidDevice) extractKernelVersionAndConfigs(ctx android.ModuleContext return extractedVersionFile, extractedConfigsFile } + +func (a *androidDevice) buildApkCertsInfo(ctx android.ModuleContext, allInstalledModules []android.Module) android.Path { + // TODO (spandandas): Add compressed + 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) + } + + apkCerts := []string{} + for _, installedModule := range allInstalledModules { + partition := "" + if commonInfo, ok := android.OtherModuleProvider(ctx, installedModule, android.CommonModuleInfoProvider); ok { + partition = commonInfo.PartitionTag + } else { + ctx.ModuleErrorf("%s does not set CommonModuleInfoKey", installedModule.Name()) + } + if info, ok := android.OtherModuleProvider(ctx, installedModule, java.AppInfoProvider); ok { + apkCerts = append(apkCerts, formatLine(info.Certificate, info.InstallApkName+".apk", partition)) + } else if info, ok := android.OtherModuleProvider(ctx, installedModule, java.AppInfosProvider); ok { + for _, certInfo := range info { + // Partition information of apk-in-apex is not exported to the legacy Make packaging system. + // Hardcode the partition to "system" + apkCerts = append(apkCerts, formatLine(certInfo.Certificate, certInfo.InstallApkName+".apk", "system")) + } + } else if info, ok := android.OtherModuleProvider(ctx, installedModule, java.RuntimeResourceOverlayInfoProvider); ok { + apkCerts = append(apkCerts, formatLine(info.Certificate, info.OutputFile.Base(), partition)) + } + } + slices.Sort(apkCerts) // sort by name + fsInfos := a.getFsInfos(ctx) + if fsInfos["system"].HasFsverity { + defaultPem, defaultKey := ctx.Config().DefaultAppCertificate(ctx) + apkCerts = append(apkCerts, formatLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifest.apk", "system")) + if info, ok := fsInfos["system_ext"]; ok && info.HasFsverity { + apkCerts = append(apkCerts, formatLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifestSystemExt.apk", "system_ext")) + } + } + + apkCertsInfo := android.PathForModuleOut(ctx, "apkcerts.txt") + android.WriteFileRuleVerbatim(ctx, apkCertsInfo, strings.Join(apkCerts, "\n")+"\n") + return apkCertsInfo +} diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go index effbd6542..7959365e8 100644 --- a/filesystem/bootimg.go +++ b/filesystem/bootimg.go @@ -201,7 +201,8 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { return } - unsignedOutput := b.buildBootImage(ctx, b.getKernelPath(ctx)) + kernelPath := b.getKernelPath(ctx) + unsignedOutput := b.buildBootImage(ctx, kernelPath) output := unsignedOutput if proptools.Bool(b.properties.Use_avb) { @@ -212,7 +213,7 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { case "default": output = b.signImage(ctx, unsignedOutput) case "make_legacy": - output = b.addAvbFooter(ctx, unsignedOutput, b.getKernelPath(ctx)) + output = b.addAvbFooter(ctx, unsignedOutput, kernelPath) default: ctx.PropertyErrorf("avb_mode", `Unknown value for avb_mode, expected "default" or "make_legacy", got: %q`, *b.properties.Avb_mode) } @@ -235,12 +236,14 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { } // Set BootimgInfo for building target_files.zip + dtbPath := b.getDtbPath(ctx) android.SetProvider(ctx, BootimgInfoProvider, BootimgInfo{ - Cmdline: b.properties.Cmdline, - Kernel: b.getKernelPath(ctx), - Dtb: b.getDtbPath(ctx), - Bootconfig: b.getBootconfigPath(ctx), - Output: output, + Cmdline: b.properties.Cmdline, + Kernel: kernelPath, + Dtb: dtbPath, + Bootconfig: b.getBootconfigPath(ctx), + Output: output, + PropFileForMiscInfo: b.buildPropFileForMiscInfo(ctx), }) extractedPublicKey := android.PathForModuleOut(ctx, b.partitionName()+".avbpubkey") @@ -263,16 +266,32 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { PublicKey: extractedPublicKey, Output: output, }) + + // Dump compliance metadata + complianceMetadataInfo := ctx.ComplianceMetadataInfo() + prebuiltFilesCopied := make([]string, 0) + if kernelPath != nil { + prebuiltFilesCopied = append(prebuiltFilesCopied, kernelPath.String()+":kernel") + } + if dtbPath != nil { + prebuiltFilesCopied = append(prebuiltFilesCopied, dtbPath.String()+":dtb.img") + } + complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied) + + if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" { + buildComplianceMetadata(ctx, bootimgRamdiskDep) + } } var BootimgInfoProvider = blueprint.NewProvider[BootimgInfo]() type BootimgInfo struct { - Cmdline []string - Kernel android.Path - Dtb android.Path - Bootconfig android.Path - Output android.Path + Cmdline []string + Kernel android.Path + Dtb android.Path + Bootconfig android.Path + Output android.Path + PropFileForMiscInfo android.Path } func (b *bootimg) getKernelPath(ctx android.ModuleContext) android.Path { @@ -491,6 +510,25 @@ func (b *bootimg) buildPropFile(ctx android.ModuleContext) (android.Path, androi return propFile, deps } +func (b *bootimg) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path { + var sb strings.Builder + addStr := func(name string, value string) { + fmt.Fprintf(&sb, "%s=%s\n", name, value) + } + + bootImgType := proptools.String(b.properties.Boot_image_type) + addStr("avb_"+bootImgType+"_add_hash_footer_args", "TODO(b/398036609)") + 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()) + addStr("avb_"+bootImgType+"_rollback_index_location", strconv.Itoa(proptools.Int(b.properties.Avb_rollback_index_location))) + } + + propFile := android.PathForModuleOut(ctx, "prop_for_misc_info") + android.WriteFileRuleVerbatim(ctx, propFile, sb.String()) + return propFile +} + var _ android.AndroidMkEntriesProvider = (*bootimg)(nil) // Implements android.AndroidMkEntriesProvider diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index fc480e6f0..b8548805b 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -30,6 +30,7 @@ import ( "android/soong/linkerconfig" "github.com/google/blueprint" + "github.com/google/blueprint/depset" "github.com/google/blueprint/proptools" ) @@ -374,6 +375,20 @@ func (fs fsType) IsUnknown() bool { return fs == unknown } +// Type string that build_image.py accepts. +func (t fsType) String() string { + switch t { + // TODO(372522486): add more types like f2fs, erofs, etc. + case ext4Type: + return "ext4" + case erofsType: + return "erofs" + case f2fsType: + return "f2fs" + } + panic(fmt.Errorf("unsupported fs type %d", t)) +} + type InstalledFilesStruct struct { Txt android.Path Json android.Path @@ -424,8 +439,8 @@ type FilesystemInfo struct { FullInstallPaths []FullInstallPathInfo - // Installed files list - InstalledFiles InstalledFilesStruct + // Installed files dep set of this module and its dependency filesystem modules + InstalledFilesDepSet depset.DepSet[InstalledFilesStruct] // Path to compress hints file for erofs filesystems // This will be nil for other fileystems like ext4 @@ -436,6 +451,10 @@ type FilesystemInfo struct { FilesystemConfig android.Path Owners []InstalledModuleInfo + + UseAvb bool + + HasFsverity bool } // FullInstallPathInfo contains information about the "full install" paths of all the files @@ -539,13 +558,13 @@ func (f *filesystem) ModifyPackagingSpec(ps *android.PackagingSpec) { } } -func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) (txt android.ModuleOutPath, json android.ModuleOutPath) { +func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) InstalledFilesStruct { fileName := "installed-files" if len(partition) > 0 { fileName += fmt.Sprintf("-%s", partition) } - txt = android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName)) - json = android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName)) + txt := android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName)) + json := android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName)) ctx.Build(pctx, android.BuildParams{ Rule: installedFilesJsonRule, @@ -564,7 +583,10 @@ func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir an Description: "Installed file list txt", }) - return txt, json + return InstalledFilesStruct{ + Txt: txt, + Json: json, + } } func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -647,11 +669,15 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { fileListFile := android.PathForModuleOut(ctx, "fileList") android.WriteFileRule(ctx, fileListFile, f.installedFilesList()) - partitionName := f.partitionName() - if partitionName == "system" { - partitionName = "" + var partitionNameForInstalledFiles string + switch f.partitionName() { + case "system": + partitionNameForInstalledFiles = "" + case "vendor_ramdisk": + partitionNameForInstalledFiles = "vendor-ramdisk" + default: + partitionNameForInstalledFiles = f.partitionName() } - installedFileTxt, installedFileJson := buildInstalledFiles(ctx, partitionName, rootDir, f.output) var erofsCompressHints android.Path if f.properties.Erofs.Compress_hints != nil { @@ -672,14 +698,17 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { BuildImagePropFileDeps: buildImagePropFileDeps, SpecsForSystemOther: f.systemOtherFiles(ctx), FullInstallPaths: fullInstallPaths, - InstalledFiles: InstalledFilesStruct{ - Txt: installedFileTxt, - Json: installedFileJson, - }, + InstalledFilesDepSet: depset.New( + depset.POSTORDER, + []InstalledFilesStruct{buildInstalledFiles(ctx, partitionNameForInstalledFiles, rootDir, f.output)}, + includeFilesInstalledFiles(ctx), + ), ErofsCompressHints: erofsCompressHints, SelinuxFc: f.selinuxFc, FilesystemConfig: f.generateFilesystemConfig(ctx, rootDir, rebasedDir), Owners: f.gatherOwners(specs), + UseAvb: proptools.Bool(f.properties.Use_avb), + HasFsverity: f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) != nil, } android.SetProvider(ctx, FilesystemProvider, fsInfo) @@ -695,6 +724,14 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { } f.setVbmetaPartitionProvider(ctx) + + // Dump metadata that can not be done in android/compliance-metadata.go + complianceMetadataInfo := ctx.ComplianceMetadataInfo() + filesContained := make([]string, 0, len(fullInstallPaths)) + for _, file := range fullInstallPaths { + filesContained = append(filesContained, file.FullInstallPath.String()) + } + complianceMetadataInfo.SetFilesContained(filesContained) } func (f *filesystem) fileystemStagingDirTimestamp(ctx android.ModuleContext) android.WritablePath { @@ -879,13 +916,24 @@ func (f *filesystem) buildNonDepsFiles( builder.Command().Text("mkdir -p").Text(filepath.Dir(dst.String())) builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String()) f.appendToEntry(ctx, dst) - // Only add the fullInstallPath logic for files in the rebased dir. The root dir - // is harder to install to. - if strings.HasPrefix(name, rebasedPrefix) { + // Add the fullInstallPath logic for files in the rebased dir, and for non-rebased files in "system" partition + // the fullInstallPath is changed to "root" which aligns to the behavior in Make. + if f.PartitionType() == "system" { + installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)) + if !strings.HasPrefix(name, rebasedPrefix) { + installPath = android.PathForModuleInPartitionInstall(ctx, "root", name) + } *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ - FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)), + FullInstallPath: installPath, SymlinkTarget: target, }) + } else { + if strings.HasPrefix(name, rebasedPrefix) { + *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ + FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)), + SymlinkTarget: target, + }) + } } } @@ -997,21 +1045,7 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and deps = append(deps, path) } - // Type string that build_image.py accepts. - fsTypeStr := func(t fsType) string { - switch t { - // TODO(372522486): add more types like f2fs, erofs, etc. - case ext4Type: - return "ext4" - case erofsType: - return "erofs" - case f2fsType: - return "f2fs" - } - panic(fmt.Errorf("unsupported fs type %v", t)) - } - - addStr("fs_type", fsTypeStr(f.fsType(ctx))) + addStr("fs_type", f.fsType(ctx).String()) addStr("mount_point", proptools.StringDefault(f.properties.Mount_point, "/")) addStr("use_dynamic_partition_size", "true") addPath("ext_mkuserimg", ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs")) @@ -1030,28 +1064,7 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and addPath("avb_key_path", key) } addStr("partition_name", f.partitionName()) - avb_add_hashtree_footer_args := "" - if !proptools.BoolDefault(f.properties.Use_fec, true) { - avb_add_hashtree_footer_args += " --do_not_generate_fec" - } - hashAlgorithm := proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256") - avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm - if f.properties.Rollback_index != nil { - rollbackIndex := proptools.Int(f.properties.Rollback_index) - if rollbackIndex < 0 { - ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") - } - avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex) - } - avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable()) - // We're not going to add BuildFingerPrintFile as a dep. If it changed, it's likely because - // the build number changed, and we don't want to trigger rebuilds solely based on the build - // number. - avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx)) - if f.properties.Security_patch != nil && proptools.String(f.properties.Security_patch) != "" { - avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), proptools.String(f.properties.Security_patch)) - } - addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args) + addStr("avb_add_hashtree_footer_args", f.getAvbAddHashtreeFooterArgs(ctx)) } if f.properties.File_contexts != nil && f.properties.Precompiled_file_contexts != nil { @@ -1100,7 +1113,7 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and addStr("f2fs_sparse_flag", "-S") } } - f.checkFsTypePropertyError(ctx, fst, fsTypeStr(fst)) + f.checkFsTypePropertyError(ctx, fst, fst.String()) if f.properties.Partition_size != nil { addStr("partition_size", strconv.FormatInt(*f.properties.Partition_size, 10)) @@ -1131,6 +1144,31 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and return propFile, deps } +func (f *filesystem) getAvbAddHashtreeFooterArgs(ctx android.ModuleContext) string { + avb_add_hashtree_footer_args := "" + if !proptools.BoolDefault(f.properties.Use_fec, true) { + avb_add_hashtree_footer_args += " --do_not_generate_fec" + } + hashAlgorithm := proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256") + avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm + if f.properties.Rollback_index != nil { + rollbackIndex := proptools.Int(f.properties.Rollback_index) + if rollbackIndex < 0 { + ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") + } + avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex) + } + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable()) + // We're not going to add BuildFingerPrintFile as a dep. If it changed, it's likely because + // the build number changed, and we don't want to trigger rebuilds solely based on the build + // number. + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx)) + if f.properties.Security_patch != nil && proptools.String(f.properties.Security_patch) != "" { + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), proptools.String(f.properties.Security_patch)) + } + return avb_add_hashtree_footer_args +} + // This method checks if there is any property set for the fstype(s) other than // the current fstype. func (f *filesystem) checkFsTypePropertyError(ctx android.ModuleContext, t fsType, fs string) { @@ -1164,6 +1202,15 @@ func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, par return rootDirs, partitions } +func includeFilesInstalledFiles(ctx android.ModuleContext) (ret []depset.DepSet[InstalledFilesStruct]) { + ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) { + if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok { + ret = append(ret, fsProvider.InstalledFilesDepSet) + } + }) + return +} + func (f *filesystem) buildCpioImage( ctx android.ModuleContext, builder *android.RuleBuilder, @@ -1426,7 +1473,7 @@ func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]androi deps := f.gatherFilteredPackagingSpecs(ctx) ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { - if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).Enabled { return false } for _, ps := range android.OtherModuleProviderOrDefault( @@ -1447,7 +1494,7 @@ func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]androi var requireModules []android.ModuleProxy ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { - if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).Enabled { return false } _, parentInPackage := modulesInPackageByModule[parent] diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go index 6d0b49016..bf7f5b64b 100644 --- a/filesystem/filesystem_test.go +++ b/filesystem/filesystem_test.go @@ -723,26 +723,47 @@ cc_library { // override_android_* modules implicitly override their base module. // If both of these are listed in `deps`, the base module should not be installed. +// Also, required deps should be updated too. func TestOverrideModulesInDeps(t *testing.T) { result := fixture.RunTestWithBp(t, ` + cc_library_shared { + name: "libfoo", + stl: "none", + system_shared_libs: [], + } + cc_library_shared { + name: "libbar", + stl: "none", + system_shared_libs: [], + } android_filesystem { name: "myfilesystem", + deps: ["myapp"], + } + android_filesystem { + name: "myfilesystem_overridden", deps: ["myapp", "myoverrideapp"], } android_app { name: "myapp", platform_apis: true, + required: ["libfoo"], } override_android_app { name: "myoverrideapp", base: "myapp", + required: ["libbar"], } `) partition := result.ModuleForTests(t, "myfilesystem", "android_common") fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList")) - android.AssertStringEquals(t, "filesystem with override app", "app/myoverrideapp/myoverrideapp.apk\n", 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) } func TestRamdiskPartitionSetsDevNodes(t *testing.T) { diff --git a/filesystem/super_image.go b/filesystem/super_image.go index 5e62fa702..cd7df027a 100644 --- a/filesystem/super_image.go +++ b/filesystem/super_image.go @@ -80,6 +80,8 @@ type SuperImageProperties struct { } // Whether the super image will be disted in the update package Super_image_in_update_package *bool + // Whether a super_empty.img should be created + Create_super_empty *bool } type PartitionGroupsInfo struct { @@ -118,6 +120,8 @@ type SuperImageInfo struct { SubImageInfo map[string]FilesystemInfo DynamicPartitionsInfo android.Path + + SuperEmptyImage android.Path } var SuperImageProvider = blueprint.NewProvider[SuperImageInfo]() @@ -163,7 +167,7 @@ func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) { } func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { - miscInfo, deps, subImageInfos := s.buildMiscInfo(ctx) + miscInfo, deps, subImageInfos := s.buildMiscInfo(ctx, false) builder := android.NewRuleBuilder(pctx, ctx) output := android.PathForModuleOut(ctx, s.installFileName()) lpMake := ctx.Config().HostToolPath(ctx, "lpmake") @@ -176,20 +180,39 @@ func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { Implicits(deps). Output(output) builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName())) + var superEmptyImage android.WritablePath + if proptools.Bool(s.properties.Create_super_empty) { + superEmptyImageBuilder := android.NewRuleBuilder(pctx, ctx) + superEmptyImage = android.PathForModuleOut(ctx, "super_empty.img") + superEmptyMiscInfo, superEmptyDeps, _ := s.buildMiscInfo(ctx, true) + if superEmptyDeps != nil { + ctx.ModuleErrorf("TODO: Handle additional deps when building super_empty.img") + } + superEmptyImageBuilder.Command().Textf("PATH=%s:\\$PATH", lpMakeDir). + BuiltTool("build_super_image"). + Text("-v"). + Input(superEmptyMiscInfo). + Implicit(lpMake). + Output(superEmptyImage) + superEmptyImageBuilder.Build("build_super_empty_image", fmt.Sprintf("Creating super empty image %s", s.BaseModuleName())) + } android.SetProvider(ctx, SuperImageProvider, SuperImageInfo{ SuperImage: output, SubImageInfo: subImageInfos, DynamicPartitionsInfo: s.generateDynamicPartitionsInfo(ctx), + SuperEmptyImage: superEmptyImage, }) ctx.SetOutputFiles([]android.Path{output}, "") ctx.CheckbuildFile(output) + + buildComplianceMetadata(ctx, subImageDepTag) } func (s *superImage) installFileName() string { return "super.img" } -func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths, map[string]FilesystemInfo) { +func (s *superImage) buildMiscInfo(ctx android.ModuleContext, superEmpty bool) (android.Path, android.Paths, map[string]FilesystemInfo) { var miscInfoString strings.Builder partitionList := s.dumpDynamicPartitionInfo(ctx, &miscInfoString) addStr := func(name string, value string) { @@ -198,6 +221,12 @@ func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, and miscInfoString.WriteString(value) miscInfoString.WriteRune('\n') } + addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update))) + if superEmpty { + miscInfo := android.PathForModuleOut(ctx, "misc_info_super_empty.txt") + android.WriteFileRule(ctx, miscInfo, miscInfoString.String()) + return miscInfo, nil, nil + } subImageInfo := make(map[string]FilesystemInfo) var deps android.Paths @@ -296,38 +325,43 @@ func (s *superImage) dumpDynamicPartitionInfo(ctx android.ModuleContext, sb *str sb.WriteRune('\n') } - addStr("build_super_partition", "true") addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions))) if proptools.Bool(s.properties.Retrofit) { addStr("dynamic_partition_retrofit", "true") } addStr("lpmake", "lpmake") + addStr("build_super_partition", "true") + if proptools.Bool(s.properties.Create_super_empty) { + addStr("build_super_empty_partition", "true") + } addStr("super_metadata_device", proptools.String(s.properties.Metadata_device)) if len(s.properties.Block_devices) > 0 { addStr("super_block_devices", strings.Join(s.properties.Block_devices, " ")) } - if proptools.Bool(s.properties.Super_image_in_update_package) { - addStr("super_image_in_update_package", "true") - } - addStr("super_partition_size", strconv.Itoa(proptools.Int(s.properties.Size))) // TODO: In make, there's more complicated logic than just this surrounding super_*_device_size addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size))) var groups, partitionList []string for _, groupInfo := range s.properties.Partition_groups { groups = append(groups, groupInfo.Name) partitionList = append(partitionList, groupInfo.PartitionList...) - addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize) - addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " ")) } + addStr("dynamic_partition_list", strings.Join(android.SortedUniqueStrings(partitionList), " ")) + addStr("super_partition_groups", strings.Join(groups, " ")) initialPartitionListLen := len(partitionList) partitionList = android.SortedUniqueStrings(partitionList) if len(partitionList) != initialPartitionListLen { ctx.ModuleErrorf("Duplicate partitions found in the partition_groups property") } - addStr("super_partition_groups", strings.Join(groups, " ")) - addStr("dynamic_partition_list", strings.Join(partitionList, " ")) + // Add Partition group info after adding `super_partition_groups` and `dynamic_partition_list` + for _, groupInfo := range s.properties.Partition_groups { + addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize) + addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " ")) + } - addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update))) + if proptools.Bool(s.properties.Super_image_in_update_package) { + addStr("super_image_in_update_package", "true") + } + addStr("super_partition_size", strconv.Itoa(proptools.Int(s.properties.Size))) if proptools.Bool(s.properties.Virtual_ab.Enable) { addStr("virtual_ab", "true") @@ -342,12 +376,12 @@ func (s *superImage) dumpDynamicPartitionInfo(ctx android.ModuleContext, sb *str } addStr("virtual_ab_compression_method", *s.properties.Virtual_ab.Compression_method) } - if s.properties.Virtual_ab.Compression_factor != nil { - addStr("virtual_ab_compression_factor", strconv.FormatInt(*s.properties.Virtual_ab.Compression_factor, 10)) - } if s.properties.Virtual_ab.Cow_version != nil { addStr("virtual_ab_cow_version", strconv.FormatInt(*s.properties.Virtual_ab.Cow_version, 10)) } + if s.properties.Virtual_ab.Compression_factor != nil { + addStr("virtual_ab_compression_factor", strconv.FormatInt(*s.properties.Virtual_ab.Compression_factor, 10)) + } } else { if s.properties.Virtual_ab.Retrofit != nil { @@ -371,6 +405,6 @@ func (s *superImage) generateDynamicPartitionsInfo(ctx android.ModuleContext) an var contents strings.Builder s.dumpDynamicPartitionInfo(ctx, &contents) dynamicPartitionsInfo := android.PathForModuleOut(ctx, "dynamic_partitions_info.txt") - android.WriteFileRule(ctx, dynamicPartitionsInfo, contents.String()) + android.WriteFileRuleVerbatim(ctx, dynamicPartitionsInfo, contents.String()) return dynamicPartitionsInfo } diff --git a/fsgen/boot_imgs.go b/fsgen/boot_imgs.go index 58ebcc4ba..0ba0a90dd 100644 --- a/fsgen/boot_imgs.go +++ b/fsgen/boot_imgs.go @@ -69,6 +69,7 @@ func createBootImage(ctx android.LoadHookContext, dtbImg dtbImg) bool { ctx.CreateModule( filesystem.BootimgFactory, &filesystem.BootimgProperties{ + Boot_image_type: proptools.StringPtr("boot"), Kernel_prebuilt: proptools.StringPtr(":" + kernelFilegroupName), Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion), Partition_size: partitionSize, diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index f00e491cc..b73fb219f 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -505,6 +505,7 @@ func partitionSpecificFsProps(ctx android.EarlyModuleContext, partitions allGene } fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch()) fsProps.Stem = proptools.StringPtr("system_ext.img") + fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) case "product": fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) fsProps.Android_filesystem_deps.System = proptools.StringPtr(partitions.nameForType("system")) @@ -853,19 +854,29 @@ func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) { Product_config *string Android_info *string Licenses []string + Dist android.Dist }{ Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "vendor-build.prop")), Vendor: proptools.BoolPtr(true), Stem: proptools.StringPtr("build.prop"), Product_config: proptools.StringPtr(":product_config"), Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop")), - Licenses: []string{"Android-Apache-2.0"}, + Dist: android.Dist{ + Targets: []string{"droidcore-unbundled"}, + Dest: proptools.StringPtr("build.prop-vendor"), + }, + Licenses: []string{"Android-Apache-2.0"}, } vendorBuildProp := ctx.CreateModule( android.BuildPropFactory, vendorBuildProps, ) - vendorBuildProp.HideFromMake() + // We don't want this to conflict with the make-built vendor build.prop, but unfortunately + // calling HideFromMake() prevents disting files, even in soong-only mode. So only call + // HideFromMake() on soong+make builds. + if ctx.Config().KatiEnabled() { + vendorBuildProp.HideFromMake() + } } func createRecoveryBuildProp(ctx android.LoadHookContext) string { diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go index 418e48bcd..81236a0a1 100644 --- a/fsgen/filesystem_creator_test.go +++ b/fsgen/filesystem_creator_test.go @@ -287,6 +287,8 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { "some/non/existing/file.txt:system/etc/file.txt", "device/sample/etc/apns-full-conf.xml:product/etc/apns-conf.xml:google", "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", } config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables = map[string]android.PartitionQualifiedVariablesType{ @@ -364,15 +366,25 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { eval := generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) android.AssertBoolEquals( t, - "module expected to set correct srcs and dsts properties", + "module expected to set correct srcs property", true, checkModuleProp(generatedModule0, func(actual interface{}) bool { if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { srcs := p.Srcs.GetOrDefault(eval, nil) - dsts := p.Dsts.GetOrDefault(eval, nil) return len(srcs) == 1 && - srcs[0] == "apns-full-conf.xml" && - len(dsts) == 1 && + srcs[0] == "apns-full-conf.xml" + } + return false + }), + ) + android.AssertBoolEquals( + t, + "module expected to set correct dsts property", + true, + checkModuleProp(generatedModule0, func(actual interface{}) bool { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + return len(dsts) == 1 && dsts[0] == "apns-conf.xml" } return false @@ -383,15 +395,25 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) android.AssertBoolEquals( t, - "module expected to set correct srcs and dsts properties", + "module expected to set correct srcs property", true, checkModuleProp(generatedModule1, func(actual interface{}) bool { if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { srcs := p.Srcs.GetOrDefault(eval, nil) - dsts := p.Dsts.GetOrDefault(eval, nil) return len(srcs) == 1 && - srcs[0] == "apns-full-conf.xml" && - len(dsts) == 1 && + srcs[0] == "apns-full-conf.xml" + } + return false + }), + ) + android.AssertBoolEquals( + t, + "module expected to set correct dsts property", + true, + checkModuleProp(generatedModule1, func(actual interface{}) bool { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + return len(dsts) == 1 && dsts[0] == "apns-conf-2.xml" } return false diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go index 9b25e77a5..4f3d2a750 100644 --- a/fsgen/fsgen_mutators.go +++ b/fsgen/fsgen_mutators.go @@ -105,12 +105,14 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam "libgsi": defaultDepCandidateProps(ctx.Config()), "llndk.libraries.txt": defaultDepCandidateProps(ctx.Config()), "logpersist.start": defaultDepCandidateProps(ctx.Config()), + "notice_xml_system": defaultDepCandidateProps(ctx.Config()), "update_engine_sideload": defaultDepCandidateProps(ctx.Config()), // keep-sorted end }, "vendor": { "fs_config_files_vendor": defaultDepCandidateProps(ctx.Config()), "fs_config_dirs_vendor": defaultDepCandidateProps(ctx.Config()), + "notice_xml_vendor": defaultDepCandidateProps(ctx.Config()), generatedModuleName(ctx.Config(), "vendor-build.prop"): defaultDepCandidateProps(ctx.Config()), }, "odm": { @@ -118,34 +120,41 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam // https://cs.android.com/android/_/android/platform/build/+/e4849e87ab660b59a6501b3928693db065ee873b:tools/fs_config/Android.mk;l=34;drc=8d6481b92c4b4e9b9f31a61545b6862090fcc14b;bpv=1;bpt=0 "fs_config_files_odm": defaultDepCandidateProps(ctx.Config()), "fs_config_dirs_odm": defaultDepCandidateProps(ctx.Config()), + "notice_xml_odm": defaultDepCandidateProps(ctx.Config()), + }, + "product": { + "notice_xml_product": defaultDepCandidateProps(ctx.Config()), }, - "product": {}, "system_ext": { // VNDK apexes are automatically included. // This hardcoded list will need to be updated if `PRODUCT_EXTRA_VNDK_VERSIONS` is updated. // https://cs.android.com/android/_/android/platform/build/+/adba533072b00c53ac0f198c550a3cbd7a00e4cd:core/main.mk;l=984;bpv=1;bpt=0;drc=174db7b179592cf07cbfd2adb0119486fda911e7 - "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()), - "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()), + "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()), + "notice_xml_system_ext": defaultDepCandidateProps(ctx.Config()), }, "userdata": {}, "system_dlkm": { // these are phony required deps of the phony fs_config_dirs_nonsystem "fs_config_dirs_system_dlkm": defaultDepCandidateProps(ctx.Config()), "fs_config_files_system_dlkm": defaultDepCandidateProps(ctx.Config()), + "notice_xml_system_dlkm": defaultDepCandidateProps(ctx.Config()), // build props are automatically added to `ALL_DEFAULT_INSTALLED_MODULES` "system_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()), }, "vendor_dlkm": { "fs_config_dirs_vendor_dlkm": defaultDepCandidateProps(ctx.Config()), "fs_config_files_vendor_dlkm": defaultDepCandidateProps(ctx.Config()), + "notice_xml_vendor_dlkm": defaultDepCandidateProps(ctx.Config()), "vendor_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()), }, "odm_dlkm": { "fs_config_dirs_odm_dlkm": defaultDepCandidateProps(ctx.Config()), "fs_config_files_odm_dlkm": defaultDepCandidateProps(ctx.Config()), + "notice_xml_odm_dlkm": defaultDepCandidateProps(ctx.Config()), "odm_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()), }, "ramdisk": {}, @@ -178,6 +187,10 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam (*fsGenState.fsDeps["product"])["system_other_avbpubkey"] = defaultDepCandidateProps(ctx.Config()) } + if len(ctx.Config().DeviceManifestFiles()) > 0 { + (*fsGenState.fsDeps["vendor"])["vendor_manifest.xml"] = defaultDepCandidateProps(ctx.Config()) + } + // Add common resources `prebuilt_res` module as dep of recovery partition (*fsGenState.fsDeps["recovery"])[fmt.Sprintf("recovery-resources-common-%s", getDpi(ctx))] = defaultDepCandidateProps(ctx.Config()) (*fsGenState.fsDeps["recovery"])[getRecoveryFontModuleName(ctx)] = defaultDepCandidateProps(ctx.Config()) diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go index e028b1d5a..df361976e 100644 --- a/fsgen/prebuilt_etc_modules_gen.go +++ b/fsgen/prebuilt_etc_modules_gen.go @@ -164,7 +164,6 @@ type prebuiltModuleProperties struct { Ramdisk *bool Srcs []string - Dsts []string No_full_install *bool @@ -199,6 +198,7 @@ var ( "etc/dsp": etc.PrebuiltDSPFactory, "etc/firmware": etc.PrebuiltFirmwareFactory, "firmware": etc.PrebuiltFirmwareFactory, + "gpu": etc.PrebuiltGPUFactory, "first_stage_ramdisk": etc.PrebuiltFirstStageRamdiskFactory, "fonts": etc.PrebuiltFontFactory, "framework": etc.PrebuiltFrameworkFactory, @@ -210,6 +210,7 @@ var ( "optee": etc.PrebuiltOpteeFactory, "overlay": etc.PrebuiltOverlayFactory, "priv-app": etc.PrebuiltPrivAppFactory, + "radio": etc.PrebuiltRadioFactory, "sbin": etc.PrebuiltSbinFactory, "system": etc.PrebuiltSystemFactory, "res": etc.PrebuiltResFactory, @@ -225,6 +226,7 @@ var ( "usr/idc": etc.PrebuiltUserIdcFactory, "vendor": etc.PrebuiltVendorFactory, "vendor_dlkm": etc.PrebuiltVendorDlkmFactory, + "vendor_overlay": etc.PrebuiltVendorOverlayFactory, "wallpaper": etc.PrebuiltWallpaperFactory, "wlc_upt": etc.PrebuiltWlcUptFactory, } @@ -299,6 +301,7 @@ func createPrebuiltEtcModulesInDirectory(ctx android.LoadHookContext, partition, etcInstallPathKey = etcInstallPath } } + moduleFactory := etcInstallPathToFactoryList[etcInstallPathKey] relDestDirFromInstallDirBase, _ := filepath.Rel(etcInstallPathKey, destDir) for fileIndex := range maxLen { @@ -348,15 +351,23 @@ func createPrebuiltEtcModulesInDirectory(ctx android.LoadHookContext, partition, }) } } else { + // If dsts property has to be set and the selected module type is prebuilt_root, + // use prebuilt_any instead. + if etcInstallPathKey == "" { + moduleFactory = etc.PrebuiltAnyFactory + } modulePropsPtr.Srcs = srcBaseFiles - dsts := []string{} + dsts := proptools.NewConfigurable[[]string](nil, nil) for _, installBaseFile := range installBaseFiles { - dsts = append(dsts, filepath.Join(relDestDirFromInstallDirBase, installBaseFile)) + dsts.AppendSimpleValue([]string{filepath.Join(relDestDirFromInstallDirBase, installBaseFile)}) } - modulePropsPtr.Dsts = dsts + + propsList = append(propsList, &etc.PrebuiltDstsProperties{ + Dsts: dsts, + }) } - ctx.CreateModuleInDirectory(etcInstallPathToFactoryList[etcInstallPathKey], srcDir, propsList...) + ctx.CreateModuleInDirectory(moduleFactory, srcDir, propsList...) moduleNames = append(moduleNames, moduleName) } diff --git a/fsgen/super_img.go b/fsgen/super_img.go index f5646365f..1d610f63c 100644 --- a/fsgen/super_img.go +++ b/fsgen/super_img.go @@ -46,6 +46,7 @@ func createSuperImage( Retrofit: proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions), Use_dynamic_partitions: proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions), Super_image_in_update_package: proptools.BoolPtr(partitionVars.BoardSuperImageInUpdatePackage), + Create_super_empty: proptools.BoolPtr(partitionVars.BuildingSuperEmptyImage), } if partitionVars.ProductVirtualAbOta { superImageProps.Virtual_ab.Enable = proptools.BoolPtr(true) diff --git a/genrule/genrule.go b/genrule/genrule.go index 6bd1fcc8d..710ec9555 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -112,8 +112,8 @@ func (t hostToolDependencyTag) AllowDisabledModuleDependency(target android.Modu func (t hostToolDependencyTag) AllowDisabledModuleDependencyProxy( ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool { - return android.OtherModuleProviderOrDefault( - ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt + return android.OtherModulePointerProviderOrDefault( + ctx, target, android.CommonModuleInfoProvider).ReplacedByPrebuilt } var _ android.AllowDisabledModuleDependency = (*hostToolDependencyTag)(nil) @@ -353,7 +353,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderInfoProvider); ok { // A HostToolProvider provides the path to a tool, which will be copied // into the sandbox. - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { if ctx.Config().AllowMissingDependencies() { ctx.AddMissingDependencies([]string{tool}) } else { diff --git a/jar/jar.go b/jar/jar.go index daad4b025..54eded93a 100644 --- a/jar/jar.go +++ b/jar/jar.go @@ -17,7 +17,6 @@ package jar import ( "bytes" "fmt" - "hash/crc32" "io" "os" "strings" @@ -94,9 +93,7 @@ func ManifestFileContents(contents []byte) (*zip.FileHeader, []byte, error) { fh := &zip.FileHeader{ Name: ManifestFile, Method: zip.Store, - CompressedSize64: uint64(len(b)), UncompressedSize64: uint64(len(b)), - CRC32: crc32.ChecksumIEEE(b), } fh.SetMode(0644) fh.SetModTime(DefaultTime) diff --git a/java/Android.bp b/java/Android.bp index 911af8336..99d9c38a6 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -78,6 +78,7 @@ bootstrap_go_package { "system_modules.go", "systemserver_classpath_fragment.go", "testing.go", + "tracereferences.go", "tradefed.go", ], testSrcs: [ diff --git a/java/app.go b/java/app.go index fe5eec32d..553c65894 100644 --- a/java/app.go +++ b/java/app.go @@ -425,6 +425,10 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon } else { moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: a.appTestHelperAppProperties.Test_suites, + }) } func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -531,7 +535,7 @@ func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVer if _, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); !ok { panic(fmt.Errorf("jni dependency is not a cc module: %v", m)) } - commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoKey) + commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoProvider) if !ok { panic(fmt.Errorf("jni dependency doesn't have CommonModuleInfo provider: %v", m)) } @@ -1229,7 +1233,7 @@ func collectJniDeps(ctx android.ModuleContext, seenModulePaths := make(map[string]bool) ctx.WalkDepsProxy(func(module, parent android.ModuleProxy) bool { - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return false } otherName := ctx.OtherModuleName(module) @@ -1249,7 +1253,7 @@ func collectJniDeps(ctx android.ModuleContext, } seenModulePaths[path.String()] = true - commonInfo := android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider) if checkNativeSdkVersion && commonInfo.SdkVersion == "" { ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not", otherName) @@ -1287,13 +1291,13 @@ func collectJniDeps(ctx android.ModuleContext, } func (a *AndroidApp) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) { - ctx.WalkDeps(func(child, parent android.Module) bool { + ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { // TODO(ccross): Should this use android.DepIsInSameApex? Right now it is applying the android app // heuristics to every transitive dependency, when it should probably be using the heuristics of the // immediate parent. isExternal := !a.GetDepInSameApexChecker().OutgoingDepIsInSameApex(ctx.OtherModuleDependencyTag(child)) - if am, ok := child.(android.ApexModule); ok { - if !do(ctx, parent, am, isExternal) { + if am, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); ok && am.IsApexModule { + if !do(ctx, parent, child, isExternal) { return false } } @@ -1307,12 +1311,12 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { } depsInfo := android.DepNameToDepInfoMap{} - a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool { + a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool { depName := to.Name() // Skip dependencies that are only available to APEXes; they are developed with updatability // in mind and don't need manual approval. - if android.OtherModuleProviderOrDefault(ctx, to, android.CommonModuleInfoKey).NotAvailableForPlatform { + if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform { return true } @@ -1322,7 +1326,7 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { depsInfo[depName] = info } else { toMinSdkVersion := "(no version)" - if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoKey); ok && + if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoProvider); ok && !info.MinSdkVersion.IsPlatform && info.MinSdkVersion.ApiLevel != nil { toMinSdkVersion = info.MinSdkVersion.ApiLevel.String() } @@ -1703,6 +1707,10 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { moduleInfoJSON.AutoTestConfig = []string{"true"} } moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, a.testProperties.Test_mainline_modules...) + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: a.testProperties.Test_suites, + }) } func testcaseRel(paths android.Paths) []string { @@ -2209,3 +2217,7 @@ func setCommonAppInfo(appInfo *AppInfo, m androidApp) { appInfo.Certificate = m.Certificate() appInfo.PrivAppAllowlist = m.PrivAppAllowlist() } + +type AppInfos []AppInfo + +var AppInfosProvider = blueprint.NewProvider[AppInfos]() diff --git a/java/app_import.go b/java/app_import.go index 37c673ca0..c0e8171d5 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -177,7 +177,7 @@ type AndroidAppImportProperties struct { Prebuilt_info *string `android:"path"` // Path of extracted apk which is extracted from prebuilt apk. Use this extracted to import. - Extract_apk *string + Extract_apk proptools.Configurable[string] // Compress the output APK using gzip. Defaults to false. Compress_apk proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"` @@ -307,7 +307,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs( func (a *AndroidAppImport) extractSubApk( ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) { - extractApkPath := *a.properties.Extract_apk + extractApkPath := a.properties.Extract_apk.GetOrDefault(ctx, "") ctx.Build(pctx, android.BuildParams{ Rule: extractApkRule, Input: inputPath, @@ -405,7 +405,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext // TODO: LOCAL_PACKAGE_SPLITS srcApk := a.prebuilt.SingleSourcePath(ctx) - if a.properties.Extract_apk != nil { + if a.properties.Extract_apk.GetOrDefault(ctx, "") != "" { extract_apk := android.PathForModuleOut(ctx, "extract-apk", ctx.ModuleName()+".apk") a.extractSubApk(ctx, srcApk, extract_apk) srcApk = extract_apk @@ -787,6 +787,10 @@ func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContex a.updateModuleInfoJSON(ctx) a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: a.testProperties.Test_suites, + }) } func (a *AndroidTestImport) updateModuleInfoJSON(ctx android.ModuleContext) { diff --git a/java/base.go b/java/base.go index 1fb44e779..1a12075bc 100644 --- a/java/base.go +++ b/java/base.go @@ -629,7 +629,7 @@ func CheckStableSdkVersion(ctx android.BaseModuleContext, module android.ModuleP return nil } if info.SdkVersion.Kind == android.SdkCorePlatform { - if useLegacyCorePlatformApi(ctx, android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).BaseModuleName) { + if useLegacyCorePlatformApi(ctx, android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).BaseModuleName) { return fmt.Errorf("non stable SDK %v - uses legacy core platform", info.SdkVersion) } else { // Treat stable core platform as stable. @@ -888,6 +888,10 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { // Add dependency on libraries that provide additional hidden api annotations. ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...) + // Add dependency on (soft) downstream libs from which to trace references during optimization. + traceRefs := j.dexProperties.Optimize.Trace_references_from.GetOrDefault(ctx, []string{}) + ctx.AddVariationDependencies(nil, traceReferencesTag, traceRefs...) + // For library dependencies that are component libraries (like stubs), add the implementation // as a dependency (dexpreopt needs to be against the implementation library, not stubs). for _, dep := range libDeps { @@ -1160,14 +1164,7 @@ func (j *Module) addGeneratedSrcJars(path android.Path) { j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path) } -func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars, - extraDepCombinedJars android.Paths) *JavaInfo { - - manifest := j.overrideManifest - if !manifest.Valid() && j.properties.Manifest != nil { - manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *j.properties.Manifest)) - } - +func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars, extraDepCombinedJars android.Paths) *JavaInfo { // Auto-propagating jarjar rules jarjarProviderData := j.collectJarJarRules(ctx) if jarjarProviderData != nil { @@ -1288,7 +1285,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath transitiveStaticLibsHeaderJars := deps.transitiveStaticLibsHeaderJars localHeaderJars, combinedHeaderJarFile := j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, - extraCombinedJars, manifest) + extraCombinedJars) combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine", false) if jarjared { @@ -1401,7 +1398,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName) kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName) - j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags, manifest) + j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags) if ctx.Failed() { return nil } @@ -1436,7 +1433,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath extraJars := slices.Clone(kotlinHeaderJars) extraJars = append(extraJars, extraCombinedJars...) var combinedHeaderJarFile android.Path - localHeaderJars, combinedHeaderJarFile = j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars, manifest) + localHeaderJars, combinedHeaderJarFile = j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars) shardingHeaderJars = localHeaderJars var jarjared bool @@ -1617,6 +1614,11 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath combinedResourceJar = combinedJar } + manifest := j.overrideManifest + if !manifest.Valid() && j.properties.Manifest != nil { + manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *j.properties.Manifest)) + } + // Combine the classes built from sources, any manifests, and any static libraries into // classes.jar. If there is only one input jar this step will be skipped. var outputFile android.Path @@ -2071,7 +2073,7 @@ func CheckKotlincFlags(ctx android.ModuleContext, flags []string) { func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths, deps deps, flags javaBuilderFlags, jarName string, - extraJars android.Paths, manifest android.OptionalPath) (localHeaderJars android.Paths, combinedHeaderJar android.Path) { + extraJars android.Paths) (localHeaderJars android.Paths, combinedHeaderJar android.Path) { if len(srcFiles) > 0 || len(srcJars) > 0 { // Compile java sources into turbine.jar. @@ -2090,7 +2092,7 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars // we cannot skip the combine step for now if there is only one jar // since we have to strip META-INF/TRANSITIVE dir from turbine.jar combinedHeaderJarOutputPath := android.PathForModuleOut(ctx, "turbine-combined", jarName) - TransformJarsToJar(ctx, combinedHeaderJarOutputPath, "for turbine", jars, manifest, + TransformJarsToJar(ctx, combinedHeaderJarOutputPath, "for turbine", jars, android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"}) return localHeaderJars, combinedHeaderJarOutputPath diff --git a/java/builder.go b/java/builder.go index ade978450..dff0032d8 100644 --- a/java/builder.go +++ b/java/builder.go @@ -310,7 +310,7 @@ var ( gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule", blueprint.RuleParams{ - Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}' ` + + Command: `${aconfig} dump-cache --dedup --format=protobuf ` + `--out ${out} ` + `${flags_path} ` + `${filter_args} `, @@ -320,8 +320,8 @@ var ( generateMetalavaRevertAnnotationsRule = pctx.AndroidStaticRule("generateMetalavaRevertAnnotationsRule", blueprint.RuleParams{ - Command: `${keep-flagged-apis} ${in} > ${out}`, - CommandDeps: []string{"${keep-flagged-apis}"}, + Command: `${aconfig-to-metalava-flags} ${in} > ${out}`, + CommandDeps: []string{"${aconfig-to-metalava-flags}"}, }) generateApiXMLRule = pctx.AndroidStaticRule("generateApiXMLRule", @@ -339,7 +339,7 @@ func init() { pctx.HostBinToolVariable("aconfig", "aconfig") pctx.HostBinToolVariable("ravenizer", "ravenizer") pctx.HostBinToolVariable("apimapper", "apimapper") - pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis") + pctx.HostBinToolVariable("aconfig-to-metalava-flags", "aconfig-to-metalava-flags") } type javaBuilderFlags struct { diff --git a/java/config/config.go b/java/config/config.go index 71025de6a..fdb8d7886 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -173,6 +173,7 @@ func init() { pctx.HostBinToolVariable("R8Cmd", "r8") pctx.HostBinToolVariable("ExtractR8RulesCmd", "extract-r8-rules") pctx.HostBinToolVariable("ResourceShrinkerCmd", "resourceshrinker") + pctx.HostBinToolVariable("TraceReferencesCmd", "tracereferences") pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi") pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks") pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string { diff --git a/java/dex.go b/java/dex.go index ed2df2103..ed9c82ba2 100644 --- a/java/dex.go +++ b/java/dex.go @@ -103,6 +103,34 @@ type DexProperties struct { // If true, transitive reverse dependencies of this module will have this // module's proguard spec appended to their optimization action Export_proguard_flags_files *bool + + // Path to a file containing a list of class names that should not be compiled using R8. + // These classes will be compiled by D8 similar to when Optimize.Enabled is false. + // + // Example: + // + // r8.exclude: + // com.example.Foo + // com.example.Bar + // com.example.Bar$Baz + // + // By default all classes are compiled using R8 when Optimize.Enabled is set. + Exclude *string `android:"path"` + + // Optional list of downstream (Java) libraries from which to trace and preserve references + // when optimizing. Note that this requires that the source reference does *not* have + // a strict lib dependency on this target; dependencies should be on intermediate targets + // statically linked into this target, e.g., if A references B, and we want to trace and + // keep references from A when optimizing B, you would create an intermediate B.impl ( + // containing all static code), have A depend on `B.impl` via libs, and set + // `trace_references_from: ["A"]` on B. + // + // Also note that these are *not* inherited across targets, they must be specified at the + // top-level target that is optimized. + // + // TODO(b/212737576): Handle this implicitly using bottom-up deps mutation and implicit + // creation of a proxy `.impl` library. + Trace_references_from proptools.Configurable[[]string] `android:"arch_variant"` } // Keep the data uncompressed. We always need uncompressed dex for execution, @@ -445,6 +473,20 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...) + traceReferencesSources := android.Paths{} + ctx.VisitDirectDepsProxyWithTag(traceReferencesTag, func(m android.ModuleProxy) { + if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok { + traceReferencesSources = append(traceReferencesSources, dep.ImplementationJars...) + } + }) + if len(traceReferencesSources) > 0 { + traceTarget := dexParams.classesJar + traceLibs := android.FirstUniquePaths(append(flags.bootClasspath.Paths(), flags.dexClasspath.Paths()...)) + traceReferencesFlags := android.PathForModuleOut(ctx, "proguard", "trace_references.flags") + TraceReferences(ctx, traceReferencesSources, traceTarget, traceLibs, traceReferencesFlags) + flagFiles = append(flagFiles, traceReferencesFlags) + } + flagFiles = android.FirstUniquePaths(flagFiles) r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include ")) @@ -528,6 +570,11 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, r8Flags = append(r8Flags, "--store-store-fence-constructor-inlining") } + if opt.Exclude != nil { + r8Flags = append(r8Flags, "--exclude", *opt.Exclude) + r8Deps = append(r8Deps, android.PathForModuleSrc(ctx, *opt.Exclude)) + } + return r8Flags, r8Deps, artProfileOutput } diff --git a/java/dex_test.go b/java/dex_test.go index 66d801dcc..e94864bbc 100644 --- a/java/dex_test.go +++ b/java/dex_test.go @@ -866,3 +866,46 @@ func TestDebugReleaseFlags(t *testing.T) { }) } } + +func TestTraceReferences(t *testing.T) { + t.Parallel() + bp := ` + android_app { + name: "app", + libs: ["lib.impl"], + srcs: ["foo.java"], + platform_apis: true, + } + + java_library { + name: "lib", + optimize: { + enabled: true, + trace_references_from: ["app"], + }, + srcs: ["bar.java"], + static_libs: ["lib.impl"], + installable: true, + } + + java_library { + name: "lib.impl", + srcs: ["baz.java"], + } + ` + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + ).RunTestWithBp(t, bp) + + appJar := result.ModuleForTests(t, "app", "android_common").Output("combined/app.jar").Output + libJar := result.ModuleForTests(t, "lib", "android_common").Output("combined/lib.jar").Output + libTraceRefs := result.ModuleForTests(t, "lib", "android_common").Rule("traceReferences") + libR8 := result.ModuleForTests(t, "lib", "android_common").Rule("r8") + + android.AssertStringDoesContain(t, "expected trace reference source from app jar", + libTraceRefs.Args["sources"], "--source "+appJar.String()) + android.AssertStringEquals(t, "expected trace reference target into lib jar", + libJar.String(), libTraceRefs.Input.String()) + android.AssertStringDoesContain(t, "expected trace reference proguard flags in lib r8 flags", + libR8.Args["r8Flags"], "trace_references.flags") +} diff --git a/java/dexpreopt.go b/java/dexpreopt.go index b21cfc968..e8e1cd405 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -650,6 +650,9 @@ func checkSystemServerOrder(ctx android.ModuleContext, libName string) { // for now just exclude any known irrelevant dependencies that would lead to incorrect errors. if _, ok := tag.(bootclasspathDependencyTag); ok { return false + } else if tag == traceReferencesTag { + // Allow ordering inversion if the dependency is purely for tracing references. + return false } depIndex := jars.IndexOfJar(dep.Name()) if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars { diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go index c97156541..9d0f539ba 100644 --- a/java/dexpreopt_check.go +++ b/java/dexpreopt_check.go @@ -100,7 +100,12 @@ func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.Mod if systemServerJar.InstallInSystemExt() && ctx.Config().InstallApexSystemServerDexpreoptSamePartition() { partition = ctx.DeviceConfig().SystemExtPath() // system_ext } - dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, systemServerJar.Name()) + var dexLocation string + if m, ok := systemServerJar.(ModuleWithStem); ok { + dexLocation = dexpreopt.GetSystemServerDexLocation(ctx, global, m.Stem()) + } else { + ctx.PropertyErrorf("dexpreopt_systemserver_check", "%v is not a ModuleWithStem", systemServerJar.Name()) + } odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType, partition) odexPath := getInstallPath(ctx, odexLocation) vdexPath := getInstallPath(ctx, pathtools.ReplaceExtension(odexLocation, "vdex")) diff --git a/java/droiddoc.go b/java/droiddoc.go index 225f201a9..3faf294de 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -195,6 +195,9 @@ func apiCheckEnabled(ctx android.ModuleContext, apiToCheck ApiToCheck, apiVersio "them instead.") } return false + } else if ctx.Config().PartialCompileFlags().Disable_stub_validation && + !ctx.Config().BuildFromTextStub() { + return false } else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" { return true } else if String(apiToCheck.Api_file) != "" { diff --git a/java/droidstubs.go b/java/droidstubs.go index caad6883e..c21592518 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -821,19 +821,17 @@ func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBu } } - if len(aconfigFlagsPaths) == 0 { - // This argument should not be added for "everything" stubs - cmd.Flag("--revert-annotation android.annotation.FlaggedApi") - return - } + // If aconfigFlagsPaths is empty then it is still important to generate the + // Metalava flags config file, albeit with an empty set of flags, so that all + // flagged APIs will be reverted. - releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String())) - revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String())) + releasedFlagsFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flags-%s.pb", stubsType.String())) + metalavaFlagsConfigFile := android.PathForModuleOut(ctx, fmt.Sprintf("flags-config-%s.xml", stubsType.String())) ctx.Build(pctx, android.BuildParams{ Rule: gatherReleasedFlaggedApisRule, Inputs: aconfigFlagsPaths, - Output: releasedFlaggedApisFile, + Output: releasedFlagsFile, Description: fmt.Sprintf("%s gather aconfig flags", stubsType), Args: map[string]string{ "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "), @@ -843,12 +841,12 @@ func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBu ctx.Build(pctx, android.BuildParams{ Rule: generateMetalavaRevertAnnotationsRule, - Input: releasedFlaggedApisFile, - Output: revertAnnotationsFile, - Description: fmt.Sprintf("%s revert annotations", stubsType), + Input: releasedFlagsFile, + Output: metalavaFlagsConfigFile, + Description: fmt.Sprintf("%s metalava flags config", stubsType), }) - cmd.FlagWithInput("@", revertAnnotationsFile) + cmd.FlagWithInput("--config-file ", metalavaFlagsConfigFile) } func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, @@ -1245,7 +1243,7 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Add options for the other optional tasks: API-lint and check-released. // We generate separate timestamp files for them. - doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) + doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().PartialCompileFlags().Disable_api_lint doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") writeSdkValues := Bool(d.properties.Write_sdk_values) diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go index dfdf87703..1f9d223b5 100644 --- a/java/droidstubs_test.go +++ b/java/droidstubs_test.go @@ -410,12 +410,12 @@ func TestAconfigDeclarations(t *testing.T) { m := result.ModuleForTests(t, "foo", "android_common") android.AssertStringDoesContain(t, "foo generates revert annotations file", - strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt") + strings.Join(m.AllOutputs(), ""), "flags-config-exportable.xml") // revert-annotations.txt passed to exportable stubs generation metalava command manifest := m.Output("metalava_exportable.sbox.textproto") cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command) - android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt") + android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "flags-config-exportable.xml") android.AssertStringDoesContain(t, "foo generates exportable stubs jar", strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar") @@ -460,7 +460,7 @@ func TestReleaseExportRuntimeApis(t *testing.T) { m := result.ModuleForTests(t, "foo", "android_common") - rule := m.Output("released-flagged-apis-exportable.txt") + rule := m.Output("released-flags-exportable.pb") exposeWritableApisFilter := "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'" android.AssertStringEquals(t, "Filter argument expected to contain READ_WRITE permissions", exposeWritableApisFilter, rule.Args["filter_args"]) } diff --git a/java/java.go b/java/java.go index c1e4f8ca0..dd9f852f0 100644 --- a/java/java.go +++ b/java/java.go @@ -578,6 +578,7 @@ var ( extraLintCheckTag = dependencyTag{name: "extra-lint-check", toolchain: true} jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true} r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true} + traceReferencesTag = dependencyTag{name: "trace-references"} syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"} javaApiContributionTag = dependencyTag{name: "java-api-contribution"} aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"} @@ -608,6 +609,7 @@ var ( kotlinPluginTag, syspropPublicStubDepTag, instrumentationForTag, + traceReferencesTag, } ) @@ -1954,6 +1956,10 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".jar", j.outputFile) } } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: j.testProperties.Test_suites, + }) } func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -1970,6 +1976,10 @@ func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContex if optionalConfig.Valid() { moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, optionalConfig.String()) } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: j.testHelperLibraryProperties.Test_suites, + }) } func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -2225,7 +2235,7 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { // install these alongside the java binary. ctx.VisitDirectDepsProxyWithTag(jniInstallTag, func(jni android.ModuleProxy) { // Use the BaseModuleName of the dependency (without any prebuilt_ prefix) - commonInfo, _ := android.OtherModuleProvider(ctx, jni, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, jni, android.CommonModuleInfoProvider) j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, commonInfo.BaseModuleName+":"+commonInfo.Target.Arch.ArchType.Bitness()) }) // Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead. @@ -2530,6 +2540,7 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { apiContributions := al.properties.Api_contributions addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") && !ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") && + !ctx.Config().PartialCompileFlags().Disable_stub_validation && proptools.BoolDefault(al.properties.Enable_validation, true) for _, apiContributionName := range apiContributions { ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName) diff --git a/java/java_test.go b/java/java_test.go index a6290a628..1ba78d49b 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -2912,12 +2912,12 @@ func TestApiLibraryAconfigDeclarations(t *testing.T) { m := result.ModuleForTests(t, "foo", "android_common") android.AssertStringDoesContain(t, "foo generates revert annotations file", - strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt") + strings.Join(m.AllOutputs(), ""), "flags-config-exportable.xml") // revert-annotations.txt passed to exportable stubs generation metalava command manifest := m.Output("metalava.sbox.textproto") cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command) - android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt") + android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "flags-config-exportable.xml") } func TestTestOnly(t *testing.T) { @@ -3193,3 +3193,72 @@ cc_library_shared { deps := findDepsOfModule(res, res.ModuleForTests(t, "myjavabin", "android_common").Module(), "mynativelib") android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(deps)) } + +func TestBootJarNotInUsesLibs(t *testing.T) { + t.Parallel() + result := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary"), + FixtureConfigureApexBootJars("myapex:mysdklibrary"), + ).RunTestWithBp(t, ` + bootclasspath_fragment { + name: "myfragment", + contents: ["mysdklibrary"], + hidden_api: { + split_packages: ["*"], + }, + } + + java_sdk_library { + name: "mysdklibrary", + srcs: ["Test.java"], + compile_dex: true, + public: {enabled: true}, + min_sdk_version: "2", + permitted_packages: ["mysdklibrary"], + sdk_version: "current", + } + + java_sdk_library { + name: "myothersdklibrary", + srcs: ["Test.java"], + compile_dex: true, + public: {enabled: true}, + min_sdk_version: "2", + permitted_packages: ["myothersdklibrary"], + sdk_version: "current", + } + + java_library { + name: "foo", + libs: [ + "bar", + "mysdklibrary.stubs", + ], + srcs: ["A.java"], + } + + java_library { + name: "bar", + libs: [ + "myothersdklibrary.stubs" + ], + } + `) + ctx := result.TestContext + fooModule := ctx.ModuleForTests(t, "foo", "android_common") + + androidMkEntries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0] + localExportSdkLibraries := androidMkEntries.EntryMap["LOCAL_EXPORT_SDK_LIBRARIES"] + android.AssertStringListDoesNotContain(t, + "boot jar should not be included in uses libs entries", + localExportSdkLibraries, + "mysdklibrary", + ) + android.AssertStringListContains(t, + "non boot jar is included in uses libs entries", + localExportSdkLibraries, + "myothersdklibrary", + ) +} diff --git a/java/jdeps.go b/java/jdeps.go index 4711dc1a4..56142c89b 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -46,7 +46,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont moduleInfos := make(map[string]android.IdeInfo) ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } diff --git a/java/kotlin.go b/java/kotlin.go index 57d0802e4..308bb0305 100644 --- a/java/kotlin.go +++ b/java/kotlin.go @@ -40,8 +40,8 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports ` -kotlin-home $emptyDir ` + ` -Xplugin=${config.KotlinAbiGenPluginJar} ` + ` -P plugin:org.jetbrains.kotlin.jvm.abi:outputDir=$headerClassesDir && ` + - `${config.SoongZipCmd} -jar $jarArgs -o $out -C $classesDir -D $classesDir -write_if_changed && ` + - `${config.SoongZipCmd} -jar $jarArgs -o $headerJar -C $headerClassesDir -D $headerClassesDir -write_if_changed && ` + + `${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir -write_if_changed && ` + + `${config.SoongZipCmd} -jar -o $headerJar -C $headerClassesDir -D $headerClassesDir -write_if_changed && ` + `rm -rf "$srcJarDir" "$classesDir" "$headerClassesDir"`, CommandDeps: []string{ "${config.KotlincCmd}", @@ -62,7 +62,7 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports Restat: true, }, "kotlincFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "classesDir", - "headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name", "jarArgs") + "headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name") var kotlinKytheExtract = pctx.AndroidStaticRule("kotlinKythe", blueprint.RuleParams{ @@ -104,7 +104,8 @@ func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Path // kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile. func (j *Module) kotlinCompile(ctx android.ModuleContext, outputFile, headerOutputFile android.WritablePath, - srcFiles, commonSrcFiles, srcJars android.Paths, flags javaBuilderFlags, manifest android.OptionalPath) { + srcFiles, commonSrcFiles, srcJars android.Paths, + flags javaBuilderFlags) { var deps android.Paths deps = append(deps, flags.kotlincClasspath...) @@ -126,12 +127,6 @@ func (j *Module) kotlinCompile(ctx android.ModuleContext, outputFile, headerOutp android.WriteFileRule(ctx, classpathRspFile, strings.Join(flags.kotlincClasspath.Strings(), " ")) deps = append(deps, classpathRspFile) - var jarArgs string - if manifest.Valid() { - jarArgs = "-m " + manifest.Path().String() - deps = append(deps, manifest.Path()) - } - ctx.Build(pctx, android.BuildParams{ Rule: kotlinc, Description: "kotlinc", @@ -152,7 +147,6 @@ func (j *Module) kotlinCompile(ctx android.ModuleContext, outputFile, headerOutp "emptyDir": android.PathForModuleOut(ctx, "kotlinc", "empty").String(), "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(), "name": kotlinName, - "jarArgs": jarArgs, }, }) diff --git a/java/lint.go b/java/lint.go index c31dfd005..dc1e51ffb 100644 --- a/java/lint.go +++ b/java/lint.go @@ -659,7 +659,7 @@ func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { var outputs []*LintInfo var dirs []string ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { - commonInfo, _ := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider) if ctx.Config().KatiEnabled() && !commonInfo.ExportedToMake { return } diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index ab4f8f81f..d2ec8bd4f 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -277,7 +277,7 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet var compatConfigMetadata android.Paths ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { - if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } if c, ok := android.OtherModuleProvider(ctx, module, PlatformCompatConfigMetadataInfoProvider); ok { diff --git a/java/ravenwood.go b/java/ravenwood.go index c4078c587..a942dc653 100644 --- a/java/ravenwood.go +++ b/java/ravenwood.go @@ -117,6 +117,8 @@ func ravenwoodTestFactory() android.Module { "ravenwood-tests", } module.testProperties.Test_options.Unit_test = proptools.BoolPtr(false) + module.Module.sourceProperties.Test_only = proptools.BoolPtr(true) + module.Module.sourceProperties.Top_level_test_target = true InitJavaModule(module, android.DeviceSupported) android.InitDefaultableModule(module) diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go index 24a02bbdc..d6493bcfa 100644 --- a/java/ravenwood_test.go +++ b/java/ravenwood_test.go @@ -230,4 +230,15 @@ func TestRavenwoodTest(t *testing.T) { android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/libred.so") android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so") android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-utils/framework-rules.ravenwood.jar") + + // Ensure they are listed as "test" modules for code coverage + expectedTestOnlyModules := []string{ + "ravenwood-test", + "ravenwood-test-empty", + } + expectedTopLevelTests := []string{ + "ravenwood-test", + "ravenwood-test-empty", + } + assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests) } diff --git a/java/robolectric.go b/java/robolectric.go index be369f780..1d204a4e0 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -284,6 +284,11 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ TestSuites: r.TestSuites(), }) + + android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{ + TestOnly: Bool(r.sourceProperties.Test_only), + TopLevelTarget: r.sourceProperties.Top_level_test_target, + }) } func generateSameDirRoboTestConfigJar(ctx android.ModuleContext, outputFile android.ModuleOutPath) { @@ -335,7 +340,8 @@ func RobolectricTestFactory() android.Module { module.Module.dexpreopter.isTest = true module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true) - + module.Module.sourceProperties.Test_only = proptools.BoolPtr(true) + module.Module.sourceProperties.Top_level_test_target = true module.testProperties.Test_suites = []string{"robolectric-tests"} InitJavaModule(module, android.DeviceSupported) diff --git a/java/robolectric_test.go b/java/robolectric_test.go index 4bf224b4f..cc16c6a26 100644 --- a/java/robolectric_test.go +++ b/java/robolectric_test.go @@ -107,4 +107,15 @@ func TestRobolectricJniTest(t *testing.T) { // Check that the .so files make it into the output. module := ctx.ModuleForTests(t, "robo-test", "android_common") module.Output(installPathPrefix + "/robo-test/lib64/jni-lib1.so") + + // Ensure they are listed as "test" modules for code coverage + expectedTestOnlyModules := []string{ + "robo-test", + } + + expectedTopLevelTests := []string{ + "robo-test", + } + assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests) + } diff --git a/java/rro.go b/java/rro.go index b3d934867..4ae8d7fc7 100644 --- a/java/rro.go +++ b/java/rro.go @@ -99,15 +99,6 @@ type RuntimeResourceOverlayProperties struct { Overrides []string } -// RuntimeResourceOverlayModule interface is used by the apex package to gather information from -// a RuntimeResourceOverlay module. -type RuntimeResourceOverlayModule interface { - android.Module - OutputFile() android.Path - Certificate() Certificate - Theme() string -} - // RRO's partition logic is different from the partition logic of other modules defined in soong/android/paths.go // The default partition for RRO is "/product" and not "/system" func rroPartition(ctx android.ModuleContext) string { @@ -217,11 +208,13 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC }) android.SetProvider(ctx, RuntimeResourceOverlayInfoProvider, RuntimeResourceOverlayInfo{ - OutputFile: r.OutputFile(), + OutputFile: r.outputFile, Certificate: r.Certificate(), Theme: r.Theme(), }) + ctx.SetOutputFiles([]android.Path{r.outputFile}, "") + buildComplianceMetadata(ctx) } @@ -252,10 +245,6 @@ func (r *RuntimeResourceOverlay) Certificate() Certificate { return r.certificate } -func (r *RuntimeResourceOverlay) OutputFile() android.Path { - return r.outputFile -} - func (r *RuntimeResourceOverlay) Theme() string { return String(r.properties.Theme) } @@ -427,6 +416,11 @@ func (a *AutogenRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android. // Install the signed apk installDir := android.PathForModuleInstall(ctx, "overlay") ctx.InstallFile(installDir, signed.Base(), signed) + + android.SetProvider(ctx, RuntimeResourceOverlayInfoProvider, RuntimeResourceOverlayInfo{ + OutputFile: signed, + Certificate: a.certificate, + }) } func (a *AutogenRuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { diff --git a/java/rro_test.go b/java/rro_test.go index 0ccc8e707..3e4fed51e 100644 --- a/java/rro_test.go +++ b/java/rro_test.go @@ -358,3 +358,21 @@ func TestRuntimeResourceOverlayFlagsPackages(t *testing.T) { "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt", ) } + +func TestCanBeDataOfTest(t *testing.T) { + android.GroupFixturePreparers( + prepareForJavaTest, + ).RunTestWithBp(t, ` + runtime_resource_overlay { + name: "foo", + sdk_version: "current", + } + android_test { + name: "bar", + data: [ + ":foo", + ], + } + `) + // Just test that this doesn't get errors +} diff --git a/java/sdk.go b/java/sdk.go index ab1c653d1..73262dab3 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -382,7 +382,7 @@ func createAPIFingerprint(ctx android.SingletonContext) { rule.Build("api_fingerprint", "generate api_fingerprint.txt") - if ctx.Config().BuildOS == android.Linux { + if ctx.Config().BuildOS.Linux() { ctx.DistForGoals([]string{"sdk", "droidcore"}, out) } } diff --git a/java/sdk_library.go b/java/sdk_library.go index 0fee529e9..00ba8b2fb 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1337,10 +1337,10 @@ func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) { func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) { android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.BaseModuleContext, do android.PayloadDepsCallback) { - ctx.WalkDeps(func(child android.Module, parent android.Module) bool { + ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { isExternal := !android.IsDepInSameApex(ctx, module, child) - if am, ok := child.(android.ApexModule); ok { - if !do(ctx, parent, am, isExternal) { + if am, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); ok && am.IsApexModule { + if !do(ctx, parent, child, isExternal) { return false } } diff --git a/java/testing.go b/java/testing.go index 3abbb8453..d7878d68d 100644 --- a/java/testing.go +++ b/java/testing.go @@ -424,7 +424,6 @@ func gatherRequiredDepsForTest() string { "kotlin-stdlib-jdk8", "kotlin-annotations", "stub-annotations", - "aconfig-annotations-lib", "aconfig_storage_stub", "unsupportedappusage", diff --git a/java/tracereferences.go b/java/tracereferences.go new file mode 100644 index 000000000..342b6a630 --- /dev/null +++ b/java/tracereferences.go @@ -0,0 +1,54 @@ +// 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 java + +import ( + "android/soong/android" + + "github.com/google/blueprint" +) + +var traceReferences = pctx.AndroidStaticRule("traceReferences", + blueprint.RuleParams{ + Command: `${config.TraceReferencesCmd} ` + + // Note that we suppress missing def errors, as we're only interested + // in the direct deps between the sources and target. + `--map-diagnostics:MissingDefinitionsDiagnostic error none ` + + `--keep-rules ` + + `--output ${out} ` + + `--target ${in} ` + + // `--source` and `--lib` are already prepended to each + // jar reference in the sources and libs joined string args. + `${sources} ` + + `${libs}`, + CommandDeps: []string{"${config.TraceReferencesCmd}"}, + }, "sources", "libs") + +// Generates keep rules in output corresponding to any references from sources +// (a list of jars) onto target (the referenced jar) that are not included in +// libs (a list of external jars). +func TraceReferences(ctx android.ModuleContext, sources android.Paths, target android.Path, libs android.Paths, + output android.WritablePath) { + ctx.Build(pctx, android.BuildParams{ + Rule: traceReferences, + Input: target, + Output: output, + Implicits: append(sources, libs...), + Args: map[string]string{ + "sources": android.JoinWithPrefix(sources.Strings(), "--source "), + "libs": android.JoinWithPrefix(libs.Strings(), "--lib "), + }, + }) +} diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go index 43fe8aa33..925d7b163 100644 --- a/linkerconfig/linkerconfig.go +++ b/linkerconfig/linkerconfig.go @@ -127,7 +127,7 @@ func BuildLinkerConfig( for _, m := range requireModules { if _, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); ok { if android.OtherModuleProviderOrDefault(ctx, m, cc.LinkableInfoProvider).HasStubsVariants && - !android.OtherModuleProviderOrDefault(ctx, m, android.CommonModuleInfoKey).Host { + !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).Host { name := ctx.OtherModuleName(m) if ccInfo, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); ok && ccInfo.LinkerInfo != nil && ccInfo.LinkerInfo.ImplementationModuleName != nil { name = *ccInfo.LinkerInfo.ImplementationModuleName diff --git a/phony/phony.go b/phony/phony.go index 4f61c4583..e75f4c809 100644 --- a/phony/phony.go +++ b/phony/phony.go @@ -104,8 +104,7 @@ type PhonyRule struct { android.ModuleBase android.DefaultableModuleBase - phonyDepsModuleNames []string - properties PhonyProperties + properties PhonyProperties } type PhonyProperties struct { @@ -126,18 +125,8 @@ func PhonyRuleFactory() android.Module { } func (p *PhonyRule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - p.phonyDepsModuleNames = p.properties.Phony_deps.GetOrDefault(ctx, nil) -} - -func (p *PhonyRule) AndroidMk() android.AndroidMkData { - return android.AndroidMkData{ - Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { - if len(p.phonyDepsModuleNames) > 0 { - depModulesStr := strings.Join(p.phonyDepsModuleNames, " ") - fmt.Fprintln(w, ".PHONY:", name) - fmt.Fprintln(w, name, ":", depModulesStr) - } - }, + for _, dep := range p.properties.Phony_deps.GetOrDefault(ctx, nil) { + ctx.Phony(ctx.ModuleName(), android.PathForPhony(ctx, dep)) } } diff --git a/python/binary.go b/python/binary.go index feac72a26..f894299f9 100644 --- a/python/binary.go +++ b/python/binary.go @@ -125,6 +125,7 @@ func (p *PythonBinaryModule) GenerateAndroidBuildActions(ctx android.ModuleConte func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) { embeddedLauncher := p.isEmbeddedLauncherEnabled() depsSrcsZips := p.collectPathsFromTransitiveDeps(ctx, embeddedLauncher) + bundleSharedLibs := p.collectSharedLibDeps(ctx) main := "" if p.autorun() { main = p.getPyMainFile(ctx, p.srcsPathMappings) @@ -149,6 +150,11 @@ func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) { srcsZips = append(srcsZips, p.srcsZip) } srcsZips = append(srcsZips, depsSrcsZips...) + if ctx.Host() && len(bundleSharedLibs) > 0 { + // only bundle shared libs for host binaries + sharedLibZip := p.zipSharedLibs(ctx, bundleSharedLibs) + srcsZips = append(srcsZips, sharedLibZip) + } p.installSource = registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath, "python3", main, p.getStem(ctx), srcsZips) @@ -159,6 +165,10 @@ func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) { sharedLibs = append(sharedLibs, ctx.OtherModuleName(dep)) } p.androidMkSharedLibs = sharedLibs + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: p.binaryProperties.Test_suites, + }) } func (p *PythonBinaryModule) AndroidMkEntries() []android.AndroidMkEntries { diff --git a/python/python.go b/python/python.go index f8f41658f..de21e39bd 100644 --- a/python/python.go +++ b/python/python.go @@ -20,11 +20,13 @@ import ( "fmt" "path/filepath" "regexp" + "sort" "strings" "android/soong/cc" "github.com/google/blueprint" + "github.com/google/blueprint/depset" "github.com/google/blueprint/proptools" "android/soong/android" @@ -36,6 +38,7 @@ type PythonLibraryInfo struct { SrcsZip android.Path PrecompiledSrcsZip android.Path PkgPath string + BundleSharedLibs android.Paths } var PythonLibraryInfoProvider = blueprint.NewProvider[PythonLibraryInfo]() @@ -105,6 +108,10 @@ type BaseProperties struct { // list of the Python libraries compatible both with Python2 and Python3. Libs []string `android:"arch_variant"` + // TODO: b/403060602 - add unit tests for this property and related code + // list of shared libraries that should be packaged with the python code for this module. + Shared_libs []string `android:"arch_variant"` + Version struct { // Python2-specific properties, including whether Python2 is supported for this module // and version-specific sources, exclusions and dependencies. @@ -158,6 +165,10 @@ type PythonLibraryModule struct { precompiledSrcsZip android.Path sourceProperties android.SourceProperties + + // The shared libraries that should be bundled with the python code for + // any standalone python binaries that depend on this module. + bundleSharedLibs android.Paths } // newModule generates new Python base module @@ -197,6 +208,10 @@ func (p *PythonLibraryModule) getBaseProperties() *BaseProperties { return &p.properties } +func (p *PythonLibraryModule) getBundleSharedLibs() android.Paths { + return p.bundleSharedLibs +} + func (p *PythonLibraryModule) init() android.Module { p.AddProperties(&p.properties, &p.protoProperties, &p.sourceProperties) android.InitAndroidArchModule(p, p.hod, p.multilib) @@ -224,6 +239,7 @@ type installDependencyTag struct { var ( pythonLibTag = dependencyTag{name: "pythonLib"} javaDataTag = dependencyTag{name: "javaData"} + sharedLibTag = dependencyTag{name: "sharedLib"} // The python interpreter, with soong module name "py3-launcher" or "py3-launcher-autorun". launcherTag = dependencyTag{name: "launcher"} launcherSharedLibTag = installDependencyTag{name: "launcherSharedLib"} @@ -288,6 +304,12 @@ func (p *PythonLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) { javaDataVariation := []blueprint.Variation{{"arch", android.Common.String()}} ctx.AddVariationDependencies(javaDataVariation, javaDataTag, p.properties.Java_data...) + if ctx.Host() { + ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), sharedLibTag, p.properties.Shared_libs...) + } else if len(p.properties.Shared_libs) > 0 { + ctx.PropertyErrorf("shared_libs", "shared_libs is not supported for device builds") + } + p.AddDepsOnPythonLauncherAndStdlib(ctx, hostStdLibTag, hostLauncherTag, hostlauncherSharedLibTag, false, ctx.Config().BuildOSTarget) } @@ -377,6 +399,25 @@ func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleCont expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...) } + var directImplementationDeps android.Paths + var transitiveImplementationDeps []depset.DepSet[android.Path] + ctx.VisitDirectDepsProxyWithTag(sharedLibTag, func(dep android.ModuleProxy) { + sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider) + if sharedLibInfo.SharedLibrary != nil { + expandedData = append(expandedData, android.OutputFilesForModule(ctx, dep, "")...) + directImplementationDeps = append(directImplementationDeps, android.OutputFilesForModule(ctx, dep, "")...) + if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok { + transitiveImplementationDeps = append(transitiveImplementationDeps, info.ImplementationDeps) + p.bundleSharedLibs = append(p.bundleSharedLibs, info.ImplementationDeps.ToList()...) + } + } else { + ctx.PropertyErrorf("shared_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep)) + } + }) + android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{ + ImplementationDeps: depset.New(depset.PREORDER, directImplementationDeps, transitiveImplementationDeps), + }) + // Validate pkg_path property pkgPath := String(p.properties.Pkg_path) if pkgPath != "" { @@ -400,8 +441,7 @@ func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleCont // generate the zipfile of all source and data files p.srcsZip = p.createSrcsZip(ctx, pkgPath) - // TODO(b/388344853): precompilation temporarily disabled for python3.13 upgrade - p.precompiledSrcsZip = p.srcsZip //p.precompileSrcs(ctx) + p.precompiledSrcsZip = p.precompileSrcs(ctx) android.SetProvider(ctx, PythonLibraryInfoProvider, PythonLibraryInfo{ SrcsPathMappings: p.getSrcsPathMappings(), @@ -409,6 +449,7 @@ func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleCont SrcsZip: p.getSrcsZip(), PkgPath: p.getPkgPath(), PrecompiledSrcsZip: p.getPrecompiledSrcsZip(), + BundleSharedLibs: p.getBundleSharedLibs(), }) } @@ -685,6 +726,56 @@ func (p *PythonLibraryModule) collectPathsFromTransitiveDeps(ctx android.ModuleC return result } +func (p *PythonLibraryModule) collectSharedLibDeps(ctx android.ModuleContext) android.Paths { + seen := make(map[android.Module]bool) + + var result android.Paths + + ctx.WalkDepsProxy(func(child, _ android.ModuleProxy) bool { + // we only collect dependencies tagged as python library deps + if ctx.OtherModuleDependencyTag(child) != pythonLibTag { + return false + } + if seen[child] { + return false + } + seen[child] = true + dep, isLibrary := android.OtherModuleProvider(ctx, child, PythonLibraryInfoProvider) + if isLibrary { + result = append(result, dep.BundleSharedLibs...) + } + return true + }) + return result +} + +func (p *PythonLibraryModule) zipSharedLibs(ctx android.ModuleContext, bundleSharedLibs android.Paths) android.Path { + // sort the paths to keep the output deterministic + sort.Slice(bundleSharedLibs, func(i, j int) bool { + return bundleSharedLibs[i].String() < bundleSharedLibs[j].String() + }) + + parArgs := []string{"-symlinks=false", "-P lib64"} + paths := android.Paths{} + for _, path := range bundleSharedLibs { + // specify relative root of file in following -f arguments + parArgs = append(parArgs, `-C `+filepath.Dir(path.String())) + parArgs = append(parArgs, `-f `+path.String()) + paths = append(paths, path) + } + srcsZip := android.PathForModuleOut(ctx, ctx.ModuleName()+".sharedlibs.srcszip") + ctx.Build(pctx, android.BuildParams{ + Rule: zip, + Description: "bundle shared libraries for python binary", + Output: srcsZip, + Implicits: paths, + Args: map[string]string{ + "args": strings.Join(parArgs, " "), + }, + }) + return srcsZip +} + // chckForDuplicateOutputPath checks whether outputPath has already been included in map m, which // would result in two files being placed in the same location. // If there is a duplicate path, an error is thrown and true is returned diff --git a/python/scripts/main.py b/python/scripts/main.py index 225dbe4c1..35cdfc47e 100644 --- a/python/scripts/main.py +++ b/python/scripts/main.py @@ -1,5 +1,13 @@ + +import os import runpy +import shutil import sys +import tempfile +import zipfile + +from pathlib import PurePath + sys.argv[0] = __loader__.archive @@ -9,4 +17,32 @@ sys.argv[0] = __loader__.archive # when people try to use it. sys.executable = None -runpy._run_module_as_main("ENTRY_POINT", alter_argv=False) +# Extract the shared libraries from the zip file into a temporary directory. +# This works around the limitations of dynamic linker. Some Python libraries +# reference the .so files relatively and so extracting only the .so files +# does not work, so we extract the entire parent directory of the .so files to a +# tempdir and then add that to sys.path. +tempdir = None +with zipfile.ZipFile(__loader__.archive) as z: + # any root so files or root directories that contain so files will be + # extracted to the tempdir so the linker load them, this minimizes the + # number of files that need to be extracted to a tempdir + extract_paths = {} + for member in z.infolist(): + if member.filename.endswith('.so'): + extract_paths[PurePath(member.filename).parts[0]] = member.filename + if extract_paths: + tempdir = tempfile.mkdtemp() + for member in z.infolist(): + if not PurePath(member.filename).parts[0] in extract_paths.keys(): + continue + if member.is_dir(): + os.makedirs(os.path.join(tempdir, member.filename)) + else: + z.extract(member, tempdir) + sys.path.insert(0, tempdir) +try: + runpy._run_module_as_main("ENTRY_POINT", alter_argv=False) +finally: + if tempdir is not None: + shutil.rmtree(tempdir) diff --git a/rust/benchmark.go b/rust/benchmark.go index daba9642e..3aa2f1779 100644 --- a/rust/benchmark.go +++ b/rust/benchmark.go @@ -146,4 +146,8 @@ func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInf } else { moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: benchmark.Properties.Test_suites, + }) } diff --git a/rust/doc.go b/rust/doc.go index fe205233d..3616c8ed5 100644 --- a/rust/doc.go +++ b/rust/doc.go @@ -37,14 +37,14 @@ func (n *rustdocSingleton) GenerateBuildActions(ctx android.SingletonContext) { FlagWithArg("-C ", docDir.String()). FlagWithArg("-D ", docDir.String()) - ctx.VisitAllModules(func(module android.Module) { - if !module.Enabled(ctx) { + ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { + if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled { return } - if m, ok := module.(*Module); ok { - if m.docTimestampFile.Valid() { - zipCmd.Implicit(m.docTimestampFile.Path()) + if m, ok := android.OtherModuleProvider(ctx, module, RustInfoProvider); ok { + if m.DocTimestampFile.Valid() { + zipCmd.Implicit(m.DocTimestampFile.Path()) } } }) diff --git a/rust/rust.go b/rust/rust.go index d8a044423..54b5d92e3 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -61,6 +61,7 @@ type RustInfo struct { SnapshotInfo *cc.SnapshotInfo SourceProviderInfo *SourceProviderInfo XrefRustFiles android.Paths + DocTimestampFile android.OptionalPath } var RustInfoProvider = blueprint.NewProvider[*RustInfo]() @@ -1173,6 +1174,7 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { RustSubName: mod.Properties.RustSubName, TransitiveAndroidMkSharedLibs: mod.transitiveAndroidMkSharedLibs, XrefRustFiles: mod.XrefRustFiles(), + DocTimestampFile: mod.docTimestampFile, } if mod.compiler != nil { rustInfo.CompilerInfo = &CompilerInfo{ @@ -1478,10 +1480,10 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { rustInfo, hasRustInfo := android.OtherModuleProvider(ctx, dep, RustInfoProvider) ccInfo, _ := android.OtherModuleProvider(ctx, dep, cc.CcInfoProvider) linkableInfo, hasLinkableInfo := android.OtherModuleProvider(ctx, dep, cc.LinkableInfoProvider) - commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) if hasRustInfo && !linkableInfo.Static && !linkableInfo.Shared { //Handle Rust Modules - makeLibName := rustMakeLibName(rustInfo, linkableInfo, &commonInfo, depName+rustInfo.RustSubName) + makeLibName := rustMakeLibName(rustInfo, linkableInfo, commonInfo, depName+rustInfo.RustSubName) switch { case depTag == dylibDepTag: @@ -1626,7 +1628,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } else if hasLinkableInfo { //Handle C dependencies - makeLibName := cc.MakeLibName(ccInfo, linkableInfo, &commonInfo, depName) + makeLibName := cc.MakeLibName(ccInfo, linkableInfo, commonInfo, depName) if !hasRustInfo { if commonInfo.Target.Os != ctx.Os() { ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) diff --git a/rust/test.go b/rust/test.go index 9833ffdb6..cedced260 100644 --- a/rust/test.go +++ b/rust/test.go @@ -165,7 +165,7 @@ func (test *testDecorator) install(ctx ModuleContext) { if linkableDep.OutputFile.Valid() { // Copy the output in "lib[64]" so that it's compatible with // the default rpath values. - commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) libDir := "lib" if commonInfo.Target.Arch.ArchType.Multilib == "lib64" { libDir = "lib64" @@ -242,6 +242,10 @@ func (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { flags.RustFlags = append(flags.RustFlags, "-Z panic_abort_tests") } + // Add a default rpath to allow tests to dlopen libraries specified in data_libs. + flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, `-Wl,-rpath,\$$ORIGIN/lib64`) + flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, `-Wl,-rpath,\$$ORIGIN/lib`) + return flags } @@ -316,6 +320,10 @@ func (test *testDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *and } else { moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite") } + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: test.Properties.Test_suites, + }) } func rustTestHostMultilib(ctx android.LoadHookContext) { diff --git a/scripts/Android.bp b/scripts/Android.bp index 94163a5c2..c0e13d52f 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -287,9 +287,13 @@ python_test_host { ], } -sh_binary_host { - name: "keep-flagged-apis", - src: "keep-flagged-apis.sh", +python_binary_host { + name: "aconfig-to-metalava-flags", + main: "aconfig-to-metalava-flags.py", + srcs: ["aconfig-to-metalava-flags.py"], + libs: [ + "libaconfig_python_proto", + ], } python_binary_host { diff --git a/scripts/aconfig-to-metalava-flags.py b/scripts/aconfig-to-metalava-flags.py new file mode 100644 index 000000000..efa85ecb3 --- /dev/null +++ b/scripts/aconfig-to-metalava-flags.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2025 The Android Open Source Project +# +# 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. + +"""Converts a set of aconfig protobuf flags to a Metalava config file.""" + +# Formatted using `pyformat -i scripts/aconfig-to-metalava-flags.py` + +import argparse +import sys +import xml.etree.ElementTree as ET + +from protos import aconfig_pb2 + +_READ_ONLY = aconfig_pb2.flag_permission.READ_ONLY +_ENABLED = aconfig_pb2.flag_state.ENABLED +_DISABLED = aconfig_pb2.flag_state.DISABLED + +# The namespace of the Metalava config file. +CONFIG_NS = 'http://www.google.com/tools/metalava/config' + + +def config_name(tag: str): + """Create a QName in the config namespace. + + :param:tag the name of the entity in the config namespace. + """ + return f'{{{CONFIG_NS}}}{tag}' + + +def main(): + """Program entry point.""" + args_parser = argparse.ArgumentParser( + description='Generate Metalava flags config from aconfig protobuf', + ) + args_parser.add_argument( + 'input', + help='The path to the aconfig protobuf file', + ) + args = args_parser.parse_args(sys.argv[1:]) + + # Read the parsed_flags from the protobuf file. + with open(args.input, 'rb') as f: + parsed_flags = aconfig_pb2.parsed_flags.FromString(f.read()) + + # Create the structure of the XML config file. + config = ET.Element(config_name('config')) + api_flags = ET.SubElement(config, config_name('api-flags')) + # Create an <api-flag> element for each parsed_flag. + for flag in parsed_flags.parsed_flag: + if flag.permission == _READ_ONLY: + # Ignore any read only disabled flags as Metalava assumes that as the + # default when an <api-flags/> element is provided so this reduces the + # size of the file. + if flag.state == _DISABLED: + continue + mutability = 'immutable' + else: + mutability = 'mutable' + if flag.state == _ENABLED: + status = 'enabled' + else: + status = 'disabled' + attributes = { + 'package': flag.package, + 'name': flag.name, + 'mutability': mutability, + 'status': status, + } + # Convert the attribute names into qualified names in, what will become, the + # default namespace for the XML file. This is needed to ensure that the + # attribute will be written in the XML file without a prefix, e.g. + # `name="flag_name"`. Without it, a namespace prefix, e.g. `ns1`, will be + # synthesized for the attribute when writing the XML file, i.e. it + # will be written as `ns1:name="flag_name"`. Strictly speaking, that is + # unnecessary as the "Namespaces in XML 1.0 (Third Edition)" specification + # says that unprefixed attribute names have no namespace. + qualified_attributes = {config_name(k): v for (k, v) in attributes.items()} + ET.SubElement(api_flags, config_name('api-flag'), qualified_attributes) + + # Create a tree and add white space so it will pretty print when written out. + tree = ET.ElementTree(config) + ET.indent(tree) + + # Write the tree using the config namespace as the default. + tree.write(sys.stdout, encoding='unicode', default_namespace=CONFIG_NS) + sys.stdout.close() + + +if __name__ == '__main__': + main() diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py index 74befd5de..a0d25465c 100644 --- a/scripts/gen_build_prop.py +++ b/scripts/gen_build_prop.py @@ -113,6 +113,7 @@ def generate_common_build_props(args): print("####################################") config = args.config + build_flags = config["BuildFlags"] partition = args.partition if partition == "system": @@ -164,6 +165,7 @@ def generate_common_build_props(args): print(f"ro.{partition}.build.version.release={config['Platform_version_last_stable']}") print(f"ro.{partition}.build.version.release_or_codename={config['Platform_version_name']}") print(f"ro.{partition}.build.version.sdk={config['Platform_sdk_version']}") + print(f"ro.{partition}.build.version.sdk_minor={build_flags['RELEASE_PLATFORM_SDK_MINOR_VERSION']}") def generate_build_info(args): print() @@ -196,6 +198,7 @@ def generate_build_info(args): print(f"ro.build.display.id?={config['BuildDesc']}") print(f"ro.build.version.incremental={config['BuildNumber']}") print(f"ro.build.version.sdk={config['Platform_sdk_version']}") + print(f"ro.build.version.sdk_minor={build_flags['RELEASE_PLATFORM_SDK_MINOR_VERSION']}") print(f"ro.build.version.preview_sdk={config['Platform_preview_sdk_version']}") print(f"ro.build.version.preview_sdk_fingerprint={config['PlatformPreviewSdkFingerprint']}") print(f"ro.build.version.codename={config['Platform_sdk_codename']}") diff --git a/scripts/keep-flagged-apis.sh b/scripts/keep-flagged-apis.sh deleted file mode 100755 index 48efb7a29..000000000 --- a/scripts/keep-flagged-apis.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -e -# -# Copyright 2023 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. - -# Convert a list of flags in the input file to a list of metalava options -# that will keep the APIs for those flags will hiding all other flagged -# APIs. - -FLAGS="$1" - -FLAGGED="android.annotation.FlaggedApi" - -# Convert the list of feature flags in the input file to Metalava options -# of the form `--revert-annotation !android.annotation.FlaggedApi("<flag>")` -# to prevent the annotated APIs from being hidden, i.e. include the annotated -# APIs in the SDK snapshots. -while read -r line; do - # Escape and quote the key for sed - escaped_line=$(echo "$line" | sed "s/'/\\\'/g; s/ /\\ /g") - - echo "--revert-annotation '!$FLAGGED(\"$escaped_line\")'" -done < "$FLAGS" - -# Revert all flagged APIs, unless listed above. -echo "--revert-annotation $FLAGGED" diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py index 175451e74..96dc5a6ce 100755 --- a/scripts/manifest_check.py +++ b/scripts/manifest_check.py @@ -132,7 +132,7 @@ def enforce_uses_libraries(manifest, required, optional, missing_optional, relax #pylint: disable=line-too-long errmsg = ''.join([ - 'mismatch in the <uses-library> tags between the build system and the ' + 'mismatch or misordering in the <uses-library> tags between the build system and the ' 'manifest:\n', '\t- required libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(required), C_OFF), '\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_required), C_OFF), diff --git a/sh/sh_binary.go b/sh/sh_binary.go index d00c056ee..57f5ad1c7 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -510,7 +510,7 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { // so that it's compatible with the default rpath values. var relPath string linkableInfo := android.OtherModuleProviderOrDefault(ctx, dep, cc.LinkableInfoProvider) - commonInfo := android.OtherModuleProviderOrDefault(ctx, dep, android.CommonModuleInfoKey) + commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider) if commonInfo.Target.Arch.ArchType.Multilib == "lib64" { relPath = filepath.Join("lib64", linkableInfo.OutputFile.Path().Base()) @@ -574,6 +574,10 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.testConfig.String()) } moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.extraTestConfigs.Strings()...) + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: s.testProperties.Test_suites, + }) } func addArch(archType string, paths android.Paths) []string { @@ -609,6 +613,8 @@ func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries { entries.AddStrings("LOCAL_EXTRA_FULL_TEST_CONFIGS", s.extraTestConfigs.Strings()...) } + entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !proptools.BoolDefault(s.testProperties.Auto_gen_config, true)) + s.testProperties.Test_options.SetAndroidMkEntries(entries) }, }, diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go index 6dd48eb5a..2b341288a 100644 --- a/tradefed_modules/test_module_config.go +++ b/tradefed_modules/test_module_config.go @@ -426,6 +426,10 @@ func (m *testModuleConfigModule) generateManifestAndConfig(ctx android.ModuleCon LocalCertificate: m.provider.LocalCertificate, IsUnitTest: m.provider.IsUnitTest, }) + + android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{ + TestSuites: m.tradefedProperties.Test_suites, + }) } var _ android.AndroidMkEntriesProvider = (*testModuleConfigHostModule)(nil) |