summaryrefslogtreecommitdiff
path: root/java/hiddenapi.go
diff options
context:
space:
mode:
Diffstat (limited to 'java/hiddenapi.go')
-rw-r--r--java/hiddenapi.go170
1 files changed, 130 insertions, 40 deletions
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index eafbf5df0..1651c1c6d 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -28,10 +28,39 @@ 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), 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 <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
+
+ // 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.
+ annotationsOnly 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
// themselves.
+ //
+ // This must be the path to the unencoded dex jar as the encoded dex jar indirectly depends on
+ // this file so using the encoded dex jar here would result in a cycle in the ninja rules.
bootDexJarPath android.Path
// The path to the CSV file that contains mappings from Java signature to various flags derived
@@ -89,52 +118,109 @@ type hiddenAPIIntf interface {
var _ hiddenAPIIntf = (*hiddenAPI)(nil)
-func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, name string, primary bool, dexJar android.OutputPath,
- implementationJar android.Path, uncompressDex bool) android.OutputPath {
- if !ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
-
- // Modules whose names are of the format <x>-hiddenapi provide hiddenapi information
- // for the boot jar module <x>. Otherwise, the module provides information for itself.
- // Either way extract the name of the boot jar module.
- bootJarName := strings.TrimSuffix(name, "-hiddenapi")
-
- // If this module is on the boot jars list (or providing information for a module
- // on the list) then extract the hiddenapi information from it, and if necessary
- // encode that information in the generated dex file.
- //
- // It is important that hiddenapi information is only gathered for/from modules on
- // 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 CtsHiddenApiBlacklist...
- // tests.
- if inList(bootJarName, ctx.Config().BootJars()) {
- // Create ninja rules to generate various CSV files needed by hiddenapi and store the paths
- // in the hiddenAPI structure.
- h.hiddenAPIGenerateCSV(ctx, implementationJar)
-
- // If this module is actually on the boot jars list and not providing
- // hiddenapi information for a module on the boot jars list then encode
- // the gathered information in the generated dex file.
- if name == bootJarName {
- hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", name+".jar").OutputPath
-
- // More than one library with the same classes can be encoded but only one can
- // be added to the global set of flags, otherwise it will result in duplicate
- // classes which is an error. Therefore, only add the dex jar of one of them
- // to the global set of flags.
- if primary {
- h.bootDexJarPath = dexJar
- }
- hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
- dexJar = hiddenAPIJar
- }
+// Initialize the hiddenapi structure
+func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, name string) {
+ // If hiddenapi processing is disabled treat this as inactive.
+ if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ return
+ }
+
+ // Modules whose names are of the format <x>-hiddenapi provide hiddenapi information for the boot
+ // jar module <x>. Otherwise, the module provides information for itself. Either way extract the
+ // 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(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 <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 = 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
+// processing.
+//
+// It ignores any module that has not had initHiddenApi() called on it and which is not in the boot
+// jar list.
+//
+// Otherwise, it generates ninja rules to do the following:
+// 1. Extract information needed for hiddenapi processing from the module and output it into CSV
+// files.
+// 2. Conditionally adds the supplied dex file to the list of files used to generate the
+// hiddenAPISingletonPathsStruct.stubsFlag file.
+// 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, dexJar android.OutputPath,
+ implementationJar android.Path, uncompressDex bool) android.OutputPath {
+
+ if !h.active {
+ return dexJar
+ }
+
+ h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar)
+
+ if !h.annotationsOnly {
+ 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)
+
+ // Use the encoded dex jar from here onwards.
+ dexJar = hiddenAPIJar
}
return dexJar
}
-func (h *hiddenAPI) hiddenAPIGenerateCSV(ctx android.ModuleContext, classesJar android.Path) {
+// hiddenAPIExtractInformation 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) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJar, classesJar android.Path) {
+ if !h.active {
+ return
+ }
+
+ // 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 !h.primary {
+ return
+ }
+
stubFlagsCSV := hiddenAPISingletonPaths(ctx).stubFlags
flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv")
@@ -173,6 +259,10 @@ func (h *hiddenAPI) hiddenAPIGenerateCSV(ctx android.ModuleContext, classesJar a
FlagWithOutput("--output=", indexCSV)
rule.Build("merged-hiddenapi-index", "Merged Hidden API index")
h.indexCSVPath = indexCSV
+
+ // Save the unencoded dex jar so it can be used when generating the
+ // hiddenAPISingletonPathsStruct.stubFlags file.
+ h.bootDexJarPath = dexJar
}
var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", blueprint.RuleParams{