diff options
45 files changed, 897 insertions, 372 deletions
diff --git a/android/apex.go b/android/apex.go index 9277ff31b..414d4e140 100644 --- a/android/apex.go +++ b/android/apex.go @@ -70,11 +70,6 @@ type ApexInfo struct { // prebuilt, the name here doesn't have the `prebuilt_` prefix. InApexModules []string - // Pointers to the ApexContents struct each of which is for apexBundle modules that this - // module is part of. The ApexContents gives information about which modules the apexBundle - // has and whether a module became part of the apexBundle via a direct dependency or not. - ApexContents []*ApexContents - // True if this is for a prebuilt_apex. // // If true then this will customize the apex processing to make it suitable for handling @@ -162,7 +157,6 @@ func (i ApexInfo) Equal(other any) bool { // ApexBundleInfo contains information about the dependencies of an apex type ApexBundleInfo struct { - Contents *ApexContents } var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_info") @@ -220,15 +214,8 @@ type ApexModule interface { // this after apex.apexMutator is run. InAnyApex() bool - // Returns true if this module is directly in any APEX. Call this AFTER apex.apexMutator is - // run. - DirectlyInAnyApex() bool - - // NotInPlatform tells whether or not this module is included in an APEX and therefore - // shouldn't be exposed to the platform (i.e. outside of the APEX) directly. A module is - // considered to be included in an APEX either when there actually is an APEX that - // explicitly has the module as its dependency or the module is not available to the - // platform, which indicates that the module belongs to at least one or more other APEXes. + // NotInPlatform returns true if the module is not available to the platform due to + // apex_available being set and not containing "//apex_available:platform". NotInPlatform() bool // Tests if this module could have APEX variants. Even when a module type implements @@ -288,17 +275,6 @@ type ApexProperties struct { // See ApexModule.InAnyApex() InAnyApex bool `blueprint:"mutated"` - // See ApexModule.DirectlyInAnyApex() - DirectlyInAnyApex bool `blueprint:"mutated"` - - // AnyVariantDirectlyInAnyApex is true in the primary variant of a module if _any_ variant - // of the module is directly in any apex. This includes host, arch, asan, etc. variants. It - // is unused in any variant that is not the primary variant. Ideally this wouldn't be used, - // as it incorrectly mixes arch variants if only one arch is in an apex, but a few places - // depend on it, for example when an ASAN variant is created before the apexMutator. Call - // this after apex.apexMutator is run. - AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"` - // See ApexModule.NotAvailableForPlatform() NotAvailableForPlatform bool `blueprint:"mutated"` @@ -335,16 +311,6 @@ type AlwaysRequireApexVariantTag interface { AlwaysRequireApexVariant() bool } -// Marker interface that identifies dependencies that should inherit the DirectlyInAnyApex state -// from the parent to the child. For example, stubs libraries are marked as DirectlyInAnyApex if -// their implementation is in an apex. -type CopyDirectlyInAnyApexTag interface { - blueprint.DependencyTag - - // Method that differentiates this interface from others. - CopyDirectlyInAnyApex() -} - // Interface that identifies dependencies to skip Apex dependency check type SkipApexAllowedDependenciesCheck interface { // Returns true to skip the Apex dependency check, which limits the allowed dependency in build. @@ -422,13 +388,8 @@ func (m *ApexModuleBase) InAnyApex() bool { } // Implements ApexModule -func (m *ApexModuleBase) DirectlyInAnyApex() bool { - return m.ApexProperties.DirectlyInAnyApex -} - -// Implements ApexModule func (m *ApexModuleBase) NotInPlatform() bool { - return m.ApexProperties.AnyVariantDirectlyInAnyApex || !m.AvailableFor(AvailableToPlatform) + return !m.AvailableFor(AvailableToPlatform) } // Implements ApexModule @@ -586,7 +547,6 @@ func mergeApexVariations(apexInfos []ApexInfo) (merged []ApexInfo, aliases [][2] // Variants having the same mergedName are deduped merged[index].InApexVariants = append(merged[index].InApexVariants, variantName) merged[index].InApexModules = append(merged[index].InApexModules, apexInfo.InApexModules...) - merged[index].ApexContents = append(merged[index].ApexContents, apexInfo.ApexContents...) merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable // Platform APIs is allowed for this module only when all APEXes containing // the module are with `use_platform_apis: true`. @@ -597,7 +557,6 @@ func mergeApexVariations(apexInfos []ApexInfo) (merged []ApexInfo, aliases [][2] apexInfo.ApexVariationName = mergedName apexInfo.InApexVariants = CopyOf(apexInfo.InApexVariants) apexInfo.InApexModules = CopyOf(apexInfo.InApexModules) - apexInfo.ApexContents = append([]*ApexContents(nil), apexInfo.ApexContents...) apexInfo.TestApexes = CopyOf(apexInfo.TestApexes) merged = append(merged, apexInfo) } @@ -685,14 +644,7 @@ func MutateApexTransition(ctx BaseModuleContext, variation string) { apexInfos, _ = mergeApexVariations(apexInfos) } - var inApex ApexMembership - for _, a := range apexInfos { - for _, apexContents := range a.ApexContents { - inApex = inApex.merge(apexContents.contents[ctx.ModuleName()]) - } - } base.ApexProperties.InAnyApex = true - base.ApexProperties.DirectlyInAnyApex = inApex == directlyInApex if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() { // Do not install the module for platform, but still allow it to output @@ -783,93 +735,6 @@ func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModul }) } -// UpdateDirectlyInAnyApex uses the final module to store if any variant of this module is directly -// in any APEX, and then copies the final value to all the modules. It also copies the -// DirectlyInAnyApex value to any transitive dependencies with a CopyDirectlyInAnyApexTag -// dependency tag. -func UpdateDirectlyInAnyApex(mctx BottomUpMutatorContext, am ApexModule) { - base := am.apexModuleBase() - // Copy DirectlyInAnyApex and InAnyApex from any transitive dependencies with a - // CopyDirectlyInAnyApexTag dependency tag. - mctx.WalkDeps(func(child, parent Module) bool { - if _, ok := mctx.OtherModuleDependencyTag(child).(CopyDirectlyInAnyApexTag); ok { - depBase := child.(ApexModule).apexModuleBase() - depBase.apexPropertiesLock.Lock() - defer depBase.apexPropertiesLock.Unlock() - depBase.ApexProperties.DirectlyInAnyApex = base.ApexProperties.DirectlyInAnyApex - depBase.ApexProperties.InAnyApex = base.ApexProperties.InAnyApex - return true - } - return false - }) - - if base.ApexProperties.DirectlyInAnyApex { - // Variants of a module are always visited sequentially in order, so it is safe to - // write to another variant of this module. For a BottomUpMutator the - // PrimaryModule() is visited first and FinalModule() is visited last. - mctx.FinalModule().(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex = true - } - - // If this is the FinalModule (last visited module) copy - // AnyVariantDirectlyInAnyApex to all the other variants - if mctx.IsFinalModule(am) { - mctx.VisitAllModuleVariants(func(variant Module) { - variant.(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex = - base.ApexProperties.AnyVariantDirectlyInAnyApex - }) - } -} - -// ApexMembership tells how a module became part of an APEX. -type ApexMembership int - -const ( - notInApex ApexMembership = 0 - indirectlyInApex = iota - directlyInApex -) - -// ApexContents gives an information about member modules of an apexBundle. Each apexBundle has an -// apexContents, and modules in that apex have a provider containing the apexContents of each -// apexBundle they are part of. -type ApexContents struct { - // map from a module name to its membership in this apexBundle - contents map[string]ApexMembership -} - -// NewApexContents creates and initializes an ApexContents that is suitable -// for use with an apex module. -// - contents is a map from a module name to information about its membership within -// the apex. -func NewApexContents(contents map[string]ApexMembership) *ApexContents { - return &ApexContents{ - contents: contents, - } -} - -// Updates an existing membership by adding a new direct (or indirect) membership -func (i ApexMembership) Add(direct bool) ApexMembership { - if direct || i == directlyInApex { - return directlyInApex - } - return indirectlyInApex -} - -// Merges two membership into one. Merging is needed because a module can be a part of an apexBundle -// in many different paths. For example, it could be dependend on by the apexBundle directly, but at -// the same time, there might be an indirect dependency to the module. In that case, the more -// specific dependency (the direct one) is chosen. -func (i ApexMembership) merge(other ApexMembership) ApexMembership { - if other == directlyInApex || i == directlyInApex { - return directlyInApex - } - - if other == indirectlyInApex || i == indirectlyInApex { - return indirectlyInApex - } - return notInApex -} - //////////////////////////////////////////////////////////////////////////////////////////////////// //Below are routines for extra safety checks. // diff --git a/android/config.go b/android/config.go index 27d3b87ba..dff3ea5bd 100644 --- a/android/config.go +++ b/android/config.go @@ -285,6 +285,10 @@ func (c Config) ReleaseCreateAconfigStorageFile() bool { return c.config.productVariables.GetBuildFlagBool("RELEASE_CREATE_ACONFIG_STORAGE_FILE") } +func (c Config) ReleaseUseSystemFeatureBuildFlags() bool { + return c.config.productVariables.GetBuildFlagBool("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS") +} + // A DeviceConfig object represents the configuration for a particular device // being built. For now there will only be one of these, but in the future there // may be multiple devices being built. @@ -1834,6 +1838,10 @@ func (c *config) ApexCompressionEnabled() bool { return Bool(c.productVariables.CompressedApex) && !c.UnbundledBuildApps() } +func (c *config) DefaultApexPayloadType() string { + return StringDefault(c.productVariables.DefaultApexPayloadType, "ext4") +} + func (c *config) UseSoongSystemImage() bool { return Bool(c.productVariables.UseSoongSystemImage) } diff --git a/android/module_context.go b/android/module_context.go index 20149074e..ae7b54f66 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -831,6 +831,11 @@ func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON { } func (m *moduleContext) SetOutputFiles(outputFiles Paths, tag string) { + for _, outputFile := range outputFiles { + if outputFile == nil { + panic("outputfiles cannot be nil") + } + } if tag == "" { if len(m.outputFiles.DefaultOutputFiles) > 0 { m.ModuleErrorf("Module %s default OutputFiles cannot be overwritten", m.ModuleName()) diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 5e4af0ba5..b90ef3b1c 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -508,11 +508,10 @@ func (p *prebuiltModule) Name() string { } func (p *prebuiltModule) GenerateAndroidBuildActions(ctx ModuleContext) { - var src Path if len(p.properties.Srcs) >= 1 { - src = p.prebuilt.SingleSourcePath(ctx) + src := p.prebuilt.SingleSourcePath(ctx) + ctx.SetOutputFiles(Paths{src}, "") } - ctx.SetOutputFiles(Paths{src}, "") } func (p *prebuiltModule) Prebuilt() *Prebuilt { diff --git a/android/rule_builder.go b/android/rule_builder.go index 403c18418..a1573868b 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -611,6 +611,7 @@ func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString b nsjailCmd.WriteString(" -m none:/tmp:tmpfs:size=1073741824") // 1GB, should be enough nsjailCmd.WriteString(" -D nsjail_build_sandbox") nsjailCmd.WriteString(" --disable_rlimits") + nsjailCmd.WriteString(" --skip_setsid") // ABFS relies on process-groups to track file operations nsjailCmd.WriteString(" -q") nsjailCmd.WriteString(" -- ") nsjailCmd.WriteString("/bin/bash -c ") diff --git a/android/sbom.go b/android/sbom.go index 2a5499ed8..f2b9c0ff1 100644 --- a/android/sbom.go +++ b/android/sbom.go @@ -15,9 +15,7 @@ package android import ( - "io" "path/filepath" - "strings" "github.com/google/blueprint" ) @@ -55,21 +53,7 @@ func (this *sbomSingleton) GenerateBuildActions(ctx SingletonContext) { if !ctx.Config().HasDeviceProduct() { return } - // Get all METADATA files and add them as implicit input - metadataFileListFile := PathForArbitraryOutput(ctx, ".module_paths", "METADATA.list") - f, err := ctx.Config().fs.Open(metadataFileListFile.String()) - if err != nil { - panic(err) - } - b, err := io.ReadAll(f) - if err != nil { - panic(err) - } - allMetadataFiles := strings.Split(string(b), "\n") - implicits := []Path{metadataFileListFile} - for _, path := range allMetadataFiles { - implicits = append(implicits, PathForSource(ctx, path)) - } + implicits := []Path{} prodVars := ctx.Config().productVariables buildFingerprintFile := PathForArbitraryOutput(ctx, "target", "product", String(prodVars.DeviceName), "build_fingerprint.txt") implicits = append(implicits, buildFingerprintFile) diff --git a/android/variable.go b/android/variable.go index 2d43c6da4..e66653096 100644 --- a/android/variable.go +++ b/android/variable.go @@ -408,9 +408,10 @@ type ProductVariables struct { Ndk_abis *bool `json:",omitempty"` - ForceApexSymlinkOptimization *bool `json:",omitempty"` - CompressedApex *bool `json:",omitempty"` - Aml_abis *bool `json:",omitempty"` + ForceApexSymlinkOptimization *bool `json:",omitempty"` + CompressedApex *bool `json:",omitempty"` + DefaultApexPayloadType *string `json:",omitempty"` + Aml_abis *bool `json:",omitempty"` DexpreoptGlobalConfig *string `json:",omitempty"` @@ -609,8 +610,12 @@ type PartitionVariables struct { ProductUseDynamicPartitionSize bool `json:",omitempty"` CopyImagesForTargetFilesZip bool `json:",omitempty"` + VendorSecurityPatch string `json:",omitempty"` + // Boot image stuff + BuildingRamdiskImage bool `json:",omitempty"` ProductBuildBootImage bool `json:",omitempty"` + ProductBuildVendorBootImage string `json:",omitempty"` ProductBuildInitBootImage bool `json:",omitempty"` BoardUsesRecoveryAsBoot bool `json:",omitempty"` BoardPrebuiltBootimage string `json:",omitempty"` @@ -618,6 +623,10 @@ type PartitionVariables struct { BoardBootimagePartitionSize string `json:",omitempty"` BoardInitBootimagePartitionSize string `json:",omitempty"` BoardBootHeaderVersion string `json:",omitempty"` + TargetKernelPath string `json:",omitempty"` + BoardUsesGenericKernelImage bool `json:",omitempty"` + BootSecurityPatch string `json:",omitempty"` + InitBootSecurityPatch string `json:",omitempty"` // Avb (android verified boot) stuff BoardAvbEnable bool `json:",omitempty"` diff --git a/apex/aconfig_test.go b/apex/aconfig_test.go index 76227a9ab..0eb8ef479 100644 --- a/apex/aconfig_test.go +++ b/apex/aconfig_test.go @@ -60,6 +60,7 @@ func TestValidationAcrossContainersExportedPass(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } aconfig_declarations { name: "my_aconfig_declarations_foo", @@ -339,6 +340,7 @@ func TestValidationAcrossContainersNotExportedFail(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } aconfig_declarations { name: "my_aconfig_declarations_foo", @@ -761,6 +763,7 @@ func TestValidationNotPropagateAcrossShared(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } java_library { name: "my_java_library_foo", diff --git a/apex/apex.go b/apex/apex.go index dc24df3d1..ed9e58a63 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -67,7 +67,6 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { // it should create a platform variant. ctx.BottomUp("mark_platform_availability", markPlatformAvailability) ctx.Transition("apex", &apexTransitionMutator{}) - ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).MutatesDependencies() } type apexBundleProperties struct { @@ -993,25 +992,7 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { return true } - // Records whether a certain module is included in this apexBundle via direct dependency or - // inndirect dependency. - contents := make(map[string]android.ApexMembership) - mctx.WalkDeps(func(child, parent android.Module) bool { - if !continueApexDepsWalk(child, parent) { - return false - } - // If the parent is apexBundle, this child is directly depended. - _, directDep := parent.(*apexBundle) - depName := mctx.OtherModuleName(child) - contents[depName] = contents[depName].Add(directDep) - return true - }) - - // The membership information is saved for later access - apexContents := android.NewApexContents(contents) - android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{ - Contents: apexContents, - }) + android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{}) minSdkVersion := a.minSdkVersion(mctx) // When min_sdk_version is not set, the apex is built against FutureApiLevel. @@ -1040,7 +1021,6 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { UsePlatformApis: a.UsePlatformApis(), InApexVariants: []string{apexVariationName}, InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo - ApexContents: []*android.ApexContents{apexContents}, TestApexes: testApexes, BaseApexName: mctx.ModuleName(), ApexAvailableName: proptools.String(a.properties.Apex_available_name), @@ -1242,14 +1222,6 @@ func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool { return true } -// See android.UpdateDirectlyInAnyApex -// TODO(jiyong): move this to android/apex.go? -func apexDirectlyInAnyMutator(mctx android.BottomUpMutatorContext) { - if am, ok := mctx.Module().(android.ApexModule); ok { - android.UpdateDirectlyInAnyApex(mctx, am) - } -} - const ( // File extensions of an APEX for different packaging methods imageApexSuffix = ".apex" @@ -1752,7 +1724,8 @@ func (a *apexBundle) setSystemLibLink(ctx android.ModuleContext) { } func (a *apexBundle) setPayloadFsType(ctx android.ModuleContext) { - switch proptools.StringDefault(a.properties.Payload_fs_type, ext4FsType) { + defaultFsType := ctx.Config().DefaultApexPayloadType() + switch proptools.StringDefault(a.properties.Payload_fs_type, defaultFsType) { case ext4FsType: a.payloadFsType = ext4 case f2fsFsType: @@ -2082,7 +2055,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, // // Skip the dependency in unbundled builds where the device image is not // being built. - if ch.IsStubsImplementationRequired() && !am.DirectlyInAnyApex() && !ctx.Config().UnbundledBuild() { + if ch.IsStubsImplementationRequired() && !am.NotInPlatform() && !ctx.Config().UnbundledBuild() { // we need a module name for Make name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName if !android.InList(name, a.makeModulesToInstall) { @@ -2179,8 +2152,6 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, ctx.PropertyErrorf("systemserverclasspath_fragments", "systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child)) } - } else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok { - // nothing } else if depTag == android.DarwinUniversalVariantTag { // nothing } else if depTag == android.RequiredDepTag { diff --git a/apex/apex_test.go b/apex/apex_test.go index d0494d67d..5b5fe5ff1 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -495,6 +495,7 @@ func TestBasicApex(t *testing.T) { "//apex_available:platform", "myapex", ], + compile_dex: true, } dex_import { @@ -664,6 +665,7 @@ func TestDefaults(t *testing.T) { sdk_version: "none", system_modules: "none", apex_available: [ "myapex" ], + compile_dex: true, } android_app { @@ -2035,6 +2037,7 @@ func TestApexMinSdkVersion_SupportsCodeNames_JavaLibs(t *testing.T) { apex_available: [ "myapex" ], sdk_version: "current", min_sdk_version: "S", // should be okay + compile_dex: true, } `, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { @@ -2584,6 +2587,7 @@ func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) { "myapex", ], min_sdk_version: "30", + compile_dex: true, } `) @@ -2611,6 +2615,7 @@ func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) { // Compile against core API surface sdk_version: "core_current", min_sdk_version: "30", + compile_dex: true, } `) @@ -2658,6 +2663,7 @@ func TestApexMinSdkVersion_Okay(t *testing.T) { ], apex_available: ["myapex"], min_sdk_version: "29", + compile_dex: true, } java_library { @@ -2737,6 +2743,7 @@ func TestJavaStableSdkVersion(t *testing.T) { srcs: ["foo/bar/MyClass.java"], sdk_version: "test_current", apex_available: ["myapex"], + compile_dex: true, } `, }, @@ -2761,6 +2768,7 @@ func TestJavaStableSdkVersion(t *testing.T) { sdk_version: "current", apex_available: ["myapex"], min_sdk_version: "29", + compile_dex: true, } `, }, @@ -2784,6 +2792,7 @@ func TestJavaStableSdkVersion(t *testing.T) { srcs: ["foo/bar/MyClass.java"], sdk_version: "test_current", apex_available: ["myapex"], + compile_dex: true, } `, }, @@ -2807,6 +2816,7 @@ func TestJavaStableSdkVersion(t *testing.T) { srcs: ["foo/bar/MyClass.java"], sdk_version: "core_platform", apex_available: ["myapex"], + compile_dex: true, } `, preparer: java.FixtureUseLegacyCorePlatformApi("myjar-uses-legacy"), @@ -2835,6 +2845,7 @@ func TestJavaStableSdkVersion(t *testing.T) { sdk_version: "current", apex_available: ["myapex"], static_libs: ["transitive-jar"], + compile_dex: true, } java_library { name: "transitive-jar", @@ -5913,6 +5924,7 @@ func TestErrorsIfDepsAreNotEnabled(t *testing.T) { system_modules: "none", enabled: false, apex_available: ["myapex"], + compile_dex: true, } `) } @@ -7525,6 +7537,7 @@ func TestJavaSDKLibrary_WithinApex(t *testing.T) { apex_available: ["myapex"], sdk_version: "none", system_modules: "none", + compile_dex: true, } java_library { @@ -7534,6 +7547,7 @@ func TestJavaSDKLibrary_WithinApex(t *testing.T) { apex_available: ["myapex"], sdk_version: "none", system_modules: "none", + compile_dex: true, } prebuilt_apis { @@ -7643,6 +7657,7 @@ func TestJavaSDKLibrary_ImportPreferred(t *testing.T) { apex_available: ["myapex"], sdk_version: "none", system_modules: "none", + compile_dex: true, } `), "source/a.java": nil, @@ -7664,6 +7679,7 @@ func TestJavaSDKLibrary_ImportPreferred(t *testing.T) { public: { enabled: true, }, + compile_dex: true, } `), "prebuilt/a.jar": nil, @@ -7680,6 +7696,7 @@ func TestJavaSDKLibrary_ImportPreferred(t *testing.T) { public: { jars: ["a.jar"], }, + compile_dex: true, } `), }), withFiles(filesForSdkLibrary), @@ -7758,6 +7775,7 @@ func TestCompatConfig(t *testing.T) { sdk_version: "none", system_modules: "none", apex_available: [ "myapex" ], + compile_dex: true, } // Make sure that a preferred prebuilt does not affect the apex contents. @@ -7997,6 +8015,7 @@ func TestSymlinksFromApexToSystem(t *testing.T) { "//apex_available:platform", ], min_sdk_version: "33", + compile_dex: true, } java_library { @@ -8605,6 +8624,7 @@ func TestApexPermittedPackagesRules(t *testing.T) { apex_available: ["myapex"], sdk_version: "none", system_modules: "none", + compile_dex: true, } java_library { name: "nonbcp_lib2", @@ -8613,6 +8633,7 @@ func TestApexPermittedPackagesRules(t *testing.T) { permitted_packages: ["a.b"], sdk_version: "none", system_modules: "none", + compile_dex: true, } apex { name: "myapex", @@ -8638,6 +8659,7 @@ func TestApexPermittedPackagesRules(t *testing.T) { permitted_packages: ["foo.bar"], sdk_version: "none", system_modules: "none", + compile_dex: true, } java_library { name: "bcp_lib2", @@ -8646,6 +8668,7 @@ func TestApexPermittedPackagesRules(t *testing.T) { permitted_packages: ["foo.bar", "bar.baz"], sdk_version: "none", system_modules: "none", + compile_dex: true, } apex { name: "myapex", @@ -8676,6 +8699,7 @@ func TestApexPermittedPackagesRules(t *testing.T) { sdk_version: "none", min_sdk_version: "29", system_modules: "none", + compile_dex: true, } java_library { name: "bcp_lib_unrestricted", @@ -8685,6 +8709,7 @@ func TestApexPermittedPackagesRules(t *testing.T) { sdk_version: "none", min_sdk_version: "29", system_modules: "none", + compile_dex: true, } apex { name: "myapex", @@ -9834,6 +9859,7 @@ func TestApexStrictUpdtabilityLint(t *testing.T) { }, sdk_version: "current", min_sdk_version: "29", + compile_dex: true, } ` fs := android.MockFS{ @@ -10268,6 +10294,7 @@ func TestAconfigFilesJavaDeps(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } java_library { @@ -10279,6 +10306,7 @@ func TestAconfigFilesJavaDeps(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } aconfig_declarations { @@ -10365,6 +10393,7 @@ func TestAconfigFilesJavaAndCcDeps(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } cc_library { @@ -10691,6 +10720,7 @@ func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } java_library { @@ -10702,6 +10732,7 @@ func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } aconfig_declarations { @@ -10776,6 +10807,7 @@ func TestAconfigFilesRemoveDuplicates(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } java_library { @@ -10787,6 +10819,7 @@ func TestAconfigFilesRemoveDuplicates(t *testing.T) { apex_available: [ "myapex", ], + compile_dex: true, } aconfig_declarations { @@ -11469,6 +11502,7 @@ func TestApexMinSdkVersionOverride(t *testing.T) { apex_available: ["com.android.apex30"], min_sdk_version: "30", sdk_version: "current", + compile_dex: true, } override_apex { @@ -11760,6 +11794,7 @@ func TestSdkLibraryTransitiveClassLoaderContext(t *testing.T) { "com.android.foo30", ], sdk_version: "core_current", + compile_dex: true, } java_library { diff --git a/apex/container_test.go b/apex/container_test.go index d1dfb9cab..395793f61 100644 --- a/apex/container_test.go +++ b/apex/container_test.go @@ -15,10 +15,11 @@ package apex import ( - "android/soong/android" - "android/soong/java" "fmt" "testing" + + "android/soong/android" + "android/soong/java" ) var checkContainerMatch = func(t *testing.T, name string, container string, expected bool, actual bool) { @@ -329,6 +330,7 @@ func TestUpdatableAndNonUpdatableApexesIdenticalMinSdkVersion(t *testing.T) { ], min_sdk_version: "30", sdk_version: "current", + compile_dex: true, } `) diff --git a/apex/prebuilt.go b/apex/prebuilt.go index acf3b91fe..2bef0cccf 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -306,10 +306,6 @@ func (p *prebuiltCommon) DepIsInSameApex(ctx android.BaseModuleContext, dep andr // extra copying of files. Contrast that with source apex modules that has to build each variant // from source. func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { - - // Collect direct dependencies into contents. - contents := make(map[string]android.ApexMembership) - // Collect the list of dependencies. var dependencies []android.ApexModule mctx.WalkDeps(func(child, parent android.Module) bool { @@ -347,21 +343,13 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { // behavior whether there is a corresponding source module present or not. depName = android.RemoveOptionalPrebuiltPrefix(depName) - // Remember if this module was added as a direct dependency. - direct := parent == mctx.Module() - contents[depName] = contents[depName].Add(direct) - // Add the module to the list of dependencies that need to have an APEX variant. dependencies = append(dependencies, child.(android.ApexModule)) return true }) - // Create contents for the prebuilt_apex and store it away for later use. - apexContents := android.NewApexContents(contents) - android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{ - Contents: apexContents, - }) + android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{}) // Create an ApexInfo for the prebuilt_apex. apexVariationName := p.ApexVariationName() @@ -369,7 +357,6 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { ApexVariationName: apexVariationName, InApexVariants: []string{apexVariationName}, InApexModules: []string{p.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix. - ApexContents: []*android.ApexContents{apexContents}, ForPrebuiltApex: true, } diff --git a/bpf/libbpf/libbpf_prog.go b/bpf/libbpf/libbpf_prog.go index 0ca7af1f7..18e03a5e7 100644 --- a/bpf/libbpf/libbpf_prog.go +++ b/bpf/libbpf/libbpf_prog.go @@ -205,7 +205,7 @@ func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext) if strings.ContainsRune(src.Base(), '_') { ctx.ModuleErrorf("invalid character '_' in source name") } - obj := android.ObjPathWithExt(ctx, "unstripped", src, "o") + obj := android.ObjPathWithExt(ctx, "unstripped", src, "bpf") ctx.Build(pctx, android.BuildParams{ Rule: libbpfProgCcRule, @@ -218,7 +218,7 @@ func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext) }, }) - objStripped := android.ObjPathWithExt(ctx, "", src, "o") + objStripped := android.ObjPathWithExt(ctx, "", src, "bpf") ctx.Build(pctx, android.BuildParams{ Rule: libbpfProgStripRule, Input: obj, @@ -230,7 +230,7 @@ func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext) libbpf.objs = append(libbpf.objs, objStripped.WithoutRel()) } - installDir := android.PathForModuleInstall(ctx, "etc", "bpf/libbpf") + installDir := android.PathForModuleInstall(ctx, "etc", "bpf") if len(libbpf.properties.Relative_install_path) > 0 { installDir = installDir.Join(ctx, libbpf.properties.Relative_install_path) } @@ -251,7 +251,7 @@ func (libbpf *libbpfProg) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w) var localModulePath string - localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf/libbpf" + localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf" if len(libbpf.properties.Relative_install_path) > 0 { localModulePath += "/" + libbpf.properties.Relative_install_path } diff --git a/bpf/libbpf/libbpf_prog_test.go b/bpf/libbpf/libbpf_prog_test.go index 7f3653df9..2b3b37841 100644 --- a/bpf/libbpf/libbpf_prog_test.go +++ b/bpf/libbpf/libbpf_prog_test.go @@ -41,7 +41,7 @@ var prepareForLibbpfProgTest = android.GroupFixturePreparers( func TestLibbpfProgDataDependency(t *testing.T) { bp := ` libbpf_prog { - name: "bpf.o", + name: "bpf.bpf", srcs: ["bpf.c"], } @@ -49,7 +49,7 @@ func TestLibbpfProgDataDependency(t *testing.T) { name: "vts_test_binary_bpf_module", compile_multilib: "first", srcs: ["BpfTest.cpp"], - data: [":bpf.o"], + data: [":bpf.bpf"], gtest: false, } ` @@ -60,7 +60,7 @@ func TestLibbpfProgDataDependency(t *testing.T) { func TestLibbpfProgSourceName(t *testing.T) { bp := ` libbpf_prog { - name: "bpf_invalid_name.o", + name: "bpf_invalid_name.bpf", srcs: ["bpf_invalid_name.c"], } ` diff --git a/cc/binary.go b/cc/binary.go index 2ac9a45bc..4b77bea64 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -505,7 +505,7 @@ func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) { // The original path becomes a symlink to the corresponding file in the // runtime APEX. translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled - if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !ctx.Host() && ctx.directlyInAnyApex() && + if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !ctx.Host() && !ctx.isSdkVariant() && !translatedArch && ctx.apexVariationName() == "" && !ctx.inRamdisk() && !ctx.inRecovery() && !ctx.inVendorRamdisk() { @@ -548,7 +548,6 @@ type ModuleContextIntf interface { apexSdkVersion() android.ApiLevel bootstrap() bool nativeCoverage() bool - directlyInAnyApex() bool isPreventInstall() bool isCfiAssemblySupportEnabled() bool getSharedFlags() *SharedFlags @@ -1692,10 +1691,6 @@ func (ctx *moduleContextImpl) nativeCoverage() bool { return ctx.mod.nativeCoverage() } -func (ctx *moduleContextImpl) directlyInAnyApex() bool { - return ctx.mod.DirectlyInAnyApex() -} - func (ctx *moduleContextImpl) isPreventInstall() bool { return ctx.mod.Properties.PreventInstall } diff --git a/cc/library.go b/cc/library.go index 8aa2add81..ea8794644 100644 --- a/cc/library.go +++ b/cc/library.go @@ -662,7 +662,7 @@ func (library *libraryDecorator) compileModuleLibApiStubs(ctx ModuleContext, fla // However, having this distinction helps guard accidental // promotion or demotion of API and also helps the API review process b/191371676 var flag string - if ctx.Module().(android.ApexModule).NotInPlatform() { + if ctx.notInPlatform() { flag = "--apex" } else { flag = "--systemapi" @@ -746,6 +746,7 @@ type versionedInterface interface { hasLLNDKStubs() bool hasLLNDKHeaders() bool hasVendorPublicLibrary() bool + isLLNDKMovedToApex() bool } var _ libraryInterface = (*libraryDecorator)(nil) @@ -1760,21 +1761,17 @@ func (library *libraryDecorator) installSymlinkToRuntimeApex(ctx ModuleContext, func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { if library.shared() { - if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() { + translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled + if library.hasStubsVariants() && !ctx.Host() && !ctx.isSdkVariant() && + InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() && + !translatedArch && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() { // Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory. // The original path becomes a symlink to the corresponding file in the // runtime APEX. - translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled - if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() && - !translatedArch && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() { - if ctx.Device() { - library.installSymlinkToRuntimeApex(ctx, file) - } - library.baseInstaller.subDir = "bootstrap" + if ctx.Device() { + library.installSymlinkToRuntimeApex(ctx, file) } - } else if ctx.directlyInAnyApex() && ctx.IsLlndk() && !isBionic(ctx.baseModuleName()) { - // Skip installing LLNDK (non-bionic) libraries moved to APEX. - ctx.Module().HideFromMake() + library.baseInstaller.subDir = "bootstrap" } library.baseInstaller.install(ctx, file) @@ -1858,6 +1855,11 @@ func (library *libraryDecorator) hasLLNDKHeaders() bool { return Bool(library.Properties.Llndk.Llndk_headers) } +// isLLNDKMovedToApex returns true if this cc_library module sets the llndk.moved_to_apex property. +func (library *libraryDecorator) isLLNDKMovedToApex() bool { + return Bool(library.Properties.Llndk.Moved_to_apex) +} + // hasVendorPublicLibrary returns true if this cc_library module has a variant that will build // vendor public library stubs. func (library *libraryDecorator) hasVendorPublicLibrary() bool { diff --git a/cc/llndk_library.go b/cc/llndk_library.go index c7950f9ff..162dd5429 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -57,17 +57,18 @@ type llndkLibraryProperties struct { // if true, make this module available to provide headers to other modules that set // llndk.symbol_file. Llndk_headers *bool + + // moved_to_apex marks this module has having been distributed through an apex module. + Moved_to_apex *bool } func makeLlndkVars(ctx android.MakeVarsContext) { - // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if - // they been moved to an apex. + // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to generate the linker config. movedToApexLlndkLibraries := make(map[string]bool) ctx.VisitAllModules(func(module android.Module) { if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() { - // Skip bionic libs, they are handled in different manner - name := library.implementationModuleName(module.(*Module).BaseModuleName()) - if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) { + if library.isLLNDKMovedToApex() { + name := library.implementationModuleName(module.(*Module).BaseModuleName()) movedToApexLlndkLibraries[name] = true } } diff --git a/cc/sanitize.go b/cc/sanitize.go index f0d734376..d8d8c7aef 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -1504,9 +1504,6 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { if Bool(sanProps.Memtag_globals) { sanitizers = append(sanitizers, "memtag-globals") - // TODO(mitchp): For now, enable memtag-heap with memtag-globals because the linker - // isn't new enough (https://reviews.llvm.org/differential/changeset/?ref=4243566). - sanitizers = append(sanitizers, "memtag-heap") } if Bool(sanProps.Fuzzer) { 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 f0242b724..2b8c39527 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 @@ -18,7 +18,7 @@ import ( "errors" "fmt" "io/fs" - "path/filepath" + "regexp" "slices" fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto_internal" @@ -73,15 +73,16 @@ func CreateState(inputs []string, inspect_contents bool, fsys StatReadFileFS) (* return ret, nil } +// We ignore any suffix digit caused by sharding. +var InspectExtsZipRegexp = regexp.MustCompile("\\.(jar|apex|apk)[0-9]*$") + // Inspect the file and extract the state of the elements in the archive. // If this is not an archive of some sort, nil is returned. func InspectFileContents(name string) ([]*fid_proto.PartialCompileInput, error) { - switch filepath.Ext(name) { - case ".jar", ".apex", ".apk": + if InspectExtsZipRegexp.Match([]byte(name)) { return inspectZipFileContents(name) - default: - return nil, nil } + return nil, nil } func inspectZipFileContents(name string) ([]*fid_proto.PartialCompileInput, error) { diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go b/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go index e69424c54..c168d5a6b 100644 --- a/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go +++ b/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go @@ -259,3 +259,25 @@ func TestCompareInternalState(t *testing.T) { } } } + +func TestCompareInspectExtsZipRegexp(t *testing.T) { + testCases := []struct { + Name string + Expected bool + }{ + {Name: ".jar", Expected: true}, + {Name: ".jar5", Expected: true}, + {Name: ".apex", Expected: true}, + {Name: ".apex9", Expected: true}, + {Name: ".apexx", Expected: false}, + {Name: ".apk", Expected: true}, + {Name: ".apk3", Expected: true}, + {Name: ".go", Expected: false}, + } + for _, tc := range testCases { + actual := InspectExtsZipRegexp.Match([]byte(tc.Name)) + if tc.Expected != actual { + t.Errorf("%s: expected %v, actual %v", tc.Name, tc.Expected, actual) + } + } +} diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go index c9bd61788..90409b318 100644 --- a/filesystem/bootimg.go +++ b/filesystem/bootimg.go @@ -26,19 +26,21 @@ import ( ) func init() { - android.RegisterModuleType("bootimg", bootimgFactory) + android.RegisterModuleType("bootimg", BootimgFactory) } type bootimg struct { android.ModuleBase - properties bootimgProperties + properties BootimgProperties output android.Path installDir android.InstallPath + + bootImageType bootImageType } -type bootimgProperties struct { +type BootimgProperties struct { // Set the name of the output. Defaults to <module_name>.img. Stem *string @@ -56,9 +58,13 @@ type bootimgProperties struct { // https://source.android.com/devices/bootloader/boot-image-header Header_version *string - // Determines if this image is for the vendor_boot partition. Default is false. Refer to - // https://source.android.com/devices/bootloader/partitions/vendor-boot-partitions - Vendor_boot *bool + // Determines the specific type of boot image this module is building. Can be boot, + // vendor_boot or init_boot. Defaults to boot. + // Refer to https://source.android.com/devices/bootloader/partitions/vendor-boot-partitions + // for vendor_boot. + // Refer to https://source.android.com/docs/core/architecture/partitions/generic-boot for + // init_boot. + Boot_image_type *string // Optional kernel commandline arguments Cmdline []string `android:"arch_variant"` @@ -67,6 +73,10 @@ type bootimgProperties struct { // and `header_version` is greater than or equal to 4. Bootconfig *string `android:"arch_variant,path"` + // The size of the partition on the device. It will be a build error if this built partition + // image exceeds this size. + Partition_size *int64 + // When set to true, sign the image with avbtool. Default is false. Use_avb *bool @@ -79,10 +89,62 @@ type bootimgProperties struct { // Hash and signing algorithm for avbtool. Default is SHA256_RSA4096. Avb_algorithm *string + + // The security patch passed to as the com.android.build.<type>.security_patch avb property. + // Replacement for the make variables BOOT_SECURITY_PATCH / INIT_BOOT_SECURITY_PATCH. + Security_patch *string +} + +type bootImageType int + +const ( + unsupported bootImageType = iota + boot + vendorBoot + initBoot +) + +func toBootImageType(ctx android.ModuleContext, bootImageType string) bootImageType { + switch bootImageType { + case "boot": + return boot + case "vendor_boot": + return vendorBoot + case "init_boot": + return initBoot + default: + ctx.ModuleErrorf("Unknown boot_image_type %s. Must be one of \"boot\", \"vendor_boot\", or \"init_boot\"", bootImageType) + } + return unsupported +} + +func (b bootImageType) String() string { + switch b { + case boot: + return "boot" + case vendorBoot: + return "vendor_boot" + case initBoot: + return "init_boot" + default: + panic("unknown boot image type") + } +} + +func (b bootImageType) isBoot() bool { + return b == boot +} + +func (b bootImageType) isVendorBoot() bool { + return b == vendorBoot +} + +func (b bootImageType) isInitBoot() bool { + return b == initBoot } // bootimg is the image for the boot partition. It consists of header, kernel, ramdisk, and dtb. -func bootimgFactory() android.Module { +func BootimgFactory() android.Module { module := &bootimg{} module.AddProperties(&module.properties) android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) @@ -112,12 +174,40 @@ func (b *bootimg) partitionName() string { } func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { - vendor := proptools.Bool(b.properties.Vendor_boot) - unsignedOutput := b.buildBootImage(ctx, vendor) + b.bootImageType = toBootImageType(ctx, proptools.StringDefault(b.properties.Boot_image_type, "boot")) + if b.bootImageType == unsupported { + return + } + + kernelProp := proptools.String(b.properties.Kernel_prebuilt) + if b.bootImageType.isVendorBoot() && kernelProp != "" { + ctx.PropertyErrorf("kernel_prebuilt", "vendor_boot partition can't have kernel") + return + } + if b.bootImageType.isBoot() && kernelProp == "" { + ctx.PropertyErrorf("kernel_prebuilt", "boot partition must have kernel") + return + } + var kernel android.Path + if kernelProp != "" { + kernel = android.PathForModuleSrc(ctx, kernelProp) + } + + unsignedOutput := b.buildBootImage(ctx, kernel) output := unsignedOutput if proptools.Bool(b.properties.Use_avb) { - output = b.signImage(ctx, unsignedOutput) + // This bootimg module supports 2 modes of avb signing, it picks between them based on + // if the private key is specified or not. If there is a key, it does a signing process + // similar to how the regular partitions (system, product, vendor, etc) are signed. + // If the key is not provided, it will just add an avb footer to the image. The avb + // footer only signing is how the make-built init_boot, boot, and vendor_boot images are + // built. + if proptools.String(b.properties.Avb_private_key) != "" { + output = b.signImage(ctx, unsignedOutput) + } else { + output = b.addAvbFooter(ctx, unsignedOutput, kernel) + } } b.installDir = android.PathForModuleInstall(ctx, "etc") @@ -127,23 +217,20 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) { b.output = output } -func (b *bootimg) buildBootImage(ctx android.ModuleContext, vendor bool) android.Path { +func (b *bootimg) buildBootImage(ctx android.ModuleContext, kernel android.Path) android.Path { output := android.PathForModuleOut(ctx, "unsigned", b.installFileName()) builder := android.NewRuleBuilder(pctx, ctx) cmd := builder.Command().BuiltTool("mkbootimg") - kernel := proptools.String(b.properties.Kernel_prebuilt) - if vendor && kernel != "" { - ctx.PropertyErrorf("kernel_prebuilt", "vendor_boot partition can't have kernel") - return output - } - if !vendor && kernel == "" { - ctx.PropertyErrorf("kernel_prebuilt", "boot partition must have kernel") - return output + if kernel != nil { + cmd.FlagWithInput("--kernel ", kernel) } - if kernel != "" { - cmd.FlagWithInput("--kernel ", android.PathForModuleSrc(ctx, kernel)) + + // These arguments are passed for boot.img and init_boot.img generation + if b.bootImageType.isBoot() || b.bootImageType.isInitBoot() { + cmd.FlagWithArg("--os_version ", ctx.Config().PlatformVersionLastStable()) + cmd.FlagWithArg("--os_patch_level ", ctx.Config().PlatformSecurityPatch()) } dtbName := proptools.String(b.properties.Dtb_prebuilt) @@ -155,7 +242,7 @@ func (b *bootimg) buildBootImage(ctx android.ModuleContext, vendor bool) android cmdline := strings.Join(b.properties.Cmdline, " ") if cmdline != "" { flag := "--cmdline " - if vendor { + if b.bootImageType.isVendorBoot() { flag = "--vendor_cmdline " } cmd.FlagWithArg(flag, proptools.ShellEscapeIncludingSpaces(cmdline)) @@ -182,7 +269,7 @@ func (b *bootimg) buildBootImage(ctx android.ModuleContext, vendor bool) android ramdisk := ctx.GetDirectDepWithTag(ramdiskName, bootimgRamdiskDep) if filesystem, ok := ramdisk.(*filesystem); ok { flag := "--ramdisk " - if vendor { + if b.bootImageType.isVendorBoot() { flag = "--vendor_ramdisk " } cmd.FlagWithInput(flag, filesystem.OutputPath()) @@ -194,7 +281,7 @@ func (b *bootimg) buildBootImage(ctx android.ModuleContext, vendor bool) android bootconfig := proptools.String(b.properties.Bootconfig) if bootconfig != "" { - if !vendor { + if !b.bootImageType.isVendorBoot() { ctx.PropertyErrorf("bootconfig", "requires vendor_boot: true") return output } @@ -205,16 +292,60 @@ func (b *bootimg) buildBootImage(ctx android.ModuleContext, vendor bool) android cmd.FlagWithInput("--vendor_bootconfig ", android.PathForModuleSrc(ctx, bootconfig)) } + // Output flag for boot.img and init_boot.img flag := "--output " - if vendor { + if b.bootImageType.isVendorBoot() { flag = "--vendor_boot " } cmd.FlagWithOutput(flag, output) + if b.properties.Partition_size != nil { + assertMaxImageSize(builder, output, *b.properties.Partition_size, proptools.Bool(b.properties.Use_avb)) + } + builder.Build("build_bootimg", fmt.Sprintf("Creating %s", b.BaseModuleName())) return output } +func (b *bootimg) addAvbFooter(ctx android.ModuleContext, unsignedImage android.Path, kernel android.Path) android.Path { + output := android.PathForModuleOut(ctx, b.installFileName()) + builder := android.NewRuleBuilder(pctx, ctx) + builder.Command().Text("cp").Input(unsignedImage).Output(output) + cmd := builder.Command().BuiltTool("avbtool"). + Text("add_hash_footer"). + FlagWithInput("--image ", output) + + if b.properties.Partition_size != nil { + cmd.FlagWithArg("--partition_size ", strconv.FormatInt(*b.properties.Partition_size, 10)) + } else { + cmd.Flag("--dynamic_partition_size") + } + + if kernel != nil { + cmd.Textf(`--salt $(sha256sum "%s" | cut -d " " -f 1)`, kernel.String()) + cmd.Implicit(kernel) + } + + cmd.FlagWithArg("--partition_name ", b.bootImageType.String()) + + if !b.bootImageType.isVendorBoot() { + cmd.FlagWithArg("--prop ", proptools.NinjaAndShellEscape(fmt.Sprintf( + "com.android.build.%s.os_version:%s", b.bootImageType.String(), ctx.Config().PlatformVersionLastStable()))) + } + + fingerprintFile := ctx.Config().BuildFingerprintFile(ctx) + cmd.FlagWithArg("--prop ", fmt.Sprintf("com.android.build.%s.fingerprint:%s", b.bootImageType.String(), fingerprintFile.String())) + cmd.OrderOnly(fingerprintFile) + + if b.properties.Security_patch != nil { + cmd.FlagWithArg("--prop ", proptools.NinjaAndShellEscape(fmt.Sprintf( + "com.android.build.%s.security_patch:%s", b.bootImageType.String(), *b.properties.Security_patch))) + } + + builder.Build("add_avb_footer", fmt.Sprintf("Adding avb footer to %s", b.BaseModuleName())) + return output +} + func (b *bootimg) signImage(ctx android.ModuleContext, unsignedImage android.Path) android.Path { propFile, toolDeps := b.buildPropFile(ctx) diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index c34677060..dadacae3d 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -162,6 +162,10 @@ type FilesystemProperties struct { // Determines if the module is auto-generated from Soong or not. If the module is // auto-generated, its deps are exempted from visibility enforcement. Is_auto_generated *bool + + // Path to the dev nodes description file. This is only needed for building the ramdisk + // partition and should not be explicitly specified. + Dev_nodes_description_file *string `android:"path" blueprint:"mutated"` } // Additional properties required to generate erofs FS partitions. @@ -210,6 +214,10 @@ func initFilesystemModule(module android.DefaultableModule, filesystemModule *fi filesystemModule.PackagingBase.AllowHighPriorityDeps = true android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitDefaultableModule(module) + + android.AddLoadHook(module, func(ctx android.LoadHookContext) { + filesystemModule.setDevNodesDescriptionProp() + }) } type depTag struct { @@ -229,6 +237,16 @@ func (t depTagWithVisibilityEnforcementBypass) ExcludeFromVisibilityEnforcement( var dependencyTagWithVisibilityEnforcementBypass = depTagWithVisibilityEnforcementBypass{} +// ramdiskDevNodesDescription is the name of the filegroup module that provides the file that +// contains the description of dev nodes added to the CPIO archive for the ramdisk partition. +const ramdiskDevNodesDescription = "ramdisk_node_list" + +func (f *filesystem) setDevNodesDescriptionProp() { + if proptools.String(f.properties.Partition_name) == "ramdisk" { + f.properties.Dev_nodes_description_file = proptools.StringPtr(":" + ramdiskDevNodesDescription) + } +} + func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) { if proptools.Bool(f.properties.Is_auto_generated) { f.AddDeps(ctx, dependencyTagWithVisibilityEnforcementBypass) @@ -659,6 +677,9 @@ func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) cmd := builder.Command(). BuiltTool("mkbootfs"). Text(rootDir.String()) // input directory + if nodeList := f.properties.Dev_nodes_description_file; nodeList != nil { + cmd.FlagWithInput("-n ", android.PathForModuleSrc(ctx, proptools.String(nodeList))) + } if compressed { cmd.Text("|"). BuiltTool("lz4"). @@ -689,6 +710,7 @@ var validPartitions = []string{ "odm_dlkm", "system_dlkm", "ramdisk", + "vendor_ramdisk", } func (f *filesystem) addMakeBuiltFiles(ctx android.ModuleContext, builder *android.RuleBuilder, rootDir android.Path) { @@ -904,3 +926,26 @@ func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]androi return provideModules, requireModules } + +// Checks that the given file doesn't exceed the given size, and will also print a warning +// if it's nearing the maximum size. Equivalent to assert-max-image-size in make: +// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/definitions.mk;l=3455;drc=993c4de29a02a6accd60ceaaee153307e1a18d10 +func assertMaxImageSize(builder *android.RuleBuilder, image android.Path, maxSize int64, addAvbLater bool) { + if addAvbLater { + // The value 69632 is derived from MAX_VBMETA_SIZE + MAX_FOOTER_SIZE in avbtool. + // Logic copied from make: + // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=228;drc=a6a0007ef24e16c0b79f439beac4a118416717e6 + maxSize -= 69632 + } + cmd := builder.Command() + cmd.Textf(`file="%s"; maxsize="%d";`+ + `total=$(stat -c "%%s" "$file" | tr -d '\n');`+ + `if [ "$total" -gt "$maxsize" ]; then `+ + ` echo "error: $file too large ($total > $maxsize)";`+ + ` false;`+ + `elif [ "$total" -gt $((maxsize - 32768)) ]; then `+ + ` echo "WARNING: $file approaching size limit ($total now; limit $maxsize)";`+ + `fi`, + image, maxSize) + cmd.Implicit(image) +} diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go index f325d96ef..746e4de74 100644 --- a/filesystem/filesystem_test.go +++ b/filesystem/filesystem_test.go @@ -666,7 +666,9 @@ func TestUseSharedVariationOfNativeLib(t *testing.T) { partition := result.ModuleForTests("myfilesystem", "android_common") fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList")) - android.AssertDeepEquals(t, "cc_library listed in deps", "lib64/libc++.so\nlib64/libc.so\nlib64/libdl.so\nlib64/libfoo.so\nlib64/libm.so\n", fileList) + android.AssertDeepEquals(t, "cc_library listed in deps", + "lib64/bootstrap/libc.so\nlib64/bootstrap/libdl.so\nlib64/bootstrap/libm.so\nlib64/libc++.so\nlib64/libc.so\nlib64/libdl.so\nlib64/libfoo.so\nlib64/libm.so\n", + fileList) } // binfoo1 overrides binbar. transitive deps of binbar should not be installed. @@ -701,7 +703,9 @@ cc_library { partition := result.ModuleForTests("myfilesystem", "android_common") fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList")) - android.AssertDeepEquals(t, "Shared library dep of overridden binary should not be installed", fileList, "bin/binfoo1\nlib64/libc++.so\nlib64/libc.so\nlib64/libdl.so\nlib64/libfoo2.so\nlib64/libm.so\n") + android.AssertDeepEquals(t, "Shared library dep of overridden binary should not be installed", + "bin/binfoo1\nlib64/bootstrap/libc.so\nlib64/bootstrap/libdl.so\nlib64/bootstrap/libm.so\nlib64/libc++.so\nlib64/libc.so\nlib64/libdl.so\nlib64/libfoo2.so\nlib64/libm.so\n", + fileList) } func TestInstallLinkerConfigFile(t *testing.T) { @@ -754,3 +758,28 @@ func TestOverrideModulesInDeps(t *testing.T) { fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList")) android.AssertStringEquals(t, "filesystem with override app", "app/myoverrideapp/myoverrideapp.apk\n", fileList) } + +func TestRamdiskPartitionSetsDevNodes(t *testing.T) { + result := android.GroupFixturePreparers( + fixture, + android.FixtureMergeMockFs(android.MockFS{ + "ramdisk_node_list": nil, + }), + ).RunTestWithBp(t, ` + android_filesystem { + name: "ramdisk_filesystem", + partition_name: "ramdisk", + } + filegroup { + name: "ramdisk_node_list", + srcs: ["ramdisk_node_list"], + } + `) + + android.AssertBoolEquals( + t, + "Generated ramdisk image expected to depend on \"ramdisk_node_list\" module", + true, + java.CheckModuleHasDependency(t, result.TestContext, "ramdisk_filesystem", "android_common", "ramdisk_node_list"), + ) +} diff --git a/fsgen/Android.bp b/fsgen/Android.bp index 8cd7518cb..a0225811e 100644 --- a/fsgen/Android.bp +++ b/fsgen/Android.bp @@ -13,6 +13,7 @@ bootstrap_go_package { "soong-kernel", ], srcs: [ + "boot_imgs.go", "filesystem_creator.go", "fsgen_mutators.go", "prebuilt_etc_modules_gen.go", diff --git a/fsgen/boot_imgs.go b/fsgen/boot_imgs.go new file mode 100644 index 000000000..b651862e0 --- /dev/null +++ b/fsgen/boot_imgs.go @@ -0,0 +1,189 @@ +package fsgen + +import ( + "android/soong/android" + "android/soong/filesystem" + "fmt" + "path/filepath" + "strconv" + + "github.com/google/blueprint/proptools" +) + +func createBootImage(ctx android.LoadHookContext) bool { + partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse + + if partitionVariables.TargetKernelPath == "" { + // There are potentially code paths that don't set TARGET_KERNEL_PATH + return false + } + + kernelDir := filepath.Dir(partitionVariables.TargetKernelPath) + kernelBase := filepath.Base(partitionVariables.TargetKernelPath) + kernelFilegroupName := generatedModuleName(ctx.Config(), "kernel") + + ctx.CreateModuleInDirectory( + android.FileGroupFactory, + kernelDir, + &struct { + Name *string + Srcs []string + Visibility []string + }{ + Name: proptools.StringPtr(kernelFilegroupName), + Srcs: []string{kernelBase}, + Visibility: []string{"//visibility:public"}, + }, + ) + + var partitionSize *int64 + if partitionVariables.BoardBootimagePartitionSize != "" { + parsed, err := strconv.ParseInt(partitionVariables.BoardBootimagePartitionSize, 10, 64) + if err != nil { + panic(fmt.Sprintf("BOARD_BOOTIMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardBootimagePartitionSize)) + } + partitionSize = &parsed + } + + var securityPatch *string + if partitionVariables.BootSecurityPatch != "" { + securityPatch = &partitionVariables.BootSecurityPatch + } + + bootImageName := generatedModuleNameForPartition(ctx.Config(), "boot") + + ctx.CreateModule( + filesystem.BootimgFactory, + &filesystem.BootimgProperties{ + Kernel_prebuilt: proptools.StringPtr(":" + kernelFilegroupName), + Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion), + Partition_size: partitionSize, + Use_avb: &partitionVariables.BoardAvbEnable, + Security_patch: securityPatch, + }, + &struct { + Name *string + }{ + Name: proptools.StringPtr(bootImageName), + }, + ) + return true +} + +func createVendorBootImage(ctx android.LoadHookContext) bool { + partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse + + bootImageName := generatedModuleNameForPartition(ctx.Config(), "vendor_boot") + + ctx.CreateModule( + filesystem.BootimgFactory, + &filesystem.BootimgProperties{ + Boot_image_type: proptools.StringPtr("vendor_boot"), + Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_ramdisk")), + Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion), + Use_avb: &partitionVariables.BoardAvbEnable, + }, + &struct { + Name *string + }{ + Name: proptools.StringPtr(bootImageName), + }, + ) + return true +} + +func createInitBootImage(ctx android.LoadHookContext) bool { + partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse + + bootImageName := generatedModuleNameForPartition(ctx.Config(), "init_boot") + + var securityPatch *string + if partitionVariables.InitBootSecurityPatch != "" { + securityPatch = &partitionVariables.InitBootSecurityPatch + } else if partitionVariables.BootSecurityPatch != "" { + securityPatch = &partitionVariables.BootSecurityPatch + } + + ctx.CreateModule( + filesystem.BootimgFactory, + &filesystem.BootimgProperties{ + Boot_image_type: proptools.StringPtr("init_boot"), + Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "ramdisk")), + Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion), + Use_avb: &partitionVariables.BoardAvbEnable, + Security_patch: securityPatch, + }, + &struct { + Name *string + }{ + Name: proptools.StringPtr(bootImageName), + }, + ) + return true +} + +// Returns the equivalent of the BUILDING_BOOT_IMAGE variable in make. Derived from this logic: +// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=458;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0 +func buildingBootImage(partitionVars android.PartitionVariables) bool { + if partitionVars.BoardUsesRecoveryAsBoot { + return false + } + + if partitionVars.ProductBuildBootImage { + return true + } + + if len(partitionVars.BoardPrebuiltBootimage) > 0 { + return false + } + + if len(partitionVars.BoardBootimagePartitionSize) > 0 { + return true + } + + // TODO: return true if BOARD_KERNEL_BINARIES is set and has a *_BOOTIMAGE_PARTITION_SIZE + // variable. However, I don't think BOARD_KERNEL_BINARIES is ever set in practice. + + return false +} + +// Returns the equivalent of the BUILDING_VENDOR_BOOT_IMAGE variable in make. Derived from this logic: +// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=518;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0 +func buildingVendorBootImage(partitionVars android.PartitionVariables) bool { + if v, exists := boardBootHeaderVersion(partitionVars); exists && v >= 3 { + x := partitionVars.ProductBuildVendorBootImage + if x == "" || x == "true" { + return true + } + } + + return false +} + +// Derived from: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=480;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0 +func buildingInitBootImage(partitionVars android.PartitionVariables) bool { + if !partitionVars.ProductBuildInitBootImage { + if partitionVars.BoardUsesRecoveryAsBoot || len(partitionVars.BoardPrebuiltInitBootimage) > 0 { + return false + } else if len(partitionVars.BoardInitBootimagePartitionSize) > 0 { + return true + } + } else { + if partitionVars.BoardUsesRecoveryAsBoot { + panic("PRODUCT_BUILD_INIT_BOOT_IMAGE is true, but so is BOARD_USES_RECOVERY_AS_BOOT. Use only one option.") + } + return true + } + return false +} + +func boardBootHeaderVersion(partitionVars android.PartitionVariables) (int, bool) { + if len(partitionVars.BoardBootHeaderVersion) == 0 { + return 0, false + } + v, err := strconv.ParseInt(partitionVars.BoardBootHeaderVersion, 10, 32) + if err != nil { + panic(fmt.Sprintf("BOARD_BOOT_HEADER_VERSION must be an int, got: %q", partitionVars.BoardBootHeaderVersion)) + } + return int(v), true +} diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index c74579aba..6bfb097af 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -47,6 +47,10 @@ type filesystemCreatorProps struct { Vbmeta_module_names []string `blueprint:"mutated"` Vbmeta_partition_names []string `blueprint:"mutated"` + + Boot_image string `blueprint:"mutated" android:"path_device_first"` + Vendor_boot_image string `blueprint:"mutated" android:"path_device_first"` + Init_boot_image string `blueprint:"mutated" android:"path_device_first"` } type filesystemCreator struct { @@ -71,6 +75,42 @@ func filesystemCreatorFactory() android.Module { return module } +func generatedPartitions(ctx android.LoadHookContext) []string { + partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse + generatedPartitions := []string{"system"} + if ctx.DeviceConfig().SystemExtPath() == "system_ext" { + generatedPartitions = append(generatedPartitions, "system_ext") + } + if ctx.DeviceConfig().BuildingVendorImage() && ctx.DeviceConfig().VendorPath() == "vendor" { + generatedPartitions = append(generatedPartitions, "vendor") + } + if ctx.DeviceConfig().BuildingProductImage() && ctx.DeviceConfig().ProductPath() == "product" { + generatedPartitions = append(generatedPartitions, "product") + } + if ctx.DeviceConfig().BuildingOdmImage() && ctx.DeviceConfig().OdmPath() == "odm" { + generatedPartitions = append(generatedPartitions, "odm") + } + if ctx.DeviceConfig().BuildingUserdataImage() && ctx.DeviceConfig().UserdataPath() == "data" { + generatedPartitions = append(generatedPartitions, "userdata") + } + if partitionVars.BuildingSystemDlkmImage { + generatedPartitions = append(generatedPartitions, "system_dlkm") + } + if partitionVars.BuildingVendorDlkmImage { + generatedPartitions = append(generatedPartitions, "vendor_dlkm") + } + if partitionVars.BuildingOdmDlkmImage { + generatedPartitions = append(generatedPartitions, "odm_dlkm") + } + if partitionVars.BuildingRamdiskImage { + generatedPartitions = append(generatedPartitions, "ramdisk") + } + if buildingVendorBootImage(partitionVars) { + generatedPartitions = append(generatedPartitions, "vendor_ramdisk") + } + return generatedPartitions +} + func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { soongGeneratedPartitions := generatedPartitions(ctx) finalSoongGeneratedPartitions := make([]string, 0, len(soongGeneratedPartitions)) @@ -83,6 +123,29 @@ func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { } } + partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse + if buildingBootImage(partitionVars) { + if createBootImage(ctx) { + f.properties.Boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "boot") + } else { + f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "boot") + } + } + if buildingVendorBootImage(partitionVars) { + if createVendorBootImage(ctx) { + f.properties.Vendor_boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "vendor_boot") + } else { + f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "vendor_boot") + } + } + if buildingInitBootImage(partitionVars) { + if createInitBootImage(ctx) { + f.properties.Init_boot_image = ":" + generatedModuleNameForPartition(ctx.Config(), "init_boot") + } else { + f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, "init_boot") + } + } + for _, x := range createVbmetaPartitions(ctx, finalSoongGeneratedPartitions) { f.properties.Vbmeta_module_names = append(f.properties.Vbmeta_module_names, x.moduleName) f.properties.Vbmeta_partition_names = append(f.properties.Vbmeta_partition_names, x.partitionName) @@ -140,13 +203,13 @@ func (f *filesystemCreator) createDeviceModule( ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps) } -func partitionSpecificFsProps(fsProps *filesystem.FilesystemProperties, partitionType string) { +func partitionSpecificFsProps(fsProps *filesystem.FilesystemProperties, partitionVars android.PartitionVariables, partitionType string) { switch partitionType { case "system": fsProps.Build_logtags = proptools.BoolPtr(true) // https://source.corp.google.com/h/googleplex-android/platform/build//639d79f5012a6542ab1f733b0697db45761ab0f3:core/packaging/flags.mk;l=21;drc=5ba8a8b77507f93aa48cc61c5ba3f31a4d0cbf37;bpv=1;bpt=0 fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) - // Identical to that of the generic_system_image + // Identical to that of the aosp_shared_system_image fsProps.Fsverity.Inputs = []string{ "etc/boot-image.prof", "etc/dirty-image-objects", @@ -176,7 +239,6 @@ func partitionSpecificFsProps(fsProps *filesystem.FilesystemProperties, partitio Name: proptools.StringPtr("system/lib/modules"), }, } - fsProps.Base_dir = proptools.StringPtr("system") case "system_ext": fsProps.Fsverity.Inputs = []string{ "framework/*", @@ -198,7 +260,6 @@ func partitionSpecificFsProps(fsProps *filesystem.FilesystemProperties, partitio Name: proptools.StringPtr("vendor/lib/modules"), }, } - fsProps.Base_dir = proptools.StringPtr("vendor") case "odm": fsProps.Symlinks = []filesystem.SymlinkDefinition{ filesystem.SymlinkDefinition{ @@ -206,10 +267,30 @@ func partitionSpecificFsProps(fsProps *filesystem.FilesystemProperties, partitio Name: proptools.StringPtr("odm/lib/modules"), }, } - fsProps.Base_dir = proptools.StringPtr("odm") case "userdata": fsProps.Base_dir = proptools.StringPtr("data") - + case "ramdisk": + // Following the logic in https://cs.android.com/android/platform/superproject/main/+/c3c5063df32748a8806ce5da5dd0db158eab9ad9:build/make/core/Makefile;l=1307 + fsProps.Dirs = android.NewSimpleConfigurable([]string{ + "debug_ramdisk", + "dev", + "metadata", + "mnt", + "proc", + "second_stage_resources", + "sys", + }) + if partitionVars.BoardUsesGenericKernelImage { + fsProps.Dirs.AppendSimpleValue([]string{ + "first_stage_ramdisk/debug_ramdisk", + "first_stage_ramdisk/dev", + "first_stage_ramdisk/metadata", + "first_stage_ramdisk/mnt", + "first_stage_ramdisk/proc", + "first_stage_ramdisk/second_stage_resources", + "first_stage_ramdisk/sys", + }) + } } } @@ -320,7 +401,7 @@ func (f *filesystemCreator) createPrebuiltKernelModules(ctx android.LoadHookCont } switch partitionType { case "system_dlkm": - props.Srcs = ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules + props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules).Strings() props.System_dlkm_specific = proptools.BoolPtr(true) if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelLoadModules) == 0 { // Create empty modules.load file for system @@ -331,7 +412,7 @@ func (f *filesystemCreator) createPrebuiltKernelModules(ctx android.LoadHookCont props.Blocklist_file = proptools.StringPtr(blocklistFile) } case "vendor_dlkm": - props.Srcs = ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelModules + props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelModules).Strings() if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules) > 0 { props.System_deps = []string{":" + generatedModuleName(ctx.Config(), "system_dlkm-kernel-modules") + "{.modules}"} } @@ -340,7 +421,7 @@ func (f *filesystemCreator) createPrebuiltKernelModules(ctx android.LoadHookCont props.Blocklist_file = proptools.StringPtr(blocklistFile) } case "odm_dlkm": - props.Srcs = ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelModules + props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelModules).Strings() props.Odm_dlkm_specific = proptools.BoolPtr(true) if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelBlocklistFile; blocklistFile != "" { props.Blocklist_file = proptools.StringPtr(blocklistFile) @@ -525,11 +606,13 @@ func generateFsProps(ctx android.EarlyModuleContext, partitionType string) (*fil fsProps.Partition_name = proptools.StringPtr(partitionType) - fsProps.Base_dir = proptools.StringPtr(partitionType) + if !strings.Contains(partitionType, "ramdisk") { + fsProps.Base_dir = proptools.StringPtr(partitionType) + } fsProps.Is_auto_generated = proptools.BoolPtr(true) - partitionSpecificFsProps(fsProps, partitionType) + partitionSpecificFsProps(fsProps, partitionVars, partitionType) // system_image properties that are not set: // - filesystemProperties.Avb_hash_algorithm @@ -546,7 +629,7 @@ func generateFsProps(ctx android.EarlyModuleContext, partitionType string) (*fil return fsProps, true } -func (f *filesystemCreator) createDiffTest(ctx android.ModuleContext, partitionType string) android.Path { +func (f *filesystemCreator) createFileListDiffTest(ctx android.ModuleContext, partitionType string) android.Path { partitionModuleName := generatedModuleNameForPartition(ctx.Config(), partitionType) systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag) filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider) @@ -591,13 +674,17 @@ func createVbmetaDiff(ctx android.ModuleContext, vbmetaModuleName string, vbmeta makeVbmetaFile := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/%s.img", ctx.Config().DeviceName(), vbmetaPartitionName)) diffTestResultFile := android.PathForModuleOut(ctx, fmt.Sprintf("diff_test_%s.txt", vbmetaModuleName)) + createDiffTest(ctx, diffTestResultFile, soongVbMetaFile, makeVbmetaFile) + return diffTestResultFile +} + +func createDiffTest(ctx android.ModuleContext, diffTestResultFile android.WritablePath, file1 android.Path, file2 android.Path) { builder := android.NewRuleBuilder(pctx, ctx) builder.Command().Text("diff"). - Input(soongVbMetaFile). - Input(makeVbmetaFile) + Input(file1). + Input(file2) builder.Command().Text("touch").Output(diffTestResultFile) - builder.Build(vbmetaModuleName+" diff test", vbmetaModuleName+" diff test") - return diffTestResultFile + builder.Build("diff test "+diffTestResultFile.String(), "diff test") } type systemImageDepTagType struct { @@ -634,7 +721,7 @@ func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContex var diffTestFiles []android.Path for _, partitionType := range f.properties.Generated_partition_types { - diffTestFile := f.createDiffTest(ctx, partitionType) + diffTestFile := f.createFileListDiffTest(ctx, partitionType) diffTestFiles = append(diffTestFiles, diffTestFile) ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile) } @@ -648,6 +735,30 @@ func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContex diffTestFiles = append(diffTestFiles, diffTestFile) ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", f.properties.Vbmeta_partition_names[i]), diffTestFile) } + if f.properties.Boot_image != "" { + diffTestFile := android.PathForModuleOut(ctx, "boot_diff_test.txt") + soongBootImg := android.PathForModuleSrc(ctx, f.properties.Boot_image) + makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/boot.img", ctx.Config().DeviceName())) + createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage) + diffTestFiles = append(diffTestFiles, diffTestFile) + ctx.Phony("soong_generated_boot_filesystem_test", diffTestFile) + } + if f.properties.Vendor_boot_image != "" { + diffTestFile := android.PathForModuleOut(ctx, "vendor_boot_diff_test.txt") + soongBootImg := android.PathForModuleSrc(ctx, f.properties.Vendor_boot_image) + makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/vendor_boot.img", ctx.Config().DeviceName())) + createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage) + diffTestFiles = append(diffTestFiles, diffTestFile) + ctx.Phony("soong_generated_vendor_boot_filesystem_test", diffTestFile) + } + if f.properties.Init_boot_image != "" { + diffTestFile := android.PathForModuleOut(ctx, "init_boot_diff_test.txt") + soongBootImg := android.PathForModuleSrc(ctx, f.properties.Init_boot_image) + makeBootImage := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/init_boot.img", ctx.Config().DeviceName())) + createDiffTest(ctx, diffTestFile, soongBootImg, makeBootImage) + diffTestFiles = append(diffTestFiles, diffTestFile) + ctx.Phony("soong_generated_init_boot_filesystem_test", diffTestFile) + } ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...) } diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go index 7b3026404..12f99566e 100644 --- a/fsgen/fsgen_mutators.go +++ b/fsgen/fsgen_mutators.go @@ -84,36 +84,6 @@ func defaultDepCandidateProps(config android.Config) *depCandidateProps { } } -func generatedPartitions(ctx android.LoadHookContext) []string { - generatedPartitions := []string{"system", "ramdisk"} - if ctx.DeviceConfig().SystemExtPath() == "system_ext" { - generatedPartitions = append(generatedPartitions, "system_ext") - } - if ctx.DeviceConfig().BuildingVendorImage() && ctx.DeviceConfig().VendorPath() == "vendor" { - generatedPartitions = append(generatedPartitions, "vendor") - } - if ctx.DeviceConfig().BuildingProductImage() && ctx.DeviceConfig().ProductPath() == "product" { - generatedPartitions = append(generatedPartitions, "product") - } - if ctx.DeviceConfig().BuildingOdmImage() && ctx.DeviceConfig().OdmPath() == "odm" { - generatedPartitions = append(generatedPartitions, "odm") - } - if ctx.DeviceConfig().BuildingUserdataImage() && ctx.DeviceConfig().UserdataPath() == "data" { - generatedPartitions = append(generatedPartitions, "userdata") - } - if ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BuildingSystemDlkmImage { - generatedPartitions = append(generatedPartitions, "system_dlkm") - } - if ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BuildingVendorDlkmImage { - generatedPartitions = append(generatedPartitions, "vendor_dlkm") - } - if ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BuildingOdmDlkmImage { - generatedPartitions = append(generatedPartitions, "odm_dlkm") - } - - return generatedPartitions -} - func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNames []string, avbpubkeyGenerated bool) *FsGenState { return ctx.Config().Once(fsGenStateOnceKey, func() interface{} { partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse @@ -176,7 +146,8 @@ func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNam "fs_config_files_odm_dlkm": defaultDepCandidateProps(ctx.Config()), "odm_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()), }, - "ramdisk": {}, + "ramdisk": {}, + "vendor_ramdisk": {}, }, fsDepsMutex: sync.Mutex{}, moduleToInstallationProps: map[string]installationProperties{}, diff --git a/fsgen/vbmeta_partitions.go b/fsgen/vbmeta_partitions.go index b7fff687d..11c57590c 100644 --- a/fsgen/vbmeta_partitions.go +++ b/fsgen/vbmeta_partitions.go @@ -19,6 +19,7 @@ import ( "android/soong/filesystem" "slices" "strconv" + "strings" "github.com/google/blueprint/proptools" ) @@ -153,8 +154,10 @@ func createVbmetaPartitions(ctx android.LoadHookContext, generatedPartitionTypes // Already handled by a chained vbmeta partition continue } - if partitionType == "ramdisk" { + if strings.Contains(partitionType, "ramdisk") || strings.Contains(partitionType, "boot") { // ramdisk is never signed with avb information + // boot partitions just have the avb footer, and don't have a corresponding vbmeta + // partition. continue } partitionModules = append(partitionModules, generatedModuleNameForPartition(ctx.Config(), partitionType)) diff --git a/java/app.go b/java/app.go index 8bb73cb38..7f80160a3 100644 --- a/java/app.go +++ b/java/app.go @@ -164,7 +164,7 @@ type appProperties struct { type overridableAppProperties struct { // The name of a certificate in the default certificate directory, blank to use the default product certificate, // or an android_app_certificate module name in the form ":module". - Certificate *string + Certificate proptools.Configurable[string] `android:"replace_instead_of_append"` // Name of the signing certificate lineage file or filegroup module. Lineage *string `android:"path"` @@ -1252,7 +1252,7 @@ func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string { if overridden { return ":" + certificate } - return String(a.overridableAppProperties.Certificate) + return a.overridableAppProperties.Certificate.GetOrDefault(ctx, "") } func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { diff --git a/java/app_import.go b/java/app_import.go index f044c6848..8951c7d9c 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -97,7 +97,7 @@ type AndroidAppImportProperties struct { // The name of a certificate in the default certificate directory or an android_app_certificate // module name in the form ":module". Should be empty if presigned or default_dev_cert is set. - Certificate *string + Certificate proptools.Configurable[string] `android:"replace_instead_of_append"` // Names of extra android_app_certificate modules to sign the apk with in the form ":module". Additional_certificates []string @@ -240,7 +240,7 @@ func disablePrebuiltsWithoutApkMutator(ctx android.BottomUpMutatorContext) { } func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) { - cert := android.SrcIsModule(String(a.properties.Certificate)) + cert := android.SrcIsModule(a.properties.Certificate.GetOrDefault(ctx, "")) if cert != "" { ctx.AddDependency(ctx.Module(), certificateTag, cert) } @@ -323,7 +323,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext } numCertPropsSet := 0 - if String(a.properties.Certificate) != "" { + if a.properties.Certificate.GetOrDefault(ctx, "") != "" { numCertPropsSet++ } if Bool(a.properties.Presigned) { @@ -406,7 +406,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext // If the certificate property is empty at this point, default_dev_cert must be set to true. // Which makes processMainCert's behavior for the empty cert string WAI. _, _, certificates := collectAppDeps(ctx, a, false, false) - a.certificate, certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx) + a.certificate, certificates = processMainCert(a.ModuleBase, a.properties.Certificate.GetOrDefault(ctx, ""), certificates, ctx) signed := android.PathForModuleOut(ctx, "signed", apkFilename) var lineageFile android.Path if lineage := String(a.properties.Lineage); lineage != "" { diff --git a/java/base.go b/java/base.go index 8dad2d9ad..3bf2e23d8 100644 --- a/java/base.go +++ b/java/base.go @@ -714,10 +714,10 @@ func (j *Module) provideHiddenAPIPropertyInfo(ctx android.ModuleContext) { // helper method for java modules to set OutputFilesProvider func setOutputFiles(ctx android.ModuleContext, m Module) { - ctx.SetOutputFiles(append(android.Paths{m.outputFile}, m.extraOutputFiles...), "") - ctx.SetOutputFiles(android.Paths{m.outputFile}, android.DefaultDistTag) - ctx.SetOutputFiles(android.Paths{m.implementationAndResourcesJar}, ".jar") - ctx.SetOutputFiles(android.Paths{m.headerJarFile}, ".hjar") + ctx.SetOutputFiles(append(android.PathsIfNonNil(m.outputFile), m.extraOutputFiles...), "") + ctx.SetOutputFiles(android.PathsIfNonNil(m.outputFile), android.DefaultDistTag) + ctx.SetOutputFiles(android.PathsIfNonNil(m.implementationAndResourcesJar), ".jar") + ctx.SetOutputFiles(android.PathsIfNonNil(m.headerJarFile), ".hjar") if m.dexer.proguardDictionary.Valid() { ctx.SetOutputFiles(android.Paths{m.dexer.proguardDictionary.Path()}, ".proguard_map") } @@ -766,7 +766,8 @@ func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool { apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) isJacocoAgent := ctx.ModuleName() == "jacocoagent" - if j.DirectlyInAnyApex() && !isJacocoAgent && !apexInfo.IsForPlatform() { + compileDex := Bool(j.dexProperties.Compile_dex) || Bool(j.properties.Installable) + if compileDex && !isJacocoAgent && !apexInfo.IsForPlatform() { if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) { return true } else if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { @@ -1735,7 +1736,12 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath completeStaticLibsImplementationJarsToCombine := completeStaticLibsImplementationJars - if j.shouldInstrument(ctx) { + apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) + + // Enable dex compilation for the APEX variants, unless it is disabled explicitly + compileDex := Bool(j.dexProperties.Compile_dex) || Bool(j.properties.Installable) + + if j.shouldInstrument(ctx) && (!ctx.Device() || compileDex) { instrumentedOutputFile := j.instrument(ctx, flags, outputFile, jarName, specs) completeStaticLibsImplementationJarsToCombine = depset.New(depset.PREORDER, android.Paths{instrumentedOutputFile}, nil) outputFile = instrumentedOutputFile @@ -1764,19 +1770,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath j.implementationAndResourcesJar = outputFile - // Enable dex compilation for the APEX variants, unless it is disabled explicitly - compileDex := j.dexProperties.Compile_dex - apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) - if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() { - if compileDex == nil { - compileDex = proptools.BoolPtr(true) - } - if j.deviceProperties.Hostdex == nil { - j.deviceProperties.Hostdex = proptools.BoolPtr(true) - } - } - - if ctx.Device() && (Bool(j.properties.Installable) || Bool(compileDex)) { + if ctx.Device() && compileDex { if j.hasCode(ctx) { if j.shouldInstrumentStatic(ctx) { j.dexer.extraProguardFlagsFiles = append(j.dexer.extraProguardFlagsFiles, @@ -2328,7 +2322,10 @@ func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret "stable.core.platform.api.stubs", "stub-annotations", "private-stub-annotations-jar", "core-lambda-stubs", - "core-generated-annotation-stubs": + "core-generated-annotation-stubs", + // jacocoagent only uses core APIs, but has to specify a non-core sdk_version so it can use + // a prebuilt SDK to avoid circular dependencies when it statically included in the bootclasspath. + "jacocoagent": return javaCore, true case android.SdkPublic.DefaultJavaLibraryName(): return javaSdk, true diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index c778f0404..375a1aaf1 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -83,10 +83,6 @@ func (b bootclasspathFragmentContentDependencyTag) ExportMember() bool { return true } -// Contents of bootclasspath fragments in an apex are considered to be directly in the apex, as if -// they were listed in java_libs. -func (b bootclasspathFragmentContentDependencyTag) CopyDirectlyInAnyApex() {} - // Contents of bootclasspath fragments require files from prebuilt apex files. func (b bootclasspathFragmentContentDependencyTag) RequiresFilesFromPrebuiltApex() {} @@ -96,7 +92,6 @@ var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyT var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag var _ android.SdkMemberDependencyTag = bootclasspathFragmentContentDepTag -var _ android.CopyDirectlyInAnyApexTag = bootclasspathFragmentContentDepTag var _ android.RequiresFilesFromPrebuiltApexTag = bootclasspathFragmentContentDepTag func IsBootclasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool { diff --git a/java/droiddoc.go b/java/droiddoc.go index 82713920d..2dda72b0e 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -578,7 +578,6 @@ func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { rule.Build("javadoc", "javadoc") - ctx.SetOutputFiles(android.Paths{j.stubsSrcJar}, "") ctx.SetOutputFiles(android.Paths{j.docZip}, ".docs.zip") } diff --git a/java/droidstubs.go b/java/droidstubs.go index cf3e21925..bc2652797 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -1011,7 +1011,7 @@ func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *andro cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput) msg += fmt.Sprintf(``+ - `3. FOR LSC ONLY: You can update the baseline by executing\n` + + `3. FOR LSC ONLY: You can update the baseline by executing\n`+ ` the following command:\n`+ ` (cd $ANDROID_BUILD_TOP && cp \\\n`+ ` "%s" \\\n`+ @@ -1374,7 +1374,7 @@ func (d *Droidstubs) setOutputFiles(ctx android.ModuleContext) { for _, stubType := range android.SortedKeys(stubsTypeToPrefix) { tagWithPrefix := stubsTypeToPrefix[stubType] + tag outputFile, err := tagToOutputFileFunc[tag](stubType) - if err == nil { + if err == nil && outputFile != nil { ctx.SetOutputFiles(android.Paths{outputFile}, tagWithPrefix) } } diff --git a/java/java.go b/java/java.go index 64ef782f5..260d33610 100644 --- a/java/java.go +++ b/java/java.go @@ -2311,14 +2311,17 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { case libTag: if provider, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { classPaths = append(classPaths, provider.HeaderJars...) + al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.AconfigIntermediateCacheOutputPaths...) } case bootClasspathTag: if provider, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { bootclassPaths = append(bootclassPaths, provider.HeaderJars...) + al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.AconfigIntermediateCacheOutputPaths...) } case staticLibTag: if provider, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok { staticLibs = append(staticLibs, provider.HeaderJars...) + al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.AconfigIntermediateCacheOutputPaths...) } case systemModulesTag: if sm, ok := android.OtherModuleProvider(ctx, dep, SystemModulesProvider); ok { diff --git a/java/java_test.go b/java/java_test.go index 54eb3e14e..d415679bd 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -3050,6 +3050,7 @@ func TestCoverage(t *testing.T) { java_library { name: "android.car", srcs: ["android.car.java"], + installable: true, } `) diff --git a/java/rro.go b/java/rro.go index 8bb9be2eb..f225e1f4e 100644 --- a/java/rro.go +++ b/java/rro.go @@ -50,7 +50,7 @@ type RuntimeResourceOverlay struct { type RuntimeResourceOverlayProperties struct { // the name of a certificate in the default certificate directory or an android_app_certificate // module name in the form ":module". - Certificate *string + Certificate proptools.Configurable[string] `android:"replace_instead_of_append"` // Name of the signing certificate lineage file. Lineage *string @@ -119,7 +119,7 @@ func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) r.aapt.deps(ctx, sdkDep) } - cert := android.SrcIsModule(String(r.properties.Certificate)) + cert := android.SrcIsModule(r.properties.Certificate.GetOrDefault(ctx, "")) if cert != "" { ctx.AddDependency(ctx.Module(), certificateTag, cert) } @@ -166,7 +166,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC // Sign the built package _, _, certificates := collectAppDeps(ctx, r, false, false) - r.certificate, certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx) + r.certificate, certificates = processMainCert(r.ModuleBase, r.properties.Certificate.GetOrDefault(ctx, ""), certificates, ctx) signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk") var lineageFile android.Path if lineage := String(r.properties.Lineage); lineage != "" { diff --git a/java/sdk_library.go b/java/sdk_library.go index f6dfcdd19..78917768b 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1314,12 +1314,6 @@ var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"} var _ android.InstallNeededDependencyTag = sdkLibraryComponentTag{} -// To satisfy the CopyDirectlyInAnyApexTag interface. Implementation library of the sdk library -// in an apex is considered to be directly in the apex, as if it was listed in java_libs. -func (t sdkLibraryComponentTag) CopyDirectlyInAnyApex() {} - -var _ android.CopyDirectlyInAnyApexTag = implLibraryTag - func (t sdkLibraryComponentTag) InstallDepNeeded() bool { return t.name == "xml-permissions-file" || t.name == "impl-library" } diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index 608a61628..3176ad94c 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -218,16 +218,11 @@ func (b systemServerClasspathFragmentContentDependencyTag) ExportMember() bool { return true } -// Contents of system server fragments in an apex are considered to be directly in the apex, as if -// they were listed in java_libs. -func (systemServerClasspathFragmentContentDependencyTag) CopyDirectlyInAnyApex() {} - // Contents of system server fragments require files from prebuilt apex files. func (systemServerClasspathFragmentContentDependencyTag) RequiresFilesFromPrebuiltApex() {} var _ android.ReplaceSourceWithPrebuilt = systemServerClasspathFragmentContentDepTag var _ android.SdkMemberDependencyTag = systemServerClasspathFragmentContentDepTag -var _ android.CopyDirectlyInAnyApexTag = systemServerClasspathFragmentContentDepTag var _ android.RequiresFilesFromPrebuiltApexTag = systemServerClasspathFragmentContentDepTag // The tag used for the dependency between the systemserverclasspath_fragment module and its contents. diff --git a/java/testing.go b/java/testing.go index 988514dea..cb3245ba7 100644 --- a/java/testing.go +++ b/java/testing.go @@ -190,6 +190,7 @@ var PrepareForTestWithJacocoInstrumentation = android.GroupFixturePreparers( "//apex_available:anyapex", "//apex_available:platform", ], + compile_dex: true, } `)), ) diff --git a/systemfeatures/Android.bp b/systemfeatures/Android.bp new file mode 100644 index 000000000..a65a6b644 --- /dev/null +++ b/systemfeatures/Android.bp @@ -0,0 +1,18 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-systemfeatures", + pkgPath: "android/soong/systemfeatures", + deps: [ + "blueprint", + "blueprint-proptools", + "soong", + "soong-android", + "soong-java", + ], + srcs: ["system_features.go"], + testSrcs: ["system_features_test.go"], + pluginFor: ["soong_build"], +} diff --git a/systemfeatures/OWNERS b/systemfeatures/OWNERS new file mode 100644 index 000000000..3e4480647 --- /dev/null +++ b/systemfeatures/OWNERS @@ -0,0 +1,2 @@ +jdduke@google.com +shayba@google.com diff --git a/systemfeatures/system_features.go b/systemfeatures/system_features.go new file mode 100644 index 000000000..0c1a56676 --- /dev/null +++ b/systemfeatures/system_features.go @@ -0,0 +1,102 @@ +// 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 systemfeatures + +import ( + "fmt" + "sort" + "strings" + + "android/soong/android" + "android/soong/genrule" +) + +var ( + pctx = android.NewPackageContext("android/soong/systemfeatures") +) + +func init() { + registerSystemFeaturesComponents(android.InitRegistrationContext) +} + +func registerSystemFeaturesComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("java_system_features_srcs", JavaSystemFeaturesSrcsFactory) +} + +type javaSystemFeaturesSrcs struct { + android.ModuleBase + properties struct { + // The fully qualified class name for the generated code, e.g., com.android.Foo + Full_class_name string + } + outputFiles android.WritablePaths +} + +var _ genrule.SourceFileGenerator = (*javaSystemFeaturesSrcs)(nil) +var _ android.SourceFileProducer = (*javaSystemFeaturesSrcs)(nil) + +func (m *javaSystemFeaturesSrcs) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Create a file name appropriate for the given fully qualified (w/ package) class name. + classNameParts := strings.Split(m.properties.Full_class_name, ".") + outputDir := android.PathForModuleGen(ctx) + outputFileName := classNameParts[len(classNameParts)-1] + ".java" + outputFile := android.PathForModuleGen(ctx, outputFileName).OutputPath + + // Collect all RELEASE_SYSTEM_FEATURE_$K:$V build flags into a list of "$K:$V" pairs. + var features []string + for k, v := range ctx.Config().ProductVariables().BuildFlags { + if strings.HasPrefix(k, "RELEASE_SYSTEM_FEATURE_") { + shortFeatureName := strings.TrimPrefix(k, "RELEASE_SYSTEM_FEATURE_") + features = append(features, fmt.Sprintf("%s:%s", shortFeatureName, v)) + } + } + // Ensure sorted outputs for consistency of flag ordering in ninja outputs. + sort.Strings(features) + + rule := android.NewRuleBuilder(pctx, ctx) + rule.Command().Text("rm -rf").Text(outputDir.String()) + rule.Command().Text("mkdir -p").Text(outputDir.String()) + rule.Command(). + BuiltTool("systemfeatures-gen-tool"). + Flag(m.properties.Full_class_name). + FlagForEachArg("--feature=", features). + FlagWithArg("--readonly=", fmt.Sprint(ctx.Config().ReleaseUseSystemFeatureBuildFlags())). + FlagWithOutput(" > ", outputFile) + rule.Build(ctx.ModuleName(), "Generating systemfeatures srcs filegroup") + + m.outputFiles = append(m.outputFiles, outputFile) +} + +func (m *javaSystemFeaturesSrcs) Srcs() android.Paths { + return m.outputFiles.Paths() +} + +func (m *javaSystemFeaturesSrcs) GeneratedSourceFiles() android.Paths { + return m.outputFiles.Paths() +} + +func (m *javaSystemFeaturesSrcs) GeneratedDeps() android.Paths { + return m.outputFiles.Paths() +} + +func (m *javaSystemFeaturesSrcs) GeneratedHeaderDirs() android.Paths { + return nil +} + +func JavaSystemFeaturesSrcsFactory() android.Module { + module := &javaSystemFeaturesSrcs{} + module.AddProperties(&module.properties) + android.InitAndroidModule(module) + return module +} diff --git a/systemfeatures/system_features_test.go b/systemfeatures/system_features_test.go new file mode 100644 index 000000000..558bb958e --- /dev/null +++ b/systemfeatures/system_features_test.go @@ -0,0 +1,51 @@ +// 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 systemfeatures + +import ( + "android/soong/android" + + "testing" +) + +func TestJavaSystemFeaturesSrcs(t *testing.T) { + bp := ` +java_system_features_srcs { + name: "system-features-srcs", + full_class_name: "com.android.test.RoSystemFeatures", +} +` + + res := android.GroupFixturePreparers( + android.FixtureRegisterWithContext(registerSystemFeaturesComponents), + android.PrepareForTestWithBuildFlag("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS", "true"), + android.PrepareForTestWithBuildFlag("RELEASE_SYSTEM_FEATURE_AUTOMOTIVE", "0"), + android.PrepareForTestWithBuildFlag("RELEASE_SYSTEM_FEATURE_TELEVISION", "UNAVAILABLE"), + android.PrepareForTestWithBuildFlag("RELEASE_SYSTEM_FEATURE_WATCH", ""), + android.PrepareForTestWithBuildFlag("RELEASE_NOT_SYSTEM_FEATURE_FOO", "BAR"), + ).RunTestWithBp(t, bp) + + module := res.ModuleForTests("system-features-srcs", "") + cmd := module.Rule("system-features-srcs").RuleParams.Command + android.AssertStringDoesContain(t, "Expected fully class name", cmd, " com.android.test.RoSystemFeatures ") + android.AssertStringDoesContain(t, "Expected readonly flag", cmd, "--readonly=true") + android.AssertStringDoesContain(t, "Expected AUTOMOTIVE feature flag", cmd, "--feature=AUTOMOTIVE:0 ") + android.AssertStringDoesContain(t, "Expected TELEVISION feature flag", cmd, "--feature=TELEVISION:UNAVAILABLE ") + android.AssertStringDoesContain(t, "Expected WATCH feature flag", cmd, "--feature=WATCH: ") + android.AssertStringDoesNotContain(t, "Unexpected FOO arg from non-system feature flag", cmd, "FOO") + + systemFeaturesModule := module.Module().(*javaSystemFeaturesSrcs) + expectedOutputPath := "out/soong/.intermediates/system-features-srcs/gen/RoSystemFeatures.java" + android.AssertPathsRelativeToTopEquals(t, "Expected output file", []string{expectedOutputPath}, systemFeaturesModule.Srcs()) +} |