From e7975ff77c662f4f25dfa60b2d11fde43ce22540 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Thu, 11 Feb 2021 15:33:37 +0000 Subject: [PATCH 1/2] Ensure that -hiddenapi modules are included in hiddenapi-index.csv Adds a test that makes sure that -hiddenapi modules that provide additional annotations for the boot jar module are included when generating the hiddenapi-index.csv file. Bug: 178361284 Test: m nothing Change-Id: I866916c9275af17954e0634347d183228d4ddc17 --- java/hiddenapi_singleton_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index 77cfff45c..df825bb3a 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -84,6 +84,12 @@ func TestHiddenAPIIndexSingleton(t *testing.T) { compile_dex: true, } + java_library { + name: "foo-hiddenapi", + srcs: ["a.java"], + compile_dex: true, + } + java_import { name: "foo", jars: ["a.jar"], @@ -102,6 +108,7 @@ func TestHiddenAPIIndexSingleton(t *testing.T) { indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index") CheckHiddenAPIRuleInputs(t, ` .intermediates/bar/android_common/hiddenapi/index.csv +.intermediates/foo-hiddenapi/android_common/hiddenapi/index.csv .intermediates/foo/android_common/hiddenapi/index.csv `, indexRule) From f75e527c2b65bf94252188f5d032eadae68a8492 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Tue, 9 Feb 2021 14:34:25 +0000 Subject: [PATCH 2/2] Move logic for selecting the primary module into initHiddenAPI() Bug: 178361284 Test: m droid Verified that hiddenapi files (both aggregated ones and for the individual modules) are not affected by this change. Also verified that the hiddenapi files created when using the prebuilts (using SOONG_CONFIG_art_module_source_build=false) are the same as when using the source. There is a slight difference in the order but otherwise identical. Change-Id: I831da5fa41eb7668b07bbdc4dd08ec2cdb8803d0 --- java/hiddenapi.go | 63 ++++++++++++++++++++++++++++++++++++++++------- java/java.go | 15 +++-------- 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/java/hiddenapi.go b/java/hiddenapi.go index 069595eb9..1651c1c6d 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -28,9 +28,27 @@ var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", bl }, "outFlag", "stubAPIFlags") type hiddenAPI struct { - // True if the module containing this structure contributes to the hiddenapi information. + // The name of the module as it would be used in the boot jars configuration, e.g. without any + // prebuilt_ prefix (if it is a prebuilt), without any "-hiddenapi" suffix if it just provides + // annotations and without any ".impl" suffix if it is a java_sdk_library implementation library. + configurationName string + + // True if the module containing this structure contributes to the hiddenapi information or has + // that information encoded within it. active bool + // Identifies the active module variant which will be used as the source of hiddenapi information. + // + // A class may be compiled into a number of different module variants each of which will need the + // hiddenapi information encoded into it and so will be marked as active. However, only one of + // them must be used as a source of information by hiddenapi otherwise it will end up with + // duplicate entries. That module will have primary=true. + // + // Note, that modules -hiddenapi that provide additional annotation information for module + // that is on the bootclasspath are marked as primary=true as they are the primary source of that + // annotation information. + primary bool + // True if the module only contains additional annotations and so does not require hiddenapi // information to be encoded in its dex file and should not be used to generate the // hiddenAPISingletonPathsStruct.stubFlags file. @@ -109,18 +127,45 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, name string) { // Modules whose names are of the format -hiddenapi provide hiddenapi information for the boot // jar module . Otherwise, the module provides information for itself. Either way extract the - // name of the boot jar module. - bootJarName := strings.TrimSuffix(name, "-hiddenapi") + // configurationName of the boot jar module. + configurationName := strings.TrimSuffix(name, "-hiddenapi") + h.configurationName = configurationName // It is important that hiddenapi information is only gathered for/from modules that are actually // on the boot jars list because the runtime only enforces access to the hidden API for the // bootclassloader. If information is gathered for modules not on the list then that will cause // failures in the CtsHiddenApiBlocklist... tests. - h.active = inList(bootJarName, ctx.Config().BootJars()) + h.active = inList(configurationName, ctx.Config().BootJars()) + if !h.active { + // The rest of the properties will be ignored if active is false. + return + } // If this module has a suffix of -hiddenapi then it only provides additional annotation // information for a module on the boot jars list. h.annotationsOnly = strings.HasSuffix(name, "-hiddenapi") + + // Determine whether this module is the primary module or not. + primary := true + + // A prebuilt module is only primary if it is preferred and conversely a source module is only + // primary if it has not been replaced by a prebuilt module. + module := ctx.Module() + if pi, ok := module.(android.PrebuiltInterface); ok { + if p := pi.Prebuilt(); p != nil { + primary = p.UsePrebuilt() + } + } else { + // The only module that will pass a different name to its module name to this method is the + // implementation library of a java_sdk_library. It has a configuration name of the same + // as its parent java_sdk_library but a module name of .impl. It is not the primary module, + // the java_sdk_library with the name of is. + primary = name == ctx.ModuleName() + + // A source module that has been replaced by a prebuilt can never be the primary module. + primary = primary && !module.IsReplacedByPrebuilt() + } + h.primary = primary } // hiddenAPIExtractAndEncode is called by any module that could contribute to the hiddenapi @@ -137,17 +182,17 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, name string) { // 3. Conditionally creates a copy of the supplied dex file into which it has encoded the hiddenapi // flags and returns this instead of the supplied dex jar, otherwise simply returns the supplied // dex jar. -func (h *hiddenAPI) hiddenAPIExtractAndEncode(ctx android.ModuleContext, name string, primary bool, dexJar android.OutputPath, +func (h *hiddenAPI) hiddenAPIExtractAndEncode(ctx android.ModuleContext, dexJar android.OutputPath, implementationJar android.Path, uncompressDex bool) android.OutputPath { if !h.active { return dexJar } - h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar, primary) + h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar) if !h.annotationsOnly { - hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", name+".jar").OutputPath + hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath // Create a copy of the dex jar which has been encoded with hiddenapi flags. hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex) @@ -164,7 +209,7 @@ func (h *hiddenAPI) hiddenAPIExtractAndEncode(ctx android.ModuleContext, name st // // It also makes the dex jar available for use when generating the // hiddenAPISingletonPathsStruct.stubFlags. -func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJar, classesJar android.Path, primary bool) { +func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJar, classesJar android.Path) { if !h.active { return } @@ -172,7 +217,7 @@ func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJa // More than one library with the same classes may need to be encoded but only one should be // used as a source of information for hidden API processing otherwise it will result in // duplicate entries in the files. - if !primary { + if !h.primary { return } diff --git a/java/java.go b/java/java.go index 8cf4ee5bb..4c6009b43 100644 --- a/java/java.go +++ b/java/java.go @@ -1798,14 +1798,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { return } - configurationName := j.ConfigurationName() - primary := configurationName == ctx.ModuleName() - // If the prebuilt is being used rather than the from source, skip this - // module to prevent duplicated classes - primary = primary && !j.IsReplacedByPrebuilt() - // Hidden API CSV generation and dex encoding - dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, configurationName, primary, dexOutputFile, j.implementationJarFile, + dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile, proptools.Bool(j.dexProperties.Uncompress_dex)) // merge dex jar with resources if necessary @@ -2917,9 +2911,6 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs) if ctx.Device() { - configurationName := j.BaseModuleName() - primary := j.Prebuilt().UsePrebuilt() - // If this is a variant created for a prebuilt_apex then use the dex implementation jar // obtained from the associated deapexer module. ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) @@ -2935,7 +2926,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo) if dexOutputPath := di.PrebuiltExportPath(j.BaseModuleName(), ".dexjar"); dexOutputPath != nil { j.dexJarFile = dexOutputPath - j.hiddenAPI.hiddenAPIExtractInformation(ctx, dexOutputPath, outputFile, primary) + j.hiddenAPIExtractInformation(ctx, dexOutputPath, outputFile) } else { // This should never happen as a variant for a prebuilt_apex is only created if the // prebuilt_apex has been configured to export the java library dex file. @@ -2967,7 +2958,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } // Hidden API CSV generation and dex encoding - dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, configurationName, primary, dexOutputFile, outputFile, + dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, outputFile, proptools.Bool(j.dexProperties.Uncompress_dex)) j.dexJarFile = dexOutputFile