aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorten Krogh-Jespersen <mkroghj@google.com>2021-03-17 15:04:53 +0100
committerMorten Krogh-Jespersen <mkroghj@google.com>2021-03-17 15:04:53 +0100
commit3ccb20e59e6263077621f7277e5c9a1065112914 (patch)
treefeb5fd5ffd8a67dc0f706070091dbb4d1f3d3a50
parent04a2efc2016f69448546116133fd3419c3a2a807 (diff)
downloadr8-3ccb20e59e6263077621f7277e5c9a1065112914.tar.gz
Move package name strategy from class minifier to repackaging
Bug: 178567065 Change-Id: Ic33d4c7278ca20b0e4670f9e73ed3257170fd3ba
-rw-r--r--src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java2
-rw-r--r--src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java61
-rw-r--r--src/main/java/com/android/tools/r8/naming/Minifier.java41
-rw-r--r--src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java6
-rw-r--r--src/main/java/com/android/tools/r8/repackaging/Repackaging.java92
-rw-r--r--src/test/java/com/android/tools/r8/repackage/RepackageFeatureWithSyntheticsTest.java4
-rw-r--r--src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java2
7 files changed, 97 insertions, 111 deletions
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 5ade4de07..9da3a401a 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.jar;
-import static com.android.tools.r8.repackaging.Repackaging.DefaultRepackagingConfiguration.TEMPORARY_PACKAGE_NAME;
import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;
import com.android.tools.r8.ByteDataView;
@@ -186,7 +185,6 @@ public class CfApplicationWriter {
}
String desc = namingLens.lookupDescriptor(clazz.type).toString();
String name = namingLens.lookupInternalName(clazz.type);
- assert !name.contains(TEMPORARY_PACKAGE_NAME);
String signature = clazz.getClassSignature().toRenamedString(namingLens, isTypeMissing);
String superName =
clazz.type == options.itemFactory.objectType
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index 04bdf338a..e53f2855e 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -18,10 +18,8 @@ import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.ProguardPackageNameList;
import com.android.tools.r8.utils.DescriptorUtils;
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.ImmutableMap;
import com.google.common.collect.Maps;
@@ -37,9 +35,7 @@ class ClassNameMinifier {
private final AppView<AppInfoWithLiveness> appView;
private final ClassNamingStrategy classNamingStrategy;
- private final PackageNamingStrategy packageNamingStrategy;
private final Iterable<? extends DexClass> classes;
- private final Set<String> usedPackagePrefixes = Sets.newHashSet();
private final Set<String> usedTypeNames = Sets.newHashSet();
private final Map<DexType, DexString> renaming = Maps.newIdentityHashMap();
private final Map<String, Namespace> states = new HashMap<>();
@@ -48,27 +44,19 @@ class ClassNameMinifier {
private final Namespace topLevelState;
private final boolean allowMixedCaseNaming;
private final Predicate<String> isUsed;
- private final ProguardPackageNameList keepPackageNames;
ClassNameMinifier(
AppView<AppInfoWithLiveness> appView,
ClassNamingStrategy classNamingStrategy,
- PackageNamingStrategy packageNamingStrategy,
Iterable<? extends DexClass> classes) {
this.appView = appView;
this.classNamingStrategy = classNamingStrategy;
- this.packageNamingStrategy = packageNamingStrategy;
this.classes = classes;
InternalOptions options = appView.options();
this.keepInnerClassStructure = options.keepInnerClassStructure();
// Initialize top-level naming state.
topLevelState = new Namespace("");
- String newPackageDescriptor =
- StringUtils.replaceAll(options.getProguardConfiguration().getPackagePrefix(), ".", "/");
- if (!newPackageDescriptor.isEmpty()) {
- registerPackagePrefixesAsUsed(newPackageDescriptor);
- }
states.put("", topLevelState);
if (options.getProguardConfiguration().hasDontUseMixedCaseClassnames()) {
@@ -78,7 +66,6 @@ class ClassNameMinifier {
allowMixedCaseNaming = true;
isUsed = usedTypeNames::contains;
}
- keepPackageNames = options.getProguardConfiguration().getKeepPackageNamesPatterns();
}
private void setUsedTypeName(String typeName) {
@@ -176,8 +163,6 @@ class ClassNameMinifier {
private void registerClassAsUsed(DexType type, DexString descriptor) {
renaming.put(type, descriptor);
- registerPackagePrefixesAsUsed(
- getParentPackagePrefix(getClassBinaryNameFromDescriptor(descriptor.toSourceString())));
setUsedTypeName(descriptor.toString());
if (keepInnerClassStructure) {
DexType outerClass = getOutClassForType(type);
@@ -192,16 +177,6 @@ class ClassNameMinifier {
}
}
- /** Registers the given package prefix and all of parent packages as used. */
- private void registerPackagePrefixesAsUsed(String packagePrefix) {
- String usedPrefix = packagePrefix;
- while (usedPrefix.length() > 0) {
- usedPackagePrefixes.add(usedPrefix);
- states.computeIfAbsent(usedPrefix, Namespace::new);
- usedPrefix = getParentPackagePrefix(usedPrefix);
- }
- }
-
private DexType getOutClassForType(DexType type) {
DexClass clazz = appView.definitionFor(type);
if (clazz == null) {
@@ -249,29 +224,8 @@ class ClassNameMinifier {
private Namespace getStateForClass(DexType type) {
String packageName = getPackageBinaryNameFromJavaType(type.getPackageDescriptor());
- // Check whether the given class should be kept.
- // or check whether the given class belongs to a package that is kept for another class.
- if (keepPackageNames.matches(type)) {
- return states.computeIfAbsent(packageName, Namespace::new);
- }
- return getStateForPackagePrefix(packageName);
- }
-
- private Namespace getStateForPackagePrefix(String prefix) {
- Namespace state = states.get(prefix);
- if (state == null) {
- // Calculate the parent package prefix, e.g., La/b/c -> La/b
- String parentPackage = getParentPackagePrefix(prefix);
- // Create a state for parent package prefix, if necessary, in a recursive manner.
- // That recursion should end when the parent package hits the top-level, "".
- Namespace superState = getStateForPackagePrefix(parentPackage);
- // From the super state, get a renamed package prefix for the current level.
- String renamedPackagePrefix = superState.nextPackagePrefix();
- // Create a new state, which corresponds to a new name space, for the current level.
- state = new Namespace(renamedPackagePrefix);
- states.put(prefix, state);
- }
- return state;
+ // Packages are repackaged and obfuscated when doing repackaging.
+ return states.computeIfAbsent(packageName, Namespace::new);
}
private Namespace getStateForOuterClass(DexType outer, String innerClassSeparator) {
@@ -326,13 +280,6 @@ class ClassNameMinifier {
return candidate;
}
- String nextPackagePrefix() {
- String next = packageNamingStrategy.next(packagePrefix, this, usedPackagePrefixes::contains);
- assert !usedPackagePrefixes.contains(next);
- usedPackagePrefixes.add(next);
- return next;
- }
-
@Override
public int getDictionaryIndex() {
return dictionaryIndex;
@@ -367,10 +314,6 @@ class ClassNameMinifier {
boolean isRenamedByApplyMapping(DexType type);
}
- protected interface PackageNamingStrategy {
- String next(char[] packagePrefix, InternalNamingState state, Predicate<String> isUsed);
- }
-
/**
* Compute parent package prefix from the given package prefix.
*
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 049b28651..c5b8ced21 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -20,7 +20,6 @@ import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.naming.ClassNameMinifier.ClassNamingStrategy;
import com.android.tools.r8.naming.ClassNameMinifier.ClassRenaming;
-import com.android.tools.r8.naming.ClassNameMinifier.PackageNamingStrategy;
import com.android.tools.r8.naming.FieldNameMinifier.FieldRenaming;
import com.android.tools.r8.naming.MethodNameMinifier.MethodRenaming;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -55,7 +54,6 @@ public class Minifier {
new ClassNameMinifier(
appView,
new MinificationClassNamingStrategy(appView),
- new MinificationPackageNamingStrategy(appView),
// Use deterministic class order to make sure renaming is deterministic.
appView.appInfo().classesWithDeterministicOrder());
ClassRenaming classRenaming = classNameMinifier.computeRenaming(timing);
@@ -106,13 +104,14 @@ public class Minifier {
private final MixedCasing mixedCasing;
BaseMinificationNamingStrategy(List<String> obfuscationDictionary, boolean dontUseMixedCasing) {
+ assert obfuscationDictionary != null;
this.obfuscationDictionary = obfuscationDictionary;
- this.obfuscationDictionaryForLookup = new HashSet<>(this.obfuscationDictionary);
+ this.obfuscationDictionaryForLookup = new HashSet<>(obfuscationDictionary);
this.mixedCasing =
dontUseMixedCasing ? MixedCasing.DONT_USE_MIXED_CASE : MixedCasing.USE_MIXED_CASE;
- assert obfuscationDictionary != null;
}
+ /** TODO(b/182992598): using char[] could give problems with unicode */
String nextName(char[] packagePrefix, InternalNamingState state) {
StringBuilder nextName = new StringBuilder();
nextName.append(packagePrefix);
@@ -186,24 +185,44 @@ public class Minifier {
}
}
- static class MinificationPackageNamingStrategy extends BaseMinificationNamingStrategy
- implements PackageNamingStrategy {
+ public static class MinificationPackageNamingStrategy extends BaseMinificationNamingStrategy {
+
+ private final InternalNamingState namingState =
+ new InternalNamingState() {
+
+ private int dictionaryIndex = 0;
+ private int nameIndex = 1;
- MinificationPackageNamingStrategy(AppView<?> appView) {
+ @Override
+ public int getDictionaryIndex() {
+ return dictionaryIndex;
+ }
+
+ @Override
+ public int incrementDictionaryIndex() {
+ return dictionaryIndex++;
+ }
+
+ @Override
+ public int incrementNameIndex() {
+ return nameIndex++;
+ }
+ };
+
+ public MinificationPackageNamingStrategy(AppView<?> appView) {
super(
appView.options().getProguardConfiguration().getPackageObfuscationDictionary(),
appView.options().getProguardConfiguration().hasDontUseMixedCaseClassnames());
}
- @Override
- public String next(char[] packagePrefix, InternalNamingState state, Predicate<String> isUsed) {
+ public String next(String packagePrefix, Predicate<String> isUsed) {
// Note that the differences between this method and the other variant for class renaming are
// 1) this one uses the different dictionary and counter,
// 2) this one does not append ';' at the end, and
- // 3) this one removes 'L' at the beginning to make the return value a binary form.
+ // 3) this one assumes no 'L' at the beginning to make the return value a binary form.
String nextPackageName;
do {
- nextPackageName = nextName(packagePrefix, state).substring(1);
+ nextPackageName = nextName(packagePrefix.toCharArray(), namingState);
} while (isUsed.test(nextPackageName));
return nextPackageName;
}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index a8e299a98..3b2c0d526 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -29,7 +29,6 @@ import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.MethodNameMinifier.MethodRenaming;
import com.android.tools.r8.naming.Minifier.MinificationClassNamingStrategy;
-import com.android.tools.r8.naming.Minifier.MinificationPackageNamingStrategy;
import com.android.tools.r8.naming.Minifier.MinifierMemberNamingStrategy;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -137,11 +136,6 @@ public class ProguardMapMinifier {
appView,
new ApplyMappingClassNamingStrategy(
appView, mappedNames, seedMapper.getMappedToDescriptorNames()),
- // The package naming strategy will actually not be used since all classes and methods
- // will be output with identity name if not found in mapping. However, there is a check
- // in the ClassNameMinifier that the strategy should produce a "fresh" name so we just
- // use the existing strategy.
- new MinificationPackageNamingStrategy(appView),
classesWithDeterministicOrder(mappedClasses));
ClassRenaming classRenaming = classNameMinifier.computeRenaming(timing);
timing.end();
diff --git a/src/main/java/com/android/tools/r8/repackaging/Repackaging.java b/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
index 056abce8b..48227b454 100644
--- a/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
+++ b/src/main/java/com/android/tools/r8/repackaging/Repackaging.java
@@ -21,6 +21,7 @@ import com.android.tools.r8.graph.ProgramPackage;
import com.android.tools.r8.graph.ProgramPackageCollection;
import com.android.tools.r8.graph.SortedProgramPackageCollection;
import com.android.tools.r8.graph.TreeFixerBase;
+import com.android.tools.r8.naming.Minifier.MinificationPackageNamingStrategy;
import com.android.tools.r8.repackaging.RepackagingLens.Builder;
import com.android.tools.r8.shaking.AnnotationFixer;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -35,6 +36,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -202,19 +204,17 @@ public class Repackaging {
Iterator<ProgramPackage> iterator = packages.iterator();
while (iterator.hasNext()) {
ProgramPackage pkg = iterator.next();
- String newPackageDescriptor =
- repackagingConfiguration.getNewPackageDescriptor(pkg, seenPackageDescriptors);
- if (pkg.getPackageDescriptor().equals(newPackageDescriptor)) {
+ if (repackagingConfiguration.isPackageInTargetLocation(pkg)) {
for (DexProgramClass alreadyRepackagedClass : pkg) {
if (!appView.appInfo().isRepackagingAllowed(alreadyRepackagedClass)) {
mappings.put(alreadyRepackagedClass.getType(), alreadyRepackagedClass.getType());
}
}
for (DexProgramClass alreadyRepackagedClass : pkg) {
- processClass(alreadyRepackagedClass, pkg, newPackageDescriptor, mappings);
+ processClass(alreadyRepackagedClass, pkg, pkg.getPackageDescriptor(), mappings);
}
- packageMappings.put(pkg.getPackageDescriptor(), newPackageDescriptor);
- seenPackageDescriptors.add(newPackageDescriptor);
+ packageMappings.put(pkg.getPackageDescriptor(), pkg.getPackageDescriptor());
+ seenPackageDescriptors.add(pkg.getPackageDescriptor());
iterator.remove();
}
}
@@ -228,15 +228,28 @@ public class Repackaging {
ExecutorService executorService)
throws ExecutionException {
// For each package, find the set of classes that can be repackaged, and move them to the
- // desired package.
+ // desired package. We iterate all packages first to see if any classes are pinned and cannot
+ // be moved, to properly reserve their package.
+ Map<ProgramPackage, Collection<DexProgramClass>> packagesWithClassesToRepackage =
+ new IdentityHashMap<>();
+ for (ProgramPackage pkg : packages) {
+ Collection<DexProgramClass> classesToRepackage =
+ computeClassesToRepackage(pkg, executorService);
+ packagesWithClassesToRepackage.put(pkg, classesToRepackage);
+ // Reserve the package name to ensure that we are not renaming to a package we cannot move.
+ if (classesToRepackage.size() != pkg.classesInPackage().size()) {
+ seenPackageDescriptors.add(pkg.getPackageDescriptor());
+ }
+ }
for (ProgramPackage pkg : packages) {
+ Collection<DexProgramClass> classesToRepackage = packagesWithClassesToRepackage.get(pkg);
+ if (classesToRepackage.isEmpty()) {
+ continue;
+ }
// Already processed packages should have been removed.
String newPackageDescriptor =
repackagingConfiguration.getNewPackageDescriptor(pkg, seenPackageDescriptors);
- assert !pkg.getPackageDescriptor().equals(newPackageDescriptor);
-
- Collection<DexProgramClass> classesToRepackage =
- computeClassesToRepackage(pkg, executorService);
+ assert !repackagingConfiguration.isPackageInTargetLocation(pkg);
for (DexProgramClass classToRepackage : classesToRepackage) {
processClass(classToRepackage, pkg, newPackageDescriptor, mappings);
}
@@ -249,8 +262,6 @@ public class Repackaging {
classesToRepackage.size() == pkg.classesInPackage().size()
? newPackageDescriptor
: pkg.getPackageDescriptor());
- // TODO(b/165783399): Investigate if repackaging can lead to different dynamic dispatch. See,
- // for example, CrossPackageInvokeSuperToPackagePrivateMethodTest.
}
}
@@ -298,6 +309,8 @@ public class Repackaging {
String getNewPackageDescriptor(ProgramPackage pkg, Set<String> seenPackageDescriptors);
+ boolean isPackageInTargetLocation(ProgramPackage pkg);
+
DexType getRepackagedType(
DexProgramClass clazz,
DexProgramClass outerClass,
@@ -310,12 +323,13 @@ public class Repackaging {
private final AppView<?> appView;
private final DexItemFactory dexItemFactory;
private final ProguardConfiguration proguardConfiguration;
- public static final String TEMPORARY_PACKAGE_NAME = "TEMPORARY_PACKAGE_NAME_FOR_";
+ private final MinificationPackageNamingStrategy packageMinificationStrategy;
public DefaultRepackagingConfiguration(AppView<?> appView) {
this.appView = appView;
this.dexItemFactory = appView.dexItemFactory();
this.proguardConfiguration = appView.options().getProguardConfiguration();
+ this.packageMinificationStrategy = new MinificationPackageNamingStrategy(appView);
}
@Override
@@ -326,13 +340,7 @@ public class Repackaging {
proguardConfiguration.getPackageObfuscationMode();
if (packageObfuscationMode.isRepackageClasses()) {
return newPackageDescriptor;
- }
- assert packageObfuscationMode.isFlattenPackageHierarchy()
- || packageObfuscationMode.isMinification();
- if (!newPackageDescriptor.isEmpty()) {
- newPackageDescriptor += DESCRIPTOR_PACKAGE_SEPARATOR;
- }
- if (packageObfuscationMode.isMinification()) {
+ } else if (packageObfuscationMode.isMinification()) {
assert !proguardConfiguration.hasApplyMappingFile();
// Always keep top-level classes since there packages can never be minified.
if (pkg.getPackageDescriptor().equals("")
@@ -340,18 +348,37 @@ public class Repackaging {
|| mayHavePinnedPackagePrivateOrProtectedItem(pkg)) {
return pkg.getPackageDescriptor();
}
- // For us to rename shaking/A to a/a if we have a class shaking/Kept, we have to propose
- // a different name than the last package name - the class will be minified in
- // ClassNameMinifier.
- newPackageDescriptor += TEMPORARY_PACKAGE_NAME + pkg.getLastPackageName();
+ // Plain minification do not support using a specified package prefix.
+ newPackageDescriptor = "";
} else {
- newPackageDescriptor += pkg.getLastPackageName();
+ assert packageObfuscationMode.isFlattenPackageHierarchy();
+ if (!newPackageDescriptor.isEmpty()) {
+ newPackageDescriptor += DESCRIPTOR_PACKAGE_SEPARATOR;
+ }
}
- String finalPackageDescriptor = newPackageDescriptor;
- for (int i = 1; seenPackageDescriptors.contains(finalPackageDescriptor); i++) {
- finalPackageDescriptor = newPackageDescriptor + INNER_CLASS_SEPARATOR + i;
+ return packageMinificationStrategy.next(
+ newPackageDescriptor, seenPackageDescriptors::contains);
+ }
+
+ @Override
+ public boolean isPackageInTargetLocation(ProgramPackage pkg) {
+ String newPackageDescriptor =
+ DescriptorUtils.getBinaryNameFromJavaType(proguardConfiguration.getPackagePrefix());
+ PackageObfuscationMode packageObfuscationMode =
+ proguardConfiguration.getPackageObfuscationMode();
+ if (packageObfuscationMode.isRepackageClasses()) {
+ return pkg.getPackageDescriptor().equals(newPackageDescriptor);
+ } else if (packageObfuscationMode.isMinification()) {
+ // Always keep top-level classes since there packages can never be minified.
+ return pkg.getPackageDescriptor().equals("")
+ || proguardConfiguration.getKeepPackageNamesPatterns().matches(pkg)
+ || mayHavePinnedPackagePrivateOrProtectedItem(pkg);
+ } else {
+ assert packageObfuscationMode.isFlattenPackageHierarchy();
+ // For flatten we will move the package into the package specified by the prefix so we can
+ // always minify the last part.
+ return false;
}
- return finalPackageDescriptor;
}
private boolean mayHavePinnedPackagePrivateOrProtectedItem(ProgramPackage pkg) {
@@ -428,6 +455,11 @@ public class Repackaging {
}
@Override
+ public boolean isPackageInTargetLocation(ProgramPackage pkg) {
+ return true;
+ }
+
+ @Override
public DexType getRepackagedType(
DexProgramClass clazz,
DexProgramClass outerClass,
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageFeatureWithSyntheticsTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageFeatureWithSyntheticsTest.java
index bd90c1462..5e6205733 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageFeatureWithSyntheticsTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageFeatureWithSyntheticsTest.java
@@ -106,14 +106,14 @@ public class RepackageFeatureWithSyntheticsTest extends RepackageTestBase {
// If it is, the access will fail resulting in a runtime exception.
compileResult.inspect(
baseInspector -> {
- assertThat(FIRST_FOO, isRepackagedAsExpected(baseInspector, "b"));
+ assertThat(FIRST_FOO, isRepackagedAsExpected(baseInspector, "a"));
assertThat(FIRST_PKG_PRIVATE, isNotRepackaged(baseInspector));
assertEquals(
getTestClasses().size() + expectedSyntheticsInBase,
baseInspector.allClasses().size());
},
featureInspector -> {
- assertThat(FIRST_FIRST_FOO, isRepackagedAsExpected(featureInspector, "a"));
+ assertThat(FIRST_FIRST_FOO, isRepackagedAsExpected(featureInspector, "b"));
assertThat(FIRST_FIRST_PKG_PRIVATE, isNotRepackaged(featureInspector));
assertEquals(
getFeatureClasses().size() + expectedSyntheticsInFeature,
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java
index 4df662250..1a3bfca28 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java
@@ -67,7 +67,7 @@ public class RepackageWithSyntheticItemTest extends RepackageTestBase {
// TODO(b/172014416): We should not be able to look this up through the repackage name
String expectedOriginalNamePrefix =
isFlattenPackageHierarchy()
- ? "foo.repackage.RepackageWithSyntheticItemTest$A"
+ ? "foo.a.RepackageWithSyntheticItemTest$A"
: "foo.RepackageWithSyntheticItemTest$A";
assertThat(
classesStartingWithfoo.get(0).getOriginalName(),