diff options
38 files changed, 825 insertions, 498 deletions
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go index f3c68c37a..5a5262485 100644 --- a/aconfig/all_aconfig_declarations.go +++ b/aconfig/all_aconfig_declarations.go @@ -129,6 +129,7 @@ func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx and invalidExportedFlags := android.PathForIntermediates(ctx, "invalid_exported_flags.txt") GenerateExportedFlagCheck(ctx, invalidExportedFlags, parsedFlagsFile, this.properties) depsFiles = append(depsFiles, invalidExportedFlags) + ctx.Phony("droidcore", invalidExportedFlags) } } diff --git a/android/Android.bp b/android/Android.bp index 00dc50ac2..71e674767 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -83,6 +83,7 @@ bootstrap_go_package { "nothing.go", "notices.go", "onceper.go", + "otatools_package_cert_zip.go", "override_module.go", "package.go", "package_ctx.go", diff --git a/android/configurable_properties.go b/android/configurable_properties.go index 2c794a186..bde33e99b 100644 --- a/android/configurable_properties.go +++ b/android/configurable_properties.go @@ -7,7 +7,8 @@ import "github.com/google/blueprint/proptools" // to indicate a "default" case. func CreateSelectOsToBool(cases map[string]*bool) proptools.Configurable[bool] { var resultCases []proptools.ConfigurableCase[bool] - for pattern, value := range cases { + for _, pattern := range SortedKeys(cases) { + value := cases[pattern] if pattern == "" { resultCases = append(resultCases, proptools.NewConfigurableCase( []proptools.ConfigurablePattern{proptools.NewDefaultConfigurablePattern()}, diff --git a/android/module.go b/android/module.go index 87377cc75..ecd0f239c 100644 --- a/android/module.go +++ b/android/module.go @@ -22,6 +22,7 @@ import ( "reflect" "slices" "sort" + "strconv" "strings" "github.com/google/blueprint" @@ -2699,6 +2700,13 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu return proptools.ConfigurableValueString(v) case "bool": return proptools.ConfigurableValueBool(v == "true") + case "int": + i, err := strconv.ParseInt(v, 10, 64) + if err != nil { + ctx.OtherModulePropertyErrorf(m, property, "integer soong_config_variable was not an int: %q", v) + return proptools.ConfigurableValueUndefined() + } + return proptools.ConfigurableValueInt(i) case "string_list": return proptools.ConfigurableValueStringList(strings.Split(v, " ")) default: diff --git a/android/neverallow.go b/android/neverallow.go index 5c90501d7..98b443ee4 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -311,9 +311,9 @@ func createLimitGenruleRules() []Rule { "trusty_tee_package", // Trusty vm target names "trusty_desktop_vm_arm64.bin", - "trusty_desktop_vm_x86_64.elf", + "trusty_desktop_vm_x86_64.bin", "trusty_desktop_test_vm_arm64.bin", - "trusty_desktop_test_vm_x86_64.elf", + "trusty_desktop_test_vm_x86_64.bin", "trusty_test_vm_arm64.bin", "trusty_test_vm_x86_64.elf", "trusty_test_vm_os_arm64.bin", @@ -388,6 +388,7 @@ func createPrebuiltEtcBpDefineRule() Rule { "prebuilt_radio", "prebuilt_gpu", "prebuilt_vendor_overlay", + "prebuilt_tee", ). DefinedInBpFile(). Because("module type not allowed to be defined in bp file") diff --git a/android/otatools_package_cert_zip.go b/android/otatools_package_cert_zip.go new file mode 100644 index 000000000..03265cad3 --- /dev/null +++ b/android/otatools_package_cert_zip.go @@ -0,0 +1,62 @@ +// Copyright 2025 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "github.com/google/blueprint" +) + +func init() { + RegisterOtatoolsPackageBuildComponents(InitRegistrationContext) + pctx.HostBinToolVariable("SoongZipCmd", "soong_zip") +} + +func RegisterOtatoolsPackageBuildComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("otatools_package_cert_files", OtatoolsPackageFactory) +} + +type OtatoolsPackage struct { + ModuleBase +} + +func OtatoolsPackageFactory() Module { + module := &OtatoolsPackage{} + InitAndroidModule(module) + return module +} + +var ( + otatoolsPackageCertRule = pctx.AndroidStaticRule("otatools_package_cert_files", blueprint.RuleParams{ + Command: "echo $out: > ${out}.d && cat $in >> ${out}.d && ${SoongZipCmd} -o $out -l $in", + CommandDeps: []string{"${SoongZipCmd}"}, + Depfile: "${out}.d", + Description: "Zip otatools-package cert files", + }) +) + +func (fg *OtatoolsPackage) GenerateAndroidBuildActions(ctx ModuleContext) { + if ctx.ModuleDir() != "build/make/tools/otatools_package" { + ctx.ModuleErrorf("There can only be one otatools_package_cert_files module in build/make/tools/otatools_package") + return + } + fileListFile := PathForArbitraryOutput(ctx, ".module_paths", "OtaToolsCertFiles.list") + otatoolsPackageCertZip := PathForModuleOut(ctx, "otatools_package_cert_files.zip") + ctx.Build(pctx, BuildParams{ + Rule: otatoolsPackageCertRule, + Input: fileListFile, + Output: otatoolsPackageCertZip, + }) + ctx.SetOutputFiles([]Path{otatoolsPackageCertZip}, "") +} diff --git a/android/packaging.go b/android/packaging.go index bb1fe4e45..bf1840929 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -506,13 +506,11 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont // all packaging specs gathered from the high priority deps. var highPriorities []PackagingSpec - // Name of the dependency which requested the packaging spec. - // If this dep is overridden, the packaging spec will not be installed via this dependency chain. - // (the packaging spec might still be installed if there are some other deps which depend on it). - var depNames []string - // list of module names overridden - var overridden []string + overridden := make(map[string]bool) + + // all installed modules which are not overridden. + modulesToInstall := make(map[string]bool) var arches []ArchType for _, target := range getSupportedTargets(ctx) { @@ -529,6 +527,7 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont return false } + // find all overridden modules and packaging specs ctx.VisitDirectDepsProxy(func(child ModuleProxy) { depTag := ctx.OtherModuleDependencyTag(child) if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() { @@ -556,20 +555,32 @@ func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleCont regularPriorities = append(regularPriorities, ps) } - depNames = append(depNames, child.Name()) - overridden = append(overridden, ps.overrides.ToSlice()...) + for o := range ps.overrides.Iter() { + overridden[o] = true + } + } + }) + + // gather modules to install, skipping overridden modules + ctx.WalkDeps(func(child, parent Module) bool { + owner := ctx.OtherModuleName(child) + if o, ok := child.(OverridableModule); ok { + if overriddenBy := o.GetOverriddenBy(); overriddenBy != "" { + owner = overriddenBy + } + } + if overridden[owner] { + return false } + modulesToInstall[owner] = true + return true }) filterOverridden := func(input []PackagingSpec) []PackagingSpec { - // input minus packaging specs that are overridden + // input minus packaging specs that are not installed var filtered []PackagingSpec - for index, ps := range input { - if ps.owner != "" && InList(ps.owner, overridden) { - continue - } - // The dependency which requested this packaging spec has been overridden. - if InList(depNames[index], overridden) { + for _, ps := range input { + if !modulesToInstall[ps.owner] { continue } filtered = append(filtered, ps) diff --git a/android/selects_test.go b/android/selects_test.go index 7f20a3d66..8e469f8e3 100644 --- a/android/selects_test.go +++ b/android/selects_test.go @@ -666,6 +666,81 @@ func TestSelects(t *testing.T) { }, }, { + name: "Select on integer soong config variable", + bp: ` + my_module_type { + name: "foo", + my_string: select(soong_config_variable("my_namespace", "my_variable"), { + 34: "34", + default: "other", + }), + } + `, + vendorVars: map[string]map[string]string{ + "my_namespace": { + "my_variable": "34", + }, + }, + vendorVarTypes: map[string]map[string]string{ + "my_namespace": { + "my_variable": "int", + }, + }, + provider: selectsTestProvider{ + my_string: proptools.StringPtr("34"), + }, + }, + { + name: "Select on integer soong config variable default", + bp: ` + my_module_type { + name: "foo", + my_string: select(soong_config_variable("my_namespace", "my_variable"), { + 34: "34", + default: "other", + }), + } + `, + vendorVars: map[string]map[string]string{ + "my_namespace": { + "my_variable": "5", + }, + }, + vendorVarTypes: map[string]map[string]string{ + "my_namespace": { + "my_variable": "int", + }, + }, + provider: selectsTestProvider{ + my_string: proptools.StringPtr("other"), + }, + }, + { + name: "Assign to integer property", + bp: ` + my_module_type { + name: "foo", + my_int64: select(soong_config_variable("my_namespace", "my_variable"), { + any @ val: val, + default: "other", + }), + } + `, + vendorVars: map[string]map[string]string{ + "my_namespace": { + "my_variable": "5", + }, + }, + vendorVarTypes: map[string]map[string]string{ + "my_namespace": { + "my_variable": "int", + }, + }, + provider: selectsTestProvider{ + my_int64: proptools.Int64Ptr(5), + }, + }, + { name: "Mismatched condition types", bp: ` my_module_type { @@ -1132,6 +1207,7 @@ my_module_type { type selectsTestProvider struct { my_bool *bool my_string *string + my_int64 *int64 my_string_list *[]string my_paths *[]string replacing_string_list *[]string @@ -1181,6 +1257,7 @@ var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]() type selectsMockModuleProperties struct { My_bool proptools.Configurable[bool] + My_int64 proptools.Configurable[int64] My_string proptools.Configurable[string] My_string_list proptools.Configurable[[]string] My_paths proptools.Configurable[[]string] `android:"path"` @@ -1213,6 +1290,7 @@ func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{ my_bool: optionalToPtr(p.properties.My_bool.Get(ctx)), my_string: optionalToPtr(p.properties.My_string.Get(ctx)), + my_int64: optionalToPtr(p.properties.My_int64.Get(ctx)), my_string_list: optionalToPtr(p.properties.My_string_list.Get(ctx)), my_paths: optionalToPtr(p.properties.My_paths.Get(ctx)), replacing_string_list: optionalToPtr(p.properties.Replacing_string_list.Get(ctx)), diff --git a/apex/apex.go b/apex/apex.go index c6566e13b..a726098c6 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -569,19 +569,6 @@ const ( shBinary ) -var ( - classes = map[string]apexFileClass{ - "app": app, - "appSet": appSet, - "etc": etc, - "javaSharedLib": javaSharedLib, - "nativeExecutable": nativeExecutable, - "nativeSharedLib": nativeSharedLib, - "nativeTest": nativeTest, - "shBinary": shBinary, - } -) - // apexFile represents a file in an APEX bundle. This is created during the first half of // GenerateAndroidBuildActions by traversing the dependencies of the APEX. Then in the second half // of the function, this is used to create commands that copies the files into a staging directory, @@ -1970,7 +1957,11 @@ 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.class = nativeTest + // We make this a nativeExecutable instead of a nativeTest because we don't want + // the androidmk modules generated in AndroidMkForFiles to be treated as real + // tests that are then packaged into suites. Our AndroidMkForFiles does not + // implement enough functionality to support real tests. + af.class = nativeExecutable vctx.filesInfo = append(vctx.filesInfo, af) return true // track transitive dependencies } else { diff --git a/cc/fdo_profile.go b/cc/fdo_profile.go index 1a3395773..c79ea1018 100644 --- a/cc/fdo_profile.go +++ b/cc/fdo_profile.go @@ -17,6 +17,8 @@ package cc import ( "android/soong/android" "github.com/google/blueprint" + + "github.com/google/blueprint/proptools" ) func init() { @@ -34,7 +36,7 @@ type fdoProfile struct { } type fdoProfileProperties struct { - Profile *string `android:"arch_variant"` + Profile proptools.Configurable[string] `android:"arch_variant,replace_instead_of_append"` } // FdoProfileInfo is provided by FdoProfileProvider @@ -47,8 +49,9 @@ var FdoProfileProvider = blueprint.NewProvider[FdoProfileInfo]() // GenerateAndroidBuildActions of fdo_profile does not have any build actions func (fp *fdoProfile) GenerateAndroidBuildActions(ctx android.ModuleContext) { - if fp.properties.Profile != nil { - path := android.PathForModuleSrc(ctx, *fp.properties.Profile) + profile := fp.properties.Profile.GetOrDefault(ctx, "") + if profile != "" { + path := android.PathForModuleSrc(ctx, profile) android.SetProvider(ctx, FdoProfileProvider, FdoProfileInfo{ Path: path, }) diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index d1440eaad..46290300c 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -573,9 +573,8 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte func getRequiredMemberOutputFile(ctx android.SdkMemberContext, ccModule *Module) android.Path { var path android.Path - outputFile := ccModule.OutputFile() - if outputFile.Valid() { - path = outputFile.Path() + if info, ok := android.OtherModuleProvider(ctx.SdkModuleContext(), ccModule, LinkableInfoProvider); ok && info.OutputFile.Valid() { + path = info.OutputFile.Path() } else { ctx.SdkModuleContext().ModuleErrorf("member variant %s does not have a valid output file", ccModule) } diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state.go b/cmd/find_input_delta/find_input_delta_lib/internal_state.go index bf4f86686..0f88159be 100644 --- a/cmd/find_input_delta/find_input_delta_lib/internal_state.go +++ b/cmd/find_input_delta/find_input_delta_lib/internal_state.go @@ -95,9 +95,14 @@ func inspectZipFileContents(name string) ([]*fid_proto.PartialCompileInput, erro } ret := []*fid_proto.PartialCompileInput{} for _, v := range rc.File { + // Only include timestamp when there is no CRC. + timeNsec := proto.Int64(v.ModTime().UnixNano()) + if v.CRC32 != 0 { + timeNsec = nil + } pci := &fid_proto.PartialCompileInput{ Name: proto.String(v.Name), - MtimeNsec: proto.Int64(v.ModTime().UnixNano()), + MtimeNsec: timeNsec, Hash: proto.String(fmt.Sprintf("%08x", v.CRC32)), } ret = append(ret, pci) diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go index b0f8cb7bf..dd98bca0b 100644 --- a/cmd/release_config/release_config_lib/release_configs.go +++ b/cmd/release_config/release_config_lib/release_configs.go @@ -314,6 +314,9 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex } } } + if flagDeclaration.Namespace == nil { + return fmt.Errorf("Flag declaration %s has no namespace.", path) + } m.FlagDeclarations = append(m.FlagDeclarations, *flagDeclaration) name := *flagDeclaration.Name diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index 3b0c0329d..7820047ab 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -78,6 +78,7 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_rfs", PrebuiltRfsFactory) ctx.RegisterModuleType("prebuilt_framework", PrebuiltFrameworkFactory) ctx.RegisterModuleType("prebuilt_res", PrebuiltResFactory) + ctx.RegisterModuleType("prebuilt_tee", PrebuiltTeeFactory) ctx.RegisterModuleType("prebuilt_wlc_upt", PrebuiltWlcUptFactory) ctx.RegisterModuleType("prebuilt_odm", PrebuiltOdmFactory) ctx.RegisterModuleType("prebuilt_vendor_dlkm", PrebuiltVendorDlkmFactory) @@ -910,6 +911,16 @@ func PrebuiltRFSAFactory() android.Module { return module } +// prebuilt_tee installs files in <partition>/tee directory. +func PrebuiltTeeFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "tee") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + return module +} + // prebuilt_media installs media files in <partition>/media directory. func PrebuiltMediaFactory() android.Module { module := &PrebuiltEtc{} diff --git a/filesystem/android_device.go b/filesystem/android_device.go index 28ecd5345..feb000dc4 100644 --- a/filesystem/android_device.go +++ b/filesystem/android_device.go @@ -748,6 +748,11 @@ func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, build } +var ( + // https://cs.android.com/android/_/android/platform/build/+/30f05352c3e6f4333c77d4af66c253572d3ea6c9:core/Makefile;l=2111-2120;drc=519f75666431ee2926e0ec8991c682b28a4c9521;bpv=1;bpt=0 + defaultTargetRecoveryFstypeMountOptions = "ext4=max_batch_time=0,commit=1,data=ordered,barrier=1,errors=panic,nodelalloc" +) + // 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 @@ -775,6 +780,7 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path { Textf("&& echo fstab_version=%s >> %s", ctx.Config().VendorConfig("recovery").String("recovery_fstab_version"), miscInfo). Textf("&& echo build_type=%s >> %s", buildType(), miscInfo). Textf("&& echo default_system_dev_certificate=%s >> %s", defaultAppCertificate(), miscInfo). + Textf("&& echo root_dir=%s >> %s", android.PathForModuleInPartitionInstall(ctx, "root"), miscInfo). ImplicitOutput(miscInfo) if len(ctx.Config().ExtraOtaRecoveryKeys()) > 0 { builder.Command().Textf(`echo "extra_recovery_keys=%s" >> %s`, strings.Join(ctx.Config().ExtraOtaRecoveryKeys(), ""), miscInfo) @@ -801,6 +807,25 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path { if fsInfos["system"].ErofsCompressHints != nil { builder.Command().Textf("echo erofs_default_compress_hints=%s >> %s", fsInfos["system"].ErofsCompressHints, miscInfo) } + if releaseTools := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Releasetools_extension)); releaseTools != nil { + builder.Command().Textf("echo tool_extensions=%s >> %s", filepath.Dir(releaseTools.String()), miscInfo) + } + // ramdisk uses `compressed_cpio` fs_type + // https://cs.android.com/android/_/android/platform/build/+/30f05352c3e6f4333c77d4af66c253572d3ea6c9:core/Makefile;l=5923-5925;drc=519f75666431ee2926e0ec8991c682b28a4c9521;bpv=1;bpt=0 + if _, ok := fsInfos["ramdisk"]; ok { + builder.Command().Textf("echo lz4_ramdisks=true >> %s", miscInfo) + } + // recovery_mount_options + // TODO: Add support for TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS which can be used to override the default + builder.Command().Textf("echo recovery_mount_options=%s >> %s", defaultTargetRecoveryFstypeMountOptions, miscInfo) + + // vintf information + if proptools.Bool(ctx.Config().ProductVariables().Enforce_vintf_manifest) { + builder.Command().Textf("echo vintf_enforce=true >> %s", miscInfo) + } + if len(ctx.Config().DeviceManifestFiles()) > 0 { + builder.Command().Textf("echo vintf_include_empty_vendor_sku=true >> %s", miscInfo) + } if a.partitionProps.Recovery_partition_name == nil { builder.Command().Textf("echo no_recovery=true >> %s", miscInfo) @@ -815,6 +840,15 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path { Textf("echo avb_enable=true >> %s", miscInfo). Textf("&& echo avb_building_vbmeta_image=true >> %s", miscInfo). Textf("&& echo avb_avbtool=avbtool >> %s", miscInfo) + for _, vbmetaPartitionName := range a.partitionProps.Vbmeta_partitions { + img := ctx.GetDirectDepProxyWithTag(vbmetaPartitionName, filesystemDepTag) + if provider, ok := android.OtherModuleProvider(ctx, img, vbmetaPartitionProvider); ok { + builder.Command().Text("cat").Input(provider.PropFileForMiscInfo).Textf(" >> %s", miscInfo) + } else { + ctx.ModuleErrorf("vbmeta dep %s does not set vbmetaPartitionProvider\n", vbmetaPartitionName) + } + } + } if a.partitionProps.Boot_partition_name != nil { builder.Command().Textf("echo boot_images=boot.img >> %s", miscInfo) @@ -825,6 +859,10 @@ func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path { if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok { // cat dynamic_partition_info.txt builder.Command().Text("cat").Input(info.DynamicPartitionsInfo).Textf(" >> %s", miscInfo) + if info.AbUpdate { + builder.Command().Textf("echo ab_update=true >> %s", miscInfo) + } + } else { ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name()) } @@ -1017,6 +1055,7 @@ func (a *androidDevice) buildApkCertsInfo(ctx android.ModuleContext, allInstalle } apkCerts := []string{} + var apkCertsFiles android.Paths for _, installedModule := range allInstalledModules { partition := "" if commonInfo, ok := android.OtherModuleProvider(ctx, installedModule, android.CommonModuleInfoProvider); ok { @@ -1025,7 +1064,11 @@ func (a *androidDevice) buildApkCertsInfo(ctx android.ModuleContext, allInstalle 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)) + if info.AppSet { + apkCertsFiles = append(apkCertsFiles, info.ApkCertsFile) + } else { + 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. @@ -1046,7 +1089,14 @@ func (a *androidDevice) buildApkCertsInfo(ctx android.ModuleContext, allInstalle } } + apkCertsInfoWithoutAppSets := android.PathForModuleOut(ctx, "apkcerts_without_app_sets.txt") + android.WriteFileRuleVerbatim(ctx, apkCertsInfoWithoutAppSets, strings.Join(apkCerts, "\n")+"\n") apkCertsInfo := android.PathForModuleOut(ctx, "apkcerts.txt") - android.WriteFileRuleVerbatim(ctx, apkCertsInfo, strings.Join(apkCerts, "\n")+"\n") + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cat, + Description: "combine apkcerts.txt", + Output: apkCertsInfo, + Inputs: append(apkCertsFiles, apkCertsInfoWithoutAppSets), + }) return apkCertsInfo } diff --git a/filesystem/android_device_product_out.go b/filesystem/android_device_product_out.go index 7d37f1ee7..aa06337ca 100644 --- a/filesystem/android_device_product_out.go +++ b/filesystem/android_device_product_out.go @@ -167,7 +167,7 @@ func (a *androidDevice) copyFilesToProductOutForSoongOnly(ctx android.ModuleCont } if proptools.String(a.deviceProps.Android_info) != "" { - installPath := android.PathForModuleInPartitionInstall(ctx, "", "android_info.txt") + installPath := android.PathForModuleInPartitionInstall(ctx, "", "android-info.txt") ctx.Build(pctx, android.BuildParams{ Rule: android.Cp, Input: android.PathForModuleSrc(ctx, *a.deviceProps.Android_info), diff --git a/filesystem/avb_add_hash_footer.go b/filesystem/avb_add_hash_footer.go index 327a41fda..c7760120d 100644 --- a/filesystem/avb_add_hash_footer.go +++ b/filesystem/avb_add_hash_footer.go @@ -70,7 +70,7 @@ type avbAddHashFooterProperties struct { Props []avbProp // The index used to prevent rollback of the image on device. - Rollback_index *int64 + Rollback_index proptools.Configurable[int64] `android:"replace_instead_of_append"` // Include descriptors from images Include_descriptors_from_images []string `android:"path,arch_variant"` @@ -134,8 +134,9 @@ func (a *avbAddHashFooter) GenerateAndroidBuildActions(ctx android.ModuleContext addAvbProp(ctx, cmd, prop) } - if a.properties.Rollback_index != nil { - rollbackIndex := proptools.Int(a.properties.Rollback_index) + rollbackIndex := a.properties.Rollback_index.Get(ctx) + if rollbackIndex.IsPresent() { + rollbackIndex := rollbackIndex.Get() if rollbackIndex < 0 { ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") } diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 846e2e5e4..e86ebf4fa 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -455,6 +455,14 @@ type FilesystemInfo struct { HasFsverity bool PropFileForMiscInfo android.Path + + // Additional avb and partition size information. + // `system_other` will use this information of `system` dep for misc_info.txt processing. + PartitionSize *int64 + UseAvb bool + AvbAlgorithm string + AvbHashAlgorithm string + AvbKey android.Path } // FullInstallPathInfo contains information about the "full install" paths of all the files @@ -711,6 +719,15 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { Owners: f.gatherOwners(specs), HasFsverity: f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) != nil, PropFileForMiscInfo: propFileForMiscInfo, + PartitionSize: f.properties.Partition_size, + } + if proptools.Bool(f.properties.Use_avb) { + fsInfo.UseAvb = true + fsInfo.AvbAlgorithm = proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096") + fsInfo.AvbHashAlgorithm = proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256") + if f.properties.Avb_private_key != nil { + fsInfo.AvbKey = android.PathForModuleSrc(ctx, *f.properties.Avb_private_key) + } } android.SetProvider(ctx, FilesystemProvider, fsInfo) @@ -1175,6 +1192,10 @@ func (f *filesystem) buildPropFileForMiscInfo(ctx android.ModuleContext) android // effect as <partition name>_disable_sparse. if f.properties.Partition_size == nil { addStr(f.partitionName()+"_disable_sparse", "true") + } else if f.partitionName() == "userdata" { + // Add userdata's partition size to misc_info.txt. + // userdata has been special-cased to make the make packaging misc_info.txt implementation + addStr("userdata_size", strconv.FormatInt(*f.properties.Partition_size, 10)) } fst := f.fsType(ctx) diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go index bf7f5b64b..e57e45cb6 100644 --- a/filesystem/filesystem_test.go +++ b/filesystem/filesystem_test.go @@ -736,15 +736,14 @@ func TestOverrideModulesInDeps(t *testing.T) { stl: "none", system_shared_libs: [], } - android_filesystem { - name: "myfilesystem", - deps: ["myapp"], + phony { + name: "myapp_phony", + required: ["myapp"], } - android_filesystem { - name: "myfilesystem_overridden", - deps: ["myapp", "myoverrideapp"], + phony { + name: "myoverrideapp_phony", + required: ["myoverrideapp"], } - android_app { name: "myapp", platform_apis: true, @@ -755,15 +754,29 @@ func TestOverrideModulesInDeps(t *testing.T) { base: "myapp", required: ["libbar"], } + android_filesystem { + name: "myfilesystem", + deps: ["myapp"], + } + android_filesystem { + name: "myfilesystem_overridden", + deps: ["myapp", "myoverrideapp"], + } + android_filesystem { + name: "myfilesystem_overridden_indirect", + deps: ["myapp_phony", "myoverrideapp_phony"], + } `) partition := result.ModuleForTests(t, "myfilesystem", "android_common") fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList")) android.AssertStringEquals(t, "filesystem without override app", "app/myapp/myapp.apk\nlib64/libfoo.so\n", fileList) - overriddenPartition := result.ModuleForTests(t, "myfilesystem_overridden", "android_common") - overriddenFileList := android.ContentFromFileRuleForTests(t, result.TestContext, overriddenPartition.Output("fileList")) - android.AssertStringEquals(t, "filesystem with override app", "app/myoverrideapp/myoverrideapp.apk\nlib64/libbar.so\n", overriddenFileList) + for _, overridden := range []string{"myfilesystem_overridden", "myfilesystem_overridden_indirect"} { + overriddenPartition := result.ModuleForTests(t, overridden, "android_common") + overriddenFileList := android.ContentFromFileRuleForTests(t, result.TestContext, overriddenPartition.Output("fileList")) + android.AssertStringEquals(t, "filesystem with "+overridden, "app/myoverrideapp/myoverrideapp.apk\nlib64/libbar.so\n", overriddenFileList) + } } func TestRamdiskPartitionSetsDevNodes(t *testing.T) { diff --git a/filesystem/super_image.go b/filesystem/super_image.go index cd7df027a..cf7e125a0 100644 --- a/filesystem/super_image.go +++ b/filesystem/super_image.go @@ -122,6 +122,8 @@ type SuperImageInfo struct { DynamicPartitionsInfo android.Path SuperEmptyImage android.Path + + AbUpdate bool } var SuperImageProvider = blueprint.NewProvider[SuperImageInfo]() @@ -201,6 +203,7 @@ func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) { SubImageInfo: subImageInfos, DynamicPartitionsInfo: s.generateDynamicPartitionsInfo(ctx), SuperEmptyImage: superEmptyImage, + AbUpdate: proptools.Bool(s.properties.Ab_update), }) ctx.SetOutputFiles([]android.Path{output}, "") ctx.CheckbuildFile(output) diff --git a/filesystem/system_other.go b/filesystem/system_other.go index cbfd78b5b..32a6cc784 100644 --- a/filesystem/system_other.go +++ b/filesystem/system_other.go @@ -16,8 +16,11 @@ package filesystem import ( "android/soong/android" + "fmt" "path/filepath" + "sort" "strings" + "time" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -117,8 +120,11 @@ func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext // TOOD: CopySpecsToDir only exists on PackagingBase, but doesn't use any fields from it. Clean this up. (&android.PackagingBase{}).CopySpecsToDir(ctx, builder, specs, stagingDir) + fullInstallPaths := []string{} if len(m.properties.Preinstall_dexpreopt_files_from) > 0 { builder.Command().Textf("touch %s", filepath.Join(stagingDir.String(), "system-other-odex-marker")) + installPath := android.PathForModuleInPartitionInstall(ctx, "system_other", "system-other-odex-marker") + fullInstallPaths = append(fullInstallPaths, installPath.String()) } builder.Command().Textf("touch").Output(stagingDirTimestamp) builder.Build("assemble_filesystem_staging_dir", "Assemble filesystem staging dir") @@ -172,16 +178,21 @@ func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext builder.Build("build_system_other_hermetic", "build system other") fsInfo := FilesystemInfo{ - Output: output, - OutputHermetic: outputHermetic, - RootDir: stagingDir, - FilesystemConfig: m.generateFilesystemConfig(ctx, stagingDir, stagingDirTimestamp), + Output: output, + OutputHermetic: outputHermetic, + RootDir: stagingDir, + FilesystemConfig: m.generateFilesystemConfig(ctx, stagingDir, stagingDirTimestamp), + PropFileForMiscInfo: m.buildPropFileForMiscInfo(ctx), } android.SetProvider(ctx, FilesystemProvider, fsInfo) ctx.SetOutputFiles(android.Paths{output}, "") ctx.CheckbuildFile(output) + + // Dump compliance metadata + complianceMetadataInfo := ctx.ComplianceMetadataInfo() + complianceMetadataInfo.SetFilesContained(fullInstallPaths) } func (s *systemOtherImage) generateFilesystemConfig(ctx android.ModuleContext, stagingDir, stagingDirTimestamp android.Path) android.Path { @@ -204,3 +215,52 @@ func (f *systemOtherImage) propFileForHermeticImg(ctx android.ModuleContext, bui Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp) return propFilePinnedTimestamp } + +func (f *systemOtherImage) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path { + var lines []string + addStr := func(name string, value string) { + lines = append(lines, fmt.Sprintf("%s=%s", name, value)) + } + + addStr("building_system_other_image", "true") + + systemImage := ctx.GetDirectDepProxyWithTag(*f.properties.System_image, systemImageDependencyTag) + systemInfo, ok := android.OtherModuleProvider(ctx, systemImage, FilesystemProvider) + if !ok { + ctx.PropertyErrorf("system_image", "Expected system_image module to provide FilesystemProvider") + return nil + } + if systemInfo.PartitionSize == nil { + addStr("system_other_disable_sparse", "true") + } + if systemInfo.UseAvb { + addStr("avb_system_other_hashtree_enable", "true") + addStr("avb_system_other_algorithm", systemInfo.AvbAlgorithm) + footerArgs := fmt.Sprintf("--hash_algorithm %s", systemInfo.AvbHashAlgorithm) + if rollbackIndex, err := f.avbRollbackIndex(ctx); err == nil { + footerArgs += fmt.Sprintf(" --rollback_index %d", rollbackIndex) + } else { + ctx.ModuleErrorf("Could not determine rollback_index %s\n", err) + } + addStr("avb_system_other_add_hashtree_footer_args", footerArgs) + if systemInfo.AvbKey != nil { + addStr("avb_system_other_key_path", systemInfo.AvbKey.String()) + } + } + + sort.Strings(lines) + + propFile := android.PathForModuleOut(ctx, "prop_file") + android.WriteFileRule(ctx, propFile, strings.Join(lines, "\n")) + return propFile +} + +// Use the default: PlatformSecurityPatch +// TODO: Get this value from vbmeta_system +func (f *systemOtherImage) avbRollbackIndex(ctx android.ModuleContext) (int64, error) { + t, err := time.Parse(time.DateOnly, ctx.Config().PlatformSecurityPatch()) + if err != nil { + return -1, err + } + return t.Unix(), err +} diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go index 01b453e25..d59a2aec5 100644 --- a/filesystem/vbmeta.go +++ b/filesystem/vbmeta.go @@ -16,7 +16,10 @@ package filesystem import ( "fmt" + "sort" "strconv" + "strings" + "time" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -124,6 +127,10 @@ type vbmetaPartitionInfo struct { // The output of the vbmeta module Output android.Path + + // Information about the vbmeta partition that will be added to misc_info.txt + // created by android_device + PropFileForMiscInfo android.Path } var vbmetaPartitionProvider = blueprint.NewProvider[vbmetaPartitionInfo]() @@ -302,6 +309,7 @@ func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) { RollbackIndexLocation: ril, PublicKey: extractedPublicKey, Output: output, + PropFileForMiscInfo: v.buildPropFileForMiscInfo(ctx), }) ctx.SetOutputFiles([]android.Path{output}, "") @@ -310,6 +318,41 @@ func (v *vbmeta) GenerateAndroidBuildActions(ctx android.ModuleContext) { setCommonFilesystemInfo(ctx, v) } +func (v *vbmeta) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path { + var lines []string + addStr := func(name string, value string) { + lines = append(lines, fmt.Sprintf("%s=%s", name, value)) + } + + addStr(fmt.Sprintf("avb_%s_algorithm", v.partitionName()), proptools.StringDefault(v.properties.Algorithm, "SHA256_RSA4096")) + if v.properties.Private_key != nil { + addStr(fmt.Sprintf("avb_%s_key_path", v.partitionName()), android.PathForModuleSrc(ctx, proptools.String(v.properties.Private_key)).String()) + } + if v.properties.Rollback_index_location != nil { + addStr(fmt.Sprintf("avb_%s_rollback_index_location", v.partitionName()), strconv.FormatInt(*v.properties.Rollback_index_location, 10)) + } + + var partitionDepNames []string + ctx.VisitDirectDepsProxyWithTag(vbmetaPartitionDep, func(child android.ModuleProxy) { + if info, ok := android.OtherModuleProvider(ctx, child, vbmetaPartitionProvider); ok { + partitionDepNames = append(partitionDepNames, info.Name) + } else { + ctx.ModuleErrorf("vbmeta dep %s does not set vbmetaPartitionProvider\n", child) + } + }) + if v.partitionName() != "vbmeta" { // skip for vbmeta to match Make's misc_info.txt + addStr(fmt.Sprintf("avb_%s", v.partitionName()), strings.Join(android.SortedUniqueStrings(partitionDepNames), " ")) + } + + addStr(fmt.Sprintf("avb_%s_args", v.partitionName()), fmt.Sprintf("--padding_size 4096 --rollback_index %s", v.rollbackIndexString(ctx))) + + sort.Strings(lines) + + propFile := android.PathForModuleOut(ctx, "prop_file_for_misc_info") + android.WriteFileRule(ctx, propFile, strings.Join(lines, "\n")) + return propFile +} + // Returns the embedded shell command that prints the rollback index func (v *vbmeta) rollbackIndexCommand(ctx android.ModuleContext) string { if v.properties.Rollback_index != nil { @@ -320,6 +363,17 @@ func (v *vbmeta) rollbackIndexCommand(ctx android.ModuleContext) string { } } +// Similar to rollbackIndexCommand, but guarantees that the rollback index is +// always computed during Soong analysis, even if v.properties.Rollback_index is nil +func (v *vbmeta) rollbackIndexString(ctx android.ModuleContext) string { + if v.properties.Rollback_index != nil { + return fmt.Sprintf("%d", *v.properties.Rollback_index) + } else { + t, _ := time.Parse(time.DateOnly, ctx.Config().PlatformSecurityPatch()) + return fmt.Sprintf("%d", t.Unix()) + } +} + var _ android.AndroidMkProviderInfoProducer = (*vbmeta)(nil) func (v *vbmeta) PrepareAndroidMKProviderInfo(config android.Config) *android.AndroidMkProviderInfo { diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go index 81236a0a1..2c4d3c817 100644 --- a/fsgen/filesystem_creator_test.go +++ b/fsgen/filesystem_creator_test.go @@ -289,6 +289,10 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { "device/sample/etc/apns-full-conf.xml:product/etc/apns-conf-2.xml", "device/sample/etc/apns-full-conf.xml:system/foo/file.txt", "device/sample/etc/apns-full-conf.xml:system/foo/apns-full-conf.xml", + "device/sample/firmware/firmware.bin:recovery/root/firmware.bin", + "device/sample/firmware/firmware.bin:recovery/root/firmware-2.bin", + "device/sample/firmware/firmware.bin:recovery/root/lib/firmware/firmware.bin", + "device/sample/firmware/firmware.bin:recovery/root/lib/firmware/firmware-2.bin", } config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables = map[string]android.PartitionQualifiedVariablesType{ @@ -309,22 +313,23 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { "frameworks/base/data/keyboards/Vendor_0079_Product_0011.kl": nil, "frameworks/base/data/keyboards/Vendor_0079_Product_18d4.kl": nil, "device/sample/etc/apns-full-conf.xml": nil, + "device/sample/firmware/firmware.bin": nil, }), ).RunTest(t) - checkModuleProp := func(m android.Module, matcher func(actual interface{}) bool) bool { + getModuleProp := func(m android.Module, matcher func(actual interface{}) string) string { for _, prop := range m.GetProperties() { - if matcher(prop) { - return true + if str := matcher(prop); str != "" { + return str } } - return false + return "" } // check generated prebuilt_* module type install path and install partition generatedModule := result.ModuleForTests(t, "system-frameworks_base_config-etc-0", "android_arm64_armv8-a").Module() - etcModule, _ := generatedModule.(*etc.PrebuiltEtc) + etcModule := generatedModule.(*etc.PrebuiltEtc) android.AssertStringEquals( t, "module expected to have etc install path", @@ -342,7 +347,7 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { // check generated prebuilt_* module specifies correct relative_install_path property generatedModule = result.ModuleForTests(t, "system-frameworks_base_data_keyboards-usr_keylayout_subdir-0", "android_arm64_armv8-a").Module() - etcModule, _ = generatedModule.(*etc.PrebuiltEtc) + etcModule = generatedModule.(*etc.PrebuiltEtc) android.AssertStringEquals( t, "module expected to set correct relative_install_path properties", @@ -350,6 +355,37 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { etcModule.SubDir(), ) + // check that generated prebuilt_* module sets correct srcs + eval := generatedModule.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to set correct srcs property", + "Vendor_0079_Product_0011.kl", + getModuleProp(generatedModule, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { + srcs := p.Srcs.GetOrDefault(eval, nil) + if len(srcs) == 2 { + return srcs[0] + } + } + return "" + }), + ) + android.AssertStringEquals( + t, + "module expected to set correct srcs property", + "Vendor_0079_Product_18d4.kl", + getModuleProp(generatedModule, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { + srcs := p.Srcs.GetOrDefault(eval, nil) + if len(srcs) == 2 { + return srcs[1] + } + } + return "" + }), + ) + // check that prebuilt_* module is not generated for non existing source file android.AssertStringEquals( t, @@ -363,60 +399,264 @@ func TestPrebuiltEtcModuleGen(t *testing.T) { generatedModule1 := result.ModuleForTests(t, "product-device_sample_etc-etc-1", "android_arm64_armv8-a").Module() // check that generated prebuilt_* module sets correct srcs and dsts property - eval := generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) - android.AssertBoolEquals( + eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( t, "module expected to set correct srcs property", - true, - checkModuleProp(generatedModule0, func(actual interface{}) bool { + "apns-full-conf.xml", + getModuleProp(generatedModule0, func(actual interface{}) string { if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { srcs := p.Srcs.GetOrDefault(eval, nil) - return len(srcs) == 1 && - srcs[0] == "apns-full-conf.xml" + if len(srcs) == 1 { + return srcs[0] + } } - return false + return "" }), ) - android.AssertBoolEquals( + android.AssertStringEquals( t, "module expected to set correct dsts property", - true, - checkModuleProp(generatedModule0, func(actual interface{}) bool { + "apns-conf.xml", + getModuleProp(generatedModule0, func(actual interface{}) string { if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { dsts := p.Dsts.GetOrDefault(eval, nil) - return len(dsts) == 1 && - dsts[0] == "apns-conf.xml" + if len(dsts) == 1 { + return dsts[0] + } } - return false + return "" }), ) // check that generated prebuilt_* module sets correct srcs and dsts property eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) - android.AssertBoolEquals( + android.AssertStringEquals( t, "module expected to set correct srcs property", - true, - checkModuleProp(generatedModule1, func(actual interface{}) bool { + "apns-full-conf.xml", + getModuleProp(generatedModule1, func(actual interface{}) string { if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { srcs := p.Srcs.GetOrDefault(eval, nil) - return len(srcs) == 1 && - srcs[0] == "apns-full-conf.xml" + if len(srcs) == 1 { + return srcs[0] + } } - return false + return "" }), ) - android.AssertBoolEquals( + android.AssertStringEquals( t, "module expected to set correct dsts property", - true, - checkModuleProp(generatedModule1, func(actual interface{}) bool { + "apns-conf-2.xml", + getModuleProp(generatedModule1, func(actual interface{}) string { if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { dsts := p.Dsts.GetOrDefault(eval, nil) - return len(dsts) == 1 && - dsts[0] == "apns-conf-2.xml" + if len(dsts) == 1 { + return dsts[0] + } + } + return "" + }), + ) + + generatedModule0 = result.ModuleForTests(t, "system-device_sample_etc-foo-0", "android_common").Module() + generatedModule1 = result.ModuleForTests(t, "system-device_sample_etc-foo-1", "android_common").Module() + + // check that generated prebuilt_* module sets correct srcs and dsts property + eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to set correct srcs property", + "apns-full-conf.xml", + getModuleProp(generatedModule0, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { + srcs := p.Srcs.GetOrDefault(eval, nil) + if len(srcs) == 1 { + return srcs[0] + } + } + return "" + }), + ) + android.AssertStringEquals( + t, + "module expected to set correct dsts property", + "foo/file.txt", + getModuleProp(generatedModule0, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) == 1 { + return dsts[0] + } + } + return "" + }), + ) + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule1.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set correct relative_install_path properties", + "foo", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module sets correct srcs + eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to set correct srcs property", + "apns-full-conf.xml", + getModuleProp(generatedModule1, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltEtcProperties); ok { + srcs := p.Srcs.GetOrDefault(eval, nil) + if len(srcs) == 1 { + return srcs[0] + } + } + return "" + }), + ) + + generatedModule0 = result.ModuleForTests(t, "recovery-device_sample_firmware-0", "android_recovery_arm64_armv8-a").Module() + generatedModule1 = result.ModuleForTests(t, "recovery-device_sample_firmware-1", "android_recovery_common").Module() + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule0.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set empty relative_install_path properties", + "", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module don't set dsts + eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to not set dsts property", + "", + getModuleProp(generatedModule0, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) != 0 { + return dsts[0] + } + } + return "" + }), + ) + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule1.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set empty relative_install_path properties", + "", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module sets correct dsts + eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to set correct dsts property", + "firmware-2.bin", + getModuleProp(generatedModule1, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) == 1 { + return dsts[0] + } + } + return "" + }), + ) + + generatedModule0 = result.ModuleForTests(t, "recovery-device_sample_firmware-lib_firmware-0", "android_recovery_common").Module() + generatedModule1 = result.ModuleForTests(t, "recovery-device_sample_firmware-lib_firmware-1", "android_recovery_common").Module() + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule0.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set correct relative_install_path properties", + "lib/firmware", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module sets correct srcs + eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to not set dsts property", + "", + getModuleProp(generatedModule0, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) != 0 { + return dsts[0] + } + } + return "" + }), + ) + + // check generated prebuilt_* module specifies correct install path and relative install path + etcModule = generatedModule1.(*etc.PrebuiltEtc) + android.AssertStringEquals( + t, + "module expected to have . install path", + ".", + etcModule.BaseDir(), + ) + android.AssertStringEquals( + t, + "module expected to set empty relative_install_path properties", + "", + etcModule.SubDir(), + ) + + // check that generated prebuilt_* module sets correct srcs + eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext)) + android.AssertStringEquals( + t, + "module expected to set correct dsts property", + "lib/firmware/firmware-2.bin", + getModuleProp(generatedModule1, func(actual interface{}) string { + if p, ok := actual.(*etc.PrebuiltDstsProperties); ok { + dsts := p.Dsts.GetOrDefault(eval, nil) + if len(dsts) == 1 { + return dsts[0] + } } - return false + return "" }), ) } diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go index df361976e..c0f114caf 100644 --- a/fsgen/prebuilt_etc_modules_gen.go +++ b/fsgen/prebuilt_etc_modules_gen.go @@ -215,6 +215,7 @@ var ( "system": etc.PrebuiltSystemFactory, "res": etc.PrebuiltResFactory, "rfs": etc.PrebuiltRfsFactory, + "tee": etc.PrebuiltTeeFactory, "tts": etc.PrebuiltVoicepackFactory, "tvconfig": etc.PrebuiltTvConfigFactory, "tvservice": etc.PrebuiltTvServiceFactory, @@ -336,32 +337,43 @@ func createPrebuiltEtcModulesInDirectory(ctx android.LoadHookContext, partition, propsList = append(propsList, &prebuiltInstallInRootProperties{ Install_in_root: proptools.BoolPtr(true), }) + // Discard any previously picked module and force it to prebuilt_{root,any} as + // they are the only modules allowed to specify the `install_in_root` property. + etcInstallPathKey = "" + relDestDirFromInstallDirBase = destDir } // Set appropriate srcs, dsts, and releative_install_path based on // the source and install file names - if allCopyFileNamesUnchanged { - modulePropsPtr.Srcs = srcBaseFiles + modulePropsPtr.Srcs = srcBaseFiles + + // prebuilt_root should only be used in very limited cases in prebuilt_etc moddule gen, where: + // - all source file names are identical to the installed file names, and + // - all source files are installed in root, not the subdirectories of root + // prebuilt_root currently does not have a good way to specify the names of the multiple + // installed files, and prebuilt_root does not allow installing files at a subdirectory + // of the root. + // Use prebuilt_any instead of prebuilt_root if either of the conditions are not met as + // a fallback behavior. + if etcInstallPathKey == "" { + if !(allCopyFileNamesUnchanged && android.InList(relDestDirFromInstallDirBase, []string{"", "."})) { + moduleFactory = etc.PrebuiltAnyFactory + } + } - // Specify relative_install_path if it is not installed in the root directory of the - // partition + if allCopyFileNamesUnchanged { + // Specify relative_install_path if it is not installed in the base directory of the module. + // In case of prebuilt_{root,any} this is equivalent to the root of the partition. if !android.InList(relDestDirFromInstallDirBase, []string{"", "."}) { propsList = append(propsList, &prebuiltSubdirProperties{ Relative_install_path: proptools.StringPtr(relDestDirFromInstallDirBase), }) } } 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 := proptools.NewConfigurable[[]string](nil, nil) for _, installBaseFile := range installBaseFiles { dsts.AppendSimpleValue([]string{filepath.Join(relDestDirFromInstallDirBase, installBaseFile)}) } - propsList = append(propsList, &etc.PrebuiltDstsProperties{ Dsts: dsts, }) diff --git a/genrule/Android.bp b/genrule/Android.bp index 49df48075..b82f2a9c3 100644 --- a/genrule/Android.bp +++ b/genrule/Android.bp @@ -14,7 +14,6 @@ bootstrap_go_package { "soong-shared", ], srcs: [ - "allowlists.go", "genrule.go", "locations.go", ], diff --git a/genrule/allowlists.go b/genrule/allowlists.go deleted file mode 100644 index 45a7f727c..000000000 --- a/genrule/allowlists.go +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -package genrule - -var ( - SandboxingDenyModuleList = []string{ - // go/keep-sorted start - // go/keep-sorted end - } -) diff --git a/genrule/genrule.go b/genrule/genrule.go index 710ec9555..a7c09e76c 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -969,30 +969,9 @@ func DefaultsFactory(props ...interface{}) android.Module { return module } -var sandboxingAllowlistKey = android.NewOnceKey("genruleSandboxingAllowlistKey") - -type sandboxingAllowlistSets struct { - sandboxingDenyModuleSet map[string]bool -} - -func getSandboxingAllowlistSets(ctx android.PathContext) *sandboxingAllowlistSets { - return ctx.Config().Once(sandboxingAllowlistKey, func() interface{} { - sandboxingDenyModuleSet := map[string]bool{} - - android.AddToStringSet(sandboxingDenyModuleSet, SandboxingDenyModuleList) - return &sandboxingAllowlistSets{ - sandboxingDenyModuleSet: sandboxingDenyModuleSet, - } - }).(*sandboxingAllowlistSets) -} - func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder { if !ctx.DeviceConfig().GenruleSandboxing() { return r.SandboxTools() } - sandboxingAllowlistSets := getSandboxingAllowlistSets(ctx) - if sandboxingAllowlistSets.sandboxingDenyModuleSet[ctx.ModuleName()] { - return r.SandboxTools() - } return r.SandboxInputs() } diff --git a/java/app.go b/java/app.go index 553c65894..05b4a9664 100644 --- a/java/app.go +++ b/java/app.go @@ -82,6 +82,7 @@ type AppInfo struct { Certificate Certificate PrivAppAllowlist android.OptionalPath OverriddenManifestPackageName *string + ApkCertsFile android.Path } var AppInfoProvider = blueprint.NewProvider[*AppInfo]() @@ -691,7 +692,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { } // Use non final ids if we are doing optimized shrinking and are using R8. - nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled() + nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled(ctx) aconfigTextFilePaths := getAconfigFilePaths(ctx) diff --git a/java/app_set.go b/java/app_set.go index 2e9d31410..6a2c678a8 100644 --- a/java/app_set.go +++ b/java/app_set.go @@ -193,9 +193,10 @@ func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) ) android.SetProvider(ctx, AppInfoProvider, &AppInfo{ - AppSet: true, - Privileged: as.Privileged(), - OutputFile: as.OutputFile(), + AppSet: true, + Privileged: as.Privileged(), + OutputFile: as.OutputFile(), + ApkCertsFile: as.apkcertsFile, }) } diff --git a/java/base.go b/java/base.go index 1a12075bc..8aa0109d0 100644 --- a/java/base.go +++ b/java/base.go @@ -1816,7 +1816,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath classesJar: outputFile, jarName: jarName, } - if j.GetProfileGuided(ctx) && j.optimizeOrObfuscateEnabled() && !j.EnableProfileRewriting(ctx) { + if j.GetProfileGuided(ctx) && j.optimizeOrObfuscateEnabled(ctx) && !j.EnableProfileRewriting(ctx) { ctx.PropertyErrorf("enable_profile_rewriting", "Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on. The attached profile should be sourced from an unoptimized/unobfuscated APK.", ) diff --git a/java/dex.go b/java/dex.go index ed9c82ba2..f2406fb3c 100644 --- a/java/dex.go +++ b/java/dex.go @@ -42,6 +42,9 @@ type DexProperties struct { // True if the module containing this has it set by default. EnabledByDefault bool `blueprint:"mutated"` + // If true, then this module will be optimized on eng builds. + Enabled_on_eng *bool + // Whether to allow that library classes inherit from program classes. // Defaults to false. Ignore_library_extends_program *bool @@ -161,7 +164,10 @@ type dexer struct { providesTransitiveHeaderJarsForR8 } -func (d *dexer) effectiveOptimizeEnabled() bool { +func (d *dexer) effectiveOptimizeEnabled(ctx android.EarlyModuleContext) bool { + if ctx.Config().Eng() { + return proptools.Bool(d.dexProperties.Optimize.Enabled_on_eng) + } return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault) } @@ -173,8 +179,8 @@ func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleCont return d.resourceShrinkingEnabled(ctx) && BoolDefault(d.Optimize.Optimized_shrink_resources, ctx.Config().UseOptimizedResourceShrinkingByDefault()) } -func (d *dexer) optimizeOrObfuscateEnabled() bool { - return d.effectiveOptimizeEnabled() && (proptools.Bool(d.dexProperties.Optimize.Optimize) || proptools.Bool(d.dexProperties.Optimize.Obfuscate)) +func (d *dexer) optimizeOrObfuscateEnabled(ctx android.EarlyModuleContext) bool { + return d.effectiveOptimizeEnabled(ctx) && (proptools.Bool(d.dexProperties.Optimize.Optimize) || proptools.Bool(d.dexProperties.Optimize.Obfuscate)) } var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", @@ -353,7 +359,7 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext, flags = append(flags, "--release") } else if ctx.Config().Eng() { flags = append(flags, "--debug") - } else if !d.effectiveOptimizeEnabled() && d.dexProperties.Optimize.EnabledByDefault { + } else if !d.effectiveOptimizeEnabled(ctx) && d.dexProperties.Optimize.EnabledByDefault { // D8 uses --debug by default, whereas R8 uses --release by default. // For targets that default to R8 usage (e.g., apps), but override this default, we still // want D8 to run in release mode, preserving semantics as much as possible between the two. @@ -627,7 +633,7 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam mergeZipsFlags = "-stripFile META-INF/*.kotlin_module -stripFile **/*.kotlin_builtins" } - useR8 := d.effectiveOptimizeEnabled() + useR8 := d.effectiveOptimizeEnabled(ctx) useD8 := !useR8 || ctx.Config().PartialCompileFlags().Use_d8 rbeR8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") rbeD8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") diff --git a/java/dex_test.go b/java/dex_test.go index e94864bbc..8c1e5f7df 100644 --- a/java/dex_test.go +++ b/java/dex_test.go @@ -797,12 +797,14 @@ func TestDebugReleaseFlags(t *testing.T) { }, { name: "app_eng", + useD8: true, isEng: true, expectedFlags: "--debug", }, { name: "app_release_eng", isEng: true, + useD8: true, dxFlags: "--release", // Eng mode does *not* override explicit dxflags. expectedFlags: "--release", diff --git a/java/java.go b/java/java.go index dd9f852f0..07e38a17e 100644 --- a/java/java.go +++ b/java/java.go @@ -670,12 +670,12 @@ func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...) - if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { + if d.effectiveOptimizeEnabled(ctx) && sdkDep.hasStandardLibs() { ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries..., ) } - if d.effectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() { + if d.effectiveOptimizeEnabled(ctx) && sdkDep.hasFrameworkLibs() { ctx.AddVariationDependencies(nil, proguardRaiseTag, config.FrameworkLibraries...) } } diff --git a/tradefed_modules/Android.bp b/tradefed_modules/Android.bp index a765a0532..37bae3928 100644 --- a/tradefed_modules/Android.bp +++ b/tradefed_modules/Android.bp @@ -14,11 +14,9 @@ bootstrap_go_package { ], srcs: [ "test_module_config.go", - "test_suite.go", ], testSrcs: [ "test_module_config_test.go", - "test_suite_test.go", ], pluginFor: ["soong_build"], } diff --git a/tradefed_modules/test_suite.go b/tradefed_modules/test_suite.go deleted file mode 100644 index 8b7babf52..000000000 --- a/tradefed_modules/test_suite.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2024 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tradefed_modules - -import ( - "encoding/json" - "path" - "path/filepath" - - "android/soong/android" - "android/soong/tradefed" - "github.com/google/blueprint" -) - -const testSuiteModuleType = "test_suite" - -type testSuiteTag struct { - blueprint.BaseDependencyTag -} - -type testSuiteManifest struct { - Name string `json:"name"` - Files []string `json:"files"` -} - -func init() { - RegisterTestSuiteBuildComponents(android.InitRegistrationContext) -} - -func RegisterTestSuiteBuildComponents(ctx android.RegistrationContext) { - ctx.RegisterModuleType(testSuiteModuleType, TestSuiteFactory) -} - -var PrepareForTestWithTestSuiteBuildComponents = android.GroupFixturePreparers( - android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents), -) - -type testSuiteProperties struct { - Description string - Tests []string `android:"path,arch_variant"` -} - -type testSuiteModule struct { - android.ModuleBase - android.DefaultableModuleBase - testSuiteProperties -} - -func (t *testSuiteModule) DepsMutator(ctx android.BottomUpMutatorContext) { - for _, test := range t.Tests { - if ctx.OtherModuleDependencyVariantExists(ctx.Config().BuildOSCommonTarget.Variations(), test) { - // Host tests. - ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), testSuiteTag{}, test) - } else { - // Target tests. - ctx.AddDependency(ctx.Module(), testSuiteTag{}, test) - } - } -} - -func (t *testSuiteModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - suiteName := ctx.ModuleName() - modulesByName := make(map[string]android.Module) - ctx.WalkDeps(func(child, parent android.Module) bool { - // Recurse into test_suite dependencies. - if ctx.OtherModuleType(child) == testSuiteModuleType { - ctx.Phony(suiteName, android.PathForPhony(ctx, child.Name())) - return true - } - - // Only write out top level test suite dependencies here. - if _, ok := ctx.OtherModuleDependencyTag(child).(testSuiteTag); !ok { - return false - } - - if !child.InstallInTestcases() { - ctx.ModuleErrorf("test_suite only supports modules installed in testcases. %q is not installed in testcases.", child.Name()) - return false - } - - modulesByName[child.Name()] = child - return false - }) - - var files []string - for name, module := range modulesByName { - // Get the test provider data from the child. - tp, ok := android.OtherModuleProvider(ctx, module, tradefed.BaseTestProviderKey) - if !ok { - // TODO: Consider printing out a list of all module types. - ctx.ModuleErrorf("%q is not a test module.", name) - continue - } - - files = append(files, packageModuleFiles(ctx, suiteName, module, tp)...) - ctx.Phony(suiteName, android.PathForPhony(ctx, name)) - } - - manifestPath := android.PathForSuiteInstall(ctx, suiteName, suiteName+".json") - b, err := json.Marshal(testSuiteManifest{Name: suiteName, Files: android.SortedUniqueStrings(files)}) - if err != nil { - ctx.ModuleErrorf("Failed to marshal manifest: %v", err) - return - } - android.WriteFileRule(ctx, manifestPath, string(b)) - - ctx.Phony(suiteName, manifestPath) -} - -func TestSuiteFactory() android.Module { - module := &testSuiteModule{} - module.AddProperties(&module.testSuiteProperties) - - android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) - android.InitDefaultableModule(module) - - return module -} - -func packageModuleFiles(ctx android.ModuleContext, suiteName string, module android.Module, tp tradefed.BaseTestProviderData) []string { - - hostOrTarget := "target" - if tp.IsHost { - hostOrTarget = "host" - } - - // suiteRoot at out/soong/packaging/<suiteName>. - suiteRoot := android.PathForSuiteInstall(ctx, suiteName) - - var installed android.InstallPaths - // Install links to installed files from the module. - if installFilesInfo, ok := android.OtherModuleProvider(ctx, module, android.InstallFilesProvider); ok { - for _, f := range installFilesInfo.InstallFiles { - // rel is anything under .../<partition>, normally under .../testcases. - rel := android.Rel(ctx, f.PartitionDir(), f.String()) - - // Install the file under <suiteRoot>/<host|target>/<partition>. - installDir := suiteRoot.Join(ctx, hostOrTarget, f.Partition(), path.Dir(rel)) - linkTo, err := filepath.Rel(installDir.String(), f.String()) - if err != nil { - ctx.ModuleErrorf("Failed to get relative path from %s to %s: %v", installDir.String(), f.String(), err) - continue - } - installed = append(installed, ctx.InstallAbsoluteSymlink(installDir, path.Base(rel), linkTo)) - } - } - - // Install config file. - if tp.TestConfig != nil { - moduleRoot := suiteRoot.Join(ctx, hostOrTarget, "testcases", module.Name()) - installed = append(installed, ctx.InstallFile(moduleRoot, module.Name()+".config", tp.TestConfig)) - } - - // Add to phony and manifest, manifestpaths are relative to suiteRoot. - var manifestEntries []string - for _, f := range installed { - manifestEntries = append(manifestEntries, android.Rel(ctx, suiteRoot.String(), f.String())) - ctx.Phony(suiteName, f) - } - return manifestEntries -} diff --git a/tradefed_modules/test_suite_test.go b/tradefed_modules/test_suite_test.go deleted file mode 100644 index 3e1472cee..000000000 --- a/tradefed_modules/test_suite_test.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2024 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -package tradefed_modules - -import ( - "android/soong/android" - "android/soong/java" - "encoding/json" - "slices" - "testing" -) - -func TestTestSuites(t *testing.T) { - t.Parallel() - ctx := android.GroupFixturePreparers( - java.PrepareForTestWithJavaDefaultModules, - android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents), - ).RunTestWithBp(t, ` - android_test { - name: "TestModule1", - sdk_version: "current", - } - - android_test { - name: "TestModule2", - sdk_version: "current", - } - - test_suite { - name: "my-suite", - description: "a test suite", - tests: [ - "TestModule1", - "TestModule2", - ] - } - `) - manifestPath := ctx.ModuleForTests(t, "my-suite", "android_common").Output("out/soong/test_suites/my-suite/my-suite.json") - var actual testSuiteManifest - if err := json.Unmarshal([]byte(android.ContentFromFileRuleForTests(t, ctx.TestContext, manifestPath)), &actual); err != nil { - t.Errorf("failed to unmarshal manifest: %v", err) - } - slices.Sort(actual.Files) - - expected := testSuiteManifest{ - Name: "my-suite", - Files: []string{ - "target/testcases/TestModule1/TestModule1.config", - "target/testcases/TestModule1/arm64/TestModule1.apk", - "target/testcases/TestModule2/TestModule2.config", - "target/testcases/TestModule2/arm64/TestModule2.apk", - }, - } - - android.AssertDeepEquals(t, "manifests differ", expected, actual) -} - -func TestTestSuitesWithNested(t *testing.T) { - t.Parallel() - ctx := android.GroupFixturePreparers( - java.PrepareForTestWithJavaDefaultModules, - android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents), - ).RunTestWithBp(t, ` - android_test { - name: "TestModule1", - sdk_version: "current", - } - - android_test { - name: "TestModule2", - sdk_version: "current", - } - - android_test { - name: "TestModule3", - sdk_version: "current", - } - - test_suite { - name: "my-child-suite", - description: "a child test suite", - tests: [ - "TestModule1", - "TestModule2", - ] - } - - test_suite { - name: "my-all-tests-suite", - description: "a parent test suite", - tests: [ - "TestModule1", - "TestModule3", - "my-child-suite", - ] - } - `) - manifestPath := ctx.ModuleForTests(t, "my-all-tests-suite", "android_common").Output("out/soong/test_suites/my-all-tests-suite/my-all-tests-suite.json") - var actual testSuiteManifest - if err := json.Unmarshal([]byte(android.ContentFromFileRuleForTests(t, ctx.TestContext, manifestPath)), &actual); err != nil { - t.Errorf("failed to unmarshal manifest: %v", err) - } - slices.Sort(actual.Files) - - expected := testSuiteManifest{ - Name: "my-all-tests-suite", - Files: []string{ - "target/testcases/TestModule1/TestModule1.config", - "target/testcases/TestModule1/arm64/TestModule1.apk", - "target/testcases/TestModule2/TestModule2.config", - "target/testcases/TestModule2/arm64/TestModule2.apk", - "target/testcases/TestModule3/TestModule3.config", - "target/testcases/TestModule3/arm64/TestModule3.apk", - }, - } - - android.AssertDeepEquals(t, "manifests differ", expected, actual) -} - -func TestTestSuitesNotInstalledInTestcases(t *testing.T) { - t.Parallel() - android.GroupFixturePreparers( - java.PrepareForTestWithJavaDefaultModules, - android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents), - ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern([]string{ - `"SomeHostTest" is not installed in testcases`, - })).RunTestWithBp(t, ` - java_test_host { - name: "SomeHostTest", - srcs: ["a.java"], - } - test_suite { - name: "my-suite", - description: "a test suite", - tests: [ - "SomeHostTest", - ] - } - `) -} diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go index cd49ec876..622aadb95 100644 --- a/ui/build/androidmk_denylist.go +++ b/ui/build/androidmk_denylist.go @@ -15,20 +15,29 @@ package build import ( + "os" + "slices" "strings" ) var androidmk_denylist []string = []string{ + "art/", "bionic/", - "chained_build_config/", + "bootable/", + "build/", "cts/", "dalvik/", "developers/", "development/", "device/common/", + "device/generic/", + "device/google/", "device/google_car/", "device/sample/", + "external/", "frameworks/", + "hardware/google/", + "hardware/interfaces/", "hardware/libhardware/", "hardware/libhardware_legacy/", "hardware/ril/", @@ -45,24 +54,38 @@ var androidmk_denylist []string = []string{ "sdk/", "system/", "test/", + "tools/", "trusty/", - // Add back toolchain/ once defensive Android.mk files are removed - //"toolchain/", - "vendor/google_contexthub/", - "vendor/google_data/", - "vendor/google_elmyra/", - "vendor/google_mhl/", - "vendor/google_pdk/", - "vendor/google_testing/", - "vendor/partner_testing/", - "vendor/partner_tools/", - "vendor/pdk/", + "toolchain/", +} + +var androidmk_allowlist []string = []string{ + "art/Android.mk", + "bootable/deprecated-ota/updater/Android.mk", +} + +func getAllLines(ctx Context, filename string) []string { + bytes, err := os.ReadFile(filename) + if err != nil { + if os.IsNotExist(err) { + return []string{} + } else { + ctx.Fatalf("Could not read %s: %v", filename, err) + } + } + return strings.Split(strings.Trim(string(bytes), " \n"), "\n") } func blockAndroidMks(ctx Context, androidMks []string) { + allowlist := getAllLines(ctx, "vendor/google/build/androidmk/allowlist.txt") + androidmk_allowlist = append(androidmk_allowlist, allowlist...) + + denylist := getAllLines(ctx, "vendor/google/build/androidmk/denylist.txt") + androidmk_denylist = append(androidmk_denylist, denylist...) + for _, mkFile := range androidMks { for _, d := range androidmk_denylist { - if strings.HasPrefix(mkFile, d) { + if strings.HasPrefix(mkFile, d) && !slices.Contains(androidmk_allowlist, mkFile) { ctx.Fatalf("Found blocked Android.mk file: %s. "+ "Please see androidmk_denylist.go for the blocked directories and contact build system team if the file should not be blocked.", mkFile) } @@ -86,6 +109,12 @@ var external_androidmks []string = []string{ // These directories hold the published Android SDK, used in Unbundled Gradle builds. "prebuilts/fullsdk-darwin", "prebuilts/fullsdk-linux", + // wpa_supplicant_8 has been converted to Android.bp and Android.mk files are kept for troubleshooting. + "external/wpa_supplicant_8/", + // Empty Android.mk in package's top directory + "external/proguard/", + "external/swig/", + "toolchain/", } var art_androidmks = []string{ diff --git a/ui/build/finder.go b/ui/build/finder.go index 783b48863..ff8908b29 100644 --- a/ui/build/finder.go +++ b/ui/build/finder.go @@ -84,8 +84,14 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) { // METADATA file of packages "METADATA", }, - // .mk files for product/board configuration. - IncludeSuffixes: []string{".mk"}, + IncludeSuffixes: []string{ + // .mk files for product/board configuration. + ".mk", + // otatools cert files + ".pk8", + ".pem", + ".avbpubkey", + }, } dumpDir := config.FileListDir() f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard), @@ -118,6 +124,18 @@ func findProductAndBoardConfigFiles(entries finder.DirEntries) (dirNames []strin return entries.DirNames, matches } +func findOtaToolsCertFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) { + matches := []string{} + for _, foundName := range entries.FileNames { + if strings.HasSuffix(foundName, ".pk8") || + strings.HasSuffix(foundName, ".pem") || + strings.HasSuffix(foundName, ".avbpubkey") { + matches = append(matches, foundName) + } + } + return entries.DirNames, matches +} + // FindSources searches for source files known to <f> and writes them to the filesystem for // use later. func FindSources(ctx Context, config Config, f *finder.Finder) { @@ -184,6 +202,17 @@ func FindSources(ctx Context, config Config, f *finder.Finder) { ctx.Fatalf("Could not find TEST_MAPPING: %v", err) } + // Recursively look for all otatools cert files. + otatools_cert_files := f.FindMatching("build/make/target/product/security", findOtaToolsCertFiles) + otatools_cert_files = append(otatools_cert_files, f.FindMatching("device", findOtaToolsCertFiles)...) + otatools_cert_files = append(otatools_cert_files, f.FindMatching("external/avb/test/data", findOtaToolsCertFiles)...) + otatools_cert_files = append(otatools_cert_files, f.FindMatching("packages/modules", findOtaToolsCertFiles)...) + otatools_cert_files = append(otatools_cert_files, f.FindMatching("vendor", findOtaToolsCertFiles)...) + err = dumpListToFile(ctx, config, otatools_cert_files, filepath.Join(dumpDir, "OtaToolsCertFiles.list")) + if err != nil { + ctx.Fatalf("Could not find otatools cert files: %v", err) + } + // Recursively look for all Android.bp files androidBps := f.FindNamedAt(".", "Android.bp") if len(androidBps) == 0 { |