PrintUses: Allow obfuscating members with package-dependent visiblity
It is important that members with package-dependent visiblity stay in
the same package as defined - otherwise, some tests may fail on access
violations.
But instead of keeping without allowing obfuscation, we should just
keep the package names.
Bug: 145310926
Change-Id: Ibbf4aec9c728c32f4f79f902c1147349fe0678b5
diff --git a/src/main/java/com/android/tools/r8/PrintUses.java b/src/main/java/com/android/tools/r8/PrintUses.java
index 0d8f3ba..2864dfb 100644
--- a/src/main/java/com/android/tools/r8/PrintUses.java
+++ b/src/main/java/com/android/tools/r8/PrintUses.java
@@ -24,6 +24,7 @@
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -31,6 +32,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
@@ -70,6 +72,7 @@
private Map<DexType, Set<DexMethod>> methods = Maps.newIdentityHashMap();
private Map<DexType, Set<DexField>> fields = Maps.newIdentityHashMap();
private Set<DexType> noObfuscationTypes = Sets.newIdentityHashSet();
+ private Set<String> keepPackageNames = Sets.newHashSet();
private final DexApplication application;
private final AppInfoWithSubtyping appInfo;
private int errors;
@@ -165,11 +168,12 @@
private void addType(DexType type) {
if (isTargetType(type) && types.add(type)) {
DexClass clazz = appInfo.definitionFor(type);
- if (clazz == null
- || clazz.accessFlags.isVisibilityDependingOnPackage()
- || !allowObfuscation) {
+ if (clazz == null || !allowObfuscation) {
noObfuscationTypes.add(type);
}
+ if (clazz != null && clazz.accessFlags.isVisibilityDependingOnPackage()) {
+ keepPackageNames.add(clazz.type.getPackageName());
+ }
methods.put(type, Sets.newIdentityHashSet());
fields.put(type, Sets.newIdentityHashSet());
}
@@ -192,9 +196,12 @@
Set<DexField> typeFields = fields.get(field.holder);
if (typeFields != null) {
assert baseField != null;
- if (!allowObfuscation || baseField.accessFlags.isVisibilityDependingOnPackage()) {
+ if (!allowObfuscation) {
noObfuscationTypes.add(field.holder);
}
+ if (baseField.accessFlags.isVisibilityDependingOnPackage()) {
+ keepPackageNames.add(baseField.field.holder.getPackageName());
+ }
typeFields.add(field);
}
}
@@ -209,9 +216,12 @@
if (typeMethods != null) {
DexEncodedMethod encodedMethod = appInfo.definitionFor(method);
assert encodedMethod != null;
- if (!allowObfuscation || encodedMethod.accessFlags.isVisibilityDependingOnPackage()) {
+ if (!allowObfuscation) {
noObfuscationTypes.add(method.holder);
}
+ if (encodedMethod.accessFlags.isVisibilityDependingOnPackage()) {
+ keepPackageNames.add(encodedMethod.method.holder.getPackageName());
+ }
typeMethods.add(method);
}
}
@@ -344,7 +354,8 @@
}
private void print() {
- errors = printer.print(application, types, noObfuscationTypes, methods, fields);
+ errors =
+ printer.print(application, types, noObfuscationTypes, keepPackageNames, methods, fields);
}
private abstract static class Printer {
@@ -378,6 +389,8 @@
abstract void printMethod(DexEncodedMethod encodedMethod, String typeName);
+ abstract void printPackageNames(List<String> packageNames);
+
void printNameAndReturn(DexEncodedMethod encodedMethod) {
if (encodedMethod.accessFlags.isConstructor()) {
printConstructorName(encodedMethod);
@@ -397,6 +410,7 @@
DexApplication application,
Set<DexType> types,
Set<DexType> noObfuscationTypes,
+ Set<String> keepPackageNames,
Map<DexType, Set<DexMethod>> methods,
Map<DexType, Set<DexField>> fields) {
int errors = 0;
@@ -431,6 +445,9 @@
}
printTypeFooter();
}
+ ArrayList<String> packageNamesToKeep = new ArrayList<>(keepPackageNames);
+ Collections.sort(packageNamesToKeep);
+ printPackageNames(packageNamesToKeep);
return errors;
}
}
@@ -457,6 +474,11 @@
}
@Override
+ void printPackageNames(List<String> packageNames) {
+ // No need to print package names for text output.
+ }
+
+ @Override
void printTypeHeader(DexClass dexClass, boolean allowObfuscation) {
appendLine(dexClass.type.toSourceString());
}
@@ -520,6 +542,11 @@
}
@Override
+ void printPackageNames(List<String> packageNames) {
+ append("-keeppackagenames " + StringUtils.join(packageNames, ",") + "\n");
+ }
+
+ @Override
public void printTypeFooter() {
appendLine("}");
}