From bae4749de28b89a5702ed8cdeda1a390ad112e50 Mon Sep 17 00:00:00 2001 From: Bill Peckham Date: Fri, 8 Jan 2021 09:34:44 -0800 Subject: [PATCH] Enable prebuilt hiddenapi CSV files. By enabling these hiddenapi CSV files to be prebuilt, it becomes possible to create a split build that supports the hiddenapi encode dex step, but doesn't contain all of the java sources needed to generate the CSV files. Bug: 175048716 Test: m nothing Test: new TestHiddenAPISingletonWithPrebuiltCsvFile Test: local build without prebuilt hiddenapi Test: local build with prebuilt hiddenapi Change-Id: I805ea3ec05860d2df211a3985ec025bf36f0d775 --- android/config.go | 4 +++ android/variable.go | 2 ++ java/hiddenapi_singleton.go | 40 +++++++++++++++++++++ java/hiddenapi_singleton_test.go | 60 ++++++++++++++++++++++++++++---- 4 files changed, 99 insertions(+), 7 deletions(-) diff --git a/android/config.go b/android/config.go index a7e0b6711..ee86d17a4 100644 --- a/android/config.go +++ b/android/config.go @@ -1026,6 +1026,10 @@ func (c *config) HasMultilibConflict(arch ArchType) bool { return c.multilibConflicts[arch] } +func (c *config) PrebuiltHiddenApiDir(ctx PathContext) string { + return String(c.productVariables.PrebuiltHiddenApiDir) +} + func (c *deviceConfig) Arches() []Arch { var arches []Arch for _, target := range c.config.Targets[Android] { diff --git a/android/variable.go b/android/variable.go index 41cd3371e..6d8cd35d9 100644 --- a/android/variable.go +++ b/android/variable.go @@ -364,6 +364,8 @@ type productVariables struct { BoardKernelModuleInterfaceVersions []string `json:",omitempty"` BoardMoveRecoveryResourcesToVendorBoot *bool `json:",omitempty"` + + PrebuiltHiddenApiDir *string `json:",omitempty"` } func boolPtr(v bool) *bool { diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index d3025247b..4bd255cbf 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -67,6 +67,19 @@ func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) 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 + // build (framework and vendor) scenario, for the vendor build to use + // prebuilt hiddenapi files from the framework build. In this scenario, + // the framework and vendor builds must use the same source to ensure + // consistency. + + if ctx.Config().PrebuiltHiddenApiDir(ctx) != "" { + h.flags = prebuiltFlagsRule(ctx) + return + } + // These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them. if ctx.Config().FrameworksBaseDirExists(ctx) { h.flags = flagsRule(ctx) @@ -212,6 +225,19 @@ func stubFlagsRule(ctx android.SingletonContext) { rule.Build("hiddenAPIStubFlagsFile", "hiddenapi stub flags") } +func prebuiltFlagsRule(ctx android.SingletonContext) android.Path { + outputPath := hiddenAPISingletonPaths(ctx).flags + inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-flags.csv") + + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Output: outputPath, + Input: inputPath, + }) + + return outputPath +} + // flagsRule creates a rule to build hiddenapi-flags.csv out of flags.csv files generated for boot image modules and // the unsupported API. func flagsRule(ctx android.SingletonContext) android.Path { @@ -391,6 +417,20 @@ func (h *hiddenAPIIndexSingleton) GenerateBuildActions(ctx android.SingletonCont return } + if ctx.Config().PrebuiltHiddenApiDir(ctx) != "" { + outputPath := hiddenAPISingletonPaths(ctx).index + inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-index.csv") + + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Output: outputPath, + Input: inputPath, + }) + + h.index = outputPath + return + } + indexes := android.Paths{} ctx.VisitAllModules(func(module android.Module) { if h, ok := module.(hiddenAPIIntf); ok { diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index 955c73932..0f9ef5841 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -23,9 +23,10 @@ import ( "github.com/google/blueprint/proptools" ) -func testConfigWithBootJars(bp string, bootJars []string) android.Config { +func testConfigWithBootJars(bp string, bootJars []string, prebuiltHiddenApiDir *string) android.Config { config := testConfig(nil, bp, nil) config.TestProductVariables.BootJars = android.CreateTestConfiguredJarList(bootJars) + config.TestProductVariables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir return config } @@ -44,8 +45,8 @@ func testHiddenAPIWithConfig(t *testing.T, config android.Config) *android.TestC return ctx } -func testHiddenAPIBootJars(t *testing.T, bp string, bootJars []string) (*android.TestContext, android.Config) { - config := testConfigWithBootJars(bp, bootJars) +func testHiddenAPIBootJars(t *testing.T, bp string, bootJars []string, prebuiltHiddenApiDir *string) (*android.TestContext, android.Config) { + config := testConfigWithBootJars(bp, bootJars, prebuiltHiddenApiDir) return testHiddenAPIWithConfig(t, config), config } @@ -64,7 +65,7 @@ func TestHiddenAPISingleton(t *testing.T) { srcs: ["a.java"], compile_dex: true, } - `, []string{":foo"}) + `, []string{":foo"}, nil) hiddenAPI := ctx.SingletonForTests("hiddenapi") hiddenapiRule := hiddenAPI.Rule("hiddenapi") @@ -81,7 +82,7 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { jars: ["a.jar"], compile_dex: true, } - `, []string{":foo"}) + `, []string{":foo"}, nil) hiddenAPI := ctx.SingletonForTests("hiddenapi") hiddenapiRule := hiddenAPI.Rule("hiddenapi") @@ -105,7 +106,7 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { compile_dex: true, prefer: false, } - `, []string{":foo"}) + `, []string{":foo"}, nil) hiddenAPI := ctx.SingletonForTests("hiddenapi") hiddenapiRule := hiddenAPI.Rule("hiddenapi") @@ -134,7 +135,7 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { compile_dex: true, prefer: true, } - `, []string{":foo"}) + `, []string{":foo"}, nil) hiddenAPI := ctx.SingletonForTests("hiddenapi") hiddenapiRule := hiddenAPI.Rule("hiddenapi") @@ -217,3 +218,48 @@ func generateSdkDexPath(module string, unbundled bool) string { } return generateDexPath(module) } + +func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) { + + // The idea behind this test is to ensure that when the build is + // confugured with a PrebuiltHiddenApiDir that the rules for the + // hiddenapi singleton copy the prebuilts to the typical output + // location, and then use that output location for the hiddenapi encode + // dex step. + + // Where to find the prebuilt hiddenapi files: + prebuiltHiddenApiDir := "path/to/prebuilt/hiddenapi" + + ctx, _ := testHiddenAPIBootJars(t, ` + java_import { + name: "foo", + jars: ["a.jar"], + compile_dex: true, + } + `, []string{":foo"}, &prebuiltHiddenApiDir) + + expectedCpInput := prebuiltHiddenApiDir + "/hiddenapi-flags.csv" + expectedCpOutput := buildDir + "/hiddenapi/hiddenapi-flags.csv" + expectedFlagsCsv := buildDir + "/hiddenapi/hiddenapi-flags.csv" + + foo := ctx.ModuleForTests("foo", "android_common") + + hiddenAPI := ctx.SingletonForTests("hiddenapi") + cpRule := hiddenAPI.Rule("Cp") + actualCpInput := cpRule.BuildParams.Input + actualCpOutput := cpRule.BuildParams.Output + encodeDexRule := foo.Rule("hiddenAPIEncodeDex") + actualFlagsCsv := encodeDexRule.BuildParams.Args["flagsCsv"] + + if actualCpInput.String() != expectedCpInput { + t.Errorf("Prebuilt hiddenapi cp rule input mismatch, actual: %s, expected: %s", actualCpInput, expectedCpInput) + } + + if actualCpOutput.String() != expectedCpOutput { + t.Errorf("Prebuilt hiddenapi cp rule output mismatch, actual: %s, expected: %s", actualCpOutput, expectedCpOutput) + } + + if actualFlagsCsv != expectedFlagsCsv { + t.Errorf("Prebuilt hiddenapi encode dex rule flags csv mismatch, actual: %s, expected: %s", actualFlagsCsv, expectedFlagsCsv) + } +}