aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@google.com>2013-11-15 13:11:24 -0800
committerXavier Ducrohet <xav@google.com>2013-11-15 13:12:03 -0800
commit18cb7aa73f2d078dfe370322e0602de11c1180ef (patch)
tree4f4af4e9d0bb72e0155a32ad36810b4d670c0527
parent9d68c2ab5f1a234b55610d892be9d25da67f69aa (diff)
downloadbuild-18cb7aa73f2d078dfe370322e0602de11c1180ef.tar.gz
Support to test proguarded apps.
Change-Id: I4cce4479c6c3e7e5e56bfe346e85ff32b486dbd3
-rw-r--r--changelog.txt1
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy180
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy2
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java4
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java5
-rw-r--r--tests/proguard/src/instrumentTest/java/com/android/tests/basic/MainTest.java7
-rw-r--r--tests/proguard/src/main/java/com/android/tests/basic/Main.java15
7 files changed, 128 insertions, 86 deletions
diff --git a/changelog.txt b/changelog.txt
index e8d0b4a..ea7659f 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,6 @@
0.7.0
- Switch to ProGuard 4.10
+ - Added ability to test proguarded (obfuscated) apps.
- Jar files are now pre-dexed for faster dexing.
- First pass at NDK integration
diff --git a/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy b/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
index b8a6c1d..de4a457 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
@@ -606,7 +606,7 @@ public abstract class BasePlugin {
project.file(
"$project.buildDir/libs/${project.archivesBaseName}-${variantData.baseName}.ap_")
}
- if (variantData.runProguard) {
+ if (variantConfiguration.buildType.runProguard) {
processResources.conventionMapping.proguardOutputFile = {
project.file("$project.buildDir/proguard/${variantData.dirName}/aapt_rules.txt")
}
@@ -1160,10 +1160,12 @@ public abstract class BasePlugin {
*/
protected void addPackageTasks(@NonNull ApkVariantData variantData,
@Nullable Task assembleTask) {
-
VariantConfiguration variantConfig = variantData.variantConfiguration
- boolean runProguard = !(variantData instanceof TestVariantData) && variantConfig.buildType.runProguard
+ boolean runProguard = variantConfig.buildType.runProguard &&
+ (variantConfig.type != VariantConfiguration.Type.TEST ||
+ (variantConfig.type == VariantConfiguration.Type.TEST &&
+ variantConfig.testedConfig.type != VariantConfiguration.Type.LIBRARY))
// common dex task configuration
String dexTaskName = "dex${variantData.name}"
@@ -1182,7 +1184,8 @@ public abstract class BasePlugin {
if (runProguard) {
// first proguard task.
- File outFile = createProguardTasks(variantData, variantConfig)
+ BaseVariantData testedVariantData = variantData instanceof TestVariantData ? variantData.testedVariantData : null as BaseVariantData
+ File outFile = createProguardTasks(variantData, testedVariantData)
// then dexing task
dexTask.dependsOn variantData.proguardTask
@@ -1348,16 +1351,25 @@ public abstract class BasePlugin {
/**
* Creates the proguarding task for the given Variant.
* @param variantData the variant data.
- * @param variantConfig the variant configuration of variantData
+ * @param testedVariantData optional. variant data representing the tested variant, null if the
+ * variant is not a test variant
* @return outFile file outputted by proguard
*/
@NonNull
protected File createProguardTasks(@NonNull BaseVariantData variantData,
- @NonNull VariantConfiguration variantConfig) {
- def proguardTask = project.tasks.create("proguard${variantData.name}", ProGuardTask);
+ @Nullable BaseVariantData testedVariantData) {
+ VariantConfiguration variantConfig = variantData.variantConfiguration
+
+ def proguardTask = project.tasks.create("proguard${variantData.name}", ProGuardTask)
proguardTask.dependsOn variantData.javaCompileTask
+ if (testedVariantData != null) {
+ proguardTask.dependsOn testedVariantData.proguardTask
+ }
+
variantData.proguardTask = proguardTask
+ // --- Output File ---
+
File outFile;
if (variantData instanceof LibraryVariantData) {
outFile = project.file(
@@ -1367,82 +1379,110 @@ public abstract class BasePlugin {
"${project.buildDir}/classes-proguard/${variantData.dirName}/classes.jar")
}
- // because the Proguard task acts on all the config right away and not when the
- // task actually runs, let's configure it in its doFirst
- proguardTask.doFirst {
- // all the config files coming from build type, product flavors.
- List<Object> proguardFiles = variantConfig.getProguardFiles(true /*includeLibs*/);
- for (Object proguardFile : proguardFiles) {
- proguardTask.configuration(proguardFile)
- }
+ // --- Proguard Config ---
- // also the config file output by aapt
- proguardTask.configuration(variantData.processResourcesTask.proguardOutputFile)
+ if (testedVariantData != null) {
+ // don't remove any code in tested app
+ proguardTask.dontshrink()
+ proguardTask.keepnames("class * extends junit.framework.TestCase")
+ proguardTask.keepclassmembers("class * extends junit.framework.TestCase {\n" +
+ " void test*(...);\n" +
+ "}")
- List<File> packagedJars = getAndroidBuilder(variantData).getPackagedJars(variantConfig)
+ // input the mapping from the tested app so that we can deal with obfuscated code
+ proguardTask.applymapping("${project.buildDir}/proguard/${testedVariantData.dirName}/mapping.txt")
- if (variantData instanceof LibraryVariantData) {
- String packageName = variantConfig.getPackageFromManifest()
- if (packageName == null) {
- throw new BuildException("Failed to read manifest", null)
- }
- packageName = packageName.replace('.', '/');
-
- // injar: the compilation output
- // exclude R files and such from output
- String exclude = '!' + packageName + "/R.class"
- exclude += (', !' + packageName + "/R\$*.class")
- exclude += (', !' + packageName + "/Manifest.class")
- exclude += (', !' + packageName + "/Manifest\$*.class")
- exclude += (', !' + packageName + "/BuildConfig.class")
- proguardTask.injars(variantData.javaCompileTask.destinationDir, filter: exclude)
-
- // include R files and such for compilation
- String include = exclude.replace('!', '')
- proguardTask.libraryjars(variantData.javaCompileTask.destinationDir, filter: include)
-
-
- // injar: the local dependencies, filter out local jars from packagedJars
- Object[] jars = LibraryPlugin.getLocalJarFileList(variantData.variantDependency)
- for (Object inJar : jars) {
- if (packagedJars.contains(inJar)) {
- packagedJars.remove(inJar);
- }
- proguardTask.injars((File) inJar, filter: '!META-INF/MANIFEST.MF')
- }
+ // for tested app, we only care about their aapt config since the base
+ // configs are the same files anyway.
+ proguardTask.configuration(testedVariantData.processResourcesTask.proguardOutputFile)
+ }
- // libjar: the library dependencies
- for (File libJar : packagedJars) {
- proguardTask.libraryjars(libJar, filter: '!META-INF/MANIFEST.MF')
- }
+ // all the config files coming from build type, product flavors.
+ List<Object> proguardFiles = variantConfig.getProguardFiles(true /*includeLibs*/)
+ for (Object proguardFile : proguardFiles) {
+ proguardTask.configuration(proguardFile)
+ }
- // ensure local jars keep their package names
- proguardTask.keeppackagenames()
- } else {
- // injar: the compilation output
- proguardTask.injars(variantData.javaCompileTask.destinationDir)
+ // also the config file output by aapt
+ proguardTask.configuration(variantData.processResourcesTask.proguardOutputFile)
+
+ // --- InJars / LibraryJars ---
- // injar: the dependencies
- for (File inJar : packagedJars) {
- proguardTask.injars(inJar, filter: '!META-INF/MANIFEST.MF')
+ List<File> packagedJars = getAndroidBuilder(variantData).getPackagedJars(variantConfig)
+
+ if (variantData instanceof LibraryVariantData) {
+ String packageName = variantConfig.getPackageFromManifest()
+ if (packageName == null) {
+ throw new BuildException("Failed to read manifest", null)
+ }
+ packageName = packageName.replace('.', '/');
+
+ // injar: the compilation output
+ // exclude R files and such from output
+ String exclude = '!' + packageName + "/R.class"
+ exclude += (', !' + packageName + "/R\$*.class")
+ exclude += (', !' + packageName + "/Manifest.class")
+ exclude += (', !' + packageName + "/Manifest\$*.class")
+ exclude += (', !' + packageName + "/BuildConfig.class")
+ proguardTask.injars(variantData.javaCompileTask.destinationDir, filter: exclude)
+
+ // include R files and such for compilation
+ String include = exclude.replace('!', '')
+ proguardTask.libraryjars(variantData.javaCompileTask.destinationDir, filter: include)
+
+ // injar: the local dependencies, filter out local jars from packagedJars
+ Object[] jars = LibraryPlugin.getLocalJarFileList(variantData.variantDependency)
+ for (Object inJar : jars) {
+ if (packagedJars.contains(inJar)) {
+ packagedJars.remove(inJar);
}
+ proguardTask.injars((File) inJar, filter: '!META-INF/MANIFEST.MF')
}
- // libraryJars: the runtime jars
- for (String runtimeJar : getRuntimeJarList()) {
- proguardTask.libraryjars(runtimeJar)
+ // libjar: the library dependencies
+ for (File libJar : packagedJars) {
+ proguardTask.libraryjars(libJar, filter: '!META-INF/MANIFEST.MF')
+ }
+
+ // ensure local jars keep their package names
+ proguardTask.keeppackagenames()
+ } else {
+ // injar: the compilation output
+ proguardTask.injars(variantData.javaCompileTask.destinationDir)
+
+ // injar: the dependencies
+ for (File inJar : packagedJars) {
+ proguardTask.injars(inJar, filter: '!META-INF/MANIFEST.MF')
}
+ }
- proguardTask.outjars(outFile)
+ // libraryJars: the runtime jars
+ for (String runtimeJar : getRuntimeJarList()) {
+ proguardTask.libraryjars(runtimeJar)
+ }
- proguardTask.dump("${project.buildDir}/proguard/${variantData.dirName}/dump.txt")
- proguardTask.printseeds(
- "${project.buildDir}/proguard/${variantData.dirName}/seeds.txt")
- proguardTask.printusage(
- "${project.buildDir}/proguard/${variantData.dirName}/usage.txt")
- proguardTask.printmapping(
- "${project.buildDir}/proguard/${variantData.dirName}/mapping.txt")
+ if (testedVariantData != null) {
+ // input the tested app as library
+ proguardTask.libraryjars(testedVariantData.javaCompileTask.destinationDir)
+ // including its dependencies
+ List<File> testedPackagedJars = getAndroidBuilder(testedVariantData).getPackagedJars(testedVariantData.variantConfiguration)
+ for (File inJar : testedPackagedJars) {
+ proguardTask.libraryjars(inJar, filter: '!META-INF/MANIFEST.MF')
+ }
}
+
+ // --- Out files ---
+
+ proguardTask.outjars(outFile)
+
+ proguardTask.dump("${project.buildDir}/proguard/${variantData.dirName}/dump.txt")
+ proguardTask.printseeds(
+ "${project.buildDir}/proguard/${variantData.dirName}/seeds.txt")
+ proguardTask.printusage(
+ "${project.buildDir}/proguard/${variantData.dirName}/usage.txt")
+ proguardTask.printmapping(
+ "${project.buildDir}/proguard/${variantData.dirName}/mapping.txt")
+
return outFile
}
diff --git a/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy b/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy
index 69c7c2f..ba86d35 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy
@@ -276,7 +276,7 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> {
if (variantConfig.buildType.runProguard) {
// run proguard on output of compile task
- createProguardTasks(variantData, variantConfig)
+ createProguardTasks(variantData, null)
// hack since bundle can't depend on variantData.proguardTask
mergeProGuardFileTask.dependsOn variantData.proguardTask
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java
index a85d8be..069143e 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java
@@ -144,10 +144,6 @@ public abstract class BaseVariantData {
return StringHelper.capitalize(variantConfiguration.getBuildType().getName());
}
- public boolean getRunProguard() {
- return getVariantConfiguration().getBuildType().isRunProguard();
- }
-
public void setOutputFile(Object file) {
outputFile = file;
}
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java
index dca2d16..ebd336c 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java
@@ -87,9 +87,4 @@ public class TestVariantData extends ApkVariantData {
public boolean getZipAlign() {
return false;
}
-
- @Override
- public boolean getRunProguard() {
- return false;
- }
}
diff --git a/tests/proguard/src/instrumentTest/java/com/android/tests/basic/MainTest.java b/tests/proguard/src/instrumentTest/java/com/android/tests/basic/MainTest.java
index cbbc52b..44bc9f4 100644
--- a/tests/proguard/src/instrumentTest/java/com/android/tests/basic/MainTest.java
+++ b/tests/proguard/src/instrumentTest/java/com/android/tests/basic/MainTest.java
@@ -38,5 +38,12 @@ public class MainTest extends ActivityInstrumentationTestCase2<Main> {
public void testTextViewContent() {
assertEquals("1234", mTextView.getText());
}
+
+ /** Test using a obfuscated class */
+ public void testObfuscatedCode() {
+ final Main a = getActivity();
+ StringProvider sp = a.getStringProvider();
+ assertEquals("42", sp.getString(42));
+ }
}
diff --git a/tests/proguard/src/main/java/com/android/tests/basic/Main.java b/tests/proguard/src/main/java/com/android/tests/basic/Main.java
index 6d3ae10..e32404a 100644
--- a/tests/proguard/src/main/java/com/android/tests/basic/Main.java
+++ b/tests/proguard/src/main/java/com/android/tests/basic/Main.java
@@ -4,20 +4,23 @@ import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
-public class Main extends Activity
-{
+public class Main extends Activity {
private int foo = 1234;
+ private final StringProvider mStringProvider = new StringProvider();
+
/** Called when the activity is first created. */
@Override
- public void onCreate(Bundle savedInstanceState)
- {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView) findViewById(R.id.dateText);
- StringProvider stringProvider = new StringProvider();
- tv.setText(stringProvider.getString(foo));
+ tv.setText(getStringProvider().getString(foo));
+ }
+
+ public StringProvider getStringProvider() {
+ return mStringProvider;
}
}