Merge CSV files generated by UnsupportedAppUsageProcessor.

Flow:
1. Annotation processor generates a CSV file per class as a CLASS_OUTPUT resource.
2. hiddenapi.go extracts individual .csv files and merges them into an index.csv file per module.
3. hiddenapi_singleton.go merges individual index.csv files into a combined .csv file.

In a follow up hiddenapi-index.csv would replace unsupportedappusage_index.csv

Bug: 145132366
Change-Id: I87d92f9c8d4b1cc1df526fc576ee3c2101116b58
Test: diff unsupportedappusage_index.csv hiddenapi-index.csv
This commit is contained in:
Artur Satayev 2020-02-19 16:39:59 +00:00
parent 112045230d
commit b5df8a04ad
2 changed files with 79 additions and 23 deletions

View File

@ -28,9 +28,10 @@ var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", bl
}, "outFlag", "stubAPIFlags")
type hiddenAPI struct {
flagsCSVPath android.Path
metadataCSVPath android.Path
bootDexJarPath android.Path
flagsCSVPath android.Path
indexCSVPath android.Path
metadataCSVPath android.Path
}
func (h *hiddenAPI) flagsCSV() android.Path {
@ -45,17 +46,21 @@ func (h *hiddenAPI) bootDexJar() android.Path {
return h.bootDexJarPath
}
func (h *hiddenAPI) indexCSV() android.Path {
return h.indexCSVPath
}
type hiddenAPIIntf interface {
flagsCSV() android.Path
metadataCSV() android.Path
bootDexJar() android.Path
flagsCSV() android.Path
indexCSV() android.Path
metadataCSV() android.Path
}
var _ hiddenAPIIntf = (*hiddenAPI)(nil)
func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOutPath, implementationJar android.Path,
uncompressDex bool) android.ModuleOutPath {
func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOutPath,
implementationJar android.Path, uncompressDex bool) android.ModuleOutPath {
if !ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
name := ctx.ModuleName()
@ -77,9 +82,8 @@ func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOu
// Derive the greylist from classes jar.
flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv")
metadataCSV := android.PathForModuleOut(ctx, "hiddenapi", "metadata.csv")
hiddenAPIGenerateCSV(ctx, flagsCSV, metadataCSV, implementationJar)
h.flagsCSVPath = flagsCSV
h.metadataCSVPath = metadataCSV
indexCSV := android.PathForModuleOut(ctx, "hiddenapi", "index.csv")
h.hiddenAPIGenerateCSV(ctx, flagsCSV, metadataCSV, indexCSV, 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
@ -96,9 +100,7 @@ func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOu
return dexJar
}
func hiddenAPIGenerateCSV(ctx android.ModuleContext, flagsCSV, metadataCSV android.WritablePath,
classesJar android.Path) {
func (h *hiddenAPI) hiddenAPIGenerateCSV(ctx android.ModuleContext, flagsCSV, metadataCSV, indexCSV android.WritablePath, classesJar android.Path) {
stubFlagsCSV := hiddenAPISingletonPaths(ctx).stubFlags
ctx.Build(pctx, android.BuildParams{
@ -112,6 +114,7 @@ func hiddenAPIGenerateCSV(ctx android.ModuleContext, flagsCSV, metadataCSV andro
"stubAPIFlags": stubFlagsCSV.String(),
},
})
h.flagsCSVPath = flagsCSV
ctx.Build(pctx, android.BuildParams{
Rule: hiddenAPIGenerateCSVRule,
@ -124,18 +127,26 @@ func hiddenAPIGenerateCSV(ctx android.ModuleContext, flagsCSV, metadataCSV andro
"stubAPIFlags": stubFlagsCSV.String(),
},
})
h.metadataCSVPath = metadataCSV
rule := android.NewRuleBuilder()
rule.Command().
BuiltTool(ctx, "merge_csv").
FlagWithInput("--zip_input=", classesJar).
FlagWithOutput("--output=", indexCSV)
rule.Build(pctx, ctx, "merged-hiddenapi-index", "Merged Hidden API index")
h.indexCSVPath = indexCSV
}
var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", blueprint.RuleParams{
Command: `rm -rf $tmpDir && mkdir -p $tmpDir && mkdir $tmpDir/dex-input && mkdir $tmpDir/dex-output && ` +
`unzip -o -q $in 'classes*.dex' -d $tmpDir/dex-input && ` +
`for INPUT_DEX in $$(find $tmpDir/dex-input -maxdepth 1 -name 'classes*.dex' | sort); do ` +
` echo "--input-dex=$${INPUT_DEX}"; ` +
` echo "--output-dex=$tmpDir/dex-output/$$(basename $${INPUT_DEX})"; ` +
`done | xargs ${config.HiddenAPI} encode --api-flags=$flagsCsv $hiddenapiFlags && ` +
`${config.SoongZipCmd} $soongZipFlags -o $tmpDir/dex.jar -C $tmpDir/dex-output -f "$tmpDir/dex-output/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" $out $tmpDir/dex.jar $in`,
Command: `rm -rf $tmpDir && mkdir -p $tmpDir && mkdir $tmpDir/dex-input && mkdir $tmpDir/dex-output &&
unzip -o -q $in 'classes*.dex' -d $tmpDir/dex-input &&
for INPUT_DEX in $$(find $tmpDir/dex-input -maxdepth 1 -name 'classes*.dex' | sort); do
echo "--input-dex=$${INPUT_DEX}";
echo "--output-dex=$tmpDir/dex-output/$$(basename $${INPUT_DEX})";
done | xargs ${config.HiddenAPI} encode --api-flags=$flagsCsv $hiddenapiFlags &&
${config.SoongZipCmd} $soongZipFlags -o $tmpDir/dex.jar -C $tmpDir/dex-output -f "$tmpDir/dex-output/classes*.dex" &&
${config.MergeZipsCmd} -D -zipToNotStrip $tmpDir/dex.jar -stripFile "classes*.dex" -stripFile "**/*.uau" $out $tmpDir/dex.jar $in`,
CommandDeps: []string{
"${config.HiddenAPI}",
"${config.SoongZipCmd}",

View File

@ -22,13 +22,15 @@ import (
func init() {
android.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
android.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory)
android.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory)
}
type hiddenAPISingletonPathsStruct struct {
stubFlags android.OutputPath
flags android.OutputPath
index android.OutputPath
metadata android.OutputPath
stubFlags android.OutputPath
}
var hiddenAPISingletonPathsKey = android.NewOnceKey("hiddenAPISingletonPathsKey")
@ -39,9 +41,10 @@ var hiddenAPISingletonPathsKey = android.NewOnceKey("hiddenAPISingletonPathsKey"
func hiddenAPISingletonPaths(ctx android.PathContext) hiddenAPISingletonPathsStruct {
return ctx.Config().Once(hiddenAPISingletonPathsKey, func() interface{} {
return hiddenAPISingletonPathsStruct{
stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
flags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-flags.csv"),
index: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-index.csv"),
metadata: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-greylist.csv"),
stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
}
}).(hiddenAPISingletonPathsStruct)
}
@ -364,3 +367,45 @@ func hiddenAPIFlagsFactory() android.Module {
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
return module
}
func hiddenAPIIndexSingletonFactory() android.Singleton {
return &hiddenAPIIndexSingleton{}
}
type hiddenAPIIndexSingleton struct {
index android.Path
}
func (h *hiddenAPIIndexSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true
if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
return
}
indexes := android.Paths{}
ctx.VisitAllModules(func(module android.Module) {
if h, ok := module.(hiddenAPIIntf); ok {
if h.indexCSV() != nil {
indexes = append(indexes, h.indexCSV())
}
}
})
rule := android.NewRuleBuilder()
rule.Command().
BuiltTool(ctx, "merge_csv").
FlagWithArg("--header=", "signature,file,startline,startcol,endline,endcol,properties").
FlagWithOutput("--output=", hiddenAPISingletonPaths(ctx).index).
Inputs(indexes)
rule.Build(pctx, ctx, "singleton-merged-hiddenapi-index", "Singleton merged Hidden API index")
h.index = hiddenAPISingletonPaths(ctx).index
}
func (h *hiddenAPIIndexSingleton) MakeVars(ctx android.MakeVarsContext) {
if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
return
}
ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_INDEX", h.index.String())
}