aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Greg Estren <gregce@google.com>2016-08-22 20:10:47 +0000
committerGravatar Philipp Wollermann <philwo@google.com>2016-08-23 09:29:27 +0000
commitdbdd4326e19bf085faa6f89db27bf13c3bc8bfc7 (patch)
tree2b1de38bff2cf7a7c2bc38d5926fa594646cea6a /src
parent63ee240af85d1822f05b537153af643563b48cb3 (diff)
Adds data binding support to the Android resource processor.
This is invoked via the new --dataBindingInfoOut flag. If specified and the rule has resources, data binding declarations in layout .xmls are stripped and fed into an aggregated .zip file under that name. The original (stripped) .xml is then fed into aapt for normal processing. If specified and the rule has no resources, an empty file is created. If not specified, everything works as before. -- MOS_MIGRATED_REVID=130973265
Diffstat (limited to 'src')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java10
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java66
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/BUILD1
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java3
4 files changed, 76 insertions, 4 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
index 14f43f9b25..7983256ec6 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
@@ -117,6 +117,13 @@ public class AndroidResourceProcessingAction {
help = "Path to where the symbolsTxt should be written.")
public Path symbolsTxtOut;
+ @Option(name = "dataBindingInfoOut",
+ defaultValue = "null",
+ converter = PathConverter.class,
+ category = "output",
+ help = "Path to where data binding's layout info output should be written.")
+ public Path dataBindingInfoOut;
+
@Option(name = "packagePath",
defaultValue = "null",
converter = PathConverter.class,
@@ -306,7 +313,8 @@ public class AndroidResourceProcessingAction {
options.mainDexProguardOutput,
options.resourcesOutput != null
? processedData.getResourceDir().resolve("values").resolve("public.xml")
- : null);
+ : null,
+ options.dataBindingInfoOut);
logger.fine(String.format("aapt finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
if (options.srcJarOutput != null) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
index 53a7057fc6..d5194a098d 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
@@ -15,7 +15,10 @@ package com.google.devtools.build.android;
import static java.nio.charset.StandardCharsets.UTF_8;
+import android.databinding.AndroidDataBinding;
+import android.databinding.cli.ProcessXmlOptions;
import com.android.annotations.Nullable;
+import com.android.builder.core.DefaultManifestParser;
import com.android.builder.core.VariantConfiguration;
import com.android.builder.dependency.SymbolFileProvider;
import com.android.builder.internal.SymbolLoader;
@@ -414,10 +417,13 @@ public class AndroidResourceProcessor {
Path packageOut,
Path proguardOut,
Path mainDexProguardOut,
- Path publicResourcesOut)
+ Path publicResourcesOut,
+ Path dataBindingInfoOut)
throws IOException, InterruptedException, LoggedErrorException, UnrecognizedSplitsException {
Path androidManifest = primaryData.getManifest();
- final Path resourceDir = primaryData.getResourceDir();
+ final Path resourceDir = processDataBindings(primaryData.getResourceDir(), dataBindingInfoOut,
+ variantType, customPackageForR, androidManifest);
+
final Path assetsDir = primaryData.getAssetDir();
if (publicResourcesOut != null) {
prepareOutputPath(publicResourcesOut.getParent());
@@ -542,6 +548,62 @@ public class AndroidResourceProcessor {
return outputWithSourceContext;
}
+ /**
+ * If resources exist and a data binding layout info file is requested: processes data binding
+ * declarations over those resources, populates the output file, and creates a new resources
+ * directory with data binding expressions stripped out (so aapt, which doesn't understand
+ * data binding, can properly read them).
+ *
+ * <p>Returns the resources directory that aapt should read.
+ */
+ private Path processDataBindings(Path resourceDir, Path dataBindingInfoOut,
+ VariantConfiguration.Type variantType, String packagePath, Path androidManifest)
+ throws IOException {
+
+ if (dataBindingInfoOut == null) {
+ return resourceDir;
+ } else if (!Files.isDirectory(resourceDir)) {
+ // No resources: no data binding needed. Create a dummy file to satisfy declared outputs.
+ Files.createFile(dataBindingInfoOut);
+ return resourceDir;
+ }
+
+ // Strip the file name (the data binding library automatically adds it back in).
+ // ** The data binding library assumes this file is called "layout-info.zip". **
+ dataBindingInfoOut = dataBindingInfoOut.getParent();
+ if (Files.notExists(dataBindingInfoOut)) {
+ Files.createDirectory(dataBindingInfoOut);
+ }
+
+ Path processedResourceDir = resourceDir.resolveSibling("res_without_databindings");
+ if (Files.notExists(processedResourceDir)) {
+ Files.createDirectory(processedResourceDir);
+ }
+
+ ProcessXmlOptions options = new ProcessXmlOptions();
+ options.setAppId(packagePath);
+ options.setLibrary(variantType == VariantConfiguration.Type.LIBRARY);
+ options.setResInput(resourceDir.toFile());
+ options.setResOutput(processedResourceDir.toFile());
+ options.setLayoutInfoOutput(dataBindingInfoOut.toFile());
+ options.setZipLayoutInfo(true); // Aggregate data-bound .xml files into a single .zip.
+
+ Object minSdk = new DefaultManifestParser().getMinSdkVersion(androidManifest.toFile());
+ if (minSdk instanceof Integer) {
+ options.setMinSdk(((Integer) minSdk).intValue());
+ } else {
+ // TODO(bazel-team): Enforce the minimum SDK check.
+ options.setMinSdk(15);
+ }
+
+ try {
+ AndroidDataBinding.doRun(options);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ return processedResourceDir;
+ }
+
/** Task to parse java package from AndroidManifest.xml */
private static final class PackageParsingTask implements Callable<String> {
diff --git a/src/tools/android/java/com/google/devtools/build/android/BUILD b/src/tools/android/java/com/google/devtools/build/android/BUILD
index aac3a058fa..f4b5689623 100644
--- a/src/tools/android/java/com/google/devtools/build/android/BUILD
+++ b/src/tools/android/java/com/google/devtools/build/android/BUILD
@@ -80,6 +80,7 @@ java_library(
"//third_party:asm",
"//third_party:guava",
"//third_party:jsr305",
+ "//third_party/java/android_databinding:exec",
"//third_party/protobuf",
],
)
diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
index ea5f1225ff..4d0498533f 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
@@ -234,7 +234,8 @@ public class ResourceShrinkerAction {
options.shrunkApk,
null /* proguardOutput */,
null /* mainDexProguardOutput */,
- null /* publicResourcesOut */);
+ null /* publicResourcesOut */,
+ null /* dataBindingInfoOut */);
if (options.shrunkResources != null) {
resourceProcessor.createResourcesZip(shrunkResources, resourceFiles.resolve("assets"),
options.shrunkResources);