aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/android/java/com')
-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.java109
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java181
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/BUILD8
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/BUILD.tools8
5 files changed, 275 insertions, 41 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 cc78940086..322180b1a2 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
@@ -13,8 +13,6 @@
// limitations under the License.
package com.google.devtools.build.android;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
import com.android.builder.core.VariantConfiguration;
import com.android.builder.core.VariantConfiguration.Type;
import com.android.ide.common.internal.AaptCruncher;
@@ -38,7 +36,6 @@ import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.TriState;
import java.io.IOException;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -283,12 +280,7 @@ public class AndroidResourceProcessingAction {
}
if (options.packageType == Type.LIBRARY) {
- Files.createDirectories(dummyManifest.getParent());
- Files.write(dummyManifest, String.format(
- "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
- + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\""
- + " package=\"%s\">"
- + "</manifest>", options.packageForR).getBytes(UTF_8));
+ resourceProcessor.writeDummyManifestForAapt(dummyManifest, options.packageForR);
processedData = new MergedAndroidData(
processedData.getResourceDir(),
processedData.getAssetDir(),
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 6e2f340623..53b7f8a9d6 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
@@ -418,12 +418,12 @@ public class AndroidResourceProcessor {
Collection<String> splits,
MergedAndroidData primaryData,
List<DependencyAndroidData> dependencyData,
- Path sourceOut,
- Path packageOut,
- Path proguardOut,
- Path mainDexProguardOut,
- Path publicResourcesOut,
- Path dataBindingInfoOut)
+ @Nullable Path sourceOut,
+ @Nullable Path packageOut,
+ @Nullable Path proguardOut,
+ @Nullable Path mainDexProguardOut,
+ @Nullable Path publicResourcesOut,
+ @Nullable Path dataBindingInfoOut)
throws IOException, InterruptedException, LoggedErrorException, UnrecognizedSplitsException {
Path androidManifest = primaryData.getManifest();
final Path resourceDir = processDataBindings(primaryData.getResourceDir(), dataBindingInfoOut,
@@ -433,7 +433,69 @@ public class AndroidResourceProcessor {
if (publicResourcesOut != null) {
prepareOutputPath(publicResourcesOut.getParent());
}
+ runAapt(aapt,
+ androidJar,
+ buildToolsVersion,
+ variantType,
+ debug,
+ customPackageForR,
+ aaptOptions,
+ resourceConfigs,
+ splits,
+ androidManifest,
+ resourceDir,
+ assetsDir,
+ sourceOut,
+ packageOut,
+ proguardOut,
+ mainDexProguardOut,
+ publicResourcesOut);
+ // The R needs to be created for each library in the dependencies,
+ // but only if the current project is not a library.
+ if (sourceOut != null && variantType != VariantConfiguration.Type.LIBRARY) {
+ writeDependencyPackageRJavaFiles(
+ dependencyData, customPackageForR, androidManifest, sourceOut);
+ }
+ // Reset the output date stamps.
+ if (proguardOut != null) {
+ Files.setLastModifiedTime(proguardOut, FileTime.fromMillis(0L));
+ }
+ if (mainDexProguardOut != null) {
+ Files.setLastModifiedTime(mainDexProguardOut, FileTime.fromMillis(0L));
+ }
+ if (packageOut != null) {
+ Files.setLastModifiedTime(packageOut, FileTime.fromMillis(0L));
+ if (!splits.isEmpty()) {
+ Iterable<Path> splitFilenames = findAndRenameSplitPackages(packageOut, splits);
+ for (Path splitFilename : splitFilenames) {
+ Files.setLastModifiedTime(splitFilename, FileTime.fromMillis(0L));
+ }
+ }
+ }
+ if (publicResourcesOut != null && Files.exists(publicResourcesOut)) {
+ Files.setLastModifiedTime(publicResourcesOut, FileTime.fromMillis(0L));
+ }
+ }
+ public void runAapt(
+ Path aapt,
+ Path androidJar,
+ @Nullable FullRevision buildToolsVersion,
+ VariantConfiguration.Type variantType,
+ boolean debug,
+ String customPackageForR,
+ AaptOptions aaptOptions,
+ Collection<String> resourceConfigs,
+ Collection<String> splits,
+ Path androidManifest,
+ Path resourceDir,
+ Path assetsDir,
+ Path sourceOut,
+ @Nullable Path packageOut,
+ @Nullable Path proguardOut,
+ @Nullable Path mainDexProguardOut,
+ @Nullable Path publicResourcesOut)
+ throws InterruptedException, LoggedErrorException, IOException {
AaptCommandBuilder commandBuilder =
new AaptCommandBuilder(aapt)
.forBuildToolsVersion(buildToolsVersion)
@@ -485,32 +547,6 @@ public class AndroidResourceProcessor {
throw new LoggedErrorException(
e.getCmdLineError(), getOutputWithSourceContext(aapt, e.getOutput()), e.getCmdLine());
}
-
- // The R needs to be created for each library in the dependencies,
- // but only if the current project is not a library.
- if (sourceOut != null && variantType != VariantConfiguration.Type.LIBRARY) {
- writeDependencyPackageRJavaFiles(
- dependencyData, customPackageForR, androidManifest, sourceOut);
- }
- // Reset the output date stamps.
- if (proguardOut != null) {
- Files.setLastModifiedTime(proguardOut, FileTime.fromMillis(0L));
- }
- if (mainDexProguardOut != null) {
- Files.setLastModifiedTime(mainDexProguardOut, FileTime.fromMillis(0L));
- }
- if (packageOut != null) {
- Files.setLastModifiedTime(packageOut, FileTime.fromMillis(0L));
- if (!splits.isEmpty()) {
- Iterable<Path> splitFilenames = findAndRenameSplitPackages(packageOut, splits);
- for (Path splitFilename : splitFilenames) {
- Files.setLastModifiedTime(splitFilename, FileTime.fromMillis(0L));
- }
- }
- }
- if (publicResourcesOut != null && Files.exists(publicResourcesOut)) {
- Files.setLastModifiedTime(publicResourcesOut, FileTime.fromMillis(0L));
- }
}
/** Adds 10 lines of source to each syntax error. Very useful for debugging. */
@@ -956,6 +992,15 @@ public class AndroidResourceProcessor {
Files.write(manifestOut, xmlDocument.prettyPrint().getBytes(UTF_8));
}
+ public void writeDummyManifestForAapt(Path dummyManifest, String packageForR) throws IOException {
+ Files.createDirectories(dummyManifest.getParent());
+ Files.write(dummyManifest, String.format(
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\""
+ + " package=\"%s\">"
+ + "</manifest>", packageForR).getBytes(UTF_8));
+ }
+
/**
* Overwrite the package attribute of {@code <manifest>} in an AndroidManifest.xml file.
*
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
new file mode 100644
index 0000000000..df8c9489a8
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceValidatorAction.java
@@ -0,0 +1,181 @@
+// Copyright 2015 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.android;
+
+import com.android.builder.core.VariantConfiguration;
+import com.android.builder.core.VariantConfiguration.Type;
+import com.android.utils.StdLogger;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.android.AndroidResourceProcessor.AaptConfigOptions;
+import com.google.devtools.build.android.AndroidResourceProcessor.FlagAaptOptions;
+import com.google.devtools.build.android.Converters.ExistingPathConverter;
+import com.google.devtools.build.android.Converters.PathConverter;
+import com.google.devtools.common.options.Option;
+import com.google.devtools.common.options.OptionsBase;
+import com.google.devtools.common.options.OptionsParser;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * Validates merged resources for an android_library via AAPT. Takes as input, the merged resources
+ * from {@link AndroidResourceMergingAction}.
+ */
+public class AndroidResourceValidatorAction {
+
+ private static final StdLogger stdLogger = new StdLogger(StdLogger.Level.WARNING);
+
+ private static final Logger logger =
+ Logger.getLogger(AndroidResourceValidatorAction.class.getName());
+
+ /** Flag specifications for this action. */
+ public static final class Options extends OptionsBase {
+
+ @Option(
+ name = "mergedResources",
+ defaultValue = "null",
+ converter = ExistingPathConverter.class,
+ category = "input",
+ help = "Path to the read merged resources archive."
+ )
+ public Path mergedResources;
+
+ @Option(
+ name = "manifest",
+ defaultValue = "null",
+ converter = ExistingPathConverter.class,
+ category = "input",
+ help = "Path for the AndroidManifest.xml."
+ )
+ public Path manifest;
+
+ @Option(
+ name = "packageForR",
+ defaultValue = "null",
+ category = "config",
+ help = "Custom java package to generate the R symbols files."
+ )
+ public String packageForR;
+
+ @Option(
+ name = "srcJarOutput",
+ defaultValue = "null",
+ converter = PathConverter.class,
+ category = "output",
+ help = "Path for the generated java source jar."
+ )
+ public Path srcJarOutput;
+
+ @Option(
+ name = "rOutput",
+ defaultValue = "null",
+ converter = PathConverter.class,
+ category = "output",
+ help = "Path to where the R.txt should be written."
+ )
+ public Path rOutput;
+ }
+
+ public static void main(String[] args) throws Exception {
+ final Stopwatch timer = Stopwatch.createStarted();
+ OptionsParser optionsParser =
+ OptionsParser.newOptionsParser(Options.class, AaptConfigOptions.class);
+ optionsParser.parseAndExitUponError(args);
+ AaptConfigOptions aaptConfigOptions = optionsParser.getOptions(AaptConfigOptions.class);
+ Options options = optionsParser.getOptions(Options.class);
+
+ final AndroidResourceProcessor resourceProcessor = new AndroidResourceProcessor(stdLogger);
+ VariantConfiguration.Type packageType = Type.LIBRARY;
+
+ Preconditions.checkNotNull(options.rOutput);
+ Preconditions.checkNotNull(options.srcJarOutput);
+ try (ScopedTemporaryDirectory scopedTmp =
+ new ScopedTemporaryDirectory("resource_validator_tmp")) {
+ Path tmp = scopedTmp.getPath();
+ Path expandedOut = tmp.resolve("tmp-expanded");
+ Path resources = expandedOut.resolve("res");
+ Path assets = expandedOut.resolve("assets");
+ Path generatedSources = tmp.resolve("generated_resources");
+ Path dummyManifest = tmp.resolve("manifest-aapt-dummy/AndroidManifest.xml");
+
+ unpackZip(options.mergedResources, expandedOut);
+ logger.fine(String.format("unpacked zip at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+
+ // We need to make the manifest aapt safe (w.r.t., placeholders). For now, just stub it out.
+ resourceProcessor.writeDummyManifestForAapt(dummyManifest, options.packageForR);
+
+ resourceProcessor.runAapt(
+ aaptConfigOptions.aapt,
+ aaptConfigOptions.androidJar,
+ aaptConfigOptions.buildToolsVersion,
+ packageType,
+ aaptConfigOptions.debug,
+ options.packageForR,
+ new FlagAaptOptions(aaptConfigOptions),
+ aaptConfigOptions.resourceConfigs,
+ ImmutableList.<String>of(),
+ dummyManifest,
+ resources,
+ assets,
+ generatedSources,
+ null, /* packageOut */
+ null, /* proguardOut */
+ null, /* mainDexProguardOut */
+ null /* publicResourcesOut */);
+ logger.fine(String.format("aapt finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+
+ resourceProcessor.copyRToOutput(
+ generatedSources, options.rOutput, VariantConfiguration.Type.LIBRARY == packageType);
+
+ resourceProcessor.createSrcJar(
+ generatedSources, options.srcJarOutput, VariantConfiguration.Type.LIBRARY == packageType);
+ } catch (Exception e) {
+ logger.log(java.util.logging.Level.SEVERE, "Unexpected", e);
+ throw e;
+ } finally {
+ resourceProcessor.shutdown();
+ }
+ logger.fine(String.format("Resources merged in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
+ }
+
+ private static void unpackZip(Path mergedResources, Path expandedOut) throws IOException {
+ byte[] buffer = new byte[4096];
+ try (ZipInputStream zis =
+ new ZipInputStream(new BufferedInputStream(Files.newInputStream(mergedResources)))) {
+ ZipEntry z = zis.getNextEntry();
+ while (z != null) {
+ String entryName = z.getName();
+ Path outputPath = expandedOut.resolve(entryName);
+ Files.createDirectories(outputPath.getParent());
+ try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(outputPath))) {
+ int count = zis.read(buffer);
+ while (count != -1) {
+ out.write(buffer, 0, count);
+ count = zis.read(buffer);
+ }
+ }
+ z = zis.getNextEntry();
+ }
+ }
+ }
+}
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 6dc6b4b2ce..d8df5b4103 100644
--- a/src/tools/android/java/com/google/devtools/build/android/BUILD
+++ b/src/tools/android/java/com/google/devtools/build/android/BUILD
@@ -50,6 +50,14 @@ java_binary(
)
java_binary(
+ name = "AndroidResourceValidatorAction",
+ main_class = "com.google.devtools.build.android.AndroidResourceValidatorAction",
+ runtime_deps = [
+ ":android_builder_lib",
+ ],
+)
+
+java_binary(
name = "ManifestMergerAction",
main_class = "com.google.devtools.build.android.ManifestMergerAction",
runtime_deps = [
diff --git a/src/tools/android/java/com/google/devtools/build/android/BUILD.tools b/src/tools/android/java/com/google/devtools/build/android/BUILD.tools
index 3a08124f58..444bf4f699 100644
--- a/src/tools/android/java/com/google/devtools/build/android/BUILD.tools
+++ b/src/tools/android/java/com/google/devtools/build/android/BUILD.tools
@@ -38,6 +38,14 @@ java_binary(
)
java_binary(
+ name = "AndroidResourceValidatorAction",
+ main_class = "com.google.devtools.build.android.AndroidResourceValidatorAction",
+ runtime_deps = [
+ ":classes",
+ ],
+)
+
+java_binary(
name = "ManifestMergerAction",
main_class = "com.google.devtools.build.android.ManifestMergerAction",
runtime_deps = [