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
Merged-In: I87d92f9c8d4b1cc1df526fc576ee3c2101116b58
Test: diff unsupportedappusage_index.csv hiddenapi-index.csv
Exempt-From-Owner-Approval: cp from r.android.com/1239709
This commit is contained in:
Artur Satayev 2020-02-19 16:39:59 +00:00
parent d775f6ae65
commit 8a950790ee
2 changed files with 79 additions and 23 deletions

View File

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

View File

@ -22,13 +22,15 @@ import (
func init() { func init() {
android.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory) android.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
android.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory)
android.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory) android.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory)
} }
type hiddenAPISingletonPathsStruct struct { type hiddenAPISingletonPathsStruct struct {
stubFlags android.OutputPath
flags android.OutputPath flags android.OutputPath
index android.OutputPath
metadata android.OutputPath metadata android.OutputPath
stubFlags android.OutputPath
} }
var hiddenAPISingletonPathsKey = android.NewOnceKey("hiddenAPISingletonPathsKey") var hiddenAPISingletonPathsKey = android.NewOnceKey("hiddenAPISingletonPathsKey")
@ -39,9 +41,10 @@ var hiddenAPISingletonPathsKey = android.NewOnceKey("hiddenAPISingletonPathsKey"
func hiddenAPISingletonPaths(ctx android.PathContext) hiddenAPISingletonPathsStruct { func hiddenAPISingletonPaths(ctx android.PathContext) hiddenAPISingletonPathsStruct {
return ctx.Config().Once(hiddenAPISingletonPathsKey, func() interface{} { return ctx.Config().Once(hiddenAPISingletonPathsKey, func() interface{} {
return hiddenAPISingletonPathsStruct{ return hiddenAPISingletonPathsStruct{
stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
flags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-flags.csv"), flags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-flags.csv"),
index: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-index.csv"),
metadata: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-greylist.csv"), metadata: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-greylist.csv"),
stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
} }
}).(hiddenAPISingletonPathsStruct) }).(hiddenAPISingletonPathsStruct)
} }
@ -364,3 +367,45 @@ func hiddenAPIFlagsFactory() android.Module {
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
return module 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())
}