summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/base.go21
-rw-r--r--java/bootclasspath_fragment.go56
-rw-r--r--java/hiddenapi.go126
-rw-r--r--java/hiddenapi_singleton_test.go53
-rw-r--r--java/java.go18
-rw-r--r--java/sdk_library.go17
6 files changed, 153 insertions, 138 deletions
diff --git a/java/base.go b/java/base.go
index 03652be05..c828503d4 100644
--- a/java/base.go
+++ b/java/base.go
@@ -229,12 +229,6 @@ type DeviceProperties struct {
// otherwise provides defaults libraries to add to the bootclasspath.
System_modules *string
- // The name of the module as used in build configuration.
- //
- // Allows a library to separate its actual name from the name used in
- // build configuration, e.g.ctx.Config().BootJars().
- ConfigurationName *string `blueprint:"mutated"`
-
// set the name of the output
Stem *string
@@ -1223,11 +1217,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
return
}
- // Update hidden API paths.
- j.hiddenAPIUpdatePaths(ctx, dexOutputFile, j.implementationJarFile)
+ // Initialize the hiddenapi structure.
+ j.initHiddenAPI(ctx, dexOutputFile, j.implementationJarFile, j.dexProperties.Uncompress_dex)
// Encode hidden API flags in dex file.
- dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile, proptools.Bool(j.dexProperties.Uncompress_dex))
+ dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
// merge dex jar with resources if necessary
if j.resourceJar != nil {
@@ -1501,15 +1495,6 @@ func (j *Module) Stem() string {
return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
}
-// ConfigurationName returns the name of the module as used in build configuration.
-//
-// This is usually the same as BaseModuleName() except for the <x>.impl libraries created by
-// java_sdk_library in which case this is the BaseModuleName() without the ".impl" suffix,
-// i.e. just <x>.
-func (j *Module) ConfigurationName() string {
- return proptools.StringDefault(j.deviceProperties.ConfigurationName, j.BaseModuleName())
-}
-
func (j *Module) JacocoReportClassesFile() android.Path {
return j.jacocoReportClassesFile
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 16aa5e2ea..b6b877b6f 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -112,6 +112,11 @@ type bootclasspathFragmentProperties struct {
Coverage BootclasspathFragmentCoverageAffectedProperties
Hidden_api HiddenAPIFlagFileProperties
+
+ // Properties that allow a fragment to depend on other fragments. This is needed for hidden API
+ // processing as it needs access to all the classes used by a fragment including those provided
+ // by other fragments.
+ BootclasspathFragmentsDepsProperties
}
type BootclasspathFragmentModule struct {
@@ -448,12 +453,54 @@ func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleCont
return imageConfig
}
+// canPerformHiddenAPIProcessing determines whether hidden API processing should be performed.
+//
+// A temporary workaround to avoid existing bootclasspath_fragments that do not provide the
+// appropriate information needed for hidden API processing breaking the build.
+// TODO(b/179354495): Remove this workaround.
+func (b *BootclasspathFragmentModule) canPerformHiddenAPIProcessing(ctx android.ModuleContext) bool {
+ // Hidden API processing is always enabled in tests.
+ if ctx.Config().TestProductVariables != nil {
+ return true
+ }
+ // A module that has fragments should have access to the information it needs in order to perform
+ // hidden API processing.
+ if len(b.properties.Fragments) != 0 {
+ return true
+ }
+
+ // The art bootclasspath fragment does not depend on any other fragments but already supports
+ // hidden API processing.
+ imageName := proptools.String(b.properties.Image_name)
+ if imageName == "art" {
+ return true
+ }
+
+ // Disable it for everything else.
+ return false
+}
+
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module) {
+ // A temporary workaround to avoid existing bootclasspath_fragments that do not provide the
+ // appropriate information needed for hidden API processing breaking the build.
+ if !b.canPerformHiddenAPIProcessing(ctx) {
+ // Nothing to do.
+ return
+ }
+
// Convert the kind specific lists of modules into kind specific lists of jars.
stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx, contents)
+ // Performing hidden API processing without stubs is not supported and it is unlikely to ever be
+ // required as the whole point of adding something to the bootclasspath fragment is to add it to
+ // the bootclasspath in order to be used by something else in the system. Without any stubs it
+ // cannot do that.
+ if len(stubJarsByKind) == 0 {
+ return
+ }
+
// Store the information for use by other modules.
bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: stubJarsByKind}
ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo)
@@ -474,15 +521,6 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.
// produceHiddenAPIAllFlagsFile produces the hidden API all-flags.csv file (and supporting files)
// for the fragment.
func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) {
- // If no stubs have been provided then don't perform hidden API processing. This is a temporary
- // workaround to avoid existing bootclasspath_fragments that do not provide stubs breaking the
- // build.
- // TODO(b/179354495): Remove this workaround.
- if len(stubJarsByKind) == 0 {
- // Nothing to do.
- return
- }
-
// Generate the rules to create the hidden API flags and update the supplied flagFileInfo with the
// paths to the created files.
hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, stubJarsByKind, flagFileInfo)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 829c47383..1e838247b 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -26,27 +26,10 @@ var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", bl
}, "outFlag", "stubAPIFlags")
type hiddenAPI struct {
- // 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) 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 <x>-hiddenapi that provide additional annotation information for module <x>
- // that is on the bootclasspath are marked as primary=true as they are the primary source of that
- // annotation information.
- primary bool
-
// The path to the dex jar that is in the boot class path. If this is nil then the associated
// module is not a boot jar, but could be one of the <x>-hiddenapi modules that provide additional
// annotations for the <x> boot dex jar but which do not actually provide a boot dex jar
@@ -60,6 +43,10 @@ type hiddenAPI struct {
// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
// processing.
classesJarPaths android.Paths
+
+ // The compressed state of the dex file being encoded. This is used to ensure that the encoded
+ // dex file has the same state.
+ uncompressDexState *bool
}
func (h *hiddenAPI) bootDexJar() android.Path {
@@ -70,6 +57,10 @@ func (h *hiddenAPI) classesJars() android.Paths {
return h.classesJarPaths
}
+func (h *hiddenAPI) uncompressDex() *bool {
+ return h.uncompressDexState
+}
+
// hiddenAPIModule is the interface a module that embeds the hiddenAPI structure must implement.
type hiddenAPIModule interface {
android.Module
@@ -79,18 +70,39 @@ type hiddenAPIModule interface {
type hiddenAPIIntf interface {
bootDexJar() android.Path
classesJars() android.Paths
+ uncompressDex() *bool
}
var _ hiddenAPIIntf = (*hiddenAPI)(nil)
// Initialize the hiddenapi structure
-func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, configurationName string) {
+//
+// uncompressedDexState should be nil when the module is a prebuilt and so does not require hidden
+// API encoding.
+func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar, classesJar android.Path, uncompressedDexState *bool) {
+
+ // Save the classes jars even if this is not active as they may be used by modular hidden API
+ // processing.
+ classesJars := android.Paths{classesJar}
+ ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
+ javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ classesJars = append(classesJars, javaInfo.ImplementationJars...)
+ })
+ h.classesJarPaths = classesJars
+
+ // Save the unencoded dex jar so it can be used when generating the
+ // hiddenAPISingletonPathsStruct.stubFlags file.
+ h.bootDexJarPath = dexJar
+
+ h.uncompressDexState = uncompressedDexState
+
// If hiddenapi processing is disabled treat this as inactive.
if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
return
}
- h.configurationName = configurationName
+ // The context module must implement hiddenAPIModule.
+ module := ctx.Module().(hiddenAPIModule)
// If the frameworks/base directories does not exist and no prebuilt hidden API flag files have
// been configured then it is not possible to do hidden API encoding.
@@ -102,52 +114,7 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, configurationNa
// 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.
- module := ctx.Module()
h.active = isModuleInBootClassPath(ctx, module)
- if !h.active {
- // The rest of the properties will be ignored if active is false.
- return
- }
-
- // 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.
- 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 configurationName to its module name to this
- // method is the implementation library of a java_sdk_library. It has a configuration name of
- // <x> the same as its parent java_sdk_library but a module name of <x>.impl. It is not the
- // primary module, the java_sdk_library with the name of <x> is.
- primary = configurationName == ctx.ModuleName()
-
- // A source module that has been replaced by a prebuilt can never be the primary module.
- if module.IsReplacedByPrebuilt() {
- if ctx.HasProvider(android.ApexInfoProvider) {
- // The source module is in an APEX but the prebuilt module on which it depends is not in an
- // APEX and so is not the one that will actually be used for hidden API processing. That
- // means it is not possible to check to see if it is a suitable replacement so just assume
- // that it is.
- primary = false
- } else {
- ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(prebuilt android.Module) {
- if h, ok := prebuilt.(hiddenAPIIntf); ok && h.bootDexJar() != nil {
- primary = false
- } else {
- ctx.ModuleErrorf(
- "hiddenapi has determined that the source module %q should be ignored as it has been"+
- " replaced by the prebuilt module %q but unfortunately it does not provide a"+
- " suitable boot dex jar", ctx.ModuleName(), ctx.OtherModuleName(prebuilt))
- }
- })
- }
- }
- }
- h.primary = primary
}
func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool {
@@ -166,13 +133,19 @@ func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Modul
//
// Otherwise, it 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.
-func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android.OutputPath, uncompressDex bool) android.OutputPath {
+func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android.OutputPath) android.OutputPath {
if !h.active {
return dexJar
}
- hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
+ // A nil uncompressDexState prevents the dex file from being encoded.
+ if h.uncompressDexState == nil {
+ ctx.ModuleErrorf("cannot encode dex file %s when uncompressDexState is nil", dexJar)
+ }
+ uncompressDex := *h.uncompressDexState
+
+ hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", dexJar.Base()).OutputPath
// Create a copy of the dex jar which has been encoded with hiddenapi flags.
hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
@@ -183,27 +156,6 @@ func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android
return dexJar
}
-// hiddenAPIUpdatePaths generates ninja rules to extract the information from the classes
-// jar, and outputs it to the appropriate module specific CSV file.
-//
-// It also makes the dex jar available for use when generating the
-// hiddenAPISingletonPathsStruct.stubFlags.
-func (h *hiddenAPI) hiddenAPIUpdatePaths(ctx android.ModuleContext, dexJar, classesJar android.Path) {
-
- // Save the classes jars even if this is not active as they may be used by modular hidden API
- // processing.
- classesJars := android.Paths{classesJar}
- ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
- javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
- classesJars = append(classesJars, javaInfo.ImplementationJars...)
- })
- h.classesJarPaths = classesJars
-
- // Save the unencoded dex jar so it can be used when generating the
- // hiddenAPISingletonPathsStruct.stubFlags file.
- h.bootDexJarPath = dexJar
-}
-
// buildRuleToGenerateAnnotationFlags builds a ninja rule to generate the annotation-flags.csv file
// from the classes jars and stub-flags.csv files.
//
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index e6b45ac20..dcd363c2c 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -274,3 +274,56 @@ func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) {
android.AssertStringEquals(t, "hiddenapi encode dex rule flags csv", expectedFlagsCsv, actualFlagsCsv)
}
+
+func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) {
+
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
+ FixtureConfigureBootJars("platform:foo"),
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+
+ // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+ // is disabled.
+ android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ shared_library: false,
+ compile_dex: true,
+ public: {enabled: true},
+ }
+ `)
+
+ checkDexEncoded := func(t *testing.T, name, unencodedDexJar, encodedDexJar string) {
+ moduleForTests := result.ModuleForTests(name, "android_common")
+
+ encodeDexRule := moduleForTests.Rule("hiddenAPIEncodeDex")
+ actualUnencodedDexJar := encodeDexRule.Input
+
+ // Make sure that the module has its dex jar encoded.
+ android.AssertStringEquals(t, "encode embedded java_library", unencodedDexJar, actualUnencodedDexJar.String())
+
+ // Make sure that the encoded dex jar is the exported one.
+ exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath()
+ android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar)
+ }
+
+ // The java_library embedded with the java_sdk_library must be dex encoded.
+ t.Run("foo", func(t *testing.T) {
+ expectedUnencodedDexJar := "out/soong/.intermediates/foo/android_common/aligned/foo.jar"
+ expectedEncodedDexJar := "out/soong/.intermediates/foo/android_common/hiddenapi/foo.jar"
+ checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar)
+ })
+
+ // The dex jar of the child implementation java_library of the java_sdk_library is not currently
+ // dex encoded.
+ t.Run("foo.impl", func(t *testing.T) {
+ fooImpl := result.ModuleForTests("foo.impl", "android_common")
+ encodeDexRule := fooImpl.MaybeRule("hiddenAPIEncodeDex")
+ if encodeDexRule.Rule != nil {
+ t.Errorf("foo.impl is not expected to be encoded")
+ }
+ })
+}
diff --git a/java/java.go b/java/java.go
index f85de3d77..45eb69339 100644
--- a/java/java.go
+++ b/java/java.go
@@ -481,11 +481,6 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo
}
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // Initialize the hiddenapi structure. Pass in the configuration name rather than the module name
- // so the hidden api will encode the <x>.impl java_ library created by java_sdk_library just as it
- // would the <x> library if <x> was configured as a boot jar.
- j.initHiddenAPI(ctx, j.ConfigurationName())
-
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
@@ -1241,9 +1236,6 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
- // Initialize the hiddenapi structure.
- j.initHiddenAPI(ctx, j.BaseModuleName())
-
if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
j.hideApexVariantFromMake = true
}
@@ -1315,7 +1307,9 @@ 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.hiddenAPIUpdatePaths(ctx, dexOutputPath, outputFile)
+
+ // Initialize the hiddenapi structure.
+ j.initHiddenAPI(ctx, dexOutputPath, outputFile, nil)
} 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.
@@ -1346,11 +1340,11 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return
}
- // Update hidden API paths.
- j.hiddenAPIUpdatePaths(ctx, dexOutputFile, outputFile)
+ // Initialize the hiddenapi structure.
+ j.initHiddenAPI(ctx, dexOutputFile, outputFile, j.dexProperties.Uncompress_dex)
// Encode hidden API flags in dex file.
- dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile, proptools.Bool(j.dexProperties.Uncompress_dex))
+ dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
j.dexJarFile = dexOutputFile
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index f04f837cc..99eacf4e7 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1235,16 +1235,13 @@ func childModuleVisibility(childVisibility []string) []string {
// Creates the implementation java library
func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
- moduleNamePtr := proptools.StringPtr(module.BaseModuleName())
-
visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)
props := struct {
- Name *string
- Visibility []string
- Instrument bool
- Libs []string
- ConfigurationName *string
+ Name *string
+ Visibility []string
+ Instrument bool
+ Libs []string
}{
Name: proptools.StringPtr(module.implLibraryModuleName()),
Visibility: visibility,
@@ -1253,9 +1250,6 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext)
// Set the impl_only libs. Note that the module's "Libs" get appended as well, via the
// addition of &module.properties below.
Libs: module.sdkLibraryProperties.Impl_only_libs,
-
- // Make the created library behave as if it had the same name as this module.
- ConfigurationName: moduleNamePtr,
}
properties := []interface{}{
@@ -2127,8 +2121,7 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
if dexOutputPath := di.PrebuiltExportPath(module.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
module.dexJarFile = dexOutputPath
- module.initHiddenAPI(ctx, module.configurationName)
- module.hiddenAPIUpdatePaths(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0])
+ module.initHiddenAPI(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
} 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.