aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWing Lam <lamwing@google.com>2013-08-20 16:38:23 -0700
committerWing Lam <lamwing@google.com>2013-08-21 11:09:36 -0700
commitc4986e7a0c8022817df8f6dabbab4e8a87bd0477 (patch)
treeba80b3f6c7fb5c15e6c44769790967fccf4462e2
parent263c42c75f782fae79f029287b5cf3e12c19039e (diff)
downloadbuild-c4986e7a0c8022817df8f6dabbab4e8a87bd0477.tar.gz
ProGuard support for libraries.
Change-Id: I38069666a4cc9f84c07337f26bd6dcdb0b253548
-rw-r--r--.gitignore2
-rw-r--r--builder-model/src/main/java/com/android/builder/model/BaseConfig.java8
-rw-r--r--builder/src/main/java/com/android/builder/AndroidBuilder.java10
-rw-r--r--builder/src/main/java/com/android/builder/DefaultBuildType.java6
-rw-r--r--builder/src/main/java/com/android/builder/VariantConfiguration.java15
-rw-r--r--builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java12
-rw-r--r--gradle/build.gradle2
-rw-r--r--gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java9
-rw-r--r--gradle/src/build-test/groovy/com/android/build/gradle/ManualBuildTest.java40
-rw-r--r--gradle/src/device-test/groovy/com/android/build/gradle/DeviceTest.java5
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy150
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy73
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy15
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy15
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java9
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java6
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java2
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java5
-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/libProguard/build.gradle26
-rw-r--r--tests/libProguard/config.pro3
-rw-r--r--tests/libProguard/src/main/AndroidManifest.xml4
-rw-r--r--tests/libProguard/src/main/java/com/android/tests/basic/StringProvider.java11
-rw-r--r--tests/libProguardConsumerFiles/A.txt1
-rw-r--r--tests/libProguardConsumerFiles/B.txt1
-rw-r--r--tests/libProguardConsumerFiles/C.txt1
-rw-r--r--tests/libProguardConsumerFiles/build.gradle32
-rw-r--r--tests/libProguardConsumerFiles/config.pro3
-rw-r--r--tests/libProguardConsumerFiles/src/main/AndroidManifest.xml4
-rw-r--r--tests/libProguardConsumerFiles/src/main/java/com/android/tests/basic/StringProvider.java11
-rw-r--r--tests/libProguardJarDep/app/build.gradle35
-rw-r--r--tests/libProguardJarDep/app/config.pro2
-rw-r--r--tests/libProguardJarDep/app/src/instrumentTest/java/com/android/tests/basic/MainTest.java42
-rw-r--r--tests/libProguardJarDep/app/src/main/AndroidManifest.xml30
-rw-r--r--tests/libProguardJarDep/app/src/main/java/com/android/tests/basic/Main.java31
-rw-r--r--tests/libProguardJarDep/app/src/main/res/drawable/icon.pngbin0 -> 2574 bytes
-rw-r--r--tests/libProguardJarDep/app/src/main/res/layout/main.xml20
-rw-r--r--tests/libProguardJarDep/app/src/main/res/values/strings.xml4
-rw-r--r--tests/libProguardJarDep/build.gradle8
-rw-r--r--tests/libProguardJarDep/lib/build.gradle30
-rw-r--r--tests/libProguardJarDep/lib/config.pro3
-rw-r--r--tests/libProguardJarDep/lib/libs/util-1.0.jarbin0 -> 1997 bytes
-rw-r--r--tests/libProguardJarDep/lib/src/main/AndroidManifest.xml5
-rw-r--r--tests/libProguardJarDep/lib/src/main/java/com/android/tests/basic/StringGetter.java23
-rw-r--r--tests/libProguardJarDep/settings.gradle2
-rw-r--r--tests/libProguardJarDep/util/build.gradle8
-rw-r--r--tests/libProguardJarDep/util/src/main/java/com/example/android/multiproject/person/People.java10
-rw-r--r--tests/libProguardJarDep/util/src/main/java/com/example/android/multiproject/person/Person.java13
-rw-r--r--tests/libProguardLibDep/app/build.gradle31
-rw-r--r--tests/libProguardLibDep/app/config.pro3
-rw-r--r--tests/libProguardLibDep/app/src/instrumentTest/java/com/android/tests/basic/MainTest.java54
-rw-r--r--tests/libProguardLibDep/app/src/main/AndroidManifest.xml30
-rw-r--r--tests/libProguardLibDep/app/src/main/java/com/android/tests/basic/Main.java46
-rw-r--r--tests/libProguardLibDep/app/src/main/res/drawable/icon.pngbin0 -> 2574 bytes
-rw-r--r--tests/libProguardLibDep/app/src/main/res/layout/main.xml20
-rw-r--r--tests/libProguardLibDep/app/src/main/res/values/strings.xml4
-rw-r--r--tests/libProguardLibDep/build.gradle8
-rw-r--r--tests/libProguardLibDep/lib/build.gradle22
-rw-r--r--tests/libProguardLibDep/lib/config.pro3
-rw-r--r--tests/libProguardLibDep/lib/consumerRules.pro6
-rw-r--r--tests/libProguardLibDep/lib/src/main/AndroidManifest.xml5
-rw-r--r--tests/libProguardLibDep/lib/src/main/java/com/android/tests/basic/StringGetter.java23
-rw-r--r--tests/libProguardLibDep/lib2/build.gradle18
-rw-r--r--tests/libProguardLibDep/lib2/config.pro3
-rw-r--r--tests/libProguardLibDep/lib2/src/main/AndroidManifest.xml4
-rw-r--r--tests/libProguardLibDep/lib2/src/main/java/com/android/tests/basic/StringProvider.java8
-rw-r--r--tests/libProguardLibDep/settings.gradle3
-rw-r--r--tests/proguardLib/lib/build.gradle4
69 files changed, 948 insertions, 103 deletions
diff --git a/.gitignore b/.gitignore
index 17e4ab3..ffc527f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,8 @@ tests/3rdPartyTests/*/build
tests/dependencies/jarProject/build
tests/flavorlib/*/build
tests/flavorlibWithFailedTests/*/build
+tests/libProguardJarDep/*/build
+tests/libProguardLibDep/*/build
tests/libsTest/*/build
tests/multiproject/*/build
tests/localJars/*/build
diff --git a/builder-model/src/main/java/com/android/builder/model/BaseConfig.java b/builder-model/src/main/java/com/android/builder/model/BaseConfig.java
index ff3efcc..fbf6eb4 100644
--- a/builder-model/src/main/java/com/android/builder/model/BaseConfig.java
+++ b/builder-model/src/main/java/com/android/builder/model/BaseConfig.java
@@ -40,4 +40,12 @@ public interface BaseConfig {
*/
@NonNull
List<File> getProguardFiles();
+
+ /**
+ * Returns the list of proguard rule files for consumers of the library to use.
+ *
+ * @return a non-null list of files.
+ */
+ @NonNull
+ List<File> getConsumerProguardFiles();
}
diff --git a/builder/src/main/java/com/android/builder/AndroidBuilder.java b/builder/src/main/java/com/android/builder/AndroidBuilder.java
index 9442f4d..34c0dd4 100644
--- a/builder/src/main/java/com/android/builder/AndroidBuilder.java
+++ b/builder/src/main/java/com/android/builder/AndroidBuilder.java
@@ -564,14 +564,14 @@ public class AndroidBuilder {
command.add(sourceOutputDir);
}
- if (type != VariantConfiguration.Type.LIBRARY && resPackageOutput != null) {
+ if (resPackageOutput != null) {
command.add("-F");
command.add(resPackageOutput);
+ }
- if (proguardOutput != null) {
- command.add("-G");
- command.add(proguardOutput);
- }
+ if (proguardOutput != null) {
+ command.add("-G");
+ command.add(proguardOutput);
}
// options controlled by build variants
diff --git a/builder/src/main/java/com/android/builder/DefaultBuildType.java b/builder/src/main/java/com/android/builder/DefaultBuildType.java
index ea82e12..5ebbd0b 100644
--- a/builder/src/main/java/com/android/builder/DefaultBuildType.java
+++ b/builder/src/main/java/com/android/builder/DefaultBuildType.java
@@ -111,7 +111,8 @@ public class DefaultBuildType extends BaseConfigImpl implements BuildType {
}
@Override
- @Nullable public String getPackageNameSuffix() {
+ @Nullable
+ public String getPackageNameSuffix() {
return mPackageNameSuffix;
}
@@ -122,7 +123,8 @@ public class DefaultBuildType extends BaseConfigImpl implements BuildType {
}
@Override
- @Nullable public String getVersionNameSuffix() {
+ @Nullable
+ public String getVersionNameSuffix() {
return mVersionNameSuffix;
}
diff --git a/builder/src/main/java/com/android/builder/VariantConfiguration.java b/builder/src/main/java/com/android/builder/VariantConfiguration.java
index 614d467..5b1b5e5 100644
--- a/builder/src/main/java/com/android/builder/VariantConfiguration.java
+++ b/builder/src/main/java/com/android/builder/VariantConfiguration.java
@@ -885,6 +885,21 @@ public class VariantConfiguration implements TestData {
return fullList;
}
+ @NonNull
+ public List<Object> getConsumerProguardFiles() {
+ List<Object> fullList = Lists.newArrayList();
+
+ // add the config files from the build type, main config and flavors
+ fullList.addAll(mDefaultConfig.getConsumerProguardFiles());
+ fullList.addAll(mBuildType.getConsumerProguardFiles());
+
+ for (DefaultProductFlavor flavor : mFlavorConfigs) {
+ fullList.addAll(flavor.getConsumerProguardFiles());
+ }
+
+ return fullList;
+ }
+
protected void validate() {
if (mType != Type.TEST) {
File manifest = mDefaultSourceProvider.getManifestFile();
diff --git a/builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java b/builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java
index e2517c5..044420b 100644
--- a/builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java
+++ b/builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java
@@ -33,6 +33,7 @@ public class BaseConfigImpl implements Serializable, BaseConfig {
private final List<String> mBuildConfigLines = Lists.newArrayList();
private final List<File> mProguardFiles = Lists.newArrayList();
+ private final List<File> mConsumerProguardFiles = Lists.newArrayList();
public void setBuildConfig(String... lines) {
mBuildConfigLines.clear();
@@ -56,12 +57,21 @@ public class BaseConfigImpl implements Serializable, BaseConfig {
return mProguardFiles;
}
+ @Override
+ @NonNull
+ public List<File> getConsumerProguardFiles() {
+ return mConsumerProguardFiles;
+ }
+
protected void _initWith(BaseConfig that) {
mBuildConfigLines.clear();
mBuildConfigLines.addAll(that.getBuildConfig());
mProguardFiles.clear();
mProguardFiles.addAll(that.getProguardFiles());
+
+ mConsumerProguardFiles.clear();
+ mConsumerProguardFiles.addAll(that.getConsumerProguardFiles());
}
@Override
@@ -73,6 +83,7 @@ public class BaseConfigImpl implements Serializable, BaseConfig {
if (!mBuildConfigLines.equals(that.mBuildConfigLines)) return false;
if (!mProguardFiles.equals(that.mProguardFiles)) return false;
+ if (!mConsumerProguardFiles.equals(that.mConsumerProguardFiles)) return false;
return true;
}
@@ -81,6 +92,7 @@ public class BaseConfigImpl implements Serializable, BaseConfig {
public int hashCode() {
int result = mBuildConfigLines.hashCode();
result = 31 * result + mProguardFiles.hashCode();
+ result = 31 * result + mConsumerProguardFiles.hashCode();
return result;
}
}
diff --git a/gradle/build.gradle b/gradle/build.gradle
index 16b99e6..89d1d47 100644
--- a/gradle/build.gradle
+++ b/gradle/build.gradle
@@ -29,7 +29,7 @@ dependencies {
groovy localGroovy()
compile project(':builder')
- runtime 'net.sf.proguard:proguard-gradle:4.9'
+ compile 'net.sf.proguard:proguard-gradle:4.9'
testCompile 'junit:junit:3.8.1'
diff --git a/gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java b/gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java
index b92239f..c2b1e0c 100644
--- a/gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java
+++ b/gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java
@@ -35,10 +35,11 @@ public class AutomatedBuildTest extends BuildTest {
private static final String[] sBuiltProjects = new String[] {
"aidl", "api", "applibtest", "assets", "attrOrder", "basic", "dependencies",
- "dependencyChecker", "flavored", "flavorlib", "flavors", "libTestDep", "libsTest",
- "localJars", "migrated", "multiproject", "multires", "overlay1", "overlay2",
- "pkgOverride", "proguard", "proguardLib", "renderscript", "renderscriptInLib",
- "renderscriptMultiSrc", "sameNamedLibs", "tictactoe" /*, "autorepo"*/
+ "dependencyChecker", "flavored", "flavorlib", "flavors", "libProguardJarDep",
+ "libProguardLibDep", "libTestDep", "libsTest", "localJars", "migrated", "multiproject",
+ "multires", "overlay1", "overlay2", "pkgOverride", "proguard", "proguardLib",
+ "renderscript", "renderscriptInLib", "renderscriptMultiSrc", "sameNamedLibs",
+ "tictactoe" /*, "autorepo"*/
};
private static final String[] sReportProjects = new String[] {
diff --git a/gradle/src/build-test/groovy/com/android/build/gradle/ManualBuildTest.java b/gradle/src/build-test/groovy/com/android/build/gradle/ManualBuildTest.java
index 0ccfc24..af0bd32 100644
--- a/gradle/src/build-test/groovy/com/android/build/gradle/ManualBuildTest.java
+++ b/gradle/src/build-test/groovy/com/android/build/gradle/ManualBuildTest.java
@@ -16,10 +16,13 @@
package com.android.build.gradle;
-import javax.imageio.ImageIO;
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
+import javax.imageio.ImageIO;
/**
* Some manual tests for building projects.
@@ -67,6 +70,29 @@ public class ManualBuildTest extends BuildTest {
}
}
+ // test whether a library project has its fields ProGuarded
+ public void testLibProguard() throws Exception {
+ File project = new File(testDir, "libProguard");
+ File fileOutput = new File(project, "build/proguard/release");
+
+ runGradleTasks(sdkDir, BasePlugin.GRADLE_MIN_VERSION,
+ project, "clean", "build");
+ checkFile(fileOutput, "mapping.txt", new String[]{"int proguardInt -> a"});
+
+ }
+
+ // test whether proguard.txt has been correctly merged
+ public void testLibProguardConsumerFile() throws Exception {
+ File project = new File(testDir, "libProguardConsumerFiles");
+ File debugFileOutput = new File(project, "build/bundles/debug");
+ File releaseFileOutput = new File(project, "build/bundles/release");
+
+ runGradleTasks(sdkDir, BasePlugin.GRADLE_MIN_VERSION,
+ project, "clean", "build");
+ checkFile(debugFileOutput, "proguard.txt", new String[]{"A"});
+ checkFile(releaseFileOutput, "proguard.txt", new String[]{"A", "B", "C"});
+ }
+
public void test3rdPartyTests() throws Exception {
// custom because we want to run deviceCheck even without devices, since we use
// a fake DeviceProvider that doesn't use a device, but only record the calls made
@@ -86,4 +112,16 @@ public class ManualBuildTest extends BuildTest {
expectedColor, rgb, f),
expectedColor, rgb);
}
+
+ private static void checkFile(File folder, String fileName, String[] expectedContents)
+ throws IOException {
+ File f = new File(folder, fileName);
+ assertTrue("File '" + f.getAbsolutePath() + "' does not exist.", f.isFile());
+
+ String contents = Files.toString(f, Charsets.UTF_8);
+ for (String expectedContent : expectedContents) {
+ assertTrue("File '" + f.getAbsolutePath() + "' does not contain: " + expectedContent,
+ contents.contains(expectedContent));
+ }
+ }
}
diff --git a/gradle/src/device-test/groovy/com/android/build/gradle/DeviceTest.java b/gradle/src/device-test/groovy/com/android/build/gradle/DeviceTest.java
index 93b53b6..388aef9 100644
--- a/gradle/src/device-test/groovy/com/android/build/gradle/DeviceTest.java
+++ b/gradle/src/device-test/groovy/com/android/build/gradle/DeviceTest.java
@@ -39,8 +39,9 @@ public class DeviceTest extends BuildTest {
private static final String[] sBuiltProjects = new String[] {
"api", "assets", "applibtest", "attrOrder", "basic", "dependencies", "flavored",
- "flavorlib", "flavors", "libTestDep", "libsTest", "migrated", "multires", "overlay1",
- "overlay2", "pkgOverride", "proguard", "proguardLib", "sameNamedLibs"
+ "flavorlib", "flavors", "libProguardJarDep", "libProguardLibDep", "libTestDep", "libsTest",
+ "migrated", "multires", "overlay1", "overlay2", "pkgOverride", "proguard", "proguardLib",
+ "sameNamedLibs"
};
public static Test suite() {
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 e85c784..4e30a74 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
@@ -118,6 +118,8 @@ import static com.android.builder.BuilderConstants.INSTRUMENT_TEST
* Base class for all Android plugins
*/
public abstract class BasePlugin {
+ protected final static String DIR_BUNDLES = "bundles";
+
public static final String GRADLE_MIN_VERSION = "1.6"
public static final String[] GRADLE_SUPPORTED_VERSIONS = [ GRADLE_MIN_VERSION, "1.7" ]
@@ -968,55 +970,11 @@ public abstract class BasePlugin {
Closure proguardFileClosure = { }
if (!(variantData instanceof TestVariantData) && variantConfig.buildType.runProguard) {
-
- def proguardTask = project.tasks.create("proguard${variantData.name}", ProGuardTask);
- proguardTask.dependsOn variantData.javaCompileTask
- variantData.proguardTask = proguardTask
-
- File outFile = project.file(
- "${project.buildDir}/classes-proguard/${variantData.dirName}/classes.jar")
-
libraryClosure = { Collections.emptyList() }
sourceClosure = { Collections.emptyList() }
- proguardFileClosure = { outFile }
-
- // 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)
- }
-
- // also the config file output by aapt
- proguardTask.configuration(variantData.processResourcesTask.proguardOutputFile)
-
- // injar: the compilation output
- proguardTask.injars(variantData.javaCompileTask.destinationDir)
-
- // injar: the dependencies
- for (File inJar : variantConfig.packagedJars) {
- proguardTask.injars(inJar, filter: '!META-INF/MANIFEST.MF')
- }
- // libraryJars: the runtime jars
- for (String runtimeJar : getRuntimeJarList()) {
- proguardTask.libraryjars(runtimeJar)
- }
-
- 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")
- }
+ File outFile = createProguardTasks(variantData, variantConfig)
+ proguardFileClosure = { outFile }
}
// Add a dex task
@@ -1147,6 +1105,106 @@ public abstract class BasePlugin {
uninstallAll.dependsOn uninstallTask
}
+ /**
+ * Creates the proguarding task for the given Variant.
+ * @param variantData the variant data.
+ * @param variantConfig the variant configuration of variantData
+ * @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);
+ proguardTask.dependsOn variantData.javaCompileTask
+ variantData.proguardTask = proguardTask
+
+ File outFile;
+ if (variantData instanceof LibraryVariantData) {
+ outFile = project.file(
+ "${project.buildDir}/$DIR_BUNDLES/${variantData.dirName}/classes.jar")
+ } else {
+ outFile = project.file(
+ "${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)
+ }
+
+ // also the config file output by aapt
+ proguardTask.configuration(variantData.processResourcesTask.proguardOutputFile)
+
+ 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)
+
+ List<File> packagedJars = variantConfig.packagedJars
+
+ // 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')
+ }
+
+ // 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 : variantConfig.packagedJars) {
+ proguardTask.injars(inJar, filter: '!META-INF/MANIFEST.MF')
+ }
+ }
+
+ // libraryJars: the runtime jars
+ for (String runtimeJar : getRuntimeJarList()) {
+ proguardTask.libraryjars(runtimeJar)
+ }
+
+ 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
+ }
+
private void createReportTasks() {
def dependencyReportTask = project.tasks.create("androidDependencies", DependencyReportTask)
dependencyReportTask.setDescription("Displays the Android dependencies of the project")
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 93420e8..750d23f 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy
@@ -58,8 +58,6 @@ import javax.inject.Inject
*/
public class LibraryPlugin extends BasePlugin implements Plugin<Project> {
- private final static String DIR_BUNDLES = "bundles";
-
LibraryExtension extension
BuildTypeData debugBuildTypeData
BuildTypeData releaseBuildTypeData
@@ -185,11 +183,6 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> {
VariantConfiguration variantConfig = variantData.variantConfiguration
DefaultBuildType buildType = variantConfig.buildType
- String packageName = variantConfig.getPackageFromManifest()
- if (packageName == null) {
- throw new BuildException("Failed to read manifest", null)
- }
-
createPrepareDependenciesTask(variantData)
// Add a task to process the manifest(s)
@@ -230,21 +223,6 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> {
// Add a compile task
createCompileTask(variantData, null/*testedVariant*/)
- // jar the classes.
- Jar jar = project.tasks.create("package${buildType.name.capitalize()}Jar", Jar);
- jar.dependsOn variantData.javaCompileTask, variantData.processJavaResources
- jar.from(variantData.javaCompileTask.outputs);
- jar.from(variantData.processJavaResources.destinationDir)
-
- jar.destinationDir = project.file("$project.buildDir/$DIR_BUNDLES/${variantData.dirName}")
- jar.archiveName = "classes.jar"
- packageName = packageName.replace('.', '/');
- jar.exclude(packageName + "/R.class")
- jar.exclude(packageName + "/R\$*.class")
- jar.exclude(packageName + "/Manifest.class")
- jar.exclude(packageName + "/Manifest\$*.class")
- jar.exclude(packageName + "/BuildConfig.class")
-
// package the aidl files into the bundle folder
Sync packageAidl = project.tasks.create("package${variantData.name}Aidl", Sync)
// packageAidl from 3 sources. the order is important to make sure the override works well.
@@ -260,24 +238,57 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> {
packageRenderscript.into(project.file(
"$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/$SdkConstants.FD_RENDERSCRIPT"))
- // package the renderscript header files files into the bundle folder
- Sync packageLocalJar = project.tasks.create("package${variantData.name}LocalJar", Sync)
- packageLocalJar.from(getLocalJarFileList(variantData.variantDependency))
- packageLocalJar.into(project.file(
- "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/$SdkConstants.LIBS_FOLDER"))
-
- // merge the proguard files together
+ // merge consumer proguard files from different build types and flavors
MergeFileTask mergeFileTask = project.tasks.create("merge${variantData.name}ProguardFiles",
MergeFileTask)
mergeFileTask.conventionMapping.inputFiles = {
- project.files(variantConfig.getProguardFiles(false)).files }
+ project.files(variantConfig.getConsumerProguardFiles()).files }
mergeFileTask.conventionMapping.outputFile = {
project.file(
"$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/$LibraryBundle.FN_PROGUARD_TXT")
}
Zip bundle = project.tasks.create("bundle${variantData.name}", Zip)
- bundle.dependsOn packageRes, jar, packageAidl, packageRenderscript, packageLocalJar, mergeFileTask
+
+ if (variantConfig.buildType.runProguard) {
+ // run proguard on output of compile task
+ createProguardTasks(variantData, variantConfig)
+
+ // hack since bundle can't depend on variantData.proguardTask
+ mergeFileTask.dependsOn variantData.proguardTask
+
+ bundle.dependsOn packageRes, packageAidl, packageRenderscript, mergeFileTask
+ } else {
+ Sync packageLocalJar = project.tasks.create("package${variantData.name}LocalJar", Sync)
+ packageLocalJar.from(getLocalJarFileList(variantData.variantDependency))
+ packageLocalJar.into(project.file(
+ "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/$SdkConstants.LIBS_FOLDER"))
+
+ // jar the classes.
+ Jar jar = project.tasks.create("package${buildType.name.capitalize()}Jar", Jar);
+ jar.dependsOn variantData.javaCompileTask, variantData.processJavaResources
+ jar.from(variantData.javaCompileTask.outputs);
+ jar.from(variantData.processJavaResources.destinationDir)
+
+ jar.destinationDir = project.file("$project.buildDir/$DIR_BUNDLES/${variantData.dirName}")
+ jar.archiveName = "classes.jar"
+
+ String packageName = variantConfig.getPackageFromManifest()
+ if (packageName == null) {
+ throw new BuildException("Failed to read manifest", null)
+ }
+ packageName = packageName.replace('.', '/');
+
+ jar.exclude(packageName + "/R.class")
+ jar.exclude(packageName + "/R\$*.class")
+ jar.exclude(packageName + "/Manifest.class")
+ jar.exclude(packageName + "/Manifest\$*.class")
+ jar.exclude(packageName + "/BuildConfig.class")
+
+ bundle.dependsOn packageRes, jar, packageAidl, packageRenderscript, packageLocalJar,
+ mergeFileTask
+ }
+
bundle.setDescription("Assembles a bundle containing the library in ${variantData.name}.");
bundle.destinationDir = project.file("$project.buildDir/libs")
bundle.extension = BuilderConstants.EXT_LIB_ARCHIVE
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy
index 6c4f97f..e8fa660 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy
@@ -86,4 +86,19 @@ public class BuildTypeDsl extends DefaultBuildType implements Serializable {
}
return this;
}
+
+ @NonNull
+ public BuildTypeDsl consumerProguardFiles(Object... proguardFileArray) {
+ consumerProguardFiles.addAll(fileResolver.resolveFiles(proguardFileArray).files);
+ return this;
+ }
+
+ @NonNull
+ public BuildTypeDsl setConsumerProguardFiles(Iterable<?> proguardFileIterable) {
+ consumerProguardFiles.clear();
+ for (Object proguardFile : proguardFileIterable) {
+ consumerProguardFiles.add(fileResolver.resolve(proguardFile));
+ }
+ return this;
+ }
}
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy
index 91a27b1..4ae05cb 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy
@@ -63,4 +63,19 @@ class ProductFlavorDsl extends DefaultProductFlavor {
}
return this;
}
+
+ @NonNull
+ public ProductFlavorDsl consumerProguardFiles(Object... proguardFileArray) {
+ consumerProguardFiles.addAll(fileResolver.resolveFiles(proguardFileArray).files);
+ return this;
+ }
+
+ @NonNull
+ public ProductFlavorDsl setconsumerProguardFiles(Iterable<?> proguardFileIterable) {
+ consumerProguardFiles.clear();
+ for (Object proguardFile : proguardFileIterable) {
+ consumerProguardFiles.add(fileResolver.resolve(proguardFile));
+ }
+ return this;
+ }
}
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java
index f5fa46c..11b387d 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java
@@ -115,8 +115,15 @@ class BuildTypeImpl implements BuildType, Serializable {
return Collections.emptyList();
}
+ @NonNull
+ @Override
+ public List<File> getProguardFiles() {
+ return Collections.emptyList();
+ }
+
+ @NonNull
@Override
- public @NonNull List<File> getProguardFiles() {
+ public List<File> getConsumerProguardFiles() {
return Collections.emptyList();
}
}
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java
index db4cb6b..0e3be19 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java
@@ -142,4 +142,10 @@ class ProductFlavorImpl implements ProductFlavor, Serializable {
public List<File> getProguardFiles() {
return Collections.emptyList();
}
+
+ @NonNull
+ @Override
+ public List<File> getConsumerProguardFiles() {
+ return Collections.emptyList();
+ }
}
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java
index 822cdfe..ef74235 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java
@@ -21,14 +21,12 @@ import com.android.build.gradle.tasks.PackageApplication;
import com.android.build.gradle.tasks.ZipAlign;
import com.android.builder.VariantConfiguration;
import org.gradle.api.DefaultTask;
-import proguard.gradle.ProGuardTask;
/**
* Base data about a variant that generates an APK file.
*/
public abstract class ApkVariantData extends BaseVariantData {
- public ProGuardTask proguardTask;
public Dex dexTask;
public PackageApplication packageApplicationTask;
public ZipAlign zipAlignTask;
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java
index 0f8d4ed..a602a29 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java
+++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java
@@ -41,11 +41,6 @@ public class ApplicationVariantData extends ApkVariantData implements TestedVari
}
@Override
- public boolean getRunProguard() {
- return getVariantConfiguration().getBuildType().isRunProguard();
- }
-
- @Override
public void setTestVariantData(@Nullable TestVariantData testVariantData) {
this.testVariantData = testVariantData;
}
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 135eeaf..f69a1d4 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
@@ -34,6 +34,7 @@ import groovy.lang.Closure;
import org.gradle.api.Task;
import org.gradle.api.tasks.Copy;
import org.gradle.api.tasks.compile.JavaCompile;
+import proguard.gradle.ProGuardTask;
import java.io.File;
@@ -57,6 +58,7 @@ public abstract class BaseVariantData {
public GenerateBuildConfig generateBuildConfigTask;
public JavaCompile javaCompileTask;
+ public ProGuardTask proguardTask;
public Copy processJavaResources;
private Object outputFile;
@@ -139,7 +141,7 @@ public abstract class BaseVariantData {
}
public boolean getRunProguard() {
- return false;
+ return getVariantConfiguration().getBuildType().isRunProguard();
}
public void setOutputFile(Object 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 ebd336c..dca2d16 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,4 +87,9 @@ public class TestVariantData extends ApkVariantData {
public boolean getZipAlign() {
return false;
}
+
+ @Override
+ public boolean getRunProguard() {
+ return false;
+ }
}
diff --git a/tests/libProguard/build.gradle b/tests/libProguard/build.gradle
new file mode 100644
index 0000000..6a522ee
--- /dev/null
+++ b/tests/libProguard/build.gradle
@@ -0,0 +1,26 @@
+buildscript {
+ repositories {
+ maven { url '../../../../out/host/gradle/repo' }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:0.5.0-SNAPSHOT'
+ }
+}
+
+apply plugin: 'android-library'
+
+android {
+ compileSdkVersion 15
+ buildToolsVersion "18.0.1"
+
+ defaultConfig {
+ versionCode 12
+ versionName "2.0"
+ minSdkVersion 16
+ targetSdkVersion 16
+ proguardFile 'config.pro'
+ }
+ release {
+ runProguard true
+ }
+}
diff --git a/tests/libProguard/config.pro b/tests/libProguard/config.pro
new file mode 100644
index 0000000..3664f87
--- /dev/null
+++ b/tests/libProguard/config.pro
@@ -0,0 +1,3 @@
+-keep public class com.android.tests.basic.StringProvider {
+ public static java.lang.String getString(int);
+}
diff --git a/tests/libProguard/src/main/AndroidManifest.xml b/tests/libProguard/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..593a287
--- /dev/null
+++ b/tests/libProguard/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.basic">
+</manifest>
diff --git a/tests/libProguard/src/main/java/com/android/tests/basic/StringProvider.java b/tests/libProguard/src/main/java/com/android/tests/basic/StringProvider.java
new file mode 100644
index 0000000..18fe927
--- /dev/null
+++ b/tests/libProguard/src/main/java/com/android/tests/basic/StringProvider.java
@@ -0,0 +1,11 @@
+package com.android.tests.basic;
+
+import java.lang.Integer;
+
+public class StringProvider {
+ private static int proguardInt = 5;
+
+ public static String getString(int foo) {
+ return Integer.toString(foo + proguardInt);
+ }
+}
diff --git a/tests/libProguardConsumerFiles/A.txt b/tests/libProguardConsumerFiles/A.txt
new file mode 100644
index 0000000..f70f10e
--- /dev/null
+++ b/tests/libProguardConsumerFiles/A.txt
@@ -0,0 +1 @@
+A
diff --git a/tests/libProguardConsumerFiles/B.txt b/tests/libProguardConsumerFiles/B.txt
new file mode 100644
index 0000000..223b783
--- /dev/null
+++ b/tests/libProguardConsumerFiles/B.txt
@@ -0,0 +1 @@
+B
diff --git a/tests/libProguardConsumerFiles/C.txt b/tests/libProguardConsumerFiles/C.txt
new file mode 100644
index 0000000..3cc58df
--- /dev/null
+++ b/tests/libProguardConsumerFiles/C.txt
@@ -0,0 +1 @@
+C
diff --git a/tests/libProguardConsumerFiles/build.gradle b/tests/libProguardConsumerFiles/build.gradle
new file mode 100644
index 0000000..fbefef8
--- /dev/null
+++ b/tests/libProguardConsumerFiles/build.gradle
@@ -0,0 +1,32 @@
+buildscript {
+ repositories {
+ maven { url '../../../../out/host/gradle/repo' }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:0.5.0-SNAPSHOT'
+ }
+}
+
+apply plugin: 'android-library'
+
+android {
+ compileSdkVersion 15
+ buildToolsVersion "18.0.1"
+
+ defaultConfig {
+ versionCode 12
+ versionName "2.0"
+ minSdkVersion 16
+ targetSdkVersion 16
+ proguardFile 'config.pro'
+ consumerProguardFiles 'A.txt'
+ }
+
+ debug {
+ }
+
+ release {
+ runProguard true
+ consumerProguardFiles 'B.txt', 'C.txt'
+ }
+}
diff --git a/tests/libProguardConsumerFiles/config.pro b/tests/libProguardConsumerFiles/config.pro
new file mode 100644
index 0000000..3664f87
--- /dev/null
+++ b/tests/libProguardConsumerFiles/config.pro
@@ -0,0 +1,3 @@
+-keep public class com.android.tests.basic.StringProvider {
+ public static java.lang.String getString(int);
+}
diff --git a/tests/libProguardConsumerFiles/src/main/AndroidManifest.xml b/tests/libProguardConsumerFiles/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..593a287
--- /dev/null
+++ b/tests/libProguardConsumerFiles/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.basic">
+</manifest>
diff --git a/tests/libProguardConsumerFiles/src/main/java/com/android/tests/basic/StringProvider.java b/tests/libProguardConsumerFiles/src/main/java/com/android/tests/basic/StringProvider.java
new file mode 100644
index 0000000..18fe927
--- /dev/null
+++ b/tests/libProguardConsumerFiles/src/main/java/com/android/tests/basic/StringProvider.java
@@ -0,0 +1,11 @@
+package com.android.tests.basic;
+
+import java.lang.Integer;
+
+public class StringProvider {
+ private static int proguardInt = 5;
+
+ public static String getString(int foo) {
+ return Integer.toString(foo + proguardInt);
+ }
+}
diff --git a/tests/libProguardJarDep/app/build.gradle b/tests/libProguardJarDep/app/build.gradle
new file mode 100644
index 0000000..8166bf8
--- /dev/null
+++ b/tests/libProguardJarDep/app/build.gradle
@@ -0,0 +1,35 @@
+apply plugin: 'android'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compile project(':lib')
+}
+
+android {
+ compileSdkVersion 15
+ buildToolsVersion "18.0.1"
+
+ testBuildType "proguard"
+
+ defaultConfig {
+ versionCode 12
+ versionName "2.0"
+ minSdkVersion 16
+ targetSdkVersion 16
+ }
+
+ buildTypes {
+ proguard.initWith(buildTypes.debug)
+ proguard {
+ runProguard true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'config.pro'
+ }
+ }
+
+ dexOptions {
+ incremental false
+ }
+}
diff --git a/tests/libProguardJarDep/app/config.pro b/tests/libProguardJarDep/app/config.pro
new file mode 100644
index 0000000..4321975
--- /dev/null
+++ b/tests/libProguardJarDep/app/config.pro
@@ -0,0 +1,2 @@
+-keep class com.google.**
+-dontwarn com.google.**
diff --git a/tests/libProguardJarDep/app/src/instrumentTest/java/com/android/tests/basic/MainTest.java b/tests/libProguardJarDep/app/src/instrumentTest/java/com/android/tests/basic/MainTest.java
new file mode 100644
index 0000000..6b3ff36
--- /dev/null
+++ b/tests/libProguardJarDep/app/src/instrumentTest/java/com/android/tests/basic/MainTest.java
@@ -0,0 +1,42 @@
+package com.android.tests.basic;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.TextView;
+
+public class MainTest extends ActivityInstrumentationTestCase2<Main> {
+
+ private TextView mTextView;
+
+ /**
+ * Creates an {@link ActivityInstrumentationTestCase2} that tests the {@link Main} activity.
+ */
+ public MainTest() {
+ super(Main.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final Main a = getActivity();
+ // ensure a valid handle to the activity has been returned
+ assertNotNull(a);
+ mTextView = (TextView) a.findViewById(R.id.dateText);
+ }
+
+ /**
+ * The name 'test preconditions' is a convention to signal that if this
+ * test doesn't pass, the test case was not set up properly and it might
+ * explain any and all failures in other tests. This is not guaranteed
+ * to run before other tests, as junit uses reflection to find the tests.
+ */
+ @MediumTest
+ public void testPreconditions() {
+ assertNotNull(mTextView);
+ }
+
+ public void testTextViewContent() {
+ assertEquals("FredBarney", mTextView.getText());
+ }
+}
+
diff --git a/tests/libProguardJarDep/app/src/main/AndroidManifest.xml b/tests/libProguardJarDep/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..4f8d570
--- /dev/null
+++ b/tests/libProguardJarDep/app/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.basic">
+ <application android:label="@string/app_name" android:icon="@drawable/icon">
+ <activity android:name=".Main"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <uses-permission android:name="com.blah" />
+
+ <permission-group android:name="foo.permission-group.COST_MONEY"
+ android:label="@string/app_name"
+ android:description="@string/app_name" />
+
+ <permission android:name="foo.permission.SEND_SMS"
+ android:permissionGroup="foo.permission-group.COST_MONEY"
+ android:label="@string/app_name"
+ android:description="@string/app_name" />
+
+ <permission android:name="foo.blah.SEND_SMS"
+ android:permissionGroup="foo.permission-group.COST_MONEY"
+ android:label="@string/app_name"
+ android:description="@string/app_name" />
+
+</manifest>
diff --git a/tests/libProguardJarDep/app/src/main/java/com/android/tests/basic/Main.java b/tests/libProguardJarDep/app/src/main/java/com/android/tests/basic/Main.java
new file mode 100644
index 0000000..f5a6953
--- /dev/null
+++ b/tests/libProguardJarDep/app/src/main/java/com/android/tests/basic/Main.java
@@ -0,0 +1,31 @@
+package com.android.tests.basic;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+import java.lang.reflect.Method;
+
+public class Main extends Activity
+{
+
+ private int foo = 1234;
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ TextView tv = (TextView) findViewById(R.id.dateText);
+
+ try {
+ // use reflection to make sure the class wasn't obfuscated
+ Class<?> theClass = Class.forName("com.android.tests.basic.StringGetter");
+ Method method = theClass.getDeclaredMethod("getString");
+ tv.setText((String) method.invoke(null));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/tests/libProguardJarDep/app/src/main/res/drawable/icon.png b/tests/libProguardJarDep/app/src/main/res/drawable/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/tests/libProguardJarDep/app/src/main/res/drawable/icon.png
Binary files differ
diff --git a/tests/libProguardJarDep/app/src/main/res/layout/main.xml b/tests/libProguardJarDep/app/src/main/res/layout/main.xml
new file mode 100644
index 0000000..89ab091
--- /dev/null
+++ b/tests/libProguardJarDep/app/src/main/res/layout/main.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Test App - Basic"
+ android:id="@+id/text"
+ />
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text=""
+ android:id="@+id/dateText"
+ />
+</LinearLayout>
+
diff --git a/tests/libProguardJarDep/app/src/main/res/values/strings.xml b/tests/libProguardJarDep/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..60ea2d0
--- /dev/null
+++ b/tests/libProguardJarDep/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">_Test-Basic</string>
+</resources>
diff --git a/tests/libProguardJarDep/build.gradle b/tests/libProguardJarDep/build.gradle
new file mode 100644
index 0000000..62a4405
--- /dev/null
+++ b/tests/libProguardJarDep/build.gradle
@@ -0,0 +1,8 @@
+buildscript {
+ repositories {
+ maven { url '../../../../out/host/gradle/repo' }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:0.5.0-SNAPSHOT'
+ }
+}
diff --git a/tests/libProguardJarDep/lib/build.gradle b/tests/libProguardJarDep/lib/build.gradle
new file mode 100644
index 0000000..40cb840
--- /dev/null
+++ b/tests/libProguardJarDep/lib/build.gradle
@@ -0,0 +1,30 @@
+apply plugin: 'android-library'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compile 'com.google.guava:guava:11.0.2'
+ compile fileTree(dir: 'libs', include: '*.jar')
+}
+
+android {
+ compileSdkVersion 15
+ buildToolsVersion "18.0.1"
+
+ defaultConfig {
+ versionCode 12
+ versionName "2.0"
+ minSdkVersion 16
+ targetSdkVersion 16
+ proguardFile 'config.pro'
+ consumerProguardFiles 'config.pro'
+ }
+ debug {
+ runProguard true
+ }
+ release {
+ runProguard true
+ }
+}
diff --git a/tests/libProguardJarDep/lib/config.pro b/tests/libProguardJarDep/lib/config.pro
new file mode 100644
index 0000000..c3fd7bd
--- /dev/null
+++ b/tests/libProguardJarDep/lib/config.pro
@@ -0,0 +1,3 @@
+-keep public class com.android.tests.basic.StringGetter {
+ public static java.lang.String getString();
+}
diff --git a/tests/libProguardJarDep/lib/libs/util-1.0.jar b/tests/libProguardJarDep/lib/libs/util-1.0.jar
new file mode 100644
index 0000000..55471dc
--- /dev/null
+++ b/tests/libProguardJarDep/lib/libs/util-1.0.jar
Binary files differ
diff --git a/tests/libProguardJarDep/lib/src/main/AndroidManifest.xml b/tests/libProguardJarDep/lib/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..950a35a
--- /dev/null
+++ b/tests/libProguardJarDep/lib/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.basic">
+ <application />
+</manifest>
diff --git a/tests/libProguardJarDep/lib/src/main/java/com/android/tests/basic/StringGetter.java b/tests/libProguardJarDep/lib/src/main/java/com/android/tests/basic/StringGetter.java
new file mode 100644
index 0000000..e9e5e76
--- /dev/null
+++ b/tests/libProguardJarDep/lib/src/main/java/com/android/tests/basic/StringGetter.java
@@ -0,0 +1,23 @@
+package com.android.tests.basic;
+
+import java.lang.String;
+import java.lang.StringBuffer;
+import com.example.android.multiproject.person.People;
+import com.example.android.multiproject.person.Person;
+
+public class StringGetter{
+
+ public static String getString() {
+ return getStringInternal();
+ }
+
+ private static String getStringInternal() {
+ StringBuffer sb = new StringBuffer();
+
+ Iterable<Person> people = new People();
+ for (Person person : people) {
+ sb.append(person.getName());
+ }
+ return sb.toString();
+ }
+}
diff --git a/tests/libProguardJarDep/settings.gradle b/tests/libProguardJarDep/settings.gradle
new file mode 100644
index 0000000..eedb2a1
--- /dev/null
+++ b/tests/libProguardJarDep/settings.gradle
@@ -0,0 +1,2 @@
+include 'app'
+include 'lib'
diff --git a/tests/libProguardJarDep/util/build.gradle b/tests/libProguardJarDep/util/build.gradle
new file mode 100644
index 0000000..dff7725
--- /dev/null
+++ b/tests/libProguardJarDep/util/build.gradle
@@ -0,0 +1,8 @@
+apply plugin: 'java'
+
+dependencies {
+ compile 'com.google.guava:guava:11.0.2'
+}
+
+sourceCompatibility = "1.6"
+targetCompatibility = "1.6"
diff --git a/tests/libProguardJarDep/util/src/main/java/com/example/android/multiproject/person/People.java b/tests/libProguardJarDep/util/src/main/java/com/example/android/multiproject/person/People.java
new file mode 100644
index 0000000..8b99248
--- /dev/null
+++ b/tests/libProguardJarDep/util/src/main/java/com/example/android/multiproject/person/People.java
@@ -0,0 +1,10 @@
+package com.example.android.multiproject.person;
+
+import java.util.Iterator;
+import com.google.common.collect.Lists;
+
+public class People implements Iterable<Person> {
+ public Iterator<Person> iterator() {
+ return Lists.newArrayList(new Person("Fred"), new Person("Barney")).iterator();
+ }
+}
diff --git a/tests/libProguardJarDep/util/src/main/java/com/example/android/multiproject/person/Person.java b/tests/libProguardJarDep/util/src/main/java/com/example/android/multiproject/person/Person.java
new file mode 100644
index 0000000..2f4aa9f
--- /dev/null
+++ b/tests/libProguardJarDep/util/src/main/java/com/example/android/multiproject/person/Person.java
@@ -0,0 +1,13 @@
+package com.example.android.multiproject.person;
+
+public class Person {
+ private final String name;
+
+ public Person(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/tests/libProguardLibDep/app/build.gradle b/tests/libProguardLibDep/app/build.gradle
new file mode 100644
index 0000000..c52309a
--- /dev/null
+++ b/tests/libProguardLibDep/app/build.gradle
@@ -0,0 +1,31 @@
+apply plugin: 'android'
+
+dependencies {
+ compile project(':lib')
+}
+
+android {
+ compileSdkVersion 15
+ buildToolsVersion "18.0.1"
+
+ testBuildType "proguard"
+
+ defaultConfig {
+ versionCode 12
+ versionName "2.0"
+ minSdkVersion 16
+ targetSdkVersion 16
+ }
+
+ buildTypes {
+ proguard.initWith(buildTypes.debug)
+ proguard {
+ runProguard true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'config.pro'
+ }
+ }
+
+ dexOptions {
+ incremental false
+ }
+}
diff --git a/tests/libProguardLibDep/app/config.pro b/tests/libProguardLibDep/app/config.pro
new file mode 100644
index 0000000..e4aadb9
--- /dev/null
+++ b/tests/libProguardLibDep/app/config.pro
@@ -0,0 +1,3 @@
+-keep public class com.android.tests.basic.Main {
+ public void getObfuscatedMethod();
+}
diff --git a/tests/libProguardLibDep/app/src/instrumentTest/java/com/android/tests/basic/MainTest.java b/tests/libProguardLibDep/app/src/instrumentTest/java/com/android/tests/basic/MainTest.java
new file mode 100644
index 0000000..f7289d1
--- /dev/null
+++ b/tests/libProguardLibDep/app/src/instrumentTest/java/com/android/tests/basic/MainTest.java
@@ -0,0 +1,54 @@
+package com.android.tests.basic;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.TextView;
+
+import java.lang.NoSuchMethodException;
+
+public class MainTest extends ActivityInstrumentationTestCase2<Main> {
+
+ private TextView mTextView;
+
+ /**
+ * Creates an {@link ActivityInstrumentationTestCase2} that tests the {@link Main} activity.
+ */
+ public MainTest() {
+ super(Main.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ final Main a = getActivity();
+ // ensure a valid handle to the activity has been returned
+ assertNotNull(a);
+ mTextView = (TextView) a.findViewById(R.id.dateText);
+ }
+
+ /**
+ * The name 'test preconditions' is a convention to signal that if this
+ * test doesn't pass, the test case was not set up properly and it might
+ * explain any and all failures in other tests. This is not guaranteed
+ * to run before other tests, as junit uses reflection to find the tests.
+ */
+ @MediumTest
+ public void testPreconditions() {
+ assertNotNull(mTextView);
+ }
+
+ public void testTextViewContent() {
+ assertEquals("1234", mTextView.getText());
+ }
+
+ public void testConsumerProguardRules() {
+ try {
+ final Main a = getActivity();
+ a.getObfuscatedMethod();
+ fail("Excepted NoSuchMethodError");
+ } catch (NoSuchMethodException e) {
+ // test passed
+ }
+ }
+}
+
diff --git a/tests/libProguardLibDep/app/src/main/AndroidManifest.xml b/tests/libProguardLibDep/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..4f8d570
--- /dev/null
+++ b/tests/libProguardLibDep/app/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.basic">
+ <application android:label="@string/app_name" android:icon="@drawable/icon">
+ <activity android:name=".Main"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <uses-permission android:name="com.blah" />
+
+ <permission-group android:name="foo.permission-group.COST_MONEY"
+ android:label="@string/app_name"
+ android:description="@string/app_name" />
+
+ <permission android:name="foo.permission.SEND_SMS"
+ android:permissionGroup="foo.permission-group.COST_MONEY"
+ android:label="@string/app_name"
+ android:description="@string/app_name" />
+
+ <permission android:name="foo.blah.SEND_SMS"
+ android:permissionGroup="foo.permission-group.COST_MONEY"
+ android:label="@string/app_name"
+ android:description="@string/app_name" />
+
+</manifest>
diff --git a/tests/libProguardLibDep/app/src/main/java/com/android/tests/basic/Main.java b/tests/libProguardLibDep/app/src/main/java/com/android/tests/basic/Main.java
new file mode 100644
index 0000000..8faebcd
--- /dev/null
+++ b/tests/libProguardLibDep/app/src/main/java/com/android/tests/basic/Main.java
@@ -0,0 +1,46 @@
+package com.android.tests.basic;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+import java.lang.ClassNotFoundException;
+import java.lang.NoSuchMethodException;
+import java.lang.reflect.Method;
+
+public class Main extends Activity
+{
+
+ private int foo = 1234;
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ TextView tv = (TextView) findViewById(R.id.dateText);
+
+ try {
+ // use reflection to make sure the class wasn't obfuscated
+ Class<?> theClass = Class.forName("com.android.tests.basic.StringGetter");
+ Method method = theClass.getDeclaredMethod("getString", int.class);
+ tv.setText((String) method.invoke(null, foo));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * use reflection to get a method that should be obfuscated
+ */
+ public void getObfuscatedMethod() throws NoSuchMethodException{
+ try {
+ Class<?> theClass = Class.forName("com.android.tests.basic.StringGetter");
+ Method method = theClass.getDeclaredMethod("getStringInternal", int.class);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/tests/libProguardLibDep/app/src/main/res/drawable/icon.png b/tests/libProguardLibDep/app/src/main/res/drawable/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/tests/libProguardLibDep/app/src/main/res/drawable/icon.png
Binary files differ
diff --git a/tests/libProguardLibDep/app/src/main/res/layout/main.xml b/tests/libProguardLibDep/app/src/main/res/layout/main.xml
new file mode 100644
index 0000000..89ab091
--- /dev/null
+++ b/tests/libProguardLibDep/app/src/main/res/layout/main.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Test App - Basic"
+ android:id="@+id/text"
+ />
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text=""
+ android:id="@+id/dateText"
+ />
+</LinearLayout>
+
diff --git a/tests/libProguardLibDep/app/src/main/res/values/strings.xml b/tests/libProguardLibDep/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..60ea2d0
--- /dev/null
+++ b/tests/libProguardLibDep/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">_Test-Basic</string>
+</resources>
diff --git a/tests/libProguardLibDep/build.gradle b/tests/libProguardLibDep/build.gradle
new file mode 100644
index 0000000..62a4405
--- /dev/null
+++ b/tests/libProguardLibDep/build.gradle
@@ -0,0 +1,8 @@
+buildscript {
+ repositories {
+ maven { url '../../../../out/host/gradle/repo' }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:0.5.0-SNAPSHOT'
+ }
+}
diff --git a/tests/libProguardLibDep/lib/build.gradle b/tests/libProguardLibDep/lib/build.gradle
new file mode 100644
index 0000000..ce3ccf6
--- /dev/null
+++ b/tests/libProguardLibDep/lib/build.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'android-library'
+
+dependencies {
+ compile project(':lib2')
+}
+
+android {
+ compileSdkVersion 15
+ buildToolsVersion "18.0.1"
+
+ defaultConfig {
+ versionCode 12
+ versionName "2.0"
+ minSdkVersion 16
+ targetSdkVersion 16
+ proguardFile 'config.pro'
+ consumerProguardFiles 'consumerRules.pro'
+ }
+ release {
+ runProguard true
+ }
+}
diff --git a/tests/libProguardLibDep/lib/config.pro b/tests/libProguardLibDep/lib/config.pro
new file mode 100644
index 0000000..4cf7cba
--- /dev/null
+++ b/tests/libProguardLibDep/lib/config.pro
@@ -0,0 +1,3 @@
+-keep public class com.android.tests.basic.StringGetter {
+ public static java.lang.String getString(int);
+}
diff --git a/tests/libProguardLibDep/lib/consumerRules.pro b/tests/libProguardLibDep/lib/consumerRules.pro
new file mode 100644
index 0000000..d09be16
--- /dev/null
+++ b/tests/libProguardLibDep/lib/consumerRules.pro
@@ -0,0 +1,6 @@
+-keep public class com.android.tests.basic.StringGetter {
+ public static java.lang.String getString(int);
+}
+-keep public class com.android.tests.basic.StringGetter {
+ public static java.lang.String getStringInternal(int);
+}
diff --git a/tests/libProguardLibDep/lib/src/main/AndroidManifest.xml b/tests/libProguardLibDep/lib/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..950a35a
--- /dev/null
+++ b/tests/libProguardLibDep/lib/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.basic">
+ <application />
+</manifest>
diff --git a/tests/libProguardLibDep/lib/src/main/java/com/android/tests/basic/StringGetter.java b/tests/libProguardLibDep/lib/src/main/java/com/android/tests/basic/StringGetter.java
new file mode 100644
index 0000000..159f359
--- /dev/null
+++ b/tests/libProguardLibDep/lib/src/main/java/com/android/tests/basic/StringGetter.java
@@ -0,0 +1,23 @@
+package com.android.tests.basic;
+
+import java.lang.RuntimeException;
+import java.lang.String;
+import java.lang.reflect.Method;
+
+public class StringGetter{
+
+ public static String getString(int foo) {
+ return getStringInternal(foo);
+ }
+
+ public static String getStringInternal(int foo) {
+ try {
+ // use reflection to make sure the class wasn't obfuscated
+ Class<?> theClass = Class.forName("com.android.tests.basic.StringProvider");
+ Method method = theClass.getDeclaredMethod("getString", int.class);
+ return (String) method.invoke(null, foo);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/tests/libProguardLibDep/lib2/build.gradle b/tests/libProguardLibDep/lib2/build.gradle
new file mode 100644
index 0000000..78da4d4
--- /dev/null
+++ b/tests/libProguardLibDep/lib2/build.gradle
@@ -0,0 +1,18 @@
+apply plugin: 'android-library'
+
+android {
+ compileSdkVersion 15
+ buildToolsVersion "18.0.1"
+
+ defaultConfig {
+ versionCode 12
+ versionName "2.0"
+ minSdkVersion 16
+ targetSdkVersion 16
+ proguardFile 'config.pro'
+ consumerProguardFiles 'config.pro'
+ }
+ release {
+ runProguard true
+ }
+}
diff --git a/tests/libProguardLibDep/lib2/config.pro b/tests/libProguardLibDep/lib2/config.pro
new file mode 100644
index 0000000..3664f87
--- /dev/null
+++ b/tests/libProguardLibDep/lib2/config.pro
@@ -0,0 +1,3 @@
+-keep public class com.android.tests.basic.StringProvider {
+ public static java.lang.String getString(int);
+}
diff --git a/tests/libProguardLibDep/lib2/src/main/AndroidManifest.xml b/tests/libProguardLibDep/lib2/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..593a287
--- /dev/null
+++ b/tests/libProguardLibDep/lib2/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.basic">
+</manifest>
diff --git a/tests/libProguardLibDep/lib2/src/main/java/com/android/tests/basic/StringProvider.java b/tests/libProguardLibDep/lib2/src/main/java/com/android/tests/basic/StringProvider.java
new file mode 100644
index 0000000..6d81901
--- /dev/null
+++ b/tests/libProguardLibDep/lib2/src/main/java/com/android/tests/basic/StringProvider.java
@@ -0,0 +1,8 @@
+package com.android.tests.basic;
+
+public class StringProvider {
+
+ public static String getString(int foo) {
+ return Integer.toString(foo);
+ }
+}
diff --git a/tests/libProguardLibDep/settings.gradle b/tests/libProguardLibDep/settings.gradle
new file mode 100644
index 0000000..d8ac2dc
--- /dev/null
+++ b/tests/libProguardLibDep/settings.gradle
@@ -0,0 +1,3 @@
+include 'app'
+include 'lib'
+include 'lib2'
diff --git a/tests/proguardLib/lib/build.gradle b/tests/proguardLib/lib/build.gradle
index 3b209bf..efbffe6 100644
--- a/tests/proguardLib/lib/build.gradle
+++ b/tests/proguardLib/lib/build.gradle
@@ -9,6 +9,6 @@ android {
versionName "2.0"
minSdkVersion 16
targetSdkVersion 16
- proguardFile 'config.pro'
+ consumerProguardFiles 'config.pro'
}
-} \ No newline at end of file
+}