aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--androidmk/cmd/androidmk/android.go58
-rw-r--r--androidmk/cmd/androidmk/androidmk_test.go36
-rw-r--r--java/androidmk.go3
-rw-r--r--java/app.go10
-rw-r--r--java/builder.go1
-rw-r--r--java/config/config.go2
-rw-r--r--java/config/makevars.go1
-rw-r--r--java/dex.go123
-rw-r--r--java/java.go37
-rw-r--r--java/java_test.go3
10 files changed, 252 insertions, 22 deletions
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 82b5eb95..3e134b6e 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -53,6 +53,7 @@ var rewriteProperties = map[string](func(variableAssignmentContext) error){
"LOCAL_SANITIZE_DIAG": sanitize("diag."),
"LOCAL_CFLAGS": cflags,
"LOCAL_UNINSTALLABLE_MODULE": invert("installable"),
+ "LOCAL_PROGUARD_ENABLED": proguardEnabled,
// composite functions
"LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))),
@@ -136,6 +137,9 @@ func init() {
"LOCAL_ANNOTATION_PROCESSORS": "annotation_processors",
"LOCAL_ANNOTATION_PROCESSOR_CLASSES": "annotation_processor_classes",
+
+ "LOCAL_PROGUARD_FLAGS": "optimize.proguard_flags",
+ "LOCAL_PROGUARD_FLAG_FILES": "optimize.proguard_flag_files",
})
addStandardProperties(bpparser.BoolType,
map[string]string{
@@ -517,6 +521,60 @@ func cflags(ctx variableAssignmentContext) error {
return includeVariableNow(bpVariable{"cflags", bpparser.ListType}, ctx)
}
+func proguardEnabled(ctx variableAssignmentContext) error {
+ val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
+ if err != nil {
+ return err
+ }
+
+ list, ok := val.(*bpparser.List)
+ if !ok {
+ return fmt.Errorf("unsupported proguard expression")
+ }
+
+ set := func(prop string, value bool) {
+ bpValue := &bpparser.Bool{
+ Value: value,
+ }
+ setVariable(ctx.file, false, ctx.prefix, prop, bpValue, true)
+ }
+
+ enable := false
+
+ for _, v := range list.Values {
+ s, ok := v.(*bpparser.String)
+ if !ok {
+ return fmt.Errorf("unsupported proguard expression")
+ }
+
+ switch s.Value {
+ case "disabled":
+ set("optimize.enabled", false)
+ case "obfuscation":
+ enable = true
+ set("optimize.obfuscate", true)
+ case "optimization":
+ enable = true
+ set("optimize.optimize", true)
+ case "full":
+ enable = true
+ case "custom":
+ set("optimize.no_aapt_flags", true)
+ enable = true
+ default:
+ return fmt.Errorf("unsupported proguard value %q", s)
+ }
+ }
+
+ if enable {
+ // This is only necessary for libraries which default to false, but we can't
+ // tell the difference between a library and an app here.
+ set("optimize.enabled", true)
+ }
+
+ return nil
+}
+
func invert(name string) func(ctx variableAssignmentContext) error {
return func(ctx variableAssignmentContext) error {
val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.BoolType)
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 22a52d46..c85aaaac 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -438,6 +438,42 @@ include $(call all-makefiles-under,$(LOCAL_PATH))
`,
expected: ``,
},
+ {
+ desc: "proguard options for java library",
+ in: `
+ include $(CLEAR_VARS)
+ # Empty
+ LOCAL_PROGUARD_ENABLED :=
+ # Disabled
+ LOCAL_PROGUARD_ENABLED := disabled
+ # Full
+ LOCAL_PROGUARD_ENABLED := full
+ # Obfuscation and optimization
+ LOCAL_PROGUARD_ENABLED := obfuscation optimization
+ # Custom
+ LOCAL_PROGUARD_ENABLED := custom
+ include $(BUILD_JAVA_LIBRARY)
+ `,
+ expected: `
+ java_library {
+ // Empty
+
+ // Disabled
+ optimize: {
+ enabled: false,
+ // Full
+ enabled: true,
+ // Obfuscation and optimization
+ obfuscate: true,
+ optimize: true,
+ enabled: true,
+ // Custom
+ no_aapt_flags: true,
+ enabled: true,
+ },
+ }
+ `,
+ },
}
func reformatBlueprint(input string) string {
diff --git a/java/androidmk.go b/java/androidmk.go
index 24fe43ad..64ef5054 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -165,6 +165,9 @@ func (app *AndroidApp) AndroidMk() android.AndroidMkData {
if app.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
}
+ if app.proguardDictionary != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_PROGUARD_DICT :=", app.proguardDictionary.String())
+ }
if app.Name() == "framework-res" {
fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
diff --git a/java/app.go b/java/app.go
index df53375a..234dcb75 100644
--- a/java/app.go
+++ b/java/app.go
@@ -125,14 +125,13 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
- //if !ctx.ContainsProperty("proguard.enabled") {
- // a.properties.Proguard.Enabled = true
- //}
-
if String(a.appProperties.Instrumentation_for) == "" {
a.properties.Instrument = true
}
+ a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
+ proguardOptionsFile)
+
if ctx.ModuleName() != "framework-res" {
a.Module.compile(ctx, a.aaptSrcJar)
}
@@ -324,6 +323,9 @@ func (a *AndroidApp) aapt2Flags(ctx android.ModuleContext) (flags []string, deps
func AndroidAppFactory() android.Module {
module := &AndroidApp{}
+ module.Module.deviceProperties.Optimize.Enabled = proptools.BoolPtr(true)
+ module.Module.deviceProperties.Optimize.Shrink = proptools.BoolPtr(true)
+
module.AddProperties(
&module.Module.properties,
&module.Module.deviceProperties,
diff --git a/java/builder.go b/java/builder.go
index dae655d7..bf826e1c 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -149,7 +149,6 @@ func init() {
type javaBuilderFlags struct {
javacFlags string
- dxFlags string
bootClasspath classpath
classpath classpath
systemModules classpath
diff --git a/java/config/config.go b/java/config/config.go
index 930e65e4..75176c98 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -106,8 +106,8 @@ func init() {
return path.String(), nil
}
})
-
pctx.HostBinToolVariable("D8Cmd", "d8")
+ pctx.HostBinToolVariable("R8Cmd", "r8-compat-proguard")
pctx.VariableFunc("TurbineJar", func(config android.Config) (string, error) {
turbine := "turbine.jar"
diff --git a/java/config/makevars.go b/java/config/makevars.go
index c382cc1a..7e125d59 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -55,6 +55,7 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.Strict("DX_COMMAND", "${DxCmd} -JXms16M -JXmx2048M")
ctx.Strict("USE_D8_DESUGAR", "false")
}
+ ctx.Strict("R8_COMPAT_PROGUARD", "${R8Cmd}")
ctx.Strict("TURBINE", "${TurbineJar}")
diff --git a/java/dex.go b/java/dex.go
index fa5c2eea..2beb2ac3 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -108,6 +108,23 @@ var d8 = pctx.AndroidStaticRule("d8",
},
"outDir", "dxFlags")
+var r8 = pctx.AndroidStaticRule("r8",
+ blueprint.RuleParams{
+ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+ `${config.R8Cmd} -injars $in --output $outDir ` +
+ `--force-proguard-compatibility ` +
+ `-printmapping $outDict ` +
+ `$dxFlags $r8Flags && ` +
+ `${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
+ `${config.MergeZipsCmd} -D -stripFile "*.class" $out $outDir/classes.dex.jar $in`,
+ CommandDeps: []string{
+ "${config.R8Cmd}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ },
+ },
+ "outDir", "outDict", "dxFlags", "r8Flags")
+
func (j *Module) dxFlags(ctx android.ModuleContext, fullD8 bool) []string {
flags := j.deviceProperties.Dxflags
if fullD8 {
@@ -144,10 +161,64 @@ func (j *Module) dxFlags(ctx android.ModuleContext, fullD8 bool) []string {
return flags
}
+func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
+ opt := j.deviceProperties.Optimize
+
+ // When an app contains references to APIs that are not in the SDK specified by
+ // its LOCAL_SDK_VERSION for example added by support library or by runtime
+ // classes added by desugar, we artifically raise the "SDK version" "linked" by
+ // ProGuard, to
+ // - suppress ProGuard warnings of referencing symbols unknown to the lower SDK version.
+ // - prevent ProGuard stripping subclass in the support library that extends class added in the higher SDK version.
+ // See b/20667396
+ var proguardRaiseDeps classpath
+ ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(dep android.Module) {
+ proguardRaiseDeps = append(proguardRaiseDeps, dep.(Dependency).HeaderJars()...)
+ })
+
+ r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
+ r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
+ r8Flags = append(r8Flags, flags.classpath.FormJavaClassPath("-libraryjars"))
+ r8Flags = append(r8Flags, "-forceprocessing")
+
+ flagFiles := android.Paths{
+ android.PathForSource(ctx, "build/make/core/proguard.flags"),
+ }
+
+ flagFiles = append(flagFiles, j.extraProguardFlagFiles...)
+ // TODO(ccross): static android library proguard files
+
+ r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include "))
+ r8Deps = append(r8Deps, flagFiles...)
+
+ // TODO(b/70942988): This is included from build/make/core/proguard.flags
+ r8Deps = append(r8Deps, android.PathForSource(ctx,
+ "build/make/core/proguard_basic_keeps.flags"))
+
+ r8Flags = append(r8Flags, j.deviceProperties.Optimize.Proguard_flags...)
+
+ // TODO(ccross): Don't shrink app instrumentation tests by default.
+ if !Bool(opt.Shrink) {
+ r8Flags = append(r8Flags, "-dontshrink")
+ }
+
+ if !Bool(opt.Optimize) {
+ r8Flags = append(r8Flags, "-dontoptimize")
+ }
+
+ // TODO(ccross): error if obufscation + app instrumentation test.
+ if !Bool(opt.Obfuscate) {
+ r8Flags = append(r8Flags, "-dontobfuscate")
+ }
+
+ return r8Flags, r8Deps
+}
+
func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
classesJar android.Path, jarName string) android.Path {
- fullD8 := ctx.Config().UseD8Desugar()
+ useR8 := Bool(j.deviceProperties.Optimize.Enabled)
+ fullD8 := useR8 || ctx.Config().UseD8Desugar()
if !fullD8 {
classesJar = j.desugar(ctx, flags, classesJar, jarName)
@@ -159,22 +230,42 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
outDir := android.PathForModuleOut(ctx, "dex")
- rule := dx
- desc := "dx"
- if fullD8 {
- rule = d8
- desc = "d8"
+ if useR8 {
+ // TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
+ // dictionary of the app and move the app from libraryjars to injars.
+ j.proguardDictionary = android.PathForModuleOut(ctx, "proguard_dictionary")
+ r8Flags, r8Deps := j.r8Flags(ctx, flags)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: r8,
+ Description: "r8",
+ Output: javalibJar,
+ Input: classesJar,
+ Implicits: r8Deps,
+ Args: map[string]string{
+ "dxFlags": strings.Join(dxFlags, " "),
+ "r8Flags": strings.Join(r8Flags, " "),
+ "outDict": j.proguardDictionary.String(),
+ "outDir": outDir.String(),
+ },
+ })
+ } else {
+ rule := dx
+ desc := "dx"
+ if fullD8 {
+ rule = d8
+ desc = "d8"
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Description: desc,
+ Output: javalibJar,
+ Input: classesJar,
+ Args: map[string]string{
+ "dxFlags": strings.Join(dxFlags, " "),
+ "outDir": outDir.String(),
+ },
+ })
}
- ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: desc,
- Output: javalibJar,
- Input: classesJar,
- Args: map[string]string{
- "dxFlags": strings.Join(dxFlags, " "),
- "outDir": outDir.String(),
- },
- })
j.dexJarFile = javalibJar
return javalibJar
diff --git a/java/java.go b/java/java.go
index f06d81d7..106284e0 100644
--- a/java/java.go
+++ b/java/java.go
@@ -191,6 +191,32 @@ type CompilerDeviceProperties struct {
Profile *string
}
+ Optimize struct {
+ // If false, disable all optimization. Defaults to true for apps, false for
+ // libraries and tests.
+ Enabled *bool
+
+ // If true, optimize for size by removing unused code. Defaults to true for apps,
+ // false for libraries and tests.
+ Shrink *bool
+
+ // If true, optimize bytecode. Defaults to false.
+ Optimize *bool
+
+ // If true, obfuscate bytecode. Defaults to false.
+ Obfuscate *bool
+
+ // If true, do not use the flag files generated by aapt that automatically keep
+ // classes referenced by the app manifest. Defaults to false.
+ No_aapt_flags *bool
+
+ // Flags to pass to proguard.
+ Proguard_flags []string
+
+ // Specifies the locations of files containing proguard flags.
+ Proguard_flags_files []string
+ }
+
// When targeting 1.9, override the modules to use with --system
System_modules *string
}
@@ -216,6 +242,9 @@ type Module struct {
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path
+ // output file containing mapping of obfuscated names
+ proguardDictionary android.Path
+
// output file suitable for installing or running
outputFile android.Path
@@ -229,6 +258,9 @@ type Module struct {
// list of .java files and srcjars that was passed to javac
compiledJavaSrcs android.Paths
compiledSrcJars android.Paths
+
+ // list of extra progurad flag files
+ extraProguardFlagFiles android.Paths
}
func (j *Module) Srcs() android.Paths {
@@ -260,6 +292,7 @@ var (
systemModulesTag = dependencyTag{name: "system modules"}
frameworkResTag = dependencyTag{name: "framework-res"}
kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
+ proguardRaiseTag = dependencyTag{name: "proguard-raise"}
)
type sdkDep struct {
@@ -377,6 +410,10 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
ctx.AddDependency(ctx.Module(), systemModulesTag, sdkDep.systemModules)
}
ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.module)
+ if Bool(j.deviceProperties.Optimize.Enabled) {
+ ctx.AddDependency(ctx.Module(), proguardRaiseTag, config.DefaultBootclasspathLibraries...)
+ ctx.AddDependency(ctx.Module(), proguardRaiseTag, config.DefaultLibraries...)
+ }
}
} else if j.deviceProperties.System_modules == nil {
ctx.PropertyErrorf("no_standard_libs",
diff --git a/java/java_test.go b/java/java_test.go
index 6e14a706..e8298a22 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -157,6 +157,9 @@ func testContext(config android.Config, bp string,
"build/soong/scripts/jar-wrapper.sh": nil,
+ "build/make/core/proguard.flags": nil,
+ "build/make/core/proguard_basic_keeps.flags": nil,
+
"jdk8/jre/lib/jce.jar": nil,
"jdk8/jre/lib/rt.jar": nil,
}