Revert "Add wrapper classes for more structured querying of resource tables" This reverts commit 5c66d967cb51141d0c0764d540d99d85405a6b29. Reason for revert: Test failures Change-Id: Ie73e2bfae768ffe2b651adf330d5feb08aff1e29
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/PackageModel.java b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/PackageModel.java deleted file mode 100644 index 4ab09d3..0000000 --- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/PackageModel.java +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2026, 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.build.shrinker.r8integration; - -import com.android.aapt.Resources.Package; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.stream.Collectors; - -public class PackageModel { - - private final Package aPackage; - private final List<TypeModel> types; - - public PackageModel(Package aPackage) { - this.aPackage = aPackage; - types = - aPackage.getTypeList().stream() - .map(type -> new TypeModel(this, type)) - .collect(Collectors.toList()); - } - - public void forEachProtoXmlFileReference(BiConsumer<Integer, String> onResourceIdToFilePath) { - types.forEach(type -> type.forEachProtoXmlFileReference(onResourceIdToFilePath)); - } - - public Package getPackage() { - return aPackage; - } - - public String getName() { - return aPackage.getPackageName(); - } -}
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 a8e1a3a..caf9406 100644 --- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java +++ b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/R8ResourceShrinkerState.java
@@ -5,9 +5,12 @@ import static com.android.build.shrinker.r8integration.LegacyResourceShrinker.getUtfReader; +import com.android.aapt.Resources; import com.android.aapt.Resources.ConfigValue; import com.android.aapt.Resources.Entry; +import com.android.aapt.Resources.FileReference; import com.android.aapt.Resources.Item; +import com.android.aapt.Resources.Package; import com.android.aapt.Resources.Primitive; import com.android.aapt.Resources.ResourceTable; import com.android.aapt.Resources.Value; @@ -61,7 +64,7 @@ private final List<Supplier<InputStream>> manifestProviders = new ArrayList<>(); private final Map<String, Supplier<InputStream>> resfileProviders = new HashMap<>(); - private final Map<ResourceTableModel, FeatureSplit> resourceTables = new HashMap<>(); + private final Map<FeatureSplit, ResourceTable> resourceTables = new HashMap<>(); private final ShrinkerDebugReporter shrinkerDebugReporter; private final boolean enableXmlInlining; private ClassReferenceCallback enqueuerCallback; @@ -168,8 +171,10 @@ // feature. if (packageNames == null) { packageNames = new HashSet<>(); - for (ResourceTableModel resourceTableModel : resourceTables.keySet()) { - resourceTableModel.forEachPackage(packageModel -> packageNames.add(packageModel.getName())); + for (ResourceTable resourceTable : resourceTables.values()) { + for (Package aPackage : resourceTable.getPackageList()) { + packageNames.add(aPackage.getPackageName()); + } } } return packageNames; @@ -200,7 +205,7 @@ public void addResourceTable(InputStream inputStream, FeatureSplit featureSplit) { this.resourceTables.put( - r8ResourceShrinkerModel.instantiateFromResourceTable(inputStream, true), featureSplit); + featureSplit, r8ResourceShrinkerModel.instantiateFromResourceTable(inputStream, true)); } public R8ResourceShrinkerModel getR8ResourceShrinkerModel() { @@ -242,9 +247,8 @@ } public void setupReferences() { - for (ResourceTableModel resourceTableModel : resourceTables.keySet()) { - new ProtoResourcesGraphBuilder( - this::getXmlOrResFileBytes, unused -> resourceTableModel.getResourceTable()) + for (ResourceTable resourceTable : resourceTables.values()) { + new ProtoResourcesGraphBuilder(this::getXmlOrResFileBytes, unused -> resourceTable) .buildGraph(r8ResourceShrinkerModel); } } @@ -261,12 +265,11 @@ Map<FeatureSplit, ResourceTable> shrunkenTables = new IdentityHashMap<>(); resourceTables.forEach( - (resourceTableModel, featureSplit) -> - shrunkenTables.put( - featureSplit, - ResourceTableUtilKt.nullOutEntriesWithIds( - resourceTableModel.getResourceTable(), resourceIdsToRemove, true))); - + (featureSplit, resourceTable) -> { + shrunkenTables.put( + featureSplit, + ResourceTableUtilKt.nullOutEntriesWithIds(resourceTable, resourceIdsToRemove, true)); + }); for (Map.Entry<Resource, String> resourceStringEntry : reachabilityMap.entrySet()) { shrinkerDebugReporter.debug( () -> @@ -277,7 +280,6 @@ for (Resource resource : resourcesToRemove) { shrinkerDebugReporter.debug(() -> resource.toString() + " is not reachable."); } - return new ShrinkerResult(resEntriesToKeep, shrunkenTables, changedXmlFiles); } @@ -455,10 +457,30 @@ public Map<Integer, Set<String>> getResourceIdToXmlFiles() { if (resourceIdToXmlFiles == null) { resourceIdToXmlFiles = new HashMap<>(); - for (ResourceTableModel resourceTableModel : resourceTables.keySet()) { - resourceTableModel.forEachProtoXmlFileReference( - (id, path) -> - resourceIdToXmlFiles.computeIfAbsent(id, unused -> new HashSet<>()).add(path)); + for (ResourceTable resourceTable : resourceTables.values()) { + for (Package packageEntry : resourceTable.getPackageList()) { + for (Resources.Type type : packageEntry.getTypeList()) { + for (Entry entry : type.getEntryList()) { + for (ConfigValue configValue : entry.getConfigValueList()) { + if (configValue.hasValue()) { + Value value = configValue.getValue(); + if (value.hasItem()) { + Item item = value.getItem(); + if (item.hasFile()) { + FileReference file = item.getFile(); + if (file.getType() == FileReference.Type.PROTO_XML) { + int id = ResourceTableUtilKt.toIdentifier(packageEntry, type, entry); + resourceIdToXmlFiles + .computeIfAbsent(id, unused -> new HashSet<>()) + .add(file.getPath()); + } + } + } + } + } + } + } + } } } return resourceIdToXmlFiles; @@ -591,12 +613,11 @@ } // Similar to instantiation in ProtoResourceTableGatherer, but using an inputstream. - ResourceTableModel instantiateFromResourceTable( - InputStream inputStream, boolean includeStyleables) { + ResourceTable instantiateFromResourceTable(InputStream inputStream, boolean includeStyleables) { try { ResourceTable resourceTable = ResourceTable.parseFrom(inputStream); instantiateFromResourceTable(resourceTable, includeStyleables); - return new ResourceTableModel(resourceTable); + return resourceTable; } catch (IOException ex) { throw new RuntimeException(ex); }
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/ResourceTableModel.java b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/ResourceTableModel.java deleted file mode 100644 index 80e74cb..0000000 --- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/ResourceTableModel.java +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright (c) 2026, 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.build.shrinker.r8integration; - -import com.android.aapt.Resources.ResourceTable; -import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -/** - * A view on top of a aapt proto resource table to allow for more structured iteration and updates. - * The underlying resource table has a setup where we have: - * - * <pre> - * ResourceTable - * -> Package - * -> Type - * -> Entry - * -> Config - * -> Value - * ->... - * -> ... - * -> ... - * -> ... - * </pre> - * - * So every ResourceTable can have multiple packages, which each can have many types (string, - * layout, ...), which can each have many entries. Every entry corresponds exactly to one resource - * id (e.g., 0x7f020003), but can have many values, one for each configuration that it is specified - * for. If a string resource has 14 translations, then the entry for that string will have 14 - * configs with a string value each. - * - * <p>By design, we do not model the underlying entries with explicit model objects to avoid the - * memory overhead and object creation cost. - */ -public class ResourceTableModel { - - private final ResourceTable resourceTable; - private final List<PackageModel> packages; - - public ResourceTableModel(ResourceTable resourceTable) { - this.resourceTable = resourceTable; - packages = - resourceTable.getPackageList().stream() - .map(aPackage -> new PackageModel(aPackage)) - .collect(Collectors.toList()); - } - - public void forEachProtoXmlFileReference(BiConsumer<Integer, String> onResourceIdToFilePath) { - packages.forEach( - packageModel -> packageModel.forEachProtoXmlFileReference(onResourceIdToFilePath)); - } - - public void forEachPackage(Consumer<PackageModel> consumer) { - packages.forEach(consumer); - } - - public ResourceTable getResourceTable() { - return resourceTable; - } -}
diff --git a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/TypeModel.java b/src/resourceshrinker/java/com/android/build/shrinker/r8integration/TypeModel.java deleted file mode 100644 index 1453243..0000000 --- a/src/resourceshrinker/java/com/android/build/shrinker/r8integration/TypeModel.java +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright (c) 2026, 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.build.shrinker.r8integration; - -import com.android.aapt.Resources; -import com.android.aapt.Resources.ConfigValue; -import com.android.aapt.Resources.Entry; -import com.android.aapt.Resources.FileReference; -import com.android.aapt.Resources.Item; -import com.android.aapt.Resources.Value; -import com.android.build.shrinker.ResourceTableUtilKt; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Predicate; - -public class TypeModel { - - private final PackageModel parent; - private final Resources.Type type; - - public TypeModel(PackageModel parent, Resources.Type type) { - this.parent = parent; - this.type = type; - } - - public void forEachProtoXmlFileReference(BiConsumer<Integer, String> onResourceIdToFilePath) { - forEachValue( - (id, value) -> { - // We don't have file references from compound resources, so only handle simple items. - onItemWithPredicate( - value, - Item::hasFile, - item -> { - FileReference file = item.getFile(); - if (file.getType() == FileReference.Type.PROTO_XML) { - onResourceIdToFilePath.accept(id, file.getPath()); - } - }); - }); - } - - private static void onItemWithPredicate( - Value value, Predicate<Item> predicate, Consumer<Item> itemConsumer) { - if (value.hasItem() && predicate.test(value.getItem())) { - itemConsumer.accept(value.getItem()); - } - } - - public void forEachValue(BiConsumer<Integer, Value> valueConsumer) { - for (Entry entry : type.getEntryList()) { - for (ConfigValue configValue : entry.getConfigValueList()) { - if (configValue.hasValue()) { - valueConsumer.accept(getId(entry), configValue.getValue()); - } - } - } - } - - private int getId(Entry entry) { - return ResourceTableUtilKt.toIdentifier(parent.getPackage(), type, entry); - } -}