aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android/aapt2
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/aapt2')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java91
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceLinker.java48
2 files changed, 111 insertions, 28 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java b/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java
index 68e12e146e..57cbcb533b 100644
--- a/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java
+++ b/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java
@@ -40,6 +40,7 @@ import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
@@ -60,6 +61,43 @@ import javax.xml.stream.events.XMLEvent;
/** Invokes aapt2 to compile resources. */
public class ResourceCompiler {
+
+ /** Types of compiled resources. */
+ public enum CompiledType {
+ NORMAL(null),
+ GENERATED("generated"),
+ DEFAULT("default");
+
+ private final String prefix;
+
+ CompiledType(String prefix) {
+ this.prefix = prefix;
+ }
+
+ boolean prefixes(String filename) {
+ return prefix != null && filename.startsWith(prefix);
+ }
+
+ public String asPrefix() {
+ return prefix;
+ }
+
+ public String asComment() {
+ return prefix;
+ }
+
+ public String prefix(String path) {
+ return prefix + "/" + path;
+ }
+ }
+
+ public static CompiledType getCompiledType(String fileName) {
+ return Arrays.stream(CompiledType.values())
+ .filter(t -> t.prefixes(fileName))
+ .findFirst()
+ .orElse(CompiledType.NORMAL);
+ }
+
static class CompileError extends Aapt2Exception {
protected CompileError(Throwable e) {
@@ -105,19 +143,28 @@ public class ResourceCompiler {
@Override
public List<Path> call() throws Exception {
final String directoryName = file.getParent().getFileName().toString();
- Qualifiers qualifiers = Qualifiers.parseFrom(directoryName);
- String filename = interpolateAapt2Filename(qualifiers, file.getFileName().toString());
+ final Qualifiers qualifiers = Qualifiers.parseFrom(directoryName);
+ final String filename = interpolateAapt2Filename(qualifiers, file.getFileName().toString());
- List<Path> results = new ArrayList<>();
- compile(directoryName, filename, results, compiledResourcesOut, file, false);
+ final List<Path> results = new ArrayList<>();
if (qualifiers.asFolderType().equals(ResourceFolderType.VALUES)) {
extractAttributes(directoryName, filename, results);
+ }
- if (qualifiers.containDefaultLocale()) {
- // aapt2 only generates pseudo locales for the default locale.
- generatedResourcesOut.ifPresent(
- out -> compile(directoryName, filename, results, out, file, true));
- }
+ if (qualifiers.containDefaultLocale()
+ && qualifiers.asFolderType().equals(ResourceFolderType.VALUES)) {
+ compile(
+ directoryName,
+ filename,
+ results,
+ compiledResourcesOut.resolve(CompiledType.DEFAULT.asPrefix()),
+ file,
+ false);
+ // aapt2 only generates pseudo locales for the default locale.
+ generatedResourcesOut.ifPresent(
+ out -> compile(directoryName, filename, results, out, file, true));
+ } else {
+ compile(directoryName, filename, results, compiledResourcesOut, file, false);
}
return results;
}
@@ -362,17 +409,33 @@ public class ResourceCompiler {
generatedResourcesOut)));
}
- ImmutableList.Builder<Path> builder = ImmutableList.builder();
+ ImmutableList.Builder<Path> compiled = ImmutableList.builder();
+ ImmutableList.Builder<Path> generated = ImmutableList.builder();
List<Throwable> compilationErrors = new ArrayList<>();
for (ListenableFuture<List<Path>> task : tasks) {
try {
- builder.addAll(task.get());
+ // Split the generated and non-generated resources into different collections.
+ // This allows the generated files to be placed first in the compile order,
+ // ensuring that the generated locale (en-XA and ar-XB) can be overwritten by
+ // user provided versions for those locales, as aapt2 will take the last value for
+ // a configuration when linking.
+ task.get()
+ .forEach(
+ path -> {
+ if (generatedResourcesOut.map(path::startsWith).orElse(false)) {
+ generated.add(path);
+ } else {
+ compiled.add(path);
+ }
+ });
} catch (InterruptedException | ExecutionException e) {
- compilationErrors.add(Optional.ofNullable(e.getCause()).orElse(e));
+ compilationErrors.add(e.getCause() != null ? e.getCause() : e);
}
}
+ generated.addAll(compiled.build());
if (compilationErrors.isEmpty()) {
- return builder.build();
+ // ensure that the generated files are before the normal files.
+ return generated.build();
}
throw CompileError.of(compilationErrors);
}
@@ -393,7 +456,7 @@ public class ResourceCompiler {
aapt2,
buildToolsVersion,
generatePseudoLocale
- ? Optional.of(compiledResources.resolve("generated"))
+ ? Optional.of(compiledResources.resolve(CompiledType.GENERATED.asPrefix()))
: Optional.empty()));
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceLinker.java b/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceLinker.java
index c5c3236043..1ca2b53eff 100644
--- a/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceLinker.java
+++ b/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceLinker.java
@@ -20,12 +20,16 @@ import com.android.repository.Revision;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.devtools.build.android.AaptCommandBuilder;
import com.google.devtools.build.android.AndroidResourceOutputs;
import com.google.devtools.build.android.Profiler;
+import com.google.devtools.build.android.aapt2.ResourceCompiler.CompiledType;
+import com.google.devtools.build.android.ziputils.DirectoryEntry;
import com.google.devtools.build.android.ziputils.ZipIn;
import com.google.devtools.build.android.ziputils.ZipOut;
import java.io.IOException;
@@ -49,7 +53,24 @@ import java.util.stream.Stream;
/** Performs linking of {@link CompiledResources} using aapt2. */
public class ResourceLinker {
+ private static final Predicate<String> IS_JAR = s -> s.endsWith(".jar");
private boolean debug;
+ private static final Predicate<DirectoryEntry> IS_FLAT_FILE =
+ h -> h.getFilename().endsWith(".flat");
+
+ private static final Predicate<DirectoryEntry> COMMENT_ABSENT =
+ h -> Strings.isNullOrEmpty(h.getComment());
+
+ private static final Predicate<DirectoryEntry> USE_GENERATED =
+ COMMENT_ABSENT.or(
+ h -> ResourceCompiler.getCompiledType(h.getFilename()) == CompiledType.GENERATED);
+
+ private static final Predicate<DirectoryEntry> USE_DEFAULT =
+ COMMENT_ABSENT.or(
+ h -> ResourceCompiler.getCompiledType(h.getComment()) != CompiledType.GENERATED);
+
+ private static final ImmutableSet<String> PSEUDO_LOCALE_FILTERS =
+ ImmutableSet.of("en_XA", "ar_XB");
/** Represents errors thrown during linking. */
public static class LinkError extends Aapt2Exception {
@@ -184,9 +205,7 @@ public class ResourceLinker {
.when(outputAsProto)
.thenAdd("--proto-format")
.addParameterableRepeated(
- "-R",
- compiledResourcesToPaths(compiled, s -> s.endsWith(".flat")),
- workingDirectory)
+ "-R", compiledResourcesToPaths(compiled, IS_FLAT_FILE), workingDirectory)
.addRepeated("-I", pathsToLinkAgainst)
.add("--auto-add-overlay")
.add("-o", outPath)
@@ -211,14 +230,11 @@ public class ResourceLinker {
.when(outputAsProto)
.thenAdd("--proto-format")
// only link against jars
- .addRepeated(
- "-I",
- pathsToLinkAgainst.stream().filter(s -> s.endsWith(".jar")).collect(toList()))
+ .addRepeated("-I", pathsToLinkAgainst.stream().filter(IS_JAR).collect(toList()))
.add("-R", outPath)
// only include non-jars
.addRepeated(
- "-R",
- pathsToLinkAgainst.stream().filter(s -> !s.endsWith(".jar")).collect(toList()))
+ "-R", pathsToLinkAgainst.stream().filter(IS_JAR.negate()).collect(toList()))
.add("--auto-add-overlay")
.add("-o", outPath.resolveSibling("transitive.apk"))
.add("--java", javaSourceDirectory)
@@ -237,7 +253,7 @@ public class ResourceLinker {
}
private List<String> compiledResourcesToPaths(
- CompiledResources compiled, Predicate<String> shouldKeep) throws IOException {
+ CompiledResources compiled, Predicate<DirectoryEntry> shouldKeep) throws IOException {
// Using sequential streams to maintain the overlay order for aapt2.
return Stream.concat(include.stream(), Stream.of(compiled))
.sequential()
@@ -249,7 +265,7 @@ public class ResourceLinker {
.collect(toList());
}
- private Path filterZip(Path path, Predicate<String> shouldKeep) throws IOException {
+ private Path filterZip(Path path, Predicate<DirectoryEntry> shouldKeep) throws IOException {
Path outPath =
workingDirectory
.resolve("filtered")
@@ -267,7 +283,7 @@ public class ResourceLinker {
final ZipOut zipOut = new ZipOut(outChannel, outPath.toString());
zipIn.scanEntries(
(in, header, dirEntry, data) -> {
- if (shouldKeep.test(header.getFilename())) {
+ if (shouldKeep.test(dirEntry)) {
zipOut.nextEntry(dirEntry);
zipOut.write(header);
zipOut.write(data);
@@ -307,7 +323,7 @@ public class ResourceLinker {
Path resourceIds = workingDirectory.resolve("ids.txt");
profiler.startTask("fulllink");
- logger.finer(
+ logger.fine(
new AaptCommandBuilder(aapt2)
.forBuildToolsVersion(buildToolsVersion)
.forVariantType(VariantType.DEFAULT)
@@ -338,7 +354,11 @@ public class ResourceLinker {
.addRepeated("-I", StaticLibrary.toPathStrings(linkAgainst))
.addParameterableRepeated(
"-R",
- compiledResourcesToPaths(compiled, s -> s.endsWith(".flat")),
+ compiledResourcesToPaths(
+ compiled,
+ resourceConfigs.stream().anyMatch(PSEUDO_LOCALE_FILTERS::contains)
+ ? IS_FLAT_FILE.and(USE_GENERATED)
+ : IS_FLAT_FILE.and(USE_DEFAULT)),
workingDirectory)
// Never compress apks.
.add("-0", "apk")
@@ -363,7 +383,7 @@ public class ResourceLinker {
outPath, rTxt, proguardConfig, mainDexProguard, javaSourceDirectory, resourceIds);
}
final Path optimized = workingDirectory.resolve("optimized.apk");
- logger.finer(
+ logger.fine(
new AaptCommandBuilder(aapt2)
.forBuildToolsVersion(buildToolsVersion)
.forVariantType(VariantType.DEFAULT)