Merge commit '5f9bf2799edba45cf60bb7bd684f6d19f438a08e' into dev-release
Change-Id: I9604ea001979aeee5ea02c9c7ffeb2483e0b05c5
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index f2dfda6..d6185c6 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -1,5 +1,5 @@
{
- "identifier": "com.tools.android:desugar_jdk_libs_configuration:2.1.0",
+ "identifier": "com.tools.android:desugar_jdk_libs_configuration:2.1.1",
"configuration_format_version": 101,
"required_compilation_api_level": 30,
"synthesized_library_classes_package_prefix": "j$.",
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
index 7303240..a576966 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
@@ -1,5 +1,5 @@
{
- "identifier": "com.tools.android:desugar_jdk_libs_configuration_minimal:2.1.0",
+ "identifier": "com.tools.android:desugar_jdk_libs_configuration_minimal:2.1.1",
"configuration_format_version": 101,
"required_compilation_api_level": 24,
"synthesized_library_classes_package_prefix": "j$.",
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
index 1aff889..19db3fa 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
@@ -1,5 +1,5 @@
{
- "identifier": "com.tools.android:desugar_jdk_libs_configuration_nio:2.1.0",
+ "identifier": "com.tools.android:desugar_jdk_libs_configuration_nio:2.1.1",
"configuration_format_version": 101,
"required_compilation_api_level": 30,
"synthesized_library_classes_package_prefix": "j$.",
diff --git a/src/main/java/com/android/tools/r8/ArchiveProtoAndroidResourceProvider.java b/src/main/java/com/android/tools/r8/ArchiveProtoAndroidResourceProvider.java
index e67c735..ca4321e 100644
--- a/src/main/java/com/android/tools/r8/ArchiveProtoAndroidResourceProvider.java
+++ b/src/main/java/com/android/tools/r8/ArchiveProtoAndroidResourceProvider.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import com.android.tools.r8.origin.ArchiveEntryOrigin;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.FileUtils;
import com.google.common.io.ByteStreams;
import java.io.ByteArrayInputStream;
@@ -49,6 +50,15 @@
this.origin = origin;
}
+ /**
+ * Creates an android resource provider from an archive.
+ *
+ * @param archive Zip archive to provide resources from.
+ */
+ public ArchiveProtoAndroidResourceProvider(Path archive) {
+ this(archive, new PathOrigin(archive));
+ }
+
@Override
public Collection<AndroidResourceInput> getAndroidResources() throws ResourceException {
try (ZipFile zipFile = FileUtils.createZipFile(archive.toFile(), StandardCharsets.UTF_8)) {
diff --git a/src/main/java/com/android/tools/r8/R8CommandParser.java b/src/main/java/com/android/tools/r8/R8CommandParser.java
index fa0a094..e3d5927 100644
--- a/src/main/java/com/android/tools/r8/R8CommandParser.java
+++ b/src/main/java/com/android/tools/r8/R8CommandParser.java
@@ -308,8 +308,7 @@
} else if (arg.equals("--android-resources")) {
Path inputPath = Paths.get(nextArg);
Path outputPath = Paths.get(nextNextArg);
- builder.setAndroidResourceProvider(
- new ArchiveProtoAndroidResourceProvider(inputPath, new PathOrigin(inputPath)));
+ builder.setAndroidResourceProvider(new ArchiveProtoAndroidResourceProvider(inputPath));
builder.setAndroidResourceConsumer(
new ArchiveProtoAndroidResourceConsumer(outputPath, inputPath));
} else if (arg.equals("--feature")) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
index fb052fb..fcd5428 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexMethod;
@@ -288,7 +289,7 @@
public void acceptNestConstructorBridge(
ProgramMethod target,
ProgramMethod bridge,
- DexProgramClass argumentClass,
+ DexClass argumentClass,
DexClassAndMethod context) {
// Intentionally empty.
}
@@ -722,7 +723,7 @@
public void acceptNestConstructorBridge(
ProgramMethod target,
ProgramMethod bridge,
- DexProgramClass argumentClass,
+ DexClass argumentClass,
DexClassAndMethod context) {
// Intentionally empty.
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
index a4465a9..93b2f34 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/D8NestBasedAccessDesugaring.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.conversion.D8MethodProcessor;
@@ -109,7 +108,7 @@
public void acceptNestConstructorBridge(
ProgramMethod target,
ProgramMethod bridge,
- DexProgramClass argumentClass,
+ DexClass argumentClass,
DexClassAndMethod context) {
methodProcessor.scheduleDesugaredMethodForProcessing(bridge);
}
@@ -229,8 +228,7 @@
private void ensureConstructorBridgeFromClasspathAccess(
ProgramMethod method, NestBasedAccessDesugaringEventConsumer eventConsumer) {
assert method.getDefinition().isInstanceInitializer();
- DexProgramClass constructorArgumentClass =
- ensureConstructorArgumentClass(method).asProgramClass();
+ DexClass constructorArgumentClass = ensureConstructorArgumentClass(method);
DexMethod bridgeReference = getConstructorBridgeReference(method, constructorArgumentClass);
synchronized (method.getHolder().getMethodCollection()) {
if (method.getHolder().lookupMethod(bridgeReference) == null) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
index 10f3501..0550d47 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
@@ -232,7 +232,7 @@
: AccessBridgeFactory.createMethodAccessorBridge(
bridgeAndTarget.getBridge(), targetMethod, dexItemFactory));
if (targetMethod.getDefinition().isInstanceInitializer()) {
- DexProgramClass argumentClass = getConstructorArgumentClass(targetMethod).asProgramClass();
+ DexClass argumentClass = getConstructorArgumentClass(targetMethod);
eventConsumer.acceptNestConstructorBridge(targetMethod, bridgeMethod, argumentClass, context);
} else {
eventConsumer.acceptNestMethodBridge(targetMethod, bridgeMethod, context);
@@ -441,34 +441,70 @@
}
private DexClass getConstructorArgumentClass(DexClassAndMethod constructor) {
- return syntheticNestConstructorTypes.get(constructor.getHolderType());
+ if (!appView.options().legacyNestDesugaringIAClasses) {
+ return syntheticNestConstructorTypes.get(constructor.getHolder().getNestHost());
+ } else {
+ return syntheticNestConstructorTypes.get(constructor.getHolderType());
+ }
}
DexClass ensureConstructorArgumentClass(DexClassAndMethod constructor) {
assert constructor.getDefinition().isInstanceInitializer();
- return syntheticNestConstructorTypes.computeIfAbsent(
- constructor.getHolderType(),
- holder -> {
- if (constructor.isProgramMethod()) {
- return appView
- .getSyntheticItems()
- .createFixedClass(
- kinds -> kinds.INIT_TYPE_ARGUMENT,
- constructor.asProgramMethod().getHolder(),
- appView,
- builder -> {});
- } else {
- assert constructor.isClasspathMethod();
- return appView
- .getSyntheticItems()
- .ensureFixedClasspathClass(
- kinds -> kinds.INIT_TYPE_ARGUMENT,
- constructor.asClasspathMethod().getHolder(),
- appView,
- ignored -> {},
- ignored -> {});
- }
- });
+ assert constructor.isProgramMethod() || constructor.isClasspathMethod();
+ if (!appView.options().legacyNestDesugaringIAClasses) {
+ DexType hostType =
+ constructor.isProgramMethod()
+ ? constructor.asProgramMethod().getHolder().getNestHost()
+ : constructor.asClasspathMethod().getHolder().getNestHost();
+ DexClass host = appView.definitionFor(hostType);
+ return syntheticNestConstructorTypes.computeIfAbsent(
+ hostType,
+ holder -> {
+ if (host.isProgramClass()) {
+ return appView
+ .getSyntheticItems()
+ .createFixedClass(
+ kinds -> kinds.INIT_TYPE_ARGUMENT,
+ host.asProgramClass(),
+ appView,
+ builder -> {});
+ } else {
+ assert host.isClasspathClass();
+ return appView
+ .getSyntheticItems()
+ .ensureFixedClasspathClass(
+ kinds -> kinds.INIT_TYPE_ARGUMENT,
+ host.asClasspathClass(),
+ appView,
+ ignored -> {},
+ ignored -> {});
+ }
+ });
+ } else {
+ return syntheticNestConstructorTypes.computeIfAbsent(
+ constructor.getHolderType(),
+ holder -> {
+ if (constructor.isProgramMethod()) {
+ return appView
+ .getSyntheticItems()
+ .createFixedClass(
+ kinds -> kinds.INIT_TYPE_ARGUMENT,
+ constructor.asProgramMethod().getHolder(),
+ appView,
+ builder -> {});
+ } else {
+ assert constructor.isClasspathMethod();
+ return appView
+ .getSyntheticItems()
+ .ensureFixedClasspathClass(
+ kinds -> kinds.INIT_TYPE_ARGUMENT,
+ constructor.asClasspathMethod().getHolder(),
+ appView,
+ ignored -> {},
+ ignored -> {});
+ }
+ });
+ }
}
DexMethod getConstructorBridgeReference(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaringEventConsumer.java
index afbeedc..8ec49e2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaringEventConsumer.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.ir.desugar.nest;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
@@ -14,7 +14,7 @@
void acceptNestConstructorBridge(
ProgramMethod target,
ProgramMethod bridge,
- DexProgramClass argumentClass,
+ DexClass argumentClass,
DexClassAndMethod context);
void acceptNestFieldGetBridge(
@@ -46,7 +46,7 @@
public void acceptNestConstructorBridge(
ProgramMethod target,
ProgramMethod bridge,
- DexProgramClass argumentClass,
+ DexClass argumentClass,
DexClassAndMethod context) {
// Intentionally empty.
}
diff --git a/src/main/java/com/android/tools/r8/profile/rewriting/ProfileRewritingCfInstructionDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/profile/rewriting/ProfileRewritingCfInstructionDesugaringEventConsumer.java
index b556923..3af5dc4 100644
--- a/src/main/java/com/android/tools/r8/profile/rewriting/ProfileRewritingCfInstructionDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/profile/rewriting/ProfileRewritingCfInstructionDesugaringEventConsumer.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.profile.rewriting.ProfileRewritingVarHandleDesugaringEventConsumerUtils.handleVarHandleDesugaringClassContext;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexMethod;
@@ -292,7 +293,7 @@
public void acceptNestConstructorBridge(
ProgramMethod target,
ProgramMethod bridge,
- DexProgramClass argumentClass,
+ DexClass argumentClass,
DexClassAndMethod context) {
nestBasedAccessDesugaringEventConsumer.acceptNestConstructorBridge(
target, bridge, argumentClass, context);
diff --git a/src/main/java/com/android/tools/r8/profile/rewriting/ProfileRewritingNestBasedAccessDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/profile/rewriting/ProfileRewritingNestBasedAccessDesugaringEventConsumer.java
index 7d731fb..c44706f 100644
--- a/src/main/java/com/android/tools/r8/profile/rewriting/ProfileRewritingNestBasedAccessDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/profile/rewriting/ProfileRewritingNestBasedAccessDesugaringEventConsumer.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.profile.rewriting;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.nest.NestBasedAccessDesugaringEventConsumer;
@@ -38,12 +38,13 @@
public void acceptNestConstructorBridge(
ProgramMethod target,
ProgramMethod bridge,
- DexProgramClass argumentClass,
+ DexClass argumentClass,
DexClassAndMethod context) {
if (context.isProgramMethod()) {
additionsCollection.applyIfContextIsInProfile(
context.asProgramMethod(),
- additionsBuilder -> additionsBuilder.addRule(argumentClass).addRule(bridge));
+ additionsBuilder ->
+ additionsBuilder.addRule(argumentClass.getReference()).addRule(bridge));
} else {
additionsCollection.accept(
additions ->
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
index 69f6f02..a63cce4 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
@@ -402,9 +402,18 @@
return;
}
assert type.isIdenticalTo(newType)
- || !info.isPinned(options)
- || info.isMinificationAllowed(options)
- || info.isRepackagingAllowed(options);
+ || !info.isPinned(options)
+ || info.isMinificationAllowed(options)
+ || info.isRepackagingAllowed(options)
+ : type.toSourceString()
+ + " -> "
+ + newType.toSourceString()
+ + ": isPinned: "
+ + info.isPinned(options)
+ + ", isMinificationAllowed: "
+ + info.isMinificationAllowed(options)
+ + ", isRepackagingAllowed: "
+ + info.isRepackagingAllowed(options);
KeepClassInfo previous = newClassInfo.put(newType, info);
assert previous == null;
});
diff --git a/src/main/java/com/android/tools/r8/shaking/rules/MaterializedRules.java b/src/main/java/com/android/tools/r8/shaking/rules/MaterializedRules.java
index c66cdf1..ad3f8f6 100644
--- a/src/main/java/com/android/tools/r8/shaking/rules/MaterializedRules.java
+++ b/src/main/java/com/android/tools/r8/shaking/rules/MaterializedRules.java
@@ -31,11 +31,11 @@
}
public MaterializedRules rewriteWithLens(NonIdentityGraphLens lens) {
- // The preconditions of these are not rewritten. We assume witnessing instructions
- // to cary the original references to deem them effectively live.
+ // The conditional rules are not rewritten. We assume witnessing instructions to carry the
+ // original references to deem them effectively live.
// TODO(b/323816623): Do we need to rewrite the consequent sets? Or would the constraints
// always ensure they remain if the keep info needs to be reapplied?
- return this;
+ return new MaterializedRules(rootConsequences.rewrittenWithLens(lens), conditionalRules);
}
public ApplicableRulesEvaluator toApplicableRules() {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
index 3340e46..572b8d1 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
@@ -26,6 +26,8 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.ReachabilitySensitiveValue;
+import com.android.tools.r8.utils.structural.HasherWrapper;
+import com.android.tools.r8.utils.structural.StructuralItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -186,11 +188,6 @@
directMethods.add(method);
}
}
- long checksum =
- 7 * (long) directMethods.hashCode()
- + 11 * (long) virtualMethods.hashCode()
- + 13 * (long) staticFields.hashCode()
- + 17 * (long) instanceFields.hashCode();
C clazz =
getClassKind()
.create(
@@ -214,7 +211,7 @@
DexEncodedMethod.EMPTY_ARRAY,
DexEncodedMethod.EMPTY_ARRAY,
factory.getSkipNameValidationForTesting(),
- c -> checksum,
+ c -> getChecksum(),
null,
ReachabilitySensitiveValue.DISABLED);
if (useSortedMethodBacking) {
@@ -224,4 +221,18 @@
clazz.setVirtualMethods(virtualMethods.toArray(DexEncodedMethod.EMPTY_ARRAY));
return clazz;
}
+
+ private long getChecksum() {
+ return 7 * hashEntries(virtualMethods, directMethods)
+ + 13 * hashEntries(instanceFields, staticFields);
+ }
+
+ private <S extends StructuralItem<S>> long hashEntries(List<S>... entryLists) {
+ // Use a hasher that is stable across jvm runs.
+ HasherWrapper hasherWrapper = HasherWrapper.murmur3128Hasher();
+ for (List<S> entryList : entryLists) {
+ entryList.stream().sorted().forEach(e -> e.hash(hasherWrapper));
+ }
+ return hasherWrapper.hash().hashCode();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 3146c85..dac665d 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -523,6 +523,10 @@
// Flag to allow force nest desugaring, even if natively supported on the chosen API level.
public boolean forceNestDesugaring =
System.getProperty("com.android.tools.r8.forceNestDesugaring") != null;
+ // Flag to use legacy generation of -IA classes for nests (only for Platform until aosp/3241282
+ // lands).
+ public boolean legacyNestDesugaringIAClasses =
+ System.getProperty("com.android.tools.r8.legacyNestDesugaringIAClasses") != null;
// TODO(b/293591931): Remove this flag.
// Flag to allow permitted subclasses annotations in DEX. See b/231930852 for context.
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
index 5ac9755..875288c 100644
--- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
+++ b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
@@ -64,6 +64,19 @@
private final Set<String> seenNoneClassValues = new HashSet<>();
private final Set<Integer> seenResourceIds = new HashSet<>();
+ private static final Set<String> SPECIAL_MANIFEST_ELEMENTS =
+ ImmutableSet.of(
+ "provider",
+ "activity",
+ "service",
+ "receiver",
+ "instrumentation",
+ "process",
+ "application");
+
+ private static final Set<String> SPECIAL_APPLICATION_ATTRIBUTES =
+ ImmutableSet.of("backupAgent", "appComponentFactory", "zygotePreloadName");
+
@FunctionalInterface
public interface ClassReferenceCallback {
boolean tryClass(String possibleClass, Origin xmlFileOrigin);
@@ -226,7 +239,7 @@
private void traceXml(String xmlFile, InputStream inputStream) {
try {
XmlNode xmlNode = XmlNode.parseFrom(inputStream);
- visitNode(xmlNode, xmlFile);
+ visitNode(xmlNode, xmlFile, null);
// Ensure that we trace the transitive reachable ids, without us having to iterate all
// resources for the reachable marker.
ProtoAndroidManifestUsageRecorderKt.recordUsagesFromNode(xmlNode, r8ResourceShrinkerModel)
@@ -237,7 +250,6 @@
}
}
-
private void tryEnqueuerOnString(String possibleClass, String xmlName) {
// There are a lot of xml tags and attributes that are evaluated over and over, if it is
// not a class, ignore it.
@@ -249,18 +261,51 @@
}
}
- private void visitNode(XmlNode xmlNode, String xmlName) {
+ private void visitNode(XmlNode xmlNode, String xmlName, String manifestPackageName) {
XmlElement element = xmlNode.getElement();
tryEnqueuerOnString(element.getName(), xmlName);
+
for (XmlAttribute xmlAttribute : element.getAttributeList()) {
+ if (xmlAttribute.getName().equals("package") && element.getName().equals("manifest")) {
+ // We are traversing a manifest, record the package name if we see it.
+ manifestPackageName = xmlAttribute.getValue();
+ }
String value = xmlAttribute.getValue();
tryEnqueuerOnString(value, xmlName);
if (value.startsWith(".")) {
// package specific names, e.g. context
getPackageNames().forEach(s -> tryEnqueuerOnString(s + value, xmlName));
}
+ if (manifestPackageName != null) {
+ // Manifest case
+ traceManifestSpecificValues(xmlName, manifestPackageName, xmlAttribute, element);
+ }
}
- element.getChildList().forEach(e -> visitNode(e, xmlName));
+ for (XmlNode node : element.getChildList()) {
+ visitNode(node, xmlName, manifestPackageName);
+ }
+ }
+
+ private void traceManifestSpecificValues(
+ String xmlName, String packageName, XmlAttribute xmlAttribute, XmlElement element) {
+ if (!SPECIAL_MANIFEST_ELEMENTS.contains(element.getName())) {
+ return;
+ }
+ // All elements can have package specific name attributes pointing at classes.
+ if (xmlAttribute.getName().equals("name")) {
+ tryEnqueuerOnString(getFullyQualifiedName(packageName, xmlAttribute), xmlName);
+ }
+ // Application elements have multiple special case attributes, where the value is potentially
+ // a class name (unqualified).
+ if (element.getName().equals("application")) {
+ if (SPECIAL_APPLICATION_ATTRIBUTES.contains(xmlAttribute.getName())) {
+ tryEnqueuerOnString(getFullyQualifiedName(packageName, xmlAttribute), xmlName);
+ }
+ }
+ }
+
+ private static String getFullyQualifiedName(String packageName, XmlAttribute xmlAttribute) {
+ return packageName + "." + xmlAttribute.getValue();
}
public Map<Integer, List<String>> getResourceIdToXmlFiles() {
diff --git a/src/test/bootstrap/com/android/tools/r8/bootstrap/BootstrapDeterminismTest.java b/src/test/bootstrap/com/android/tools/r8/bootstrap/BootstrapDeterminismTest.java
index 6afaa95..1ba438d 100644
--- a/src/test/bootstrap/com/android/tools/r8/bootstrap/BootstrapDeterminismTest.java
+++ b/src/test/bootstrap/com/android/tools/r8/bootstrap/BootstrapDeterminismTest.java
@@ -6,6 +6,7 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.ClassFileConsumer;
+import com.android.tools.r8.DexIndexedConsumer.ArchiveConsumer;
import com.android.tools.r8.JdkClassFileProvider;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -51,6 +52,18 @@
assertTrue(Files.exists(logDirectory.resolve("0.log")));
}
+ @Test
+ public void testD8DeterminismWithChecksums() throws Exception {
+ Path logDirectory = temp.newFolder().toPath();
+ Path ref = compileD8WithChecksums(1, logDirectory);
+ for (int i = 2; i <= ITERATIONS; i++) {
+ Path next = compileD8WithChecksums(i, logDirectory);
+ assertProgramsEqual(ref, next);
+ }
+ // Check that setting the determinism checker wrote a log file.
+ assertTrue(Files.exists(logDirectory.resolve("0.log")));
+ }
+
private Path compile(int iteration, Path logDirectory) throws Exception {
System.out.println("= compiling " + iteration + "/" + ITERATIONS + " ======================");
Path out = temp.newFolder().toPath().resolve("out.jar");
@@ -71,4 +84,25 @@
.compile();
return out;
}
+
+ private Path compileD8WithChecksums(int iteration, Path logDirectory) throws Exception {
+ System.out.println("= compiling d8 " + iteration + "/" + ITERATIONS + " =====================");
+ Path out = temp.newFolder().toPath().resolve("out.jar");
+ testForD8(Backend.DEX)
+ .addProgramFiles(ToolHelper.getR8WithRelocatedDeps())
+ .addLibraryProvider(JdkClassFileProvider.fromSystemJdk())
+ .addOptionsModification(
+ options -> {
+ options
+ .getTestingOptions()
+ .setDeterminismChecker(DeterminismChecker.createWithFileBacking(logDirectory));
+ // Ensure that we generate the same check sums, see b/359616078
+ options.encodeChecksums = true;
+ })
+ .allowStdoutMessages()
+ .allowStderrMessages()
+ .setProgramConsumer(new ArchiveConsumer(out))
+ .compile();
+ return out;
+ }
}
diff --git a/src/test/examplesJava11/nesthostexample/NestInitArgumentContextTest.java b/src/test/examplesJava11/nesthostexample/NestInitArgumentContextTest.java
index 0dec846..2de3600 100644
--- a/src/test/examplesJava11/nesthostexample/NestInitArgumentContextTest.java
+++ b/src/test/examplesJava11/nesthostexample/NestInitArgumentContextTest.java
@@ -29,10 +29,15 @@
@Parameter(1)
public boolean intermediate;
- @Parameters(name = "{0}, intermediate = {1}")
+ @Parameter(2)
+ public boolean legacyNestDesugaringIAClasses;
+
+ @Parameters(name = "{0}, intermediate = {1}, legacyNestDesugaringIAClasses = {2}")
public static List<Object[]> data() {
return buildParameters(
- getTestParameters().withDexRuntimesAndAllApiLevels().build(), BooleanUtils.values());
+ getTestParameters().withDexRuntimesAndAllApiLevels().build(),
+ BooleanUtils.values(),
+ BooleanUtils.values());
}
@Test
@@ -41,11 +46,13 @@
.addProgramClassesAndInnerClasses(NestInitArgumentContextClass.class)
.setMinApi(parameters)
.setIntermediate(intermediate)
+ .addOptionsModification(
+ options -> options.legacyNestDesugaringIAClasses = legacyNestDesugaringIAClasses)
.compile()
.inspect(
inspector ->
assertEquals(
- 5,
+ legacyNestDesugaringIAClasses ? 5 : 1,
inspector.allClasses().stream()
.map(ClassSubject::getFinalName)
.filter(name -> name.endsWith("-IA"))
@@ -69,11 +76,13 @@
.addClasspathClasses(innerClasses)
.setMinApi(parameters)
.setIntermediate(intermediate)
+ .addOptionsModification(
+ options -> options.legacyNestDesugaringIAClasses = legacyNestDesugaringIAClasses)
.compile()
.inspect(
inspector ->
assertEquals(
- 1,
+ legacyNestDesugaringIAClasses ? 1 : 0,
inspector.allClasses().stream()
.map(ClassSubject::getFinalName)
.filter(name -> name.endsWith("-IA"))
@@ -87,6 +96,8 @@
.addClasspathClasses(innerClasses)
.setMinApi(parameters)
.setIntermediate(intermediate)
+ .addOptionsModification(
+ options -> options.legacyNestDesugaringIAClasses = legacyNestDesugaringIAClasses)
.compile()
.inspect(
inspector ->
@@ -102,11 +113,13 @@
.addProgramFiles(innerClassesCompiled)
.addProgramFiles(outerClassCompiled)
.setMinApi(parameters)
+ .addOptionsModification(
+ options -> options.legacyNestDesugaringIAClasses = legacyNestDesugaringIAClasses)
.compile()
.inspect(
inspector ->
assertEquals(
- 5,
+ legacyNestDesugaringIAClasses ? 5 : 1,
inspector.allClasses().stream()
.map(ClassSubject::getFinalName)
.filter(name -> name.endsWith("-IA"))
diff --git a/src/test/examplesJava11/nesthostexample/NestOnProgramOnClassPathTest.java b/src/test/examplesJava11/nesthostexample/NestOnProgramOnClassPathTest.java
index d2e3d0c..974683a 100644
--- a/src/test/examplesJava11/nesthostexample/NestOnProgramOnClassPathTest.java
+++ b/src/test/examplesJava11/nesthostexample/NestOnProgramOnClassPathTest.java
@@ -64,13 +64,13 @@
inner.inspect(
inspector -> {
assertThisNumberOfBridges(inspector, 3);
- assertNestConstructor(inspector);
+ assertNoNestConstructor(inspector);
});
D8TestCompileResult host = compileClassesWithD8ProgramClasses(nestHost, nestHost);
host.inspect(
inspector -> {
assertThisNumberOfBridges(inspector, 1);
- assertNestConstructor(inspector);
+ assertInitArgumentClass(inspector);
});
}
@@ -100,10 +100,14 @@
.compile();
}
- private static void assertNestConstructor(CodeInspector inspector) {
+ private static void assertInitArgumentClass(CodeInspector inspector) {
assertTrue(inspector.allClasses().stream().anyMatch(FoundClassSubject::isSynthetic));
}
+ private static void assertNoNestConstructor(CodeInspector inspector) {
+ assertTrue(inspector.allClasses().stream().noneMatch(FoundClassSubject::isSynthetic));
+ }
+
private static void assertThisNumberOfBridges(CodeInspector inspector, int numBridges) {
for (FoundClassSubject clazz : inspector.allClasses()) {
if (!clazz.isSynthetic()) {
diff --git a/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithApplicationAttributesTest.java b/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithApplicationAttributesTest.java
new file mode 100644
index 0000000..2770b77
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithApplicationAttributesTest.java
@@ -0,0 +1,99 @@
+// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.androidresources;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AndroidManifestWithApplicationAttributesTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameter(1)
+ public String attributeName;
+
+ @Parameters(name = "{0}, attributeName: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDefaultDexRuntime().withAllApiLevels().build(),
+ ImmutableList.of("backupAgent", "appComponentFactory", "zygotePreloadName"));
+ }
+
+ private static final String INNER_CLASS_NAME =
+ AndroidManifestWithApplicationAttributesTest.class.getSimpleName()
+ + "$"
+ + Bar.class.getSimpleName();
+
+ public static String MANIFEST_WITH_MANIFEST_PACKAGE_USAGE_SUB_APPLICATION =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ + " xmlns:tools=\"http://schemas.android.com/tools\""
+ + " package=\""
+ + AndroidManifestWithApplicationAttributesTest.class.getPackage().getName()
+ + "\""
+ + ">\n"
+ + " <application android:%s=\""
+ + INNER_CLASS_NAME
+ + "\"/>"
+ + "</manifest>";
+
+ public AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
+ return new AndroidTestResourceBuilder()
+ .withManifest(
+ String.format(MANIFEST_WITH_MANIFEST_PACKAGE_USAGE_SUB_APPLICATION, attributeName))
+ .build(temp);
+ }
+
+ @Test
+ public void testManifestReferences() throws Exception {
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(Bar.class)
+ .addAndroidResources(getTestResources(temp))
+ .enableOptimizedShrinking()
+ .compile()
+ .inspect(
+ codeInspector -> {
+ ClassSubject barClass = codeInspector.clazz(Bar.class);
+ assertThat(barClass, isPresentAndNotRenamed());
+ // We should have two and only two methods, the two constructors.
+ assertEquals(barClass.allMethods(MethodSubject::isInstanceInitializer).size(), 2);
+ assertEquals(barClass.allMethods().size(), 2);
+ });
+ }
+
+ // Only referenced from Manifest file
+ public static class Bar {
+ // We should keep this since this is a provider
+ public Bar() {
+ System.out.println("init");
+ }
+
+ public Bar(String x) {
+ System.out.println("init with string");
+ }
+
+ public void bar() {
+ System.out.println("never kept");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithApplicationElementTest.java b/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithApplicationElementTest.java
new file mode 100644
index 0000000..5e3ea38
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithApplicationElementTest.java
@@ -0,0 +1,101 @@
+// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.androidresources;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AndroidManifestWithApplicationElementTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameter(1)
+ public String elementType;
+
+ @Parameters(name = "{0}, elementType: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDefaultDexRuntime().withAllApiLevels().build(),
+ ImmutableList.of("provider", "activity", "service", "receiver"));
+ }
+
+ private static final String INNER_CLASS_NAME =
+ AndroidManifestWithApplicationElementTest.class.getSimpleName()
+ + "$"
+ + Bar.class.getSimpleName();
+
+ public static String MANIFEST_WITH_MANIFEST_PACKAGE_USAGE_SUB_APPLICATION =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ + " xmlns:tools=\"http://schemas.android.com/tools\""
+ + " package=\""
+ + AndroidManifestWithApplicationElementTest.class.getPackage().getName()
+ + "\""
+ + ">\n"
+ + " <application>\n"
+ + " <%s android:name=\""
+ + INNER_CLASS_NAME
+ + "\"/>"
+ + " </application>\n"
+ + "</manifest>";
+
+ public AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
+ return new AndroidTestResourceBuilder()
+ .withManifest(
+ String.format(MANIFEST_WITH_MANIFEST_PACKAGE_USAGE_SUB_APPLICATION, elementType))
+ .build(temp);
+ }
+
+ @Test
+ public void testManifestReferences() throws Exception {
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(Bar.class)
+ .addAndroidResources(getTestResources(temp))
+ .enableOptimizedShrinking()
+ .compile()
+ .inspect(
+ codeInspector -> {
+ ClassSubject barClass = codeInspector.clazz(Bar.class);
+ assertThat(barClass, isPresentAndNotRenamed());
+ // We should have two and only two methods, the two constructors.
+ assertEquals(barClass.allMethods(MethodSubject::isInstanceInitializer).size(), 2);
+ assertEquals(barClass.allMethods().size(), 2);
+ });
+ }
+
+ // Only referenced from Manifest file
+ public static class Bar {
+ // We should keep this since this is a provider
+ public Bar() {
+ System.out.println("init");
+ }
+
+ public Bar(String x) {
+ System.out.println("init with string");
+ }
+
+ public void bar() {
+ System.out.println("never kept");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithManifestEntriesTest.java b/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithManifestEntriesTest.java
new file mode 100644
index 0000000..6037077
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithManifestEntriesTest.java
@@ -0,0 +1,99 @@
+// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.androidresources;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AndroidManifestWithManifestEntriesTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameter(1)
+ public String elementType;
+
+ @Parameters(name = "{0}, elementType: {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDefaultDexRuntime().withAllApiLevels().build(),
+ ImmutableList.of("application", "instrumentation"));
+ }
+
+ private static final String INNER_CLASS_NAME =
+ AndroidManifestWithManifestEntriesTest.class.getSimpleName()
+ + "$"
+ + Bar.class.getSimpleName();
+
+ public static String MANIFEST_WITH_MANIFEST_PACKAGE_USAGE_SUB_APPLICATION =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ + " xmlns:tools=\"http://schemas.android.com/tools\""
+ + " package=\""
+ + AndroidManifestWithManifestEntriesTest.class.getPackage().getName()
+ + "\""
+ + ">\n"
+ + " <%s android:name=\""
+ + INNER_CLASS_NAME
+ + "\"/>\n"
+ + "</manifest>";
+
+ public AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
+ return new AndroidTestResourceBuilder()
+ .withManifest(
+ String.format(MANIFEST_WITH_MANIFEST_PACKAGE_USAGE_SUB_APPLICATION, elementType))
+ .build(temp);
+ }
+
+ @Test
+ public void testManifestReferences() throws Exception {
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(Bar.class)
+ .addAndroidResources(getTestResources(temp))
+ .enableOptimizedShrinking()
+ .compile()
+ .inspect(
+ codeInspector -> {
+ ClassSubject barClass = codeInspector.clazz(Bar.class);
+ assertThat(barClass, isPresentAndNotRenamed());
+ // We should have two and only two methods, the two constructors.
+ assertEquals(barClass.allMethods(MethodSubject::isInstanceInitializer).size(), 2);
+ assertEquals(barClass.allMethods().size(), 2);
+ });
+ }
+
+ // Only referenced from Manifest file
+ public static class Bar {
+ // We should keep this since this is a provider
+ public Bar() {
+ System.out.println("init");
+ }
+
+ public Bar(String x) {
+ System.out.println("init with string");
+ }
+
+ public void bar() {
+ System.out.println("never kept");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithProcessesTest.java b/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithProcessesTest.java
new file mode 100644
index 0000000..e4f8583
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/androidresources/AndroidManifestWithProcessesTest.java
@@ -0,0 +1,92 @@
+// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.androidresources;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class AndroidManifestWithProcessesTest extends TestBase {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection parameters() {
+ return getTestParameters().withDefaultDexRuntime().withAllApiLevels().build();
+ }
+
+ private static final String INNER_CLASS_NAME =
+ AndroidManifestWithProcessesTest.class.getSimpleName() + "$" + Bar.class.getSimpleName();
+
+ public static String MANIFEST_WITH_PROCESS =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ + "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+ + " xmlns:tools=\"http://schemas.android.com/tools\""
+ + " package=\""
+ + AndroidManifestWithProcessesTest.class.getPackage().getName()
+ + "\""
+ + ">\n"
+ + " <application>\n"
+ + " <processes>\n"
+ + " <process android:process=\":sub\" android:name=\""
+ + INNER_CLASS_NAME
+ + "\"/>\n"
+ + " </processes>\n"
+ + " </application>\n"
+ + "</manifest>";
+
+ public AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
+ return new AndroidTestResourceBuilder().withManifest(MANIFEST_WITH_PROCESS).build(temp);
+ }
+
+ @Test
+ public void testManifestReferences() throws Exception {
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters)
+ .addProgramClasses(Bar.class)
+ .addAndroidResources(getTestResources(temp))
+ .enableOptimizedShrinking()
+ .compile()
+ .inspect(
+ codeInspector -> {
+ ClassSubject barClass = codeInspector.clazz(Bar.class);
+ assertThat(barClass, isPresentAndNotRenamed());
+ // We should have two and only two methods, the two constructors.
+ assertEquals(barClass.allMethods(MethodSubject::isInstanceInitializer).size(), 2);
+ assertEquals(barClass.allMethods().size(), 2);
+ });
+ }
+
+ // Only referenced from Manifest file
+ public static class Bar {
+ // We should keep this since this is a provider
+ public Bar() {
+ System.out.println("init");
+ }
+
+ public Bar(String x) {
+ System.out.println("init with string");
+ }
+
+ public void bar() {
+ System.out.println("never kept");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterStandaloneMonthTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterStandaloneMonthTest.java
index 0a83c05..60f5174 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterStandaloneMonthTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DateTimeFormatterStandaloneMonthTest.java
@@ -5,12 +5,11 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
-import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK8_DESCRIPTOR;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_DESCRIPTOR;
import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.getJdk8Jdk11;
import com.android.tools.r8.SingleTestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
import com.android.tools.r8.utils.StringUtils;
@@ -30,21 +29,6 @@
StringUtils.lines(
"1 - 1", "2 - 2", "3 - 3", "4 - 4", "5 - 5", "6 - 6", "7 - 7", "8 - 8", "9 - 9",
"10 - 10", "11 - 11", "12 - 12");
- private static final String expectedOutputLibJdk11 =
- StringUtils.lines(
- "Jan - January",
- "Feb - February",
- "Mar - March",
- "Apr - April",
- "May - May",
- "Jun - June",
- "Jul - July",
- "Aug - August",
- "Sep - September",
- "Oct - October",
- "Nov - November",
- // TODO(b/323306225): December is missing.
- " - ");
private static final String expectedOutput =
StringUtils.lines(
"Jan - January",
@@ -90,15 +74,11 @@
.addKeepMainRule(TestClass.class)
.run(parameters.getRuntime(), TestClass.class)
.assertSuccess();
- if (apiLevelWithJavaTime(parameters)) {
- run.assertSuccessWithOutput(expectedOutput);
- } else if (libraryDesugaringSpecification.getDescriptor() == JDK8_DESCRIPTOR) {
- run.assertSuccessWithOutput(expectedOutputDesugaredLibJdk8);
- } else if (parameters.getRuntime().asDex().getVersion().isEqualTo(Version.V4_0_4)) {
- // Not sure why this works for Dalvik 4.0.4, but not really relevant.
+ if (apiLevelWithJavaTime(parameters)
+ || libraryDesugaringSpecification.getDescriptor() == JDK11_DESCRIPTOR) {
run.assertSuccessWithOutput(expectedOutput);
} else {
- run.assertSuccessWithOutput(expectedOutputLibJdk11);
+ run.assertSuccessWithOutput(expectedOutputDesugaredLibJdk8);
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
index 3c7248a..b2ea090 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
@@ -91,9 +91,9 @@
parameters.isCfRuntime(),
result ->
result.assertSuccessWithOutputLines(
- "Outer$Inner-IA, 1",
- "int, Outer$Inner-IA, 2",
- "int, int, Outer$Inner-IA, 3",
+ "Outer-IA, 1",
+ "int, Outer-IA, 2",
+ "int, int, Outer-IA, 3",
"int, int, 2",
"int, 1",
"0"),
@@ -102,9 +102,9 @@
"0",
"int, 1",
"int, int, 2",
- "int, int, Outer$Inner-IA, 3",
- "int, Outer$Inner-IA, 2",
- "Outer$Inner-IA, 1"));
+ "int, int, Outer-IA, 3",
+ "int, Outer-IA, 2",
+ "Outer-IA, 1"));
}
@Test
diff --git a/src/test/java/com/android/tools/r8/profile/art/completeness/NestBasedAccessBridgesProfileRewritingTest.java b/src/test/java/com/android/tools/r8/profile/art/completeness/NestBasedAccessBridgesProfileRewritingTest.java
index 5756f2e..2b2d2f0 100644
--- a/src/test/java/com/android/tools/r8/profile/art/completeness/NestBasedAccessBridgesProfileRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/profile/art/completeness/NestBasedAccessBridgesProfileRewritingTest.java
@@ -107,7 +107,6 @@
inspect(
profileInspector,
inspector,
- false,
parameters.canUseNestBasedAccessesWhenDesugaring(),
false);
}
@@ -117,7 +116,6 @@
inspect(
profileInspector,
inspector,
- parameters.canHaveNonReboundConstructorInvoke(),
parameters.canUseNestBasedAccesses(),
true);
}
@@ -125,7 +123,6 @@
private void inspect(
ArtProfileInspector profileInspector,
CodeInspector inspector,
- boolean canHaveNonReboundConstructorInvoke,
boolean canUseNestBasedAccesses,
boolean isR8)
throws Exception {
@@ -135,7 +132,7 @@
ClassSubject syntheticConstructorArgumentClassSubject =
inspector.clazz(
SyntheticItemsTestUtils.syntheticNestConstructorArgumentClass(
- Reference.classFromClass(NestMember.class)));
+ Reference.classFromClass(Main.class)));
assertThat(
syntheticConstructorArgumentClassSubject, notIf(isPresent(), canUseNestBasedAccesses));
diff --git a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
index 3412d54..7ef9b00 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
@@ -966,9 +966,7 @@
Path resourceZip = testResource.getResourceZip();
featureSplitGenerator
.setAndroidResourceConsumer(new ArchiveProtoAndroidResourceConsumer(outputFile))
- .setAndroidResourceProvider(
- new ArchiveProtoAndroidResourceProvider(
- resourceZip, new PathOrigin(resourceZip)))
+ .setAndroidResourceProvider(new ArchiveProtoAndroidResourceProvider(resourceZip))
.setProgramConsumer(DexIndexedConsumer.emptyConsumer());
return featureSplitGenerator.build();
@@ -997,10 +995,10 @@
AndroidTestResource testResource) {
Path resources = testResource.getResourceZip();
if (testResource.getAdditionalKeepRuleFiles().isEmpty()) {
- return new ArchiveProtoAndroidResourceProvider(resources, new PathOrigin(resources));
+ return new ArchiveProtoAndroidResourceProvider(resources);
}
ArchiveProtoAndroidResourceProvider provider =
- new ArchiveProtoAndroidResourceProvider(resources, new PathOrigin(resources)) {
+ new ArchiveProtoAndroidResourceProvider(resources) {
@Override
public Collection<AndroidResourceInput> getAndroidResources() throws ResourceException {
ArrayList<AndroidResourceInput> resourceInputs =
diff --git a/third_party/openjdk/desugar_jdk_libs_11.tar.gz.sha1 b/third_party/openjdk/desugar_jdk_libs_11.tar.gz.sha1
index 8779e19..ac5fd5a 100644
--- a/third_party/openjdk/desugar_jdk_libs_11.tar.gz.sha1
+++ b/third_party/openjdk/desugar_jdk_libs_11.tar.gz.sha1
@@ -1 +1 @@
-5b02bd53b6df482392dbd41b04c137b0b3c99388
\ No newline at end of file
+f4f486f37cf801466634ffbf584adb80dc839f4d
\ No newline at end of file
diff --git a/tools/r8_release.py b/tools/r8_release.py
index 5e0f695..e524f5c 100755
--- a/tools/r8_release.py
+++ b/tools/r8_release.py
@@ -649,7 +649,8 @@
# TODO(b/237636871): Cleanup and generalize.
if (not (library_version.startswith('1.1') or
library_version.startswith('1.2') or
- library_version.startswith('2.0'))):
+ library_version.startswith('2.0') or
+ library_version.startswith('2.1'))):
print(
"Release script does not support desugared library version %s" %
library_version)
@@ -658,7 +659,7 @@
postfixes = ['']
if library_version.startswith('1.2'):
postfixes = ['_legacy']
- if library_version.startswith('2.0'):
+ if library_version.startswith('2.0') or library_version.startswith('2.1'):
postfixes = ['_minimal', '', '_nio']
with utils.TempDir() as temp: