2021-04-08 18:49:27 +02:00
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package java
import (
2021-05-13 18:31:51 +02:00
"strings"
2021-04-08 18:49:27 +02:00
"android/soong/android"
2021-04-09 00:01:37 +02:00
"github.com/google/blueprint"
2021-04-08 18:49:27 +02:00
)
// Contains support for processing hiddenAPI in a modular fashion.
2021-04-21 15:10:42 +02:00
type hiddenAPIStubsDependencyTag struct {
blueprint . BaseDependencyTag
sdkKind android . SdkKind
}
func ( b hiddenAPIStubsDependencyTag ) ExcludeFromApexContents ( ) {
}
func ( b hiddenAPIStubsDependencyTag ) ReplaceSourceWithPrebuilt ( ) bool {
return false
}
2021-04-28 00:20:26 +02:00
func ( b hiddenAPIStubsDependencyTag ) SdkMemberType ( child android . Module ) android . SdkMemberType {
// If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
// property, otherwise treat if it was specified in the java_header_libs property.
if javaSdkLibrarySdkMemberType . IsInstance ( child ) {
return javaSdkLibrarySdkMemberType
}
return javaHeaderLibsSdkMemberType
}
func ( b hiddenAPIStubsDependencyTag ) ExportMember ( ) bool {
// Export the module added via this dependency tag from the sdk.
return true
}
2021-04-21 15:10:42 +02:00
// Avoid having to make stubs content explicitly visible to dependent modules.
//
// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
// with proper dependencies.
// TODO(b/177892522): Remove this and add needed visibility.
func ( b hiddenAPIStubsDependencyTag ) ExcludeFromVisibilityEnforcement ( ) {
}
var _ android . ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag { }
var _ android . ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag { }
var _ android . ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag { }
2021-04-28 00:20:26 +02:00
var _ android . SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag { }
2021-04-21 15:10:42 +02:00
2021-04-15 14:31:38 +02:00
// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
// API processing.
var hiddenAPIRelevantSdkKinds = [ ] android . SdkKind {
android . SdkPublic ,
android . SdkSystem ,
android . SdkTest ,
android . SdkCorePlatform ,
}
2021-04-21 15:10:42 +02:00
// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
// needed to produce the hidden API monolithic stub flags file.
func hiddenAPIComputeMonolithicStubLibModules ( config android . Config ) map [ android . SdkKind ] [ ] string {
var publicStubModules [ ] string
var systemStubModules [ ] string
var testStubModules [ ] string
var corePlatformStubModules [ ] string
if config . AlwaysUsePrebuiltSdks ( ) {
// Build configuration mandates using prebuilt stub modules
publicStubModules = append ( publicStubModules , "sdk_public_current_android" )
systemStubModules = append ( systemStubModules , "sdk_system_current_android" )
testStubModules = append ( testStubModules , "sdk_test_current_android" )
} else {
// Use stub modules built from source
publicStubModules = append ( publicStubModules , "android_stubs_current" )
systemStubModules = append ( systemStubModules , "android_system_stubs_current" )
testStubModules = append ( testStubModules , "android_test_stubs_current" )
}
// We do not have prebuilts of the core platform api yet
corePlatformStubModules = append ( corePlatformStubModules , "legacy.core.platform.api.stubs" )
// Allow products to define their own stubs for custom product jars that apps can use.
publicStubModules = append ( publicStubModules , config . ProductHiddenAPIStubs ( ) ... )
systemStubModules = append ( systemStubModules , config . ProductHiddenAPIStubsSystem ( ) ... )
testStubModules = append ( testStubModules , config . ProductHiddenAPIStubsTest ( ) ... )
if config . IsEnvTrue ( "EMMA_INSTRUMENT" ) {
2021-05-14 11:45:25 +02:00
// Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
// allows everyone access but it is needed to ensure consistent flags between the
// bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
2021-04-21 15:10:42 +02:00
publicStubModules = append ( publicStubModules , "jacoco-stubs" )
2021-05-14 11:45:25 +02:00
systemStubModules = append ( systemStubModules , "jacoco-stubs" )
testStubModules = append ( testStubModules , "jacoco-stubs" )
2021-04-21 15:10:42 +02:00
}
m := map [ android . SdkKind ] [ ] string { }
m [ android . SdkPublic ] = publicStubModules
m [ android . SdkSystem ] = systemStubModules
m [ android . SdkTest ] = testStubModules
m [ android . SdkCorePlatform ] = corePlatformStubModules
return m
}
// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
// identify the source of the dependency.
func hiddenAPIAddStubLibDependencies ( ctx android . BottomUpMutatorContext , sdkKindToStubLibModules map [ android . SdkKind ] [ ] string ) {
module := ctx . Module ( )
for _ , sdkKind := range hiddenAPIRelevantSdkKinds {
modules := sdkKindToStubLibModules [ sdkKind ]
ctx . AddDependency ( module , hiddenAPIStubsDependencyTag { sdkKind : sdkKind } , modules ... )
}
}
// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
// in hiddenAPIAddStubLibDependencies.
2021-05-13 22:25:05 +02:00
func hiddenAPIGatherStubLibDexJarPaths ( ctx android . ModuleContext , contents [ ] android . Module ) map [ android . SdkKind ] android . Paths {
2021-04-21 15:10:42 +02:00
m := map [ android . SdkKind ] android . Paths { }
2021-05-13 22:25:05 +02:00
// If the contents includes any java_sdk_library modules then add them to the stubs.
for _ , module := range contents {
if _ , ok := module . ( SdkLibraryDependency ) ; ok {
for _ , kind := range [ ] android . SdkKind { android . SdkPublic , android . SdkSystem , android . SdkTest } {
dexJar := hiddenAPIRetrieveDexJarBuildPath ( ctx , module , kind )
if dexJar != nil {
m [ kind ] = append ( m [ kind ] , dexJar )
}
}
}
}
2021-04-21 15:10:42 +02:00
ctx . VisitDirectDepsIf ( isActiveModule , func ( module android . Module ) {
tag := ctx . OtherModuleDependencyTag ( module )
if hiddenAPIStubsTag , ok := tag . ( hiddenAPIStubsDependencyTag ) ; ok {
kind := hiddenAPIStubsTag . sdkKind
2021-04-25 11:13:54 +02:00
dexJar := hiddenAPIRetrieveDexJarBuildPath ( ctx , module , kind )
2021-04-21 15:10:42 +02:00
if dexJar != nil {
m [ kind ] = append ( m [ kind ] , dexJar )
}
}
} )
2021-05-13 22:25:05 +02:00
// Normalize the paths, i.e. remove duplicates and sort.
for k , v := range m {
m [ k ] = android . SortedUniquePaths ( v )
}
2021-04-21 15:10:42 +02:00
return m
}
// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
// available, or reports an error.
2021-04-25 11:13:54 +02:00
func hiddenAPIRetrieveDexJarBuildPath ( ctx android . ModuleContext , module android . Module , kind android . SdkKind ) android . Path {
var dexJar android . Path
if sdkLibrary , ok := module . ( SdkLibraryDependency ) ; ok {
dexJar = sdkLibrary . SdkApiStubDexJar ( ctx , kind )
} else if j , ok := module . ( UsesLibraryDependency ) ; ok {
dexJar = j . DexJarBuildPath ( )
2021-04-21 15:10:42 +02:00
} else {
ctx . ModuleErrorf ( "dependency %s of module type %s does not support providing a dex jar" , module , ctx . OtherModuleType ( module ) )
2021-04-25 11:13:54 +02:00
return nil
}
if dexJar == nil {
ctx . ModuleErrorf ( "dependency %s does not provide a dex jar, consider setting compile_dex: true" , module )
2021-04-21 15:10:42 +02:00
}
2021-04-25 11:13:54 +02:00
return dexJar
2021-04-21 15:10:42 +02:00
}
var sdkKindToHiddenapiListOption = map [ android . SdkKind ] string {
android . SdkPublic : "public-stub-classpath" ,
android . SdkSystem : "system-stub-classpath" ,
android . SdkTest : "test-stub-classpath" ,
android . SdkCorePlatform : "core-platform-stub-classpath" ,
}
// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
//
// The rule is initialized but not built so that the caller can modify it and select an appropriate
// name.
2021-04-15 14:32:00 +02:00
func ruleToGenerateHiddenAPIStubFlagsFile ( ctx android . BuilderContext , outputPath android . WritablePath , bootDexJars android . Paths , sdkKindToPathList map [ android . SdkKind ] android . Paths ) * android . RuleBuilder {
2021-04-21 15:10:42 +02:00
// Singleton rule which applies hiddenapi on all boot class path dex files.
rule := android . NewRuleBuilder ( pctx , ctx )
tempPath := tempPathForRestat ( ctx , outputPath )
command := rule . Command ( ) .
Tool ( ctx . Config ( ) . HostToolPath ( ctx , "hiddenapi" ) ) .
Text ( "list" ) .
FlagForEachInput ( "--boot-dex=" , bootDexJars )
// Iterate over the sdk kinds in a fixed order.
for _ , sdkKind := range hiddenAPIRelevantSdkKinds {
paths := sdkKindToPathList [ sdkKind ]
if len ( paths ) > 0 {
option := sdkKindToHiddenapiListOption [ sdkKind ]
command . FlagWithInputList ( "--" + option + "=" , paths , ":" )
}
}
// Add the output path.
command . FlagWithOutput ( "--out-api-flags=" , tempPath )
commitChangeForRestat ( rule , tempPath , outputPath )
return rule
}
2021-04-14 16:01:56 +02:00
// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
// information obtained from annotations within the source code in order to create the complete set
// of flags that should be applied to the dex implementation jars on the bootclasspath.
2021-04-08 18:49:27 +02:00
//
// Each property contains a list of paths. With the exception of the Unsupported_packages the paths
// of each property reference a plain text file that contains a java signature per line. The flags
// for each of those signatures will be updated in a property specific way.
//
// The Unsupported_packages property contains a list of paths, each of which is a plain text file
// with one Java package per line. All members of all classes within that package (but not nested
// packages) will be updated in a property specific way.
2021-04-14 16:01:56 +02:00
type HiddenAPIFlagFileProperties struct {
2021-04-08 18:49:27 +02:00
// Marks each signature in the referenced files as being unsupported.
2021-04-08 21:12:41 +02:00
Unsupported [ ] string ` android:"path" `
2021-04-08 18:49:27 +02:00
// Marks each signature in the referenced files as being unsupported because it has been removed.
// Any conflicts with other flags are ignored.
2021-04-08 21:12:41 +02:00
Removed [ ] string ` android:"path" `
2021-04-08 18:49:27 +02:00
// Marks each signature in the referenced files as being supported only for targetSdkVersion <= R
// and low priority.
2021-04-08 21:12:41 +02:00
Max_target_r_low_priority [ ] string ` android:"path" `
2021-04-08 18:49:27 +02:00
// Marks each signature in the referenced files as being supported only for targetSdkVersion <= Q.
2021-04-08 21:12:41 +02:00
Max_target_q [ ] string ` android:"path" `
2021-04-08 18:49:27 +02:00
// Marks each signature in the referenced files as being supported only for targetSdkVersion <= P.
2021-04-08 21:12:41 +02:00
Max_target_p [ ] string ` android:"path" `
2021-04-08 18:49:27 +02:00
// Marks each signature in the referenced files as being supported only for targetSdkVersion <= O
// and low priority. Any conflicts with other flags are ignored.
2021-04-08 21:12:41 +02:00
Max_target_o_low_priority [ ] string ` android:"path" `
2021-04-08 18:49:27 +02:00
// Marks each signature in the referenced files as being blocked.
2021-04-08 21:12:41 +02:00
Blocked [ ] string ` android:"path" `
2021-04-08 18:49:27 +02:00
// Marks each signature in every package in the referenced files as being unsupported.
2021-04-08 21:12:41 +02:00
Unsupported_packages [ ] string ` android:"path" `
}
2021-04-14 16:01:56 +02:00
func ( p * HiddenAPIFlagFileProperties ) hiddenAPIFlagFileInfo ( ctx android . ModuleContext ) hiddenAPIFlagFileInfo {
info := hiddenAPIFlagFileInfo { categoryToPaths : map [ * hiddenAPIFlagFileCategory ] android . Paths { } }
2021-04-14 10:50:43 +02:00
for _ , category := range hiddenAPIFlagFileCategories {
2021-04-19 14:21:20 +02:00
paths := android . PathsForModuleSrc ( ctx , category . propertyValueReader ( p ) )
2021-04-14 10:50:43 +02:00
info . categoryToPaths [ category ] = paths
2021-04-08 21:12:41 +02:00
}
2021-04-14 10:50:43 +02:00
return info
2021-04-08 21:12:41 +02:00
}
2021-04-14 10:50:43 +02:00
type hiddenAPIFlagFileCategory struct {
// propertyName is the name of the property for this category.
propertyName string
2021-04-08 21:12:41 +02:00
2021-04-19 14:21:20 +02:00
// propertyValueReader retrieves the value of the property for this category from the set of
2021-04-14 10:50:43 +02:00
// properties.
2021-04-19 14:21:20 +02:00
propertyValueReader func ( properties * HiddenAPIFlagFileProperties ) [ ] string
2021-04-08 21:12:41 +02:00
2021-04-14 10:50:43 +02:00
// commandMutator adds the appropriate command line options for this category to the supplied
// command
commandMutator func ( command * android . RuleBuilderCommand , path android . Path )
}
2021-04-08 21:12:41 +02:00
2021-04-14 10:50:43 +02:00
var hiddenAPIFlagFileCategories = [ ] * hiddenAPIFlagFileCategory {
2021-04-14 16:01:56 +02:00
// See HiddenAPIFlagFileProperties.Unsupported
2021-04-14 10:50:43 +02:00
{
propertyName : "unsupported" ,
2021-04-19 14:21:20 +02:00
propertyValueReader : func ( properties * HiddenAPIFlagFileProperties ) [ ] string {
2021-04-14 10:50:43 +02:00
return properties . Unsupported
} ,
commandMutator : func ( command * android . RuleBuilderCommand , path android . Path ) {
command . FlagWithInput ( "--unsupported " , path )
} ,
} ,
2021-04-14 16:01:56 +02:00
// See HiddenAPIFlagFileProperties.Removed
2021-04-14 10:50:43 +02:00
{
propertyName : "removed" ,
2021-04-19 14:21:20 +02:00
propertyValueReader : func ( properties * HiddenAPIFlagFileProperties ) [ ] string {
2021-04-14 10:50:43 +02:00
return properties . Removed
} ,
commandMutator : func ( command * android . RuleBuilderCommand , path android . Path ) {
command . FlagWithInput ( "--unsupported " , path ) . Flag ( "--ignore-conflicts " ) . FlagWithArg ( "--tag " , "removed" )
} ,
} ,
2021-04-14 16:01:56 +02:00
// See HiddenAPIFlagFileProperties.Max_target_r_low_priority
2021-04-14 10:50:43 +02:00
{
propertyName : "max_target_r_low_priority" ,
2021-04-19 14:21:20 +02:00
propertyValueReader : func ( properties * HiddenAPIFlagFileProperties ) [ ] string {
2021-04-14 10:50:43 +02:00
return properties . Max_target_r_low_priority
} ,
commandMutator : func ( command * android . RuleBuilderCommand , path android . Path ) {
command . FlagWithInput ( "--max-target-r " , path ) . FlagWithArg ( "--tag " , "lo-prio" )
} ,
} ,
2021-04-14 16:01:56 +02:00
// See HiddenAPIFlagFileProperties.Max_target_q
2021-04-14 10:50:43 +02:00
{
propertyName : "max_target_q" ,
2021-04-19 14:21:20 +02:00
propertyValueReader : func ( properties * HiddenAPIFlagFileProperties ) [ ] string {
2021-04-14 10:50:43 +02:00
return properties . Max_target_q
} ,
commandMutator : func ( command * android . RuleBuilderCommand , path android . Path ) {
command . FlagWithInput ( "--max-target-q " , path )
} ,
} ,
2021-04-14 16:01:56 +02:00
// See HiddenAPIFlagFileProperties.Max_target_p
2021-04-14 10:50:43 +02:00
{
propertyName : "max_target_p" ,
2021-04-19 14:21:20 +02:00
propertyValueReader : func ( properties * HiddenAPIFlagFileProperties ) [ ] string {
2021-04-14 10:50:43 +02:00
return properties . Max_target_p
} ,
commandMutator : func ( command * android . RuleBuilderCommand , path android . Path ) {
command . FlagWithInput ( "--max-target-p " , path )
} ,
} ,
2021-04-14 16:01:56 +02:00
// See HiddenAPIFlagFileProperties.Max_target_o_low_priority
2021-04-14 10:50:43 +02:00
{
propertyName : "max_target_o_low_priority" ,
2021-04-19 14:21:20 +02:00
propertyValueReader : func ( properties * HiddenAPIFlagFileProperties ) [ ] string {
2021-04-14 10:50:43 +02:00
return properties . Max_target_o_low_priority
} ,
commandMutator : func ( command * android . RuleBuilderCommand , path android . Path ) {
command . FlagWithInput ( "--max-target-o " , path ) . Flag ( "--ignore-conflicts " ) . FlagWithArg ( "--tag " , "lo-prio" )
} ,
} ,
2021-04-14 16:01:56 +02:00
// See HiddenAPIFlagFileProperties.Blocked
2021-04-14 10:50:43 +02:00
{
propertyName : "blocked" ,
2021-04-19 14:21:20 +02:00
propertyValueReader : func ( properties * HiddenAPIFlagFileProperties ) [ ] string {
2021-04-14 10:50:43 +02:00
return properties . Blocked
} ,
commandMutator : func ( command * android . RuleBuilderCommand , path android . Path ) {
command . FlagWithInput ( "--blocked " , path )
} ,
} ,
2021-04-14 16:01:56 +02:00
// See HiddenAPIFlagFileProperties.Unsupported_packages
2021-04-14 10:50:43 +02:00
{
propertyName : "unsupported_packages" ,
2021-04-19 14:21:20 +02:00
propertyValueReader : func ( properties * HiddenAPIFlagFileProperties ) [ ] string {
2021-04-14 10:50:43 +02:00
return properties . Unsupported_packages
} ,
commandMutator : func ( command * android . RuleBuilderCommand , path android . Path ) {
command . FlagWithInput ( "--unsupported " , path ) . Flag ( "--packages " )
} ,
} ,
}
2021-04-15 14:32:00 +02:00
// hiddenAPIFlagFileInfo contains paths resolved from HiddenAPIFlagFileProperties and also generated
// by hidden API processing.
//
// This is used both for an individual bootclasspath_fragment to provide it to other modules and
// for a module to collate the files from the fragments it depends upon. That is why the fields are
// all Paths even though they are initialized with a single path.
2021-04-14 16:01:56 +02:00
type hiddenAPIFlagFileInfo struct {
2021-04-14 10:50:43 +02:00
// categoryToPaths maps from the flag file category to the paths containing information for that
// category.
categoryToPaths map [ * hiddenAPIFlagFileCategory ] android . Paths
2021-04-15 14:32:00 +02:00
// The paths to the generated stub-flags.csv files.
StubFlagsPaths android . Paths
// The paths to the generated annotation-flags.csv files.
AnnotationFlagsPaths android . Paths
// The paths to the generated metadata.csv files.
MetadataPaths android . Paths
// The paths to the generated index.csv files.
IndexPaths android . Paths
// The paths to the generated all-flags.csv files.
AllFlagsPaths android . Paths
2021-04-08 18:49:27 +02:00
}
2021-04-08 21:12:41 +02:00
2021-04-09 00:01:37 +02:00
func ( i * hiddenAPIFlagFileInfo ) append ( other hiddenAPIFlagFileInfo ) {
for _ , category := range hiddenAPIFlagFileCategories {
i . categoryToPaths [ category ] = append ( i . categoryToPaths [ category ] , other . categoryToPaths [ category ] ... )
}
2021-04-15 14:32:00 +02:00
i . StubFlagsPaths = append ( i . StubFlagsPaths , other . StubFlagsPaths ... )
i . AnnotationFlagsPaths = append ( i . AnnotationFlagsPaths , other . AnnotationFlagsPaths ... )
i . MetadataPaths = append ( i . MetadataPaths , other . MetadataPaths ... )
i . IndexPaths = append ( i . IndexPaths , other . IndexPaths ... )
i . AllFlagsPaths = append ( i . AllFlagsPaths , other . AllFlagsPaths ... )
2021-04-09 00:01:37 +02:00
}
var hiddenAPIFlagFileInfoProvider = blueprint . NewProvider ( hiddenAPIFlagFileInfo { } )
2021-05-13 18:31:51 +02:00
// pathForValidation creates a path of the same type as the supplied type but with a name of
// <path>.valid.
//
// e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
// an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
func pathForValidation ( ctx android . PathContext , path android . WritablePath ) android . WritablePath {
extWithoutLeadingDot := strings . TrimPrefix ( path . Ext ( ) , "." )
return path . ReplaceExtension ( ctx , extWithoutLeadingDot + ".valid" )
}
2021-04-15 14:32:00 +02:00
// buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
// the flags from all the modules, the stub flags, augmented with some additional configuration
// files.
2021-04-08 21:12:41 +02:00
//
// baseFlagsPath is the path to the flags file containing all the information from the stubs plus
// an entry for every single member in the dex implementation jars of the individual modules. Every
// signature in any of the other files MUST be included in this file.
//
2021-05-14 11:38:00 +02:00
// annotationFlags is the path to the annotation flags file generated from annotation information
// in each module.
2021-04-08 21:12:41 +02:00
//
2021-05-14 11:38:00 +02:00
// flagFileInfo is a struct containing paths to files that augment the information provided by
// the annotationFlags.
func buildRuleToGenerateHiddenApiFlags ( ctx android . BuilderContext , name , desc string , outputPath android . WritablePath , baseFlagsPath android . Path , annotationFlags android . Path , flagFileInfo * hiddenAPIFlagFileInfo ) {
2021-05-13 18:31:51 +02:00
// The file which is used to record that the flags file is valid.
var validFile android . WritablePath
// If there are flag files that have been generated by fragments on which this depends then use
// them to validate the flag file generated by the rules created by this method.
if allFlagsPaths := flagFileInfo . AllFlagsPaths ; len ( allFlagsPaths ) > 0 {
// The flags file generated by the rule created by this method needs to be validated to ensure
// that it is consistent with the flag files generated by the individual fragments.
validFile = pathForValidation ( ctx , outputPath )
// Create a rule to validate the output from the following rule.
rule := android . NewRuleBuilder ( pctx , ctx )
rule . Command ( ) .
BuiltTool ( "verify_overlaps" ) .
Input ( outputPath ) .
Inputs ( allFlagsPaths ) .
// If validation passes then update the file that records that.
Text ( "&& touch" ) . Output ( validFile )
rule . Build ( name + "Validation" , desc + " validation" )
}
// Create the rule that will generate the flag files.
2021-04-21 23:12:35 +02:00
tempPath := tempPathForRestat ( ctx , outputPath )
2021-04-08 21:12:41 +02:00
rule := android . NewRuleBuilder ( pctx , ctx )
command := rule . Command ( ) .
BuiltTool ( "generate_hiddenapi_lists" ) .
FlagWithInput ( "--csv " , baseFlagsPath ) .
2021-05-14 11:38:00 +02:00
Input ( annotationFlags ) .
2021-04-08 21:12:41 +02:00
FlagWithOutput ( "--output " , tempPath )
2021-04-14 10:50:43 +02:00
// Add the options for the different categories of flag files.
for _ , category := range hiddenAPIFlagFileCategories {
2021-04-15 14:32:00 +02:00
paths := flagFileInfo . categoryToPaths [ category ]
2021-04-14 10:50:43 +02:00
for _ , path := range paths {
category . commandMutator ( command , path )
}
2021-04-08 21:12:41 +02:00
}
commitChangeForRestat ( rule , tempPath , outputPath )
2021-05-13 18:31:51 +02:00
if validFile != nil {
// Add the file that indicates that the file generated by this is valid.
//
// This will cause the validation rule above to be run any time that the output of this rule
// changes but the validation will run in parallel with other rules that depend on this file.
command . Validation ( validFile )
}
2021-04-15 14:32:00 +02:00
rule . Build ( name , desc )
}
// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment
// of the bootclasspath.
//
// It takes:
// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
// * The list of modules that are the contents of the fragment.
// * The additional manually curated flag files to use.
//
// It generates:
// * stub-flags.csv
// * annotation-flags.csv
// * metadata.csv
// * index.csv
// * all-flags.csv
2021-05-14 11:38:00 +02:00
func hiddenAPIGenerateAllFlagsForBootclasspathFragment ( ctx android . ModuleContext , contents [ ] hiddenAPIModule , stubJarsByKind map [ android . SdkKind ] android . Paths , flagFileInfo * hiddenAPIFlagFileInfo ) {
2021-04-15 14:32:00 +02:00
hiddenApiSubDir := "modular-hiddenapi"
// Generate the stub-flags.csv.
2021-05-14 11:38:00 +02:00
bootDexJars := extractBootDexJarsFromHiddenAPIModules ( ctx , contents )
2021-04-15 14:32:00 +02:00
stubFlagsCSV := android . PathForModuleOut ( ctx , hiddenApiSubDir , "stub-flags.csv" )
rule := ruleToGenerateHiddenAPIStubFlagsFile ( ctx , stubFlagsCSV , bootDexJars , stubJarsByKind )
rule . Build ( "modularHiddenAPIStubFlagsFile" , "modular hiddenapi stub flags" )
2021-05-14 11:38:00 +02:00
// Extract the classes jars from the contents.
classesJars := extractClassJarsFromHiddenAPIModules ( ctx , contents )
2021-04-15 14:32:00 +02:00
// Generate the set of flags from the annotations in the source code.
annotationFlagsCSV := android . PathForModuleOut ( ctx , hiddenApiSubDir , "annotation-flags.csv" )
2021-05-14 10:58:48 +02:00
buildRuleToGenerateAnnotationFlags ( ctx , "modular hiddenapi annotation flags" , classesJars , stubFlagsCSV , annotationFlagsCSV )
2021-04-15 14:32:00 +02:00
// Generate the metadata from the annotations in the source code.
metadataCSV := android . PathForModuleOut ( ctx , hiddenApiSubDir , "metadata.csv" )
2021-05-14 10:58:48 +02:00
buildRuleToGenerateMetadata ( ctx , "modular hiddenapi metadata" , classesJars , stubFlagsCSV , metadataCSV )
2021-04-15 14:32:00 +02:00
2021-05-14 11:38:00 +02:00
// Generate the index file from the CSV files in the classes jars.
2021-04-15 14:32:00 +02:00
indexCSV := android . PathForModuleOut ( ctx , hiddenApiSubDir , "index.csv" )
2021-05-14 10:58:48 +02:00
buildRuleToGenerateIndex ( ctx , "modular hiddenapi index" , classesJars , indexCSV )
2021-04-15 14:32:00 +02:00
// Removed APIs need to be marked and in order to do that the flagFileInfo needs to specify files
// containing dex signatures of all the removed APIs. In the monolithic files that is done by
// manually combining all the removed.txt files for each API and then converting them to dex
// signatures, see the combined-removed-dex module. That will all be done automatically in future.
// For now removed APIs are ignored.
// TODO(b/179354495): handle removed apis automatically.
// Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
// files.
outputPath := android . PathForModuleOut ( ctx , hiddenApiSubDir , "all-flags.csv" )
2021-05-14 11:38:00 +02:00
buildRuleToGenerateHiddenApiFlags ( ctx , "modularHiddenApiAllFlags" , "modular hiddenapi all flags" , outputPath , stubFlagsCSV , annotationFlagsCSV , flagFileInfo )
2021-04-15 14:32:00 +02:00
// Store the paths in the info for use by other modules and sdk snapshot generation.
flagFileInfo . StubFlagsPaths = android . Paths { stubFlagsCSV }
flagFileInfo . AnnotationFlagsPaths = android . Paths { annotationFlagsCSV }
flagFileInfo . MetadataPaths = android . Paths { metadataCSV }
flagFileInfo . IndexPaths = android . Paths { indexCSV }
flagFileInfo . AllFlagsPaths = android . Paths { outputPath }
2021-04-08 21:12:41 +02:00
}
2021-05-14 11:38:00 +02:00
// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents.
func gatherHiddenAPIModuleFromContents ( ctx android . ModuleContext , contents [ ] android . Module ) [ ] hiddenAPIModule {
hiddenAPIModules := [ ] hiddenAPIModule { }
for _ , module := range contents {
if hiddenAPI , ok := module . ( hiddenAPIModule ) ; ok {
hiddenAPIModules = append ( hiddenAPIModules , hiddenAPI )
} else if _ , ok := module . ( * DexImport ) ; ok {
// Ignore this for the purposes of hidden API processing
} else {
ctx . ModuleErrorf ( "module %s does not implement hiddenAPIModule" , module )
}
}
return hiddenAPIModules
}
// extractBootDexJarsFromHiddenAPIModules extracts the boot dex jars from the supplied modules.
func extractBootDexJarsFromHiddenAPIModules ( ctx android . ModuleContext , contents [ ] hiddenAPIModule ) android . Paths {
bootDexJars := android . Paths { }
for _ , module := range contents {
bootDexJar := module . bootDexJar ( )
if bootDexJar == nil {
ctx . ModuleErrorf ( "module %s does not provide a dex jar" , module )
} else {
bootDexJars = append ( bootDexJars , bootDexJar )
}
}
return bootDexJars
}
// extractClassJarsFromHiddenAPIModules extracts the class jars from the supplied modules.
func extractClassJarsFromHiddenAPIModules ( ctx android . ModuleContext , contents [ ] hiddenAPIModule ) android . Paths {
classesJars := android . Paths { }
for _ , module := range contents {
classesJars = append ( classesJars , module . classesJars ( ) ... )
}
return classesJars
}