diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go index 74830d385..52b1689ba 100644 --- a/apex/platform_bootclasspath_test.go +++ b/apex/platform_bootclasspath_test.go @@ -137,9 +137,12 @@ func TestPlatformBootclasspathDependencies(t *testing.T) { ) java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{ + // The configured contents of BootJars. "com.android.art:baz", "com.android.art:quuz", "platform:foo", + + // The configured contents of UpdatableBootJars. "myapex:bar", }) @@ -149,11 +152,24 @@ func TestPlatformBootclasspathDependencies(t *testing.T) { // Make sure that the myplatform-bootclasspath has the correct dependencies. CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{ + // The following are stubs. + `platform:android_stubs_current`, + `platform:android_system_stubs_current`, + `platform:android_test_stubs_current`, + `platform:legacy.core.platform.api.stubs`, + + // Needed for generating the boot image. `platform:dex2oatd`, + + // The configured contents of BootJars. `com.android.art:baz`, `com.android.art:quuz`, `platform:foo`, + + // The configured contents of UpdatableBootJars. `myapex:bar`, + + // The fragments. `com.android.art:art-bootclasspath-fragment`, }) } diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index 8daf197c6..8cc6f8f23 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -21,6 +21,30 @@ import ( // Contains support for processing hiddenAPI in a modular fashion. +type hiddenAPIStubsDependencyTag struct { + blueprint.BaseDependencyTag + sdkKind android.SdkKind +} + +func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() { +} + +func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool { + return false +} + +// Avoid having to make stubs content explicitly visible to dependent modules. +// +// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules +// with proper dependencies. +// TODO(b/177892522): Remove this and add needed visibility. +func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() { +} + +var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{} +var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{} +var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{} + // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden // API processing. var hiddenAPIRelevantSdkKinds = []android.SdkKind{ @@ -30,6 +54,125 @@ var hiddenAPIRelevantSdkKinds = []android.SdkKind{ android.SdkCorePlatform, } +// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs +// needed to produce the hidden API monolithic stub flags file. +func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string { + var publicStubModules []string + var systemStubModules []string + var testStubModules []string + var corePlatformStubModules []string + + if config.AlwaysUsePrebuiltSdks() { + // Build configuration mandates using prebuilt stub modules + publicStubModules = append(publicStubModules, "sdk_public_current_android") + systemStubModules = append(systemStubModules, "sdk_system_current_android") + testStubModules = append(testStubModules, "sdk_test_current_android") + } else { + // Use stub modules built from source + publicStubModules = append(publicStubModules, "android_stubs_current") + systemStubModules = append(systemStubModules, "android_system_stubs_current") + testStubModules = append(testStubModules, "android_test_stubs_current") + } + // We do not have prebuilts of the core platform api yet + corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs") + + // Allow products to define their own stubs for custom product jars that apps can use. + publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...) + systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...) + testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...) + if config.IsEnvTrue("EMMA_INSTRUMENT") { + publicStubModules = append(publicStubModules, "jacoco-stubs") + } + + m := map[android.SdkKind][]string{} + m[android.SdkPublic] = publicStubModules + m[android.SdkSystem] = systemStubModules + m[android.SdkTest] = testStubModules + m[android.SdkCorePlatform] = corePlatformStubModules + return m +} + +// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in +// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to +// identify the source of the dependency. +func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) { + module := ctx.Module() + for _, sdkKind := range hiddenAPIRelevantSdkKinds { + modules := sdkKindToStubLibModules[sdkKind] + ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...) + } +} + +// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added +// in hiddenAPIAddStubLibDependencies. +func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext) map[android.SdkKind]android.Paths { + m := map[android.SdkKind]android.Paths{} + ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) { + tag := ctx.OtherModuleDependencyTag(module) + if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok { + kind := hiddenAPIStubsTag.sdkKind + dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module) + if dexJar != nil { + m[kind] = append(m[kind], dexJar) + } + } + }) + return m +} + +// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if +// available, or reports an error. +func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module) android.Path { + if j, ok := module.(UsesLibraryDependency); ok { + dexJar := j.DexJarBuildPath() + if dexJar != nil { + return dexJar + } + ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module) + } else { + ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module)) + } + return nil +} + +var sdkKindToHiddenapiListOption = map[android.SdkKind]string{ + android.SdkPublic: "public-stub-classpath", + android.SdkSystem: "system-stub-classpath", + android.SdkTest: "test-stub-classpath", + android.SdkCorePlatform: "core-platform-stub-classpath", +} + +// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file. +// +// The rule is initialized but not built so that the caller can modify it and select an appropriate +// name. +func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.OutputPath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder { + // Singleton rule which applies hiddenapi on all boot class path dex files. + rule := android.NewRuleBuilder(pctx, ctx) + + tempPath := tempPathForRestat(ctx, outputPath) + + command := rule.Command(). + Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")). + Text("list"). + FlagForEachInput("--boot-dex=", bootDexJars) + + // Iterate over the sdk kinds in a fixed order. + for _, sdkKind := range hiddenAPIRelevantSdkKinds { + paths := sdkKindToPathList[sdkKind] + if len(paths) > 0 { + option := sdkKindToHiddenapiListOption[sdkKind] + command.FlagWithInputList("--"+option+"=", paths, ":") + } + } + + // Add the output path. + command.FlagWithOutput("--out-api-flags=", tempPath) + + commitChangeForRestat(rule, tempPath, outputPath) + return rule +} + // HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the // information obtained from annotations within the source code in order to create the complete set // of flags that should be applied to the dex implementation jars on the bootclasspath. diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 2e1f8dbd6..3cc88e606 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -127,8 +127,6 @@ func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) return } - stubFlagsRule(ctx) - // If there is a prebuilt hiddenapi dir, generate rules to use the // files within. Generally, we build the hiddenapi files from source // during the build, ensuring consistency. It's possible, in a split @@ -160,137 +158,6 @@ func (h *hiddenAPISingleton) MakeVars(ctx android.MakeVarsContext) { ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", h.flags.String()) } -// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs -// needed to produce the hidden API monolithic stub flags file. -func hiddenAPIComputeMonolithicStubLibModules(ctx android.BuilderContext) map[android.SdkKind][]string { - var publicStubModules []string - var systemStubModules []string - var testStubModules []string - var corePlatformStubModules []string - - if ctx.Config().AlwaysUsePrebuiltSdks() { - // Build configuration mandates using prebuilt stub modules - publicStubModules = append(publicStubModules, "sdk_public_current_android") - systemStubModules = append(systemStubModules, "sdk_system_current_android") - testStubModules = append(testStubModules, "sdk_test_current_android") - } else { - // Use stub modules built from source - publicStubModules = append(publicStubModules, "android_stubs_current") - systemStubModules = append(systemStubModules, "android_system_stubs_current") - testStubModules = append(testStubModules, "android_test_stubs_current") - } - // We do not have prebuilts of the core platform api yet - corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs") - - // Allow products to define their own stubs for custom product jars that apps can use. - publicStubModules = append(publicStubModules, ctx.Config().ProductHiddenAPIStubs()...) - systemStubModules = append(systemStubModules, ctx.Config().ProductHiddenAPIStubsSystem()...) - testStubModules = append(testStubModules, ctx.Config().ProductHiddenAPIStubsTest()...) - if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") { - publicStubModules = append(publicStubModules, "jacoco-stubs") - } - - m := map[android.SdkKind][]string{} - m[android.SdkPublic] = publicStubModules - m[android.SdkSystem] = systemStubModules - m[android.SdkTest] = testStubModules - m[android.SdkCorePlatform] = corePlatformStubModules - return m -} - -// stubFlagsRule creates the rule to build hiddenapi-stub-flags.txt out of dex jars from stub modules and boot image -// modules. -func stubFlagsRule(ctx android.SingletonContext) { - - sdkKindToModules := hiddenAPIComputeMonolithicStubLibModules(ctx) - - // Create a set of path slices into which the DexJarBuildPath from the stub modules can be stored. - sdkKindToPathList := map[android.SdkKind]android.Paths{} - for sdkKind, modules := range sdkKindToModules { - sdkKindToPathList[sdkKind] = make(android.Paths, len(modules)) - } - - var bootDexJars android.Paths - ctx.VisitAllModules(func(module android.Module) { - // Collect dex jar paths for the modules listed above. - if j, ok := module.(UsesLibraryDependency); ok { - name := ctx.ModuleName(module) - for _, sdkKind := range hiddenAPIRelevantSdkKinds { - if i := android.IndexList(name, sdkKindToModules[sdkKind]); i != -1 { - sdkKindToPathList[sdkKind][i] = j.DexJarBuildPath() - } - } - } - - // Collect dex jar paths for modules that had hiddenapi encode called on them. - if h, ok := module.(hiddenAPIIntf); ok { - if jar := h.bootDexJar(); jar != nil { - bootDexJars = append(bootDexJars, jar) - } - } - }) - - var missingDeps []string - // Ensure all modules were converted to paths - for _, sdkKind := range hiddenAPIRelevantSdkKinds { - pathList := sdkKindToPathList[sdkKind] - for i := range pathList { - if pathList[i] == nil { - moduleName := sdkKindToModules[sdkKind][i] - pathList[i] = android.PathForOutput(ctx, "missing/module", moduleName) - if ctx.Config().AllowMissingDependencies() { - missingDeps = append(missingDeps, moduleName) - } else { - ctx.Errorf("failed to find dex jar path for module %q", moduleName) - } - } - } - } - - outputPath := hiddenAPISingletonPaths(ctx).stubFlags - rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, outputPath, bootDexJars, sdkKindToPathList) - rule.MissingDeps(missingDeps) - rule.Build("hiddenAPIStubFlagsFile", "hiddenapi stub flags") -} - -var sdkKindToHiddenapiListOption = map[android.SdkKind]string{ - android.SdkPublic: "public-stub-classpath", - android.SdkSystem: "system-stub-classpath", - android.SdkTest: "test-stub-classpath", - android.SdkCorePlatform: "core-platform-stub-classpath", -} - -// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file. -// -// The rule is initialized but not built so that the caller can modify it and select an appropriate -// name. -func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.SingletonContext, outputPath android.OutputPath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder { - // Singleton rule which applies hiddenapi on all boot class path dex files. - rule := android.NewRuleBuilder(pctx, ctx) - - tempPath := tempPathForRestat(ctx, outputPath) - - command := rule.Command(). - Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")). - Text("list"). - FlagForEachInput("--boot-dex=", bootDexJars) - - // Iterate over the sdk - for _, sdkKind := range hiddenAPIRelevantSdkKinds { - paths := sdkKindToPathList[sdkKind] - if len(paths) > 0 { - option := sdkKindToHiddenapiListOption[sdkKind] - command.FlagWithInputList("--"+option+"=", paths, ":") - } - } - - // Add the output path. - command.FlagWithOutput("--out-api-flags=", tempPath) - - commitChangeForRestat(rule, tempPath, outputPath) - return rule -} - // Checks to see whether the supplied module variant is in the list of boot jars. // // This is similar to logic in getBootImageJar() so any changes needed here are likely to be needed diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index 5ea9a5bca..3ab22772a 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -23,12 +23,20 @@ import ( "github.com/google/blueprint/proptools" ) +// TODO(b/177892522): Move these tests into a more appropriate place. + func fixtureSetPrebuiltHiddenApiDirProductVariable(prebuiltHiddenApiDir *string) android.FixturePreparer { return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir }) } +var prepareForTestWithDefaultPlatformBootclasspath = android.FixtureAddTextFile("frameworks/base/boot/Android.bp", ` + platform_bootclasspath { + name: "platform-bootclasspath", + } +`) + var hiddenApiFixtureFactory = android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithHiddenApiBuildComponents) @@ -36,6 +44,7 @@ func TestHiddenAPISingleton(t *testing.T) { result := android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), + prepareForTestWithDefaultPlatformBootclasspath, ).RunTestWithBp(t, ` java_library { name: "foo", @@ -44,8 +53,8 @@ func TestHiddenAPISingleton(t *testing.T) { } `) - hiddenAPI := result.SingletonForTests("hiddenapi") - hiddenapiRule := hiddenAPI.Rule("hiddenapi") + hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags") want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar" android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want) } @@ -59,6 +68,7 @@ func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), + prepareForTestWithDefaultPlatformBootclasspath, ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorMessage)). RunTestWithBp(t, ` java_library { @@ -79,6 +89,7 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { result := android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), + prepareForTestWithDefaultPlatformBootclasspath, ).RunTestWithBp(t, ` java_import { name: "foo", @@ -87,8 +98,8 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { } `) - hiddenAPI := result.SingletonForTests("hiddenapi") - hiddenapiRule := hiddenAPI.Rule("hiddenapi") + hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags") want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar" android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want) } @@ -97,6 +108,7 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { result := android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), + prepareForTestWithDefaultPlatformBootclasspath, ).RunTestWithBp(t, ` java_library { name: "foo", @@ -112,8 +124,8 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { } `) - hiddenAPI := result.SingletonForTests("hiddenapi") - hiddenapiRule := hiddenAPI.Rule("hiddenapi") + hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags") fromSourceJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar" android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, fromSourceJarArg) @@ -125,6 +137,7 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { result := android.GroupFixturePreparers( hiddenApiFixtureFactory, FixtureConfigureBootJars("platform:foo"), + prepareForTestWithDefaultPlatformBootclasspath, ).RunTestWithBp(t, ` java_library { name: "foo", @@ -140,8 +153,8 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { } `) - hiddenAPI := result.SingletonForTests("hiddenapi") - hiddenapiRule := hiddenAPI.Rule("hiddenapi") + hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags") prebuiltJarArg := "--boot-dex=out/soong/.intermediates/prebuilt_foo/android_common/dex/foo.jar" android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, prebuiltJarArg) @@ -184,13 +197,14 @@ func TestHiddenAPISingletonSdks(t *testing.T) { result := android.GroupFixturePreparers( hiddenApiFixtureFactory, tc.preparer, + prepareForTestWithDefaultPlatformBootclasspath, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild) }), ).RunTest(t) - hiddenAPI := result.SingletonForTests("hiddenapi") - hiddenapiRule := hiddenAPI.Rule("hiddenapi") + hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common") + hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags") wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild) android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantPublicStubs) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index ba758ddfb..568f5e406 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -140,6 +140,8 @@ func (b *platformBootclasspathModule) OutputFiles(tag string) (android.Paths, er } func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) { + b.hiddenAPIDepsMutator(ctx) + if SkipDexpreoptBootJars(ctx) { return } @@ -149,6 +151,16 @@ func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorCon dexpreopt.RegisterToolDeps(ctx) } +func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) { + if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") { + return + } + + // Add dependencies onto the stub lib modules. + sdkKindToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config()) + hiddenAPIAddStubLibDependencies(ctx, sdkKindToStubLibModules) +} + func platformBootclasspathDepsMutator(ctx android.BottomUpMutatorContext) { m := ctx.Module() if p, ok := m.(*platformBootclasspathModule); ok { @@ -353,10 +365,24 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. baseFlagsPath := hiddenAPISingletonPaths(ctx).stubFlags ruleToGenerateHiddenApiFlags(ctx, outputPath, baseFlagsPath, moduleSpecificFlagsPaths, flagFileInfo) + b.generateHiddenAPIStubFlagsRules(ctx, hiddenAPISupportingModules) b.generateHiddenAPIIndexRules(ctx, hiddenAPISupportingModules) b.generatedHiddenAPIMetadataRules(ctx, hiddenAPISupportingModules) } +func (b *platformBootclasspathModule) generateHiddenAPIStubFlagsRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) { + bootDexJars := android.Paths{} + for _, module := range modules { + bootDexJars = append(bootDexJars, module.bootDexJar()) + } + + sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx) + + outputPath := hiddenAPISingletonPaths(ctx).stubFlags + rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, outputPath, bootDexJars, sdkKindToStubPaths) + rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags") +} + func (b *platformBootclasspathModule) generateHiddenAPIIndexRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) { indexes := android.Paths{} for _, module := range modules {