From 6a766453fd32697f612674bf675a17866e896256 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Mon, 12 Apr 2021 14:15:22 +0100 Subject: [PATCH] Export monolithic hidden API files from platform_bootclasspath Makes the monolithic hidden API files accessible from the platform_bootclasspath so they can be output to the dist build target and used by other modules, e.g. by doing something like this: java_resources: [ ":platform-bootclasspath{hiddenapi-flags.csv}", ], It makes the paths relative to the out/soong/hiddenapi directory rather than the out/soong directory to make them easier to use in the java_resources property without changing the structure of the APK. Without that attempting to use them in a java_resources property will result in them being copied to a hiddenapi/ within the APK instead of being used at the top level as existing APKs like CtsHiddenApiBlocklistTestApiTestCases expect. Bug: 177892522 Test: m nothing Change-Id: I829412fc7d25411e0c2e0713d0d219a18f4af2ee --- java/hiddenapi_singleton.go | 12 ++++--- java/platform_bootclasspath.go | 50 +++++++++++++++++++++++++++++ java/platform_bootclasspath_test.go | 41 +++++++++++++++++++++++ 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index 641e19f60..37c394a5a 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -101,11 +101,15 @@ var hiddenAPISingletonPathsKey = android.NewOnceKey("hiddenAPISingletonPathsKey" // yet been created. func hiddenAPISingletonPaths(ctx android.PathContext) hiddenAPISingletonPathsStruct { return ctx.Config().Once(hiddenAPISingletonPathsKey, func() interface{} { + // Make the paths relative to the out/soong/hiddenapi directory instead of to the out/soong/ + // directory. This ensures that if they are used as java_resources they do not end up in a + // hiddenapi directory in the resulting APK. + hiddenapiDir := android.PathForOutput(ctx, "hiddenapi") return hiddenAPISingletonPathsStruct{ - flags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-flags.csv"), - index: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-index.csv"), - metadata: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-unsupported.csv"), - stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"), + flags: hiddenapiDir.Join(ctx, "hiddenapi-flags.csv"), + index: hiddenapiDir.Join(ctx, "hiddenapi-index.csv"), + metadata: hiddenapiDir.Join(ctx, "hiddenapi-unsupported.csv"), + stubFlags: hiddenapiDir.Join(ctx, "hiddenapi-stub-flags.txt"), } }).(hiddenAPISingletonPathsStruct) } diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index e292d8057..86ab70865 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -15,6 +15,8 @@ package java import ( + "fmt" + "android/soong/android" "android/soong/dexpreopt" "github.com/google/blueprint" @@ -69,6 +71,15 @@ type platformBootclasspathModule struct { // // Currently only for testing. fragments []android.Module + + // Path to the monolithic hiddenapi-flags.csv file. + hiddenAPIFlagsCSV android.Path + + // Path to the monolithic hiddenapi-index.csv file. + hiddenAPIIndexCSV android.Path + + // Path to the monolithic hiddenapi-unsupported.csv file. + hiddenAPIMetadataCSV android.Path } // ApexVariantReference specifies a particular apex variant of a module. @@ -98,6 +109,34 @@ func platformBootclasspathFactory() android.Module { return m } +var _ android.OutputFileProducer = (*platformBootclasspathModule)(nil) + +// A minimal AndroidMkEntries is needed in order to support the dists property. +func (b *platformBootclasspathModule) AndroidMkEntries() []android.AndroidMkEntries { + return []android.AndroidMkEntries{ + { + Class: "FAKE", + // Need at least one output file in order for this to take effect. + OutputFile: android.OptionalPathForPath(b.hiddenAPIFlagsCSV), + Include: "$(BUILD_PHONY_PACKAGE)", + }, + } +} + +// Make the hidden API files available from the platform-bootclasspath module. +func (b *platformBootclasspathModule) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case "hiddenapi-flags.csv": + return android.Paths{b.hiddenAPIFlagsCSV}, nil + case "hiddenapi-index.csv": + return android.Paths{b.hiddenAPIIndexCSV}, nil + case "hiddenapi-metadata.csv": + return android.Paths{b.hiddenAPIMetadataCSV}, nil + } + + return nil, fmt.Errorf("unknown tag %s", tag) +} + func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) { if SkipDexpreoptBootJars(ctx) { return @@ -222,6 +261,17 @@ func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleCont // generateHiddenAPIBuildActions generates all the hidden API related build rules. func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module) { + // Save the paths to the monolithic files for retrieval via OutputFiles() + // Make the paths relative to the out/soong/hiddenapi directory instead of to the out/soong/ + // directory. This ensures that if they are used as java_resources they do not end up in a + // hiddenapi directory in the resulting APK. + relToHiddenapiDir := func(path android.OutputPath) android.Path { + return path + } + b.hiddenAPIFlagsCSV = relToHiddenapiDir(hiddenAPISingletonPaths(ctx).flags) + b.hiddenAPIIndexCSV = relToHiddenapiDir(hiddenAPISingletonPaths(ctx).index) + b.hiddenAPIMetadataCSV = relToHiddenapiDir(hiddenAPISingletonPaths(ctx).metadata) + moduleSpecificFlagsPaths := android.Paths{} for _, module := range modules { if h, ok := module.(hiddenAPIIntf); ok { diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go index ebbe3a5ee..a0d05016a 100644 --- a/java/platform_bootclasspath_test.go +++ b/java/platform_bootclasspath_test.go @@ -131,3 +131,44 @@ func TestPlatformBootclasspath(t *testing.T) { }) }) } + +func TestPlatformBootclasspath_Dist(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithPlatformBootclasspath, + dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar"), + android.PrepareForTestWithAndroidMk, + android.FixtureWithRootAndroidBp(` + platform_bootclasspath { + name: "platform-bootclasspath", + dists: [ + { + targets: ["droidcore"], + tag: "hiddenapi-flags.csv", + }, + ], + } + + java_library { + name: "bar", + srcs: ["a.java"], + system_modules: "none", + sdk_version: "none", + compile_dex: true, + } + + java_library { + name: "foo", + srcs: ["a.java"], + system_modules: "none", + sdk_version: "none", + compile_dex: true, + } + `), + ).RunTest(t) + + platformBootclasspath := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) + entries := android.AndroidMkEntriesForTest(t, result.TestContext, platformBootclasspath) + goals := entries[0].GetDistForGoals(platformBootclasspath) + android.AssertStringEquals(t, "platform dist goals phony", ".PHONY: droidcore\n", goals[0]) + android.AssertStringEquals(t, "platform dist goals call", "$(call dist-for-goals,droidcore,out/soong/hiddenapi/hiddenapi-flags.csv:hiddenapi-flags.csv)\n", android.StringRelativeToTop(result.Config, goals[1])) +}