diff --git a/java/aapt2.go b/java/aapt2.go index 17ee6ee42..445e91298 100644 --- a/java/aapt2.go +++ b/java/aapt2.go @@ -202,7 +202,8 @@ var mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets", func aapt2Link(ctx android.ModuleContext, packageRes, genJar, proguardOptions, rTxt android.WritablePath, flags []string, deps android.Paths, - compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) { + compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths, + featureFlagsPaths android.Paths) { var inFlags []string @@ -255,6 +256,11 @@ func aapt2Link(ctx android.ModuleContext, }) } + for _, featureFlagsPath := range featureFlagsPaths { + deps = append(deps, featureFlagsPath) + inFlags = append(inFlags, "--feature-flags", "@"+featureFlagsPath.String()) + } + // Note the absence of splitPackages. The caller is supposed to compose and provide --split flag // values via the flags parameter when it wants to split outputs. // TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably diff --git a/java/aar.go b/java/aar.go index 57a05d47b..1ab452965 100644 --- a/java/aar.go +++ b/java/aar.go @@ -349,6 +349,7 @@ type aaptBuildActionOptions struct { excludedLibs []string enforceDefaultTargetSdkVersion bool extraLinkFlags []string + aconfigTextFiles android.Paths } func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptions) { @@ -529,7 +530,8 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio transitiveAssets = android.ReverseSliceInPlace(staticDeps.assets()) } aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, - linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages) + linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages, + opts.aconfigTextFiles) // Extract assets from the resource package output so that they can be used later in aapt2link // for modules that depend on this one. if android.PrefixInList(linkFlags, "-A ") { @@ -1193,7 +1195,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { transitiveAssets := android.ReverseSliceInPlace(staticDeps.assets()) aapt2Link(ctx, a.exportPackage, nil, proguardOptionsFile, a.rTxt, - linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil) + linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil, nil) a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar") resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true) diff --git a/java/app.go b/java/app.go index 0f46b4ec8..d8822aff3 100755 --- a/java/app.go +++ b/java/app.go @@ -22,7 +22,9 @@ import ( "path/filepath" "strings" + "android/soong/aconfig" "android/soong/testing" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -170,6 +172,9 @@ type overridableAppProperties struct { // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed // from PRODUCT_PACKAGES. Overrides []string + + // Names of aconfig_declarations modules that specify aconfig flags that the app depends on. + Flags_packages []string } type AndroidApp struct { @@ -316,6 +321,10 @@ func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutato `must be names of android_app_certificate modules in the form ":module"`) } } + + for _, aconfig_declaration := range a.overridableAppProperties.Flags_packages { + ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration) + } } func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -500,13 +509,27 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { if a.Updatable() { a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion } + + var aconfigTextFilePaths android.Paths + ctx.VisitDirectDepsWithTag(aconfigDeclarationTag, func(dep android.Module) { + if provider, ok := ctx.OtherModuleProvider(dep, aconfig.DeclarationsProviderKey).(aconfig.DeclarationsProviderData); ok { + aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath) + } else { + ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+ + "flags_packages property, but %s is not aconfig_declarations module type", + dep.Name(), + ) + } + }) + a.aapt.buildActions(ctx, aaptBuildActionOptions{ - android.SdkContext(a), - a.classLoaderContexts, - a.usesLibraryProperties.Exclude_uses_libs, - a.enforceDefaultTargetSdkVersion(), - aaptLinkFlags, + sdkContext: android.SdkContext(a), + classLoaderContexts: a.classLoaderContexts, + excludedLibs: a.usesLibraryProperties.Exclude_uses_libs, + enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(), + extraLinkFlags: aaptLinkFlags, + aconfigTextFiles: aconfigTextFilePaths, }, ) diff --git a/java/app_test.go b/java/app_test.go index 5cb4a2301..0936b281a 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -4333,3 +4333,48 @@ func TestApexGlobalMinSdkVersionOverride(t *testing.T) { ) } + +func TestAppFlagsPackages(t *testing.T) { + ctx := testApp(t, ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + flags_packages: [ + "bar", + "baz", + ], + } + aconfig_declarations { + name: "bar", + package: "com.example.package", + srcs: [ + "bar.aconfig", + ], + } + aconfig_declarations { + name: "baz", + package: "com.example.package", + srcs: [ + "baz.aconfig", + ], + } + `) + + foo := ctx.ModuleForTests("foo", "android_common") + + // android_app module depends on aconfig_declarations listed in flags_packages + android.AssertBoolEquals(t, "foo expected to depend on bar", true, + CheckModuleHasDependency(t, ctx, "foo", "android_common", "bar")) + + android.AssertBoolEquals(t, "foo expected to depend on baz", true, + CheckModuleHasDependency(t, ctx, "foo", "android_common", "baz")) + + aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link") + linkInFlags := aapt2LinkRule.Args["inFlags"] + android.AssertStringDoesContain(t, + "aapt2 link command expected to pass feature flags arguments", + linkInFlags, + "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt", + ) +} diff --git a/java/java.go b/java/java.go index 2236d05b2..d5d22b2aa 100644 --- a/java/java.go +++ b/java/java.go @@ -409,6 +409,7 @@ var ( syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"} javaApiContributionTag = dependencyTag{name: "java-api-contribution"} depApiSrcsTag = dependencyTag{name: "dep-api-srcs"} + aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"} jniInstallTag = installDependencyTag{name: "jni install"} binaryInstallTag = installDependencyTag{name: "binary install"} usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false) diff --git a/java/java_test.go b/java/java_test.go index 0c750ebe1..d4b056bc9 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -26,6 +26,7 @@ import ( "github.com/google/blueprint/proptools" + "android/soong/aconfig" "android/soong/android" "android/soong/cc" "android/soong/dexpreopt" @@ -47,6 +48,8 @@ var prepareForJavaTest = android.GroupFixturePreparers( cc.PrepareForTestWithCcBuildComponents, // Include all the default java modules. PrepareForTestWithDexpreopt, + // Include aconfig modules. + aconfig.PrepareForTestWithAconfigBuildComponents, ) func TestMain(m *testing.M) {