diff options
author | Melisa CZ <melisacz@google.com> | 2024-05-13 14:46:22 +0000 |
---|---|---|
committer | Melisa CZ <melisacz@google.com> | 2024-05-13 15:52:34 +0000 |
commit | acc63236ae9d85530467d2175cae4d3ca0f0b9b5 (patch) | |
tree | 53f5b9e88d4f310c86870bd56ff055ef9289e847 | |
parent | 7abe78fe73fb94c384f149016ae329586e39c28d (diff) | |
parent | 878d37fe960945e1b2eec430f1649d43910a4fd0 (diff) | |
download | google-smali-master.tar.gz |
This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update external/google-smali
For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
Test: TreeHugger
Change-Id: I9150aa0e64f80c0f248e5c56e796058f45bf2298
119 files changed, 3004 insertions, 900 deletions
@@ -8,12 +8,12 @@ third_party { license_type: NOTICE last_upgrade_date { year: 2024 - month: 2 - day: 7 + month: 5 + day: 13 } identifier { type: "Git" value: "https://github.com/google/smali" - version: "3.0.4" + version: "3.0.7" } } diff --git a/baksmali/Android.bp b/baksmali/Android.bp index 6fc3f7ea..347be56b 100644 --- a/baksmali/Android.bp +++ b/baksmali/Android.bp @@ -14,10 +14,10 @@ * limitations under the License. */ - // Create a new baksmali.properties file using the correct version +// Create a new baksmali.properties file using the correct version genrule { name: "android-baksmali_version", - defaults : ["android-smali_version_defaults"], + defaults: ["android-smali_version_defaults"], out: ["android-baksmali.properties"], } @@ -35,6 +35,7 @@ java_binary_host { manifest: "manifest.txt", static_libs: [ + "guava", "smali-dexlib2", "android-smali-util", "jcommander", @@ -43,4 +44,4 @@ java_binary_host { java_resources: [":android-baksmali_version"], wrapper: ":android-baksmali_script", -}
\ No newline at end of file +} diff --git a/baksmali/src/test/java/com/android/tools/smali/baksmali/InstructionMethodItemTest.java b/baksmali/src/test/java/com/android/tools/smali/baksmali/InstructionMethodItemTest.java index 492b3c7c..10ffccf6 100644 --- a/baksmali/src/test/java/com/android/tools/smali/baksmali/InstructionMethodItemTest.java +++ b/baksmali/src/test/java/com/android/tools/smali/baksmali/InstructionMethodItemTest.java @@ -151,7 +151,8 @@ public class InstructionMethodItemTest { BaksmaliWriter writer = new BaksmaliWriter(stringWriter); methodItem.writeTo(writer); - Assert.assertEquals("#Invalid reference\n#const-string v0, blahblahblah\nnop", stringWriter.toString()); + Assert.assertEquals("#Invalid reference" + System.lineSeparator() + + "#const-string v0, blahblahblah" + System.lineSeparator() + "nop", stringWriter.toString()); } private static class TestMethod extends BaseMethodReference implements Method { diff --git a/baksmali/src/test/java/com/android/tools/smali/baksmali/formatter/BaksmaliWriterTest.java b/baksmali/src/test/java/com/android/tools/smali/baksmali/formatter/BaksmaliWriterTest.java index be621620..963c8e80 100644 --- a/baksmali/src/test/java/com/android/tools/smali/baksmali/formatter/BaksmaliWriterTest.java +++ b/baksmali/src/test/java/com/android/tools/smali/baksmali/formatter/BaksmaliWriterTest.java @@ -179,10 +179,10 @@ public class BaksmaliWriterTest { ))); Assert.assertEquals( - ".subannotation Lannotation/`type with spaces`;\n" + - " `element with spaces 1` = Ldefining/class/`with spaces`;->`fieldName with spaces`:Lfield/`type with spaces`;\n" + + ".subannotation Lannotation/`type with spaces`;" + System.lineSeparator() + + " `element with spaces 1` = Ldefining/class/`with spaces`;->`fieldName with spaces`:Lfield/`type with spaces`;" + System.lineSeparator() + " `element with spaces 2` = Ldefining/class/`with spaces`;->`methodName with spaces`(" + - "L`param with spaces 1`;L`param with spaces 2`;)Lreturn/type/`with spaces`;\n" + + "L`param with spaces 1`;L`param with spaces 2`;)Lreturn/type/`with spaces`;" + System.lineSeparator() + ".end subannotation", output.toString()); } @@ -196,9 +196,9 @@ public class BaksmaliWriterTest { new ImmutableMethodEncodedValue(getMethodReferenceWithSpaces())))); Assert.assertEquals( - "{\n" + - " Ldefining/class/`with spaces`;->`fieldName with spaces`:Lfield/`type with spaces`;,\n" + - " Ldefining/class/`with spaces`;->`methodName with spaces`(L`param with spaces 1`;L`param with spaces 2`;)Lreturn/type/`with spaces`;\n" + + "{" + System.lineSeparator() + + " Ldefining/class/`with spaces`;->`fieldName with spaces`:Lfield/`type with spaces`;," + System.lineSeparator() + + " Ldefining/class/`with spaces`;->`methodName with spaces`(L`param with spaces 1`;L`param with spaces 2`;)Lreturn/type/`with spaces`;" + System.lineSeparator() + "}", output.toString()); } diff --git a/build.gradle b/build.gradle index ecc1f848..148abf70 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ apply plugin: 'idea' -version = '3.0.4' +version = '3.0.7' def jcommanderVersion = '' if (!('release' in gradle.startParameter.taskNames)) { diff --git a/dexlib2/Android.bp b/dexlib2/Android.bp index 1e9d6e42..0c69645b 100644 --- a/dexlib2/Android.bp +++ b/dexlib2/Android.bp @@ -14,7 +14,7 @@ * limitations under the License. */ - java_library_host { +java_library_host { name: "smali-dexlib2", srcs: [ @@ -23,9 +23,7 @@ ], static_libs: [ - "guava", "jsr305", - "auto_android_annotation_stubs", ], errorprone: { @@ -43,13 +41,8 @@ java_library_host { ":third_party-smali-dexlib2", ], - libs: [ - "guava", - ], - static_libs: [ "jsr305", - "auto_android_annotation_stubs", ], errorprone: { @@ -59,7 +52,6 @@ java_library_host { }, } - java_library { name: "smali-dexlib2-device", @@ -68,19 +60,12 @@ java_library { ":third_party-smali-dexlib2", ], - libs: [ - "guava", - ], - static_libs: [ "jsr305", ], sdk_version: "system_server_current", min_sdk_version: "33", - apex_available: [ - "com.android.adservices" - ], optimize: { enabled: true, @@ -92,4 +77,8 @@ java_library { "-Xep:ComparableType:WARN", ], }, -}
\ No newline at end of file + + apex_available: [ + "//apex_available:anyapex", + ], +} diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/DexFileFactory.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/DexFileFactory.java index c464c474..eb5675a1 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/DexFileFactory.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/DexFileFactory.java @@ -55,6 +55,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.Collections; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -460,7 +461,7 @@ public final class DexFileFactory { } @Nonnull @Override public List<String> getDexEntryNames() { - return unmodifiableList(List.of(entryName)); + return Collections.singletonList(entryName); } @Nullable @Override public DexEntry<DexBackedDexFile> getEntry(@Nonnull String entryName) { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/MethodHandleType.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/MethodHandleType.java index 6ba1726b..c0003dec 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/MethodHandleType.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/MethodHandleType.java @@ -50,16 +50,21 @@ public class MethodHandleType { public static final int INVOKE_DIRECT = 7; public static final int INVOKE_INTERFACE = 8; - private static final Map<Integer, String> methodHandleTypeNames = unmodifiableMap(Map.of( - STATIC_PUT, "static-put", - STATIC_GET, "static-get", - INSTANCE_PUT, "instance-put", - INSTANCE_GET, "instance-get", - INVOKE_STATIC, "invoke-static", - INVOKE_INSTANCE, "invoke-instance", - INVOKE_CONSTRUCTOR, "invoke-constructor", - INVOKE_DIRECT, "invoke-direct", - INVOKE_INTERFACE, "invoke-interface")); + private static final Map<Integer, String> methodHandleTypeNames; + + static { + Map<Integer, String> temp = new HashMap<>(); + temp.put(STATIC_PUT, "static-put"); + temp.put(STATIC_GET, "static-get"); + temp.put(INSTANCE_PUT, "instance-put"); + temp.put(INSTANCE_GET, "instance-get"); + temp.put(INVOKE_STATIC, "invoke-static"); + temp.put(INVOKE_INSTANCE, "invoke-instance"); + temp.put(INVOKE_CONSTRUCTOR, "invoke-constructor"); + temp.put(INVOKE_DIRECT, "invoke-direct"); + temp.put(INVOKE_INTERFACE, "invoke-interface"); + methodHandleTypeNames = unmodifiableMap(temp); + } private static final Map<String, Integer> inverse = getInverse(); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/Opcode.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/Opcode.java index d0ca08d7..bd8dc5f2 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/Opcode.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/Opcode.java @@ -30,12 +30,12 @@ package com.android.tools.smali.dexlib2; -import com.google.common.collect.ImmutableRangeMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Range; -import com.google.common.collect.RangeMap; +import com.android.tools.smali.util.UnmodifiableRangeMap; +import com.android.tools.smali.util.Range; import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public enum Opcode @@ -348,8 +348,8 @@ public enum Opcode // values and minApis provide a mapping of api -> bytecode value. // the apis in minApis are guaranteed to be - public final RangeMap<Integer, Short> apiToValueMap; - public final RangeMap<Integer, Short> artVersionToValueMap; + public final UnmodifiableRangeMap<Integer, Short> apiToValueMap; + public final UnmodifiableRangeMap<Integer, Short> artVersionToValueMap; public final String name; public final int referenceType; @@ -371,8 +371,8 @@ public enum Opcode Opcode(List<VersionConstraint> versionConstraints, String opcodeName, int referenceType, int referenceType2, Format format, int flags) { - ImmutableRangeMap.Builder<Integer, Short> apiToValueBuilder = ImmutableRangeMap.builder(); - ImmutableRangeMap.Builder<Integer, Short> artVersionToValueBuilder = ImmutableRangeMap.builder(); + UnmodifiableRangeMap.Builder<Integer, Short> apiToValueBuilder = UnmodifiableRangeMap.builder(); + UnmodifiableRangeMap.Builder<Integer, Short> artVersionToValueBuilder = UnmodifiableRangeMap.builder(); for (VersionConstraint versionConstraint : versionConstraints) { if (!versionConstraint.apiRange.isEmpty()) { @@ -393,41 +393,41 @@ public enum Opcode } private static List<VersionConstraint> firstApi(int opcodeValue, int api) { - return Lists.newArrayList(new VersionConstraint(Range.atLeast(api), Range.openClosed(0, 0), opcodeValue)); + return Arrays.asList(new VersionConstraint(Range.atLeast(api), Range.openClosed(0, 0), opcodeValue)); } private static List<VersionConstraint> lastApi(int opcodeValue, int api) { - return Lists.newArrayList(new VersionConstraint(Range.atMost(api), Range.openClosed(0, 0), opcodeValue)); + return Arrays.asList(new VersionConstraint(Range.atMost(api), Range.openClosed(0, 0), opcodeValue)); } private static List<VersionConstraint> betweenApi(int opcodeValue, int minApi, int maxApi) { - return Lists.newArrayList(new VersionConstraint(Range.closed(minApi, maxApi), Range.openClosed(0, 0), + return Arrays.asList(new VersionConstraint(Range.closed(minApi, maxApi), Range.openClosed(0, 0), opcodeValue)); } private static List<VersionConstraint> firstArtVersion(int opcodeValue, int artVersion) { - return Lists.newArrayList(new VersionConstraint(Range.openClosed(0, 0), Range.atLeast(artVersion), opcodeValue)); + return Arrays.asList(new VersionConstraint(Range.openClosed(0, 0), Range.atLeast(artVersion), opcodeValue)); } private static List<VersionConstraint> lastArtVersion(int opcodeValue, int artVersion) { - return Lists.newArrayList(new VersionConstraint(Range.openClosed(0, 0), Range.atMost(artVersion), opcodeValue)); + return Arrays.asList(new VersionConstraint(Range.openClosed(0, 0), Range.atMost(artVersion), opcodeValue)); } private static List<VersionConstraint> allVersions(int opcodeValue) { - return Lists.newArrayList(new VersionConstraint(Range.<Integer>all(), Range.<Integer>all(), opcodeValue)); + return Arrays.asList(new VersionConstraint(Range.allValues(), Range.allValues(), opcodeValue)); } private static List<VersionConstraint> allApis(int opcodeValue) { - return Lists.newArrayList(new VersionConstraint(Range.<Integer>all(), Range.openClosed(0, 0), opcodeValue)); + return Arrays.asList(new VersionConstraint(Range.allValues(), Range.openClosed(0, 0), opcodeValue)); } private static List<VersionConstraint> allArtVersions(int opcodeValue) { - return Lists.newArrayList(new VersionConstraint(Range.openClosed(0, 0), Range.<Integer>all(), opcodeValue)); + return Arrays.asList(new VersionConstraint(Range.openClosed(0, 0), Range.allValues(), opcodeValue)); } @SuppressWarnings("unchecked") private static List<VersionConstraint> combine(List<VersionConstraint>... versionConstraints) { - List<VersionConstraint> combinedList = Lists.newArrayList(); + List<VersionConstraint> combinedList = new ArrayList<>(); for (List<VersionConstraint> versionConstraintList: versionConstraints) { combinedList.addAll(versionConstraintList); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/Opcodes.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/Opcodes.java index 176c5175..4c5b597e 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/Opcodes.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/Opcodes.java @@ -30,16 +30,16 @@ package com.android.tools.smali.dexlib2; -import com.google.common.collect.RangeMap; +import static com.android.tools.smali.dexlib2.VersionMap.NO_VERSION; +import static com.android.tools.smali.dexlib2.VersionMap.mapApiToArtVersion; +import static com.android.tools.smali.dexlib2.VersionMap.mapArtVersionToApi; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.EnumMap; import java.util.HashMap; -import static com.android.tools.smali.dexlib2.VersionMap.NO_VERSION; -import static com.android.tools.smali.dexlib2.VersionMap.mapApiToArtVersion; -import static com.android.tools.smali.dexlib2.VersionMap.mapArtVersionToApi; +import com.android.tools.smali.util.UnmodifiableRangeMap; public class Opcodes { @@ -103,7 +103,7 @@ public class Opcodes { } for (Opcode opcode: Opcode.values()) { - RangeMap<Integer, Short> versionToValueMap; + UnmodifiableRangeMap<Integer, Short> versionToValueMap; if (isArt()) { versionToValueMap = opcode.artVersionToValueMap; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/AnalyzedInstruction.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/AnalyzedInstruction.java index b67fee76..adc18485 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/AnalyzedInstruction.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/AnalyzedInstruction.java @@ -42,15 +42,15 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference; import com.android.tools.smali.dexlib2.iface.reference.Reference; import com.android.tools.smali.dexlib2.iface.reference.TypeReference; import com.android.tools.smali.util.ExceptionWithContext; -import com.google.common.base.Objects; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import java.util.ArrayList; import java.util.BitSet; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; import javax.annotation.Nonnull; @@ -301,7 +301,7 @@ public class AnalyzedInstruction implements Comparable<AnalyzedInstruction> { protected boolean overridePredecessorRegisterType(@Nonnull AnalyzedInstruction predecessor, int registerNumber, @Nonnull RegisterType registerType, BitSet verifiedInstructions) { if (predecessorRegisterOverrides == null) { - predecessorRegisterOverrides = Maps.newHashMap(); + predecessorRegisterOverrides = new HashMap<>(); } predecessorRegisterOverrides.put(new PredecessorOverrideKey(predecessor, registerNumber), registerType); @@ -482,7 +482,7 @@ public class AnalyzedInstruction implements Comparable<AnalyzedInstruction> { } public List<Integer> getSetRegisters() { - List<Integer> setRegisters = Lists.newArrayList(); + List<Integer> setRegisters = new ArrayList<>(); if (instruction.getOpcode().setsRegister()) { setRegisters.add(getDestinationRegister()); @@ -667,12 +667,12 @@ public class AnalyzedInstruction implements Comparable<AnalyzedInstruction> { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PredecessorOverrideKey that = (PredecessorOverrideKey)o; - return com.google.common.base.Objects.equal(registerNumber, that.registerNumber) && - Objects.equal(analyzedInstruction, that.analyzedInstruction); + return Objects.equals(registerNumber, that.registerNumber) && + Objects.equals(analyzedInstruction, that.analyzedInstruction); } @Override public int hashCode() { - return Objects.hashCode(analyzedInstruction, registerNumber); + return Objects.hash(analyzedInstruction, registerNumber); } } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ArrayProto.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ArrayProto.java index 740dbc8c..699b4237 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ArrayProto.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ArrayProto.java @@ -36,7 +36,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference; import com.android.tools.smali.dexlib2.immutable.reference.ImmutableFieldReference; import com.android.tools.smali.dexlib2.util.TypeUtils; import com.android.tools.smali.util.ExceptionWithContext; -import com.google.common.base.Strings; +import com.android.tools.smali.util.StringUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -141,7 +141,7 @@ public class ArrayProto implements TypeProto { return other.getCommonSuperclass(this); } - private static final String BRACKETS = Strings.repeat("[", 256); + private static final String BRACKETS = StringUtils.repeat("[", 256); @Nonnull private static String makeArrayType(@Nonnull String elementType, int dimensions) { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassPath.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassPath.java index 1b6f0a00..e2aadc64 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassPath.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassPath.java @@ -32,21 +32,20 @@ package com.android.tools.smali.dexlib2.analysis; import com.android.tools.smali.dexlib2.Opcodes; import com.android.tools.smali.dexlib2.analysis.reflection.ReflectionClassDef; +import com.android.tools.smali.dexlib2.analysis.util.LruCache; +import com.android.tools.smali.dexlib2.analysis.util.MemoizingSupplier; import com.android.tools.smali.dexlib2.iface.ClassDef; import com.android.tools.smali.dexlib2.immutable.ImmutableDexFile; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; +import com.android.tools.smali.util.IteratorUtils; import javax.annotation.Nonnull; import java.io.IOException; import java.io.Serializable; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.function.Supplier; public class ClassPath { @Nonnull private final TypeProto unknownClass; @@ -104,7 +103,7 @@ public class ClassPath { loadPrimitiveType("D"); loadPrimitiveType("L"); - this.classProviders = Lists.newArrayList(classProviders); + this.classProviders = (List<ClassProvider>)IteratorUtils.toList(classProviders); this.classProviders.add(getBasicClasses()); } @@ -114,13 +113,14 @@ public class ClassPath { private static ClassProvider getBasicClasses() { // fallbacks for some special classes that we assume are present - return new DexClassProvider(new ImmutableDexFile(Opcodes.getDefault(), ImmutableSet.of( + return new DexClassProvider(new ImmutableDexFile(Opcodes.getDefault(), + Collections.unmodifiableSet(new HashSet<>(Arrays.asList( new ReflectionClassDef(Class.class), new ReflectionClassDef(Cloneable.class), new ReflectionClassDef(Object.class), new ReflectionClassDef(Serializable.class), new ReflectionClassDef(String.class), - new ReflectionClassDef(Throwable.class)))); + new ReflectionClassDef(Throwable.class)))))); } public boolean isArt() { @@ -129,21 +129,19 @@ public class ClassPath { @Nonnull public TypeProto getClass(@Nonnull CharSequence type) { - return loadedClasses.getUnchecked(type.toString()); + return loadedClasses.get(type.toString()); } - private final CacheLoader<String, TypeProto> classLoader = new CacheLoader<String, TypeProto>() { - @Override public TypeProto load(String type) throws Exception { - if (type.charAt(0) == '[') { - return new ArrayProto(ClassPath.this, type); + @Nonnull private LruCache<String, TypeProto> loadedClasses = new LruCache<String, TypeProto>(30000) { + @Override protected TypeProto create(String key) { + if (key.charAt(0) == '[') { + return new ArrayProto(ClassPath.this, key); } else { - return new ClassProto(ClassPath.this, type); + return new ClassProto(ClassPath.this, key); } } }; - @Nonnull private LoadingCache<String, TypeProto> loadedClasses = CacheBuilder.newBuilder().build(classLoader); - @Nonnull public ClassDef getClassDef(String type) { for (ClassProvider provider: classProviders) { @@ -164,7 +162,7 @@ public class ClassPath { return checkPackagePrivateAccess; } - private final Supplier<OdexedFieldInstructionMapper> fieldInstructionMapperSupplier = Suppliers.memoize( + private final Supplier<OdexedFieldInstructionMapper> fieldInstructionMapperSupplier = MemoizingSupplier.memoize( new Supplier<OdexedFieldInstructionMapper>() { @Override public OdexedFieldInstructionMapper get() { return new OdexedFieldInstructionMapper(isArt()); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassPathResolver.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassPathResolver.java index e5d92dad..6057b144 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassPathResolver.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassPathResolver.java @@ -36,14 +36,13 @@ import com.android.tools.smali.dexlib2.dexbacked.OatFile; import com.android.tools.smali.dexlib2.iface.DexFile; import com.android.tools.smali.dexlib2.iface.MultiDexContainer; import com.android.tools.smali.dexlib2.iface.MultiDexContainer.DexEntry; -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; +import com.android.tools.smali.util.StringUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.List; public class ClassPathResolver { @@ -182,7 +181,6 @@ public class ClassPathResolver { // It's not a local path, so let's try to resolve it as a device path, relative to one of the provided // directories List<String> pathComponents = splitDevicePath(entry); - Joiner pathJoiner = Joiner.on(File.separatorChar); for (String directory: classPathDirs) { File directoryFile = new File(directory); @@ -191,7 +189,8 @@ public class ClassPathResolver { } for (int i=0; i<pathComponents.size(); i++) { - String partialPath = pathJoiner.join(pathComponents.subList(i, pathComponents.size())); + String partialPath = StringUtils.join( + pathComponents.subList(i, pathComponents.size()), File.separator); File entryFile = new File(directoryFile, partialPath); if (entryFile.exists() && entryFile.isFile()) { pathEntryLoader.loadEntry(entryFile, true); @@ -205,7 +204,7 @@ public class ClassPathResolver { @Nonnull private static List<String> splitDevicePath(@Nonnull String path) { - return Lists.newArrayList(Splitter.on('/').split(path)); + return Arrays.asList(path.split("/")); } static class NotFoundException extends Exception { @@ -250,14 +249,14 @@ public class ClassPathResolver { } if (apiLevel <= 8) { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core.jar", "/system/framework/ext.jar", "/system/framework/framework.jar", "/system/framework/android.policy.jar", "/system/framework/services.jar"); } else if (apiLevel <= 11) { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core.jar", "/system/framework/bouncycastle.jar", "/system/framework/ext.jar", @@ -266,7 +265,7 @@ public class ClassPathResolver { "/system/framework/services.jar", "/system/framework/core-junit.jar"); } else if (apiLevel <= 13) { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core.jar", "/system/framework/apache-xml.jar", "/system/framework/bouncycastle.jar", @@ -276,7 +275,7 @@ public class ClassPathResolver { "/system/framework/services.jar", "/system/framework/core-junit.jar"); } else if (apiLevel <= 15) { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core.jar", "/system/framework/core-junit.jar", "/system/framework/bouncycastle.jar", @@ -288,7 +287,7 @@ public class ClassPathResolver { "/system/framework/filterfw.jar"); } else if (apiLevel <= 17) { // this is correct as of api 17/4.2.2 - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core.jar", "/system/framework/core-junit.jar", "/system/framework/bouncycastle.jar", @@ -300,7 +299,7 @@ public class ClassPathResolver { "/system/framework/services.jar", "/system/framework/apache-xml.jar"); } else if (apiLevel <= 18) { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core.jar", "/system/framework/core-junit.jar", "/system/framework/bouncycastle.jar", @@ -313,7 +312,7 @@ public class ClassPathResolver { "/system/framework/services.jar", "/system/framework/apache-xml.jar"); } else if (apiLevel <= 19) { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core.jar", "/system/framework/conscrypt.jar", "/system/framework/core-junit.jar", @@ -329,7 +328,7 @@ public class ClassPathResolver { "/system/framework/apache-xml.jar", "/system/framework/webviewchromium.jar"); } else if (apiLevel <= 22) { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core-libart.jar", "/system/framework/conscrypt.jar", "/system/framework/okhttp.jar", @@ -344,7 +343,7 @@ public class ClassPathResolver { "/system/framework/android.policy.jar", "/system/framework/apache-xml.jar"); } else if (apiLevel <= 23) { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core-libart.jar", "/system/framework/conscrypt.jar", "/system/framework/okhttp.jar", @@ -358,7 +357,7 @@ public class ClassPathResolver { "/system/framework/apache-xml.jar", "/system/framework/org.apache.http.legacy.boot.jar"); } else /*if (apiLevel <= 24)*/ { - return Lists.newArrayList( + return Arrays.asList( "/system/framework/core-oj.jar", "/system/framework/core-libart.jar", "/system/framework/conscrypt.jar", @@ -378,7 +377,7 @@ public class ClassPathResolver { private static List<String> bootClassPathForOat(@Nonnull OatFile oatFile) { List<String> bcp = oatFile.getBootClassPath(); if(bcp.isEmpty()) { - return Lists.newArrayList("boot.oat"); + return Arrays.asList("boot.oat"); } else { return replaceElementsSuffix(bcp, ".art", ".oat"); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassProto.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassProto.java index 34743ec8..368eda95 100755 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassProto.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/ClassProto.java @@ -32,6 +32,7 @@ package com.android.tools.smali.dexlib2.analysis; import com.android.tools.smali.dexlib2.AccessFlags; import com.android.tools.smali.dexlib2.HiddenApiRestriction; +import com.android.tools.smali.dexlib2.analysis.util.MemoizingSupplier; import com.android.tools.smali.dexlib2.analysis.util.TypeProtoUtils; import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference; import com.android.tools.smali.dexlib2.iface.Annotation; @@ -45,17 +46,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference; import com.android.tools.smali.dexlib2.util.AlignmentUtils; import com.android.tools.smali.dexlib2.util.MethodUtil; import com.android.tools.smali.util.ExceptionWithContext; +import com.android.tools.smali.util.IteratorUtils; import com.android.tools.smali.util.SparseArray; -import com.google.common.base.Joiner; -import com.google.common.base.Predicates; -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.primitives.Ints; +import com.android.tools.smali.util.StringUtils; import java.util.ArrayList; import java.util.Collections; @@ -66,9 +59,11 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.PriorityQueue; import java.util.Set; +import java.util.function.Supplier; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Map.Entry; +import java.util.function.Predicate; /** * A class "prototype". This contains things like the interfaces, the superclass, the vtable and the instance fields @@ -105,7 +100,7 @@ public class ClassProto implements TypeProto { } - @Nonnull private final Supplier<ClassDef> classDefSupplier = Suppliers.memoize(new Supplier<ClassDef>() { + @Nonnull private final Supplier<ClassDef> classDefSupplier = MemoizingSupplier.memoize(new Supplier<ClassDef>() { @Override public ClassDef get() { return classPath.getClassDef(type); } @@ -151,10 +146,10 @@ public class ClassProto implements TypeProto { */ @Nonnull private final Supplier<LinkedHashMap<String, ClassDef>> preDefaultMethodInterfaceSupplier = - Suppliers.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() { + MemoizingSupplier.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() { @Override public LinkedHashMap<String, ClassDef> get() { Set<String> unresolvedInterfaces = new HashSet<>(0); - LinkedHashMap<String, ClassDef> interfaces = Maps.newLinkedHashMap(); + LinkedHashMap<String, ClassDef> interfaces = new LinkedHashMap<>(); try { for (String interfaceType: getClassDef().getInterfaces()) { @@ -227,10 +222,10 @@ public class ClassProto implements TypeProto { */ @Nonnull private final Supplier<LinkedHashMap<String, ClassDef>> postDefaultMethodInterfaceSupplier = - Suppliers.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() { + MemoizingSupplier.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() { @Override public LinkedHashMap<String, ClassDef> get() { Set<String> unresolvedInterfaces = new HashSet<String>(0); - LinkedHashMap<String, ClassDef> interfaces = Maps.newLinkedHashMap(); + LinkedHashMap<String, ClassDef> interfaces = new LinkedHashMap<>(); String superclass = getSuperclass(); if (superclass != null) { @@ -290,7 +285,7 @@ public class ClassProto implements TypeProto { @Nonnull protected Set<String> getUnresolvedInterfaces() { if (unresolvedInterfaces == null) { - return ImmutableSet.of(); + return Collections.emptySet(); } return unresolvedInterfaces; } @@ -305,12 +300,15 @@ public class ClassProto implements TypeProto { */ @Nonnull protected Iterable<ClassDef> getDirectInterfaces() { - Iterable<ClassDef> directInterfaces = - FluentIterable.from(getInterfaces().values()).filter(Predicates.notNull()); + Iterable<ClassDef> directInterfaces = IteratorUtils.filter(getInterfaces().values(), new Predicate<ClassDef>() { + @Override public boolean test(@Nullable ClassDef input) { + return input != null; + } + }); if (!interfacesFullyResolved) { throw new UnresolvedClassException("Interfaces for class %s not fully resolved: %s", getType(), - Joiner.on(',').join(getUnresolvedInterfaces())); + StringUtils.join(getUnresolvedInterfaces(), ",")); } return directInterfaces; @@ -428,15 +426,17 @@ public class ClassProto implements TypeProto { return classPath.getUnknownClass(); } - List<TypeProto> thisChain = Lists.<TypeProto>newArrayList(this); - Iterables.addAll(thisChain, TypeProtoUtils.getSuperclassChain(this)); + List<TypeProto> thisChain = new ArrayList<>(); + thisChain.add(this); + IteratorUtils.addAll(thisChain, TypeProtoUtils.getSuperclassChain(this).iterator()); - List<TypeProto> otherChain = Lists.newArrayList(other); - Iterables.addAll(otherChain, TypeProtoUtils.getSuperclassChain(other)); + List<TypeProto> otherChain = new ArrayList<>(); + otherChain.add(other); + IteratorUtils.addAll(otherChain, TypeProtoUtils.getSuperclassChain(other).iterator()); // reverse them, so that the first entry is either Ljava/lang/Object; or Ujava/lang/Object; - thisChain = Lists.reverse(thisChain); - otherChain = Lists.reverse(otherChain); + Collections.reverse(thisChain); + Collections.reverse(otherChain); for (int i=Math.min(thisChain.size(), otherChain.size())-1; i>=0; i--) { TypeProto typeProto = thisChain.get(i); @@ -507,7 +507,7 @@ public class ClassProto implements TypeProto { } @Nonnull private final Supplier<SparseArray<FieldReference>> dalvikInstanceFieldsSupplier = - Suppliers.memoize(new Supplier<SparseArray<FieldReference>>() { + MemoizingSupplier.memoize(new Supplier<SparseArray<FieldReference>>() { @Override public SparseArray<FieldReference> get() { //This is a bit of an "involved" operation. We need to follow the same algorithm that dalvik uses to //arrange fields, so that we end up with the same field offsets (which is needed for deodexing). @@ -654,7 +654,7 @@ public class ClassProto implements TypeProto { @Nonnull private ArrayList<Field> getSortedInstanceFields(@Nonnull ClassDef classDef) { - ArrayList<Field> fields = Lists.newArrayList(classDef.getInstanceFields()); + ArrayList<Field> fields = (ArrayList<Field>)IteratorUtils.toList(classDef.getInstanceFields()); Collections.sort(fields); return fields; } @@ -677,21 +677,21 @@ public class ClassProto implements TypeProto { if (oatVersion >= 67) { return new FieldGap(offset, size) { @Override public int compareTo(@Nonnull FieldGap o) { - int result = Ints.compare(o.size, size); + int result = Integer.compare(o.size, size); if (result != 0) { return result; } - return Ints.compare(offset, o.offset); + return Integer.compare(offset, o.offset); } }; } else { return new FieldGap(offset, size) { @Override public int compareTo(@Nonnull FieldGap o) { - int result = Ints.compare(size, o.size); + int result = Integer.compare(size, o.size); if (result != 0) { return result; } - return Ints.compare(o.offset, offset); + return Integer.compare(o.offset, offset); } }; } @@ -704,7 +704,7 @@ public class ClassProto implements TypeProto { } @Nonnull private final Supplier<SparseArray<FieldReference>> artInstanceFieldsSupplier = - Suppliers.memoize(new Supplier<SparseArray<FieldReference>>() { + MemoizingSupplier.memoize(new Supplier<SparseArray<FieldReference>>() { @Override public SparseArray<FieldReference> get() { // We need to follow the same algorithm that art uses to arrange fields, so that we end up with the @@ -781,10 +781,10 @@ public class ClassProto implements TypeProto { @Nonnull private ArrayList<Field> getSortedInstanceFields(@Nonnull ClassDef classDef) { - ArrayList<Field> fields = Lists.newArrayList(classDef.getInstanceFields()); + ArrayList<Field> fields = (ArrayList<Field>)IteratorUtils.toList(classDef.getInstanceFields()); Collections.sort(fields, new Comparator<Field>() { @Override public int compare(Field field1, Field field2) { - int result = Ints.compare(getFieldSortOrder(field1), getFieldSortOrder(field2)); + int result = Integer.compare(getFieldSortOrder(field1), getFieldSortOrder(field2)); if (result != 0) { return result; } @@ -891,9 +891,9 @@ public class ClassProto implements TypeProto { } //TODO: check the case when we have a package private method that overrides an interface method - @Nonnull private final Supplier<List<Method>> preDefaultMethodVtableSupplier = Suppliers.memoize(new Supplier<List<Method>>() { + @Nonnull private final Supplier<List<Method>> preDefaultMethodVtableSupplier = MemoizingSupplier.memoize(new Supplier<List<Method>>() { @Override public List<Method> get() { - List<Method> vtable = Lists.newArrayList(); + List<Method> vtable = new ArrayList<>(); //copy the virtual methods from the superclass String superclassType; @@ -926,7 +926,7 @@ public class ClassProto implements TypeProto { // we don't end up trying to call invoke-virtual using an interface, which will fail verification Iterable<ClassDef> interfaces = getDirectInterfaces(); for (ClassDef interfaceDef: interfaces) { - List<Method> interfaceMethods = Lists.newArrayList(); + List<Method> interfaceMethods = new ArrayList<>(); for (Method interfaceMethod: interfaceDef.getVirtualMethods()) { interfaceMethods.add(new ReparentedMethod(interfaceMethod, type)); } @@ -942,9 +942,9 @@ public class ClassProto implements TypeProto { * produce multiple vtable entries for a given virtual method. This supplier duplicates this buggy logic in order to * generate an identical vtable */ - @Nonnull private final Supplier<List<Method>> buggyPostDefaultMethodVtableSupplier = Suppliers.memoize(new Supplier<List<Method>>() { + @Nonnull private final Supplier<List<Method>> buggyPostDefaultMethodVtableSupplier = MemoizingSupplier.memoize(new Supplier<List<Method>>() { @Override public List<Method> get() { - List<Method> vtable = Lists.newArrayList(); + List<Method> vtable = new ArrayList<>(); //copy the virtual methods from the superclass String superclassType; @@ -973,13 +973,13 @@ public class ClassProto implements TypeProto { if (!isInterface()) { addToVtable(getClassDef().getVirtualMethods(), vtable, true, true); - List<String> interfaces = Lists.newArrayList(getInterfaces().keySet()); + List<String> interfaces = new ArrayList<>(getInterfaces().keySet()); - List<Method> defaultMethods = Lists.newArrayList(); - List<Method> defaultConflictMethods = Lists.newArrayList(); - List<Method> mirandaMethods = Lists.newArrayList(); + List<Method> defaultMethods = new ArrayList<>(); + List<Method> defaultConflictMethods = new ArrayList<>(); + List<Method> mirandaMethods = new ArrayList<>(); - final HashMap<MethodReference, Integer> methodOrder = Maps.newHashMap(); + final HashMap<MethodReference, Integer> methodOrder = new HashMap<>(); for (int i=interfaces.size()-1; i>=0; i--) { String interfaceType = interfaces.get(i); @@ -1070,7 +1070,7 @@ public class ClassProto implements TypeProto { Comparator<MethodReference> comparator = new Comparator<MethodReference>() { @Override public int compare(MethodReference o1, MethodReference o2) { - return Ints.compare(methodOrder.get(o1), methodOrder.get(o2)); + return Integer.compare(methodOrder.get(o1), methodOrder.get(o2)); } }; @@ -1089,9 +1089,9 @@ public class ClassProto implements TypeProto { } }); - @Nonnull private final Supplier<List<Method>> postDefaultMethodVtableSupplier = Suppliers.memoize(new Supplier<List<Method>>() { + @Nonnull private final Supplier<List<Method>> postDefaultMethodVtableSupplier = MemoizingSupplier.memoize(new Supplier<List<Method>>() { @Override public List<Method> get() { - List<Method> vtable = Lists.newArrayList(); + List<Method> vtable = new ArrayList<>(); //copy the virtual methods from the superclass String superclassType; @@ -1120,13 +1120,14 @@ public class ClassProto implements TypeProto { if (!isInterface()) { addToVtable(getClassDef().getVirtualMethods(), vtable, true, true); - Iterable<ClassDef> interfaces = Lists.reverse(Lists.newArrayList(getDirectInterfaces())); + List<ClassDef> interfaces = IteratorUtils.toList(getDirectInterfaces()); + Collections.reverse(interfaces); - List<Method> defaultMethods = Lists.newArrayList(); - List<Method> defaultConflictMethods = Lists.newArrayList(); - List<Method> mirandaMethods = Lists.newArrayList(); + List<Method> defaultMethods = new ArrayList<>(); + List<Method> defaultConflictMethods = new ArrayList<>(); + List<Method> mirandaMethods = new ArrayList<>(); - final HashMap<MethodReference, Integer> methodOrder = Maps.newHashMap(); + final HashMap<MethodReference, Integer> methodOrder = new HashMap<>(); for (ClassDef interfaceDef: interfaces) { for (Method interfaceMethod : interfaceDef.getVirtualMethods()) { @@ -1190,7 +1191,7 @@ public class ClassProto implements TypeProto { Comparator<MethodReference> comparator = new Comparator<MethodReference>() { @Override public int compare(MethodReference o1, MethodReference o2) { - return Ints.compare(methodOrder.get(o1), methodOrder.get(o2)); + return Integer.compare(methodOrder.get(o1), methodOrder.get(o2)); } }; @@ -1211,7 +1212,7 @@ public class ClassProto implements TypeProto { private void addToVtable(@Nonnull Iterable<? extends Method> localMethods, @Nonnull List<Method> vtable, boolean replaceExisting, boolean sort) { if (sort) { - ArrayList<Method> methods = Lists.newArrayList(localMethods); + ArrayList<Method> methods = (ArrayList<Method>)IteratorUtils.toList(localMethods); Collections.sort(methods); localMethods = methods; } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/CustomInlineMethodResolver.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/CustomInlineMethodResolver.java index 7c59c4b2..a78b092c 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/CustomInlineMethodResolver.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/CustomInlineMethodResolver.java @@ -37,14 +37,14 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod; import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter; import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference; import com.android.tools.smali.dexlib2.immutable.util.ParamUtil; -import com.google.common.io.Files; +import com.android.tools.smali.util.InputStreamUtil; import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.FileInputStream; import java.io.StringReader; import javax.annotation.Nonnull; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -85,7 +85,8 @@ public class CustomInlineMethodResolver extends InlineMethodResolver { } public CustomInlineMethodResolver(@Nonnull ClassPath classPath, @Nonnull File inlineTable) throws IOException { - this(classPath, Files.asCharSource(inlineTable, StandardCharsets.UTF_8).read()); + this(classPath, new String( + InputStreamUtil.toByteArray(new FileInputStream(inlineTable)), StandardCharsets.UTF_8)); } @Override diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/DexClassProvider.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/DexClassProvider.java index db9fb99c..f0eb027a 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/DexClassProvider.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/DexClassProvider.java @@ -32,14 +32,14 @@ package com.android.tools.smali.dexlib2.analysis; import com.android.tools.smali.dexlib2.iface.ClassDef; import com.android.tools.smali.dexlib2.iface.DexFile; -import com.google.common.collect.Maps; import javax.annotation.Nullable; +import java.util.HashMap; import java.util.Map; public class DexClassProvider implements ClassProvider { private final DexFile dexFile; - private Map<String, ClassDef> classMap = Maps.newHashMap(); + private Map<String, ClassDef> classMap = new HashMap<>(); public DexClassProvider(DexFile dexFile) { this.dexFile = dexFile; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/InlineMethodResolver.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/InlineMethodResolver.java index 5e7322a2..fbf5bce1 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/InlineMethodResolver.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/InlineMethodResolver.java @@ -30,15 +30,19 @@ package com.android.tools.smali.dexlib2.analysis; +import static java.util.Collections.unmodifiableList; + import com.android.tools.smali.dexlib2.iface.Method; import com.android.tools.smali.dexlib2.iface.instruction.InlineIndexInstruction; import com.android.tools.smali.dexlib2.iface.instruction.VariableRegisterInstruction; import com.android.tools.smali.dexlib2.immutable.ImmutableMethod; import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter; import com.android.tools.smali.dexlib2.immutable.util.ParamUtil; -import com.google.common.collect.ImmutableList; +import com.android.tools.smali.util.IteratorUtils; import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; public abstract class InlineMethodResolver { // These are the possible values for the accessFlag field on a resolved inline method @@ -65,7 +69,8 @@ public abstract class InlineMethodResolver { @Nonnull private static Method inlineMethod(int accessFlags, @Nonnull String cls, @Nonnull String name, @Nonnull String params, @Nonnull String returnType) { - ImmutableList<ImmutableMethodParameter> paramList = ImmutableList.copyOf(ParamUtil.parseParamString(params)); + List<ImmutableMethodParameter> paramList = unmodifiableList( + IteratorUtils.toList(ParamUtil.parseParamString(params))); return new ImmutableMethod(cls, name, paramList, returnType, accessFlags, null, null, null); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/MethodAnalyzer.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/MethodAnalyzer.java index b6174a26..3af6cb97 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/MethodAnalyzer.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/MethodAnalyzer.java @@ -76,15 +76,15 @@ import com.android.tools.smali.dexlib2.util.TypeUtils; import com.android.tools.smali.dexlib2.writer.util.TryListBuilder; import com.android.tools.smali.util.BitSetUtils; import com.android.tools.smali.util.ExceptionWithContext; +import com.android.tools.smali.util.IteratorUtils; import com.android.tools.smali.util.SparseArray; -import com.google.common.base.Function; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.BitSet; +import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; /** * The MethodAnalyzer performs several functions. It "analyzes" the instructions and infers the register types @@ -329,14 +329,8 @@ public class MethodAnalyzer { } public List<Instruction> getInstructions() { - return Lists.transform(analyzedInstructions.getValues(), new Function<AnalyzedInstruction, Instruction>() { - @Nullable @Override public Instruction apply(@Nullable AnalyzedInstruction input) { - if (input == null) { - return null; - } - return input.instruction; - } - }); + return analyzedInstructions.getValues().stream().map( + input -> input == null ? null : input.instruction).collect(Collectors.toList()); } @Nullable @@ -458,7 +452,8 @@ public class MethodAnalyzer { private void buildInstructionList() { int registerCount = methodImpl.getRegisterCount(); - ImmutableList<Instruction> instructions = ImmutableList.copyOf(methodImpl.getInstructions()); + List<Instruction> instructions = Collections.unmodifiableList( + IteratorUtils.toList(methodImpl.getInstructions())); analyzedInstructions.ensureCapacity(instructions.size()); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/PathEntryLoader.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/PathEntryLoader.java index 3f65298b..698eb1f5 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/PathEntryLoader.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/PathEntryLoader.java @@ -35,12 +35,12 @@ import com.android.tools.smali.dexlib2.Opcodes; import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile; import com.android.tools.smali.dexlib2.dexbacked.OatFile; import com.android.tools.smali.dexlib2.iface.MultiDexContainer; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -51,8 +51,8 @@ public class PathEntryLoader { return opcodes; } - final Set<File> loadedFiles = Sets.newHashSet(); - final List<ClassProvider> classProviders = Lists.newArrayList(); + final Set<File> loadedFiles = new HashSet<>(); + final List<ClassProvider> classProviders = new ArrayList<>(); public List<ClassProvider> getClassProviders() { return classProviders; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionClassDef.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionClassDef.java index b1404509..1451a269 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionClassDef.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionClassDef.java @@ -35,11 +35,10 @@ import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.ClassDef; import com.android.tools.smali.dexlib2.iface.Field; import com.android.tools.smali.dexlib2.iface.Method; -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterators; +import com.android.tools.smali.util.ChainedIterator; +import com.android.tools.smali.util.IteratorUtils; +import com.android.tools.smali.util.TransformedIterator; + import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference; import javax.annotation.Nonnull; @@ -48,8 +47,13 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.AbstractSet; import java.util.Iterator; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; +import java.util.Arrays; +import java.util.Collections; /** * Wraps a ClassDef around a class loaded in the current VM @@ -79,17 +83,10 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef { return ReflectionUtils.javaToDexName(superClass.getName()); } - @Nonnull @Override public List<String> getInterfaces() { - return ImmutableList.copyOf(Iterators.transform(Iterators.forArray(cls.getInterfaces()), new Function<Class, String>() { - @Nullable - @Override - public String apply(@Nullable Class input) { - if (input == null) { - return null; - } - return ReflectionUtils.javaToDexName(input.getName()); - } - })); + @Nonnull @Override public List<String> getInterfaces() { + return Arrays.asList(cls.getInterfaces()).stream().map( + i -> i == null ? null : ReflectionUtils.javaToDexName(i.getName())) + .collect(Collectors.toList()); } @Nullable @Override public String getSourceFile() { @@ -97,27 +94,25 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef { } @Nonnull @Override public Set<? extends Annotation> getAnnotations() { - return ImmutableSet.of(); + return Collections.emptySet(); } @Nonnull @Override public Iterable<? extends Field> getStaticFields() { return new Iterable<Field>() { @Nonnull @Override public Iterator<Field> iterator() { - Iterator<java.lang.reflect.Field> staticFields = Iterators.filter( - Iterators.forArray(cls.getDeclaredFields()), + Iterator<java.lang.reflect.Field> staticFields = IteratorUtils.filter( + Arrays.asList(cls.getDeclaredFields()), new Predicate<java.lang.reflect.Field>() { - @Override public boolean apply(@Nullable java.lang.reflect.Field input) { + @Override public boolean test(@Nullable java.lang.reflect.Field input) { return input!=null && Modifier.isStatic(input.getModifiers()); } }); - return Iterators.transform(staticFields, - new Function<java.lang.reflect.Field, Field>() { - @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) { - return new ReflectionField(input); - } - } - ); + return new TransformedIterator<java.lang.reflect.Field, Field>(staticFields, new Function<java.lang.reflect.Field, Field>() { + @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) { + return new ReflectionField(input); + } + }); } }; } @@ -125,15 +120,15 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef { @Nonnull @Override public Iterable<? extends Field> getInstanceFields() { return new Iterable<Field>() { @Nonnull @Override public Iterator<Field> iterator() { - Iterator<java.lang.reflect.Field> staticFields = Iterators.filter( - Iterators.forArray(cls.getDeclaredFields()), + Iterator<java.lang.reflect.Field> staticFields = IteratorUtils.filter( + Arrays.asList(cls.getDeclaredFields()), new Predicate<java.lang.reflect.Field>() { - @Override public boolean apply(@Nullable java.lang.reflect.Field input) { + @Override public boolean test(@Nullable java.lang.reflect.Field input) { return input!=null && !Modifier.isStatic(input.getModifiers()); } }); - return Iterators.transform(staticFields, + return new TransformedIterator<java.lang.reflect.Field, Field>(staticFields, new Function<java.lang.reflect.Field, Field>() { @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) { return new ReflectionField(input); @@ -147,7 +142,8 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef { @Nonnull @Override public Set<? extends Field> getFields() { return new AbstractSet<Field>() { @Nonnull @Override public Iterator<Field> iterator() { - return Iterators.transform(Iterators.forArray(cls.getDeclaredFields()), + return new TransformedIterator<java.lang.reflect.Field, Field>( + Arrays.asList(cls.getDeclaredFields()), new Function<java.lang.reflect.Field, Field>() { @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) { return new ReflectionField(input); @@ -166,28 +162,30 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef { return new Iterable<Method>() { @Nonnull @Override public Iterator<Method> iterator() { Iterator<Method> constructorIterator = - Iterators.transform(Iterators.forArray(cls.getDeclaredConstructors()), + new TransformedIterator<Constructor, Method>( + Arrays.asList(cls.getDeclaredConstructors()).iterator(), new Function<Constructor, Method>() { @Nullable @Override public Method apply(@Nullable Constructor input) { return new ReflectionConstructor(input); } }); - Iterator<java.lang.reflect.Method> directMethods = Iterators.filter( - Iterators.forArray(cls.getDeclaredMethods()), + Iterator<java.lang.reflect.Method> directMethods = IteratorUtils.filter( + Arrays.asList(cls.getDeclaredMethods()), new Predicate<java.lang.reflect.Method>() { - @Override public boolean apply(@Nullable java.lang.reflect.Method input) { + @Override public boolean test(@Nullable java.lang.reflect.Method input) { return input != null && (input.getModifiers() & DIRECT_MODIFIERS) != 0; } }); - Iterator<Method> methodIterator = Iterators.transform(directMethods, + Iterator<Method> methodIterator = new TransformedIterator<java.lang.reflect.Method, Method>( + directMethods, new Function<java.lang.reflect.Method, Method>() { @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) { return new ReflectionMethod(input); } }); - return Iterators.concat(constructorIterator, methodIterator); + return new ChainedIterator<Method>(constructorIterator, methodIterator); } }; } @@ -195,15 +193,15 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef { @Nonnull @Override public Iterable<? extends Method> getVirtualMethods() { return new Iterable<Method>() { @Nonnull @Override public Iterator<Method> iterator() { - Iterator<java.lang.reflect.Method> directMethods = Iterators.filter( - Iterators.forArray(cls.getDeclaredMethods()), + Iterator<java.lang.reflect.Method> directMethods = IteratorUtils.filter( + Arrays.asList(cls.getDeclaredMethods()), new Predicate<java.lang.reflect.Method>() { - @Override public boolean apply(@Nullable java.lang.reflect.Method input) { + @Override public boolean test(@Nullable java.lang.reflect.Method input) { return input != null && (input.getModifiers() & DIRECT_MODIFIERS) == 0; } }); - return Iterators.transform(directMethods, + return new TransformedIterator<java.lang.reflect.Method, Method>(directMethods, new Function<java.lang.reflect.Method, Method>() { @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) { return new ReflectionMethod(input); @@ -217,7 +215,8 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef { return new AbstractSet<Method>() { @Nonnull @Override public Iterator<Method> iterator() { Iterator<Method> constructorIterator = - Iterators.transform(Iterators.forArray(cls.getDeclaredConstructors()), + new TransformedIterator<Constructor, Method>( + Arrays.asList(cls.getDeclaredConstructors()), new Function<Constructor, Method>() { @Nullable @Override public Method apply(@Nullable Constructor input) { return new ReflectionConstructor(input); @@ -225,13 +224,14 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef { }); Iterator<Method> methodIterator = - Iterators.transform(Iterators.forArray(cls.getDeclaredMethods()), + new TransformedIterator<java.lang.reflect.Method, Method>( + Arrays.asList(cls.getDeclaredMethods()), new Function<java.lang.reflect.Method, Method>() { @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) { return new ReflectionMethod(input); } }); - return Iterators.concat(constructorIterator, methodIterator); + return new ChainedIterator<Method>(constructorIterator, methodIterator); } @Override public int size() { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionConstructor.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionConstructor.java index 80ba4bee..ff112391 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionConstructor.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionConstructor.java @@ -37,13 +37,13 @@ import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.Method; import com.android.tools.smali.dexlib2.iface.MethodImplementation; import com.android.tools.smali.dexlib2.iface.MethodParameter; -import com.google.common.collect.ImmutableSet; import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.util.AbstractList; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -62,7 +62,7 @@ public class ReflectionConstructor extends BaseMethodReference implements Method @Override public MethodParameter get(final int index) { return new BaseMethodParameter() { @Nonnull @Override public Set<? extends Annotation> getAnnotations() { - return ImmutableSet.of(); + return Collections.emptySet(); } @Nullable @Override public String getName() { @@ -86,7 +86,7 @@ public class ReflectionConstructor extends BaseMethodReference implements Method } @Nonnull @Override public Set<? extends Annotation> getAnnotations() { - return ImmutableSet.of(); + return Collections.emptySet(); } @Nullable @Override public MethodImplementation getImplementation() { @@ -120,6 +120,6 @@ public class ReflectionConstructor extends BaseMethodReference implements Method } @Nonnull @Override public Set<HiddenApiRestriction> getHiddenApiRestrictions() { - return ImmutableSet.of(); + return Collections.emptySet(); } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionField.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionField.java index d35f90d4..5205ea01 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionField.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionField.java @@ -34,12 +34,12 @@ import com.android.tools.smali.dexlib2.HiddenApiRestriction; import com.android.tools.smali.dexlib2.analysis.reflection.util.ReflectionUtils; import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.Field; -import com.google.common.collect.ImmutableSet; import com.android.tools.smali.dexlib2.base.reference.BaseFieldReference; import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collections; import java.util.Set; public class ReflectionField extends BaseFieldReference implements Field { @@ -58,7 +58,7 @@ public class ReflectionField extends BaseFieldReference implements Field { } @Nonnull @Override public Set<? extends Annotation> getAnnotations() { - return ImmutableSet.of(); + return Collections.emptySet(); } @Nonnull @Override public String getDefiningClass() { @@ -74,6 +74,6 @@ public class ReflectionField extends BaseFieldReference implements Field { } @Nonnull @Override public Set<HiddenApiRestriction> getHiddenApiRestrictions() { - return ImmutableSet.of(); + return Collections.emptySet(); } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionMethod.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionMethod.java index 24396b13..40f5d4aa 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionMethod.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/ReflectionMethod.java @@ -37,12 +37,12 @@ import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.Method; import com.android.tools.smali.dexlib2.iface.MethodImplementation; import com.android.tools.smali.dexlib2.iface.MethodParameter; -import com.google.common.collect.ImmutableSet; import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.AbstractList; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -61,7 +61,7 @@ public class ReflectionMethod extends BaseMethodReference implements Method { @Override public MethodParameter get(final int index) { return new BaseMethodParameter() { @Nonnull @Override public Set<? extends Annotation> getAnnotations() { - return ImmutableSet.of(); + return Collections.emptySet(); } @Nullable @Override public String getName() { @@ -85,7 +85,7 @@ public class ReflectionMethod extends BaseMethodReference implements Method { } @Nonnull @Override public Set<? extends Annotation> getAnnotations() { - return ImmutableSet.of(); + return Collections.emptySet(); } @Nullable @Override public MethodImplementation getImplementation() { @@ -119,6 +119,6 @@ public class ReflectionMethod extends BaseMethodReference implements Method { } @Nonnull @Override public Set<HiddenApiRestriction> getHiddenApiRestrictions() { - return ImmutableSet.of(); + return Collections.emptySet(); } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/util/ReflectionUtils.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/util/ReflectionUtils.java index 2fb8bdcd..ab4a2897 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/util/ReflectionUtils.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/reflection/util/ReflectionUtils.java @@ -30,21 +30,39 @@ package com.android.tools.smali.dexlib2.analysis.reflection.util; -import com.google.common.collect.ImmutableBiMap; +import static java.util.Collections.unmodifiableMap; + +import java.util.Map; +import java.util.HashMap; public class ReflectionUtils { - private static ImmutableBiMap<String, String> primitiveMap = ImmutableBiMap.<String, String>builder() - .put("boolean", "Z") - .put("int", "I") - .put("long", "J") - .put("double", "D") - .put("void", "V") - .put("float", "F") - .put("char", "C") - .put("short", "S") - .put("byte", "B") - .build(); + private static Map<String, String> primitiveMap; + + static { + Map<String, String> temp = new HashMap<>(); + temp.put("boolean", "Z"); + temp.put("int", "I"); + temp.put("long", "J"); + temp.put("double", "D"); + temp.put("void", "V"); + temp.put("float", "F"); + temp.put("char", "C"); + temp.put("short", "S"); + temp.put("byte", "B"); + primitiveMap = unmodifiableMap(temp); + } + + private static Map<String, String> primitiveMapInverse = getInverse(); + + private static Map<String, String> getInverse() { + Map<String, String> temp = new HashMap<>(); + for (Map.Entry<String, String> entry : primitiveMap.entrySet()) { + temp.put(entry.getValue(), entry.getKey()); + } + return unmodifiableMap(temp); + } + public static String javaToDexName(String javaName) { if (javaName.charAt(0) == '[') { @@ -63,8 +81,8 @@ public class ReflectionUtils { return dexName.replace('/', '.'); } - if (primitiveMap.inverse().containsKey(dexName)) { - return primitiveMap.inverse().get(dexName); + if (primitiveMapInverse.containsKey(dexName)) { + return primitiveMapInverse.get(dexName); } return dexName.replace('/', '.').substring(1, dexName.length()-1); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/util/LruCache.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/util/LruCache.java new file mode 100644 index 00000000..5c971893 --- /dev/null +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/util/LruCache.java @@ -0,0 +1,400 @@ +/* + * Copyright 2024, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.tools.smali.dexlib2.analysis.util; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + + +/** + * Based on android.util.LruCache. + * A cache that holds strong references to a limited number of values. Each time + * a value is accessed, it is moved to the head of a queue. When a value is + * added to a full cache, the value at the end of that queue is evicted and may + * become eligible for garbage collection. + * + * <p>If your cached values hold resources that need to be explicitly released, + * override {@link #entryRemoved}. + * + * <p>If a cache miss should be computed on demand for the corresponding keys, + * override {@link #create}. This simplifies the calling code, allowing it to + * assume a value will always be returned, even when there's a cache miss. + * + * <p>By default, the cache size is measured in the number of entries. Override + * {@link #sizeOf} to size the cache in different units. For example, this cache + * is limited to 4MiB of bitmaps: + * <pre> {@code + * int cacheSize = 4 * 1024 * 1024; // 4MiB + * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) { + * protected int sizeOf(String key, Bitmap value) { + * return value.getByteCount(); + * } + * }}</pre> + * + * <p>This class is thread-safe. Perform multiple cache operations atomically by + * synchronizing on the cache: <pre> {@code + * synchronized (cache) { + * if (cache.get(key) == null) { + * cache.put(key, value); + * } + * }}</pre> + * + * <p>This class does not allow null to be used as a key or value. A return + * value of null from {@link #get}, {@link #put} or {@link #remove} is + * unambiguous: the key was not in the cache. + */ + +public class LruCache<K, V> { + private final LinkedHashMap<K, V> map; + + /** Size of this cache in units. Not necessarily the number of elements. */ + private int size; + private int maxSize; + + private int putCount; + private int createCount; + private int evictionCount; + private int hitCount; + private int missCount; + + /** + * @param maxSize for caches that do not override {@link #sizeOf}, this is + * the maximum number of entries in the cache. For all other caches, + * this is the maximum sum of the sizes of the entries in this cache. + */ + public LruCache(int maxSize) { + if (maxSize <= 0) { + throw new IllegalArgumentException("maxSize <= 0"); + } + this.maxSize = maxSize; + this.map = new LinkedHashMap<K, V>(0, 0.75f, true); + } + + /** + * Sets the size of the cache. + * + * @param maxSize The new maximum size. + */ + public void resize(int maxSize) { + if (maxSize <= 0) { + throw new IllegalArgumentException("maxSize <= 0"); + } + + synchronized (this) { + this.maxSize = maxSize; + } + trimToSize(maxSize); + } + + /** + * Returns the value for {@code key} if it exists in the cache or can be + * created by {@code #create}. If a value was returned, it is moved to the + * head of the queue. This returns null if a value is not cached and cannot + * be created. + */ + public final V get(K key) { + if (key == null) { + throw new NullPointerException("key == null"); + } + + V mapValue; + synchronized (this) { + mapValue = map.get(key); + if (mapValue != null) { + hitCount++; + return mapValue; + } + missCount++; + } + + /* + * Attempt to create a value. This may take a long time, and the map + * may be different when create() returns. If a conflicting value was + * added to the map while create() was working, we leave that value in + * the map and release the created value. + */ + + V createdValue = create(key); + if (createdValue == null) { + return null; + } + + synchronized (this) { + createCount++; + mapValue = map.put(key, createdValue); + + if (mapValue != null) { + // There was a conflict so undo that last put + map.put(key, mapValue); + } else { + size += safeSizeOf(key, createdValue); + } + } + + if (mapValue != null) { + entryRemoved(false, key, createdValue, mapValue); + return mapValue; + } else { + trimToSize(maxSize); + return createdValue; + } + } + + /** + * Caches {@code value} for {@code key}. The value is moved to the head of + * the queue. + * + * @return the previous value mapped by {@code key}. + */ + public final V put(K key, V value) { + if (key == null || value == null) { + throw new NullPointerException("key == null || value == null"); + } + + V previous; + synchronized (this) { + putCount++; + size += safeSizeOf(key, value); + previous = map.put(key, value); + if (previous != null) { + size -= safeSizeOf(key, previous); + } + } + + if (previous != null) { + entryRemoved(false, key, previous, value); + } + + trimToSize(maxSize); + return previous; + } + + /** + * Remove the eldest entries until the total of remaining entries is at or + * below the requested size. + * + * @param maxSize the maximum size of the cache before returning. May be -1 + * to evict even 0-sized elements. + */ + public void trimToSize(int maxSize) { + while (true) { + K key; + V value; + synchronized (this) { + if (size < 0 || (map.isEmpty() && size != 0)) { + throw new IllegalStateException(getClass().getName() + + ".sizeOf() is reporting inconsistent results!"); + } + + if (size <= maxSize) { + break; + } + + Map.Entry<K, V> toEvict = eldest(); + if (toEvict == null) { + break; + } + + key = toEvict.getKey(); + value = toEvict.getValue(); + map.remove(key); + size -= safeSizeOf(key, value); + evictionCount++; + } + + entryRemoved(true, key, value, null); + } + } + + + private Map.Entry<K, V> eldest() { + final Iterator<Map.Entry<K, V>> it = map.entrySet().iterator(); + return it.hasNext() ? it.next() : null; + } + + /** + * Removes the entry for {@code key} if it exists. + * + * @return the previous value mapped by {@code key}. + */ + public final V remove(K key) { + if (key == null) { + throw new NullPointerException("key == null"); + } + + V previous; + synchronized (this) { + previous = map.remove(key); + if (previous != null) { + size -= safeSizeOf(key, previous); + } + } + + if (previous != null) { + entryRemoved(false, key, previous, null); + } + + return previous; + } + + /** + * Called for entries that have been evicted or removed. This method is + * invoked when a value is evicted to make space, removed by a call to + * {@link #remove}, or replaced by a call to {@link #put}. The default + * implementation does nothing. + * + * <p>The method is called without synchronization: other threads may + * access the cache while this method is executing. + * + * @param evicted true if the entry is being removed to make space, false + * if the removal was caused by a {@link #put} or {@link #remove}. + * @param newValue the new value for {@code key}, if it exists. If non-null, + * this removal was caused by a {@link #put} or a {@link #get}. Otherwise it was caused by + * an eviction or a {@link #remove}. + */ + protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} + + /** + * Called after a cache miss to compute a value for the corresponding key. + * Returns the computed value or null if no value can be computed. The + * default implementation returns null. + * + * <p>The method is called without synchronization: other threads may + * access the cache while this method is executing. + * + * <p>If a value for {@code key} exists in the cache when this method + * returns, the created value will be released with {@link #entryRemoved} + * and discarded. This can occur when multiple threads request the same key + * at the same time (causing multiple values to be created), or when one + * thread calls {@link #put} while another is creating a value for the same + * key. + */ + protected V create(K key) { + return null; + } + + private int safeSizeOf(K key, V value) { + int result = sizeOf(key, value); + if (result < 0) { + throw new IllegalStateException("Negative size: " + key + "=" + value); + } + return result; + } + + /** + * Returns the size of the entry for {@code key} and {@code value} in + * user-defined units. The default implementation returns 1 so that size + * is the number of entries and max size is the maximum number of entries. + * + * <p>An entry's size must not change while it is in the cache. + */ + protected int sizeOf(K key, V value) { + return 1; + } + + /** + * Clear the cache, calling {@link #entryRemoved} on each removed entry. + */ + public final void evictAll() { + trimToSize(-1); // -1 will evict 0-sized elements + } + + /** + * For caches that do not override {@link #sizeOf}, this returns the number + * of entries in the cache. For all other caches, this returns the sum of + * the sizes of the entries in this cache. + */ + public synchronized final int size() { + return size; + } + + /** + * For caches that do not override {@link #sizeOf}, this returns the maximum + * number of entries in the cache. For all other caches, this returns the + * maximum sum of the sizes of the entries in this cache. + */ + public synchronized final int maxSize() { + return maxSize; + } + + /** + * Returns the number of times {@link #get} returned a value that was + * already present in the cache. + */ + public synchronized final int hitCount() { + return hitCount; + } + + /** + * Returns the number of times {@link #get} returned null or required a new + * value to be created. + */ + public synchronized final int missCount() { + return missCount; + } + + /** + * Returns the number of times {@link #create(Object)} returned a value. + */ + public synchronized final int createCount() { + return createCount; + } + + /** + * Returns the number of times {@link #put} was called. + */ + public synchronized final int putCount() { + return putCount; + } + + /** + * Returns the number of values that have been evicted. + */ + public synchronized final int evictionCount() { + return evictionCount; + } + + /** + * Returns a copy of the current contents of the cache, ordered from least + * recently accessed to most recently accessed. + */ + public synchronized final Map<K, V> snapshot() { + return new LinkedHashMap<K, V>(map); + } + + @Override public synchronized final String toString() { + int accesses = hitCount + missCount; + int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0; + return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", + maxSize, hitCount, missCount, hitPercent); + } +} diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/util/MemoizingSupplier.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/util/MemoizingSupplier.java new file mode 100644 index 00000000..c9622f1a --- /dev/null +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/analysis/util/MemoizingSupplier.java @@ -0,0 +1,72 @@ +/* + * Copyright 2024, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.tools.smali.dexlib2.analysis.util; + +import java.util.function.Supplier; + +/** + * Based on Guava's NonSerializableMemoizing Supplier. This implementation is thread safe. + */ +public class MemoizingSupplier<T> implements Supplier<T> { + // Delegate will only be null when the value was successfuly computed + private volatile Supplier<T> delegate; + private T value; + + private MemoizingSupplier(Supplier<T> delegate) { + if (delegate == null) { + throw new NullPointerException("delegate == null"); + } + this.delegate = delegate; + } + + @Override + public T get() { + // Because Supplier is read-heavy, we use the "double-checked locking" pattern. + if (delegate != null) { + synchronized (this) { + if (delegate != null) { + T t = delegate.get(); + value = t; + delegate = null; + } + } + } + // This is safe because we checked `delegate.` + return value; + } + + public static <T extends Object> MemoizingSupplier<T> memoize(Supplier<T> delegate) { + if (delegate instanceof MemoizingSupplier) { + return (MemoizingSupplier<T>) delegate; + } + return new MemoizingSupplier<>(delegate); + } +} diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/BuilderTryBlock.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/BuilderTryBlock.java index 25c079d3..19c05b10 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/BuilderTryBlock.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/BuilderTryBlock.java @@ -30,12 +30,13 @@ package com.android.tools.smali.dexlib2.builder; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.base.BaseTryBlock; import com.android.tools.smali.dexlib2.iface.reference.TypeReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collections; import java.util.List; public class BuilderTryBlock extends BaseTryBlock<BuilderExceptionHandler> { @@ -75,6 +76,6 @@ public class BuilderTryBlock extends BaseTryBlock<BuilderExceptionHandler> { } @Nonnull @Override public List<? extends BuilderExceptionHandler> getExceptionHandlers() { - return ImmutableList.of(exceptionHandler); + return Collections.unmodifiableList(Arrays.asList(exceptionHandler)); } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/LocatedItems.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/LocatedItems.java index 6adf69ec..9060713b 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/LocatedItems.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/LocatedItems.java @@ -30,10 +30,9 @@ package com.android.tools.smali.dexlib2.builder; -import com.google.common.collect.ImmutableList; - import java.util.AbstractSet; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -50,7 +49,7 @@ public abstract class LocatedItems<T extends ItemWithLocation> { @Nonnull private List<T> getItems() { if (items == null) { - return ImmutableList.of(); + return Collections.emptyList(); } return items; } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/MutableMethodImplementation.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/MutableMethodImplementation.java index 2be0f22a..40f9dd77 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/MutableMethodImplementation.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/MutableMethodImplementation.java @@ -122,11 +122,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.PackedSwitchPay import com.android.tools.smali.dexlib2.iface.instruction.formats.SparseSwitchPayload; import com.android.tools.smali.dexlib2.iface.reference.TypeReference; import com.android.tools.smali.util.ExceptionWithContext; -import com.google.common.base.Function; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; @@ -138,8 +133,9 @@ import javax.annotation.Nullable; public class MutableMethodImplementation implements MethodImplementation { private final int registerCount; - final ArrayList<MethodLocation> instructionList = Lists.newArrayList(new MethodLocation(null, 0, 0)); - private final ArrayList<BuilderTryBlock> tryBlocks = Lists.newArrayList(); + final ArrayList<MethodLocation> instructionList = new ArrayList<>( + Arrays.asList(new MethodLocation(null, 0, 0))); + private final ArrayList<BuilderTryBlock> tryBlocks = new ArrayList<>(); private boolean fixInstructions = true; public MutableMethodImplementation(@Nonnull MethodImplementation methodImplementation) { @@ -162,7 +158,7 @@ public class MutableMethodImplementation implements MethodImplementation { codeAddressToIndex[instructionList.get(i).codeAddress] = i; } - List<Task> switchPayloadTasks = Lists.newArrayList(); + List<Task> switchPayloadTasks = new ArrayList<>(); index = 0; for (final Instruction instruction: methodImplementation.getInstructions()) { final MethodLocation location = instructionList.get(index); @@ -256,17 +252,20 @@ public class MutableMethodImplementation implements MethodImplementation { if (fixInstructions) { fixInstructions(); } - return Iterables.concat( - Iterables.transform(instructionList, new Function<MethodLocation, Iterable<? extends DebugItem>>() { - @Nullable @Override public Iterable<? extends DebugItem> apply(@Nullable MethodLocation input) { - assert input != null; - if (fixInstructions) { - throw new IllegalStateException("This iterator was invalidated by a change to" + - " this MutableMethodImplementation."); - } - return input.getDebugItems(); - } - })); + + ArrayList<DebugItem> debugItems = new ArrayList<>(); + + for (MethodLocation methodLocation: instructionList) { + assert methodLocation != null; + + if (fixInstructions) { + throw new IllegalStateException("This iterator was invalidated by a change to" + + " this MutableMethodImplementation."); + } + debugItems.addAll(methodLocation.getDebugItems()); + } + + return Collections.unmodifiableList(debugItems); } public void addCatch(@Nullable TypeReference type, @Nonnull Label from, @@ -438,7 +437,7 @@ public class MutableMethodImplementation implements MethodImplementation { } private void fixInstructions() { - HashSet<MethodLocation> payloadLocations = Sets.newHashSet(); + HashSet<MethodLocation> payloadLocations = new HashSet<>(); for (MethodLocation location: instructionList) { BuilderInstruction instruction = location.instruction; @@ -1104,7 +1103,7 @@ public class MutableMethodImplementation implements MethodImplementation { baseAddress = switchLocation.codeAddress; } - List<Label> labels = Lists.newArrayList(); + List<Label> labels = new ArrayList<>(); for (SwitchElement element: switchElements) { labels.add(newLabel(codeAddressToIndex, element.getOffset() + baseAddress)); } @@ -1129,7 +1128,7 @@ public class MutableMethodImplementation implements MethodImplementation { baseAddress = switchLocation.codeAddress; } - List<SwitchLabelElement> labelElements = Lists.newArrayList(); + List<SwitchLabelElement> labelElements = new ArrayList<>(); for (SwitchElement element: switchElements) { labelElements.add(new SwitchLabelElement(element.getKey(), newLabel(codeAddressToIndex, element.getOffset() + baseAddress))); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderArrayPayload.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderArrayPayload.java index a42ee87b..d3cc40cf 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderArrayPayload.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderArrayPayload.java @@ -34,10 +34,10 @@ import com.android.tools.smali.dexlib2.Format; import com.android.tools.smali.dexlib2.Opcode; import com.android.tools.smali.dexlib2.builder.BuilderInstruction; import com.android.tools.smali.dexlib2.iface.instruction.formats.ArrayPayload; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collections; import java.util.List; public class BuilderArrayPayload extends BuilderInstruction implements ArrayPayload { @@ -50,7 +50,7 @@ public class BuilderArrayPayload extends BuilderInstruction implements ArrayPayl @Nullable List<Number> arrayElements) { super(OPCODE); this.elementWidth = elementWidth; - this.arrayElements = arrayElements==null?ImmutableList.<Number>of():arrayElements; + this.arrayElements = arrayElements == null ? Collections.emptyList() : arrayElements; } @Override public int getElementWidth() { return elementWidth; } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderPackedSwitchPayload.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderPackedSwitchPayload.java index cac33505..fd872d15 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderPackedSwitchPayload.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderPackedSwitchPayload.java @@ -35,11 +35,12 @@ import com.android.tools.smali.dexlib2.Opcode; import com.android.tools.smali.dexlib2.builder.BuilderSwitchPayload; import com.android.tools.smali.dexlib2.builder.Label; import com.android.tools.smali.dexlib2.iface.instruction.formats.PackedSwitchPayload; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; import javax.annotation.Nonnull; import javax.annotation.Nullable; + +import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class BuilderPackedSwitchPayload extends BuilderSwitchPayload implements @@ -52,9 +53,9 @@ public class BuilderPackedSwitchPayload extends BuilderSwitchPayload implements @Nullable List<? extends Label> switchElements) { super(OPCODE); if (switchElements == null) { - this.switchElements = ImmutableList.of(); + this.switchElements = Collections.emptyList(); } else { - this.switchElements = Lists.newArrayList(); + this.switchElements = new ArrayList<>(); int key = startKey; for (Label target: switchElements) { this.switchElements.add(new BuilderSwitchElement(this, key++, target)); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderSparseSwitchPayload.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderSparseSwitchPayload.java index 6b4c021b..b1e935cc 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderSparseSwitchPayload.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/builder/instruction/BuilderSparseSwitchPayload.java @@ -35,13 +35,13 @@ import com.android.tools.smali.dexlib2.Opcode; import com.android.tools.smali.dexlib2.builder.BuilderSwitchPayload; import com.android.tools.smali.dexlib2.builder.SwitchLabelElement; import com.android.tools.smali.dexlib2.iface.instruction.formats.SparseSwitchPayload; -import com.google.common.base.Function; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collections; import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; public class BuilderSparseSwitchPayload extends BuilderSwitchPayload implements SparseSwitchPayload { @@ -52,14 +52,14 @@ public class BuilderSparseSwitchPayload extends BuilderSwitchPayload implements public BuilderSparseSwitchPayload(@Nullable List<? extends SwitchLabelElement> switchElements) { super(OPCODE); if (switchElements == null) { - this.switchElements = ImmutableList.of(); + this.switchElements = Collections.emptyList(); } else { - this.switchElements = Lists.transform(switchElements, new Function<SwitchLabelElement, BuilderSwitchElement>() { + this.switchElements = switchElements.stream().map(new Function<SwitchLabelElement, BuilderSwitchElement>() { @Nullable @Override public BuilderSwitchElement apply(@Nullable SwitchLabelElement element) { assert element != null; return new BuilderSwitchElement(BuilderSparseSwitchPayload.this, element.key, element.target); } - }); + }).collect(Collectors.toList()); } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedMethod.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedMethod.java index 84e6e831..3e0327ee 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedMethod.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/DexBackedMethod.java @@ -155,7 +155,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method { } }; } - return unmodifiableList(List.of()); + return Collections.emptyList(); } @Nonnull diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/OatFile.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/OatFile.java index a6011b42..8b41ab8b 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/OatFile.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/OatFile.java @@ -170,11 +170,11 @@ public class OatFile extends DexBuffer implements MultiDexContainer<DexBackedDex @Nonnull public List<String> getBootClassPath() { if (getOatVersion() < 75) { - return Collections.unmodifiableList(List.of()); + return Collections.emptyList(); } String bcp = oatHeader.getKeyValue("bootclasspath"); if (bcp == null) { - return Collections.unmodifiableList(List.of()); + return Collections.emptyList(); } return Arrays.asList(bcp.split(":")); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/instruction/DexBackedArrayPayload.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/instruction/DexBackedArrayPayload.java index ec93d9a3..da4996b0 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/instruction/DexBackedArrayPayload.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/dexbacked/instruction/DexBackedArrayPayload.java @@ -81,7 +81,7 @@ public class DexBackedArrayPayload extends DexBackedInstruction implements Array } if (elementCount == 0) { - return Collections.unmodifiableList(List.of()); + return Collections.emptyList(); } switch (elementWidth) { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableAnnotation.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableAnnotation.java index 7168c397..ca55368b 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableAnnotation.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableAnnotation.java @@ -35,16 +35,16 @@ import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.AnnotationElement; import com.android.tools.smali.util.ImmutableConverter; import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableSet; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.Set; public class ImmutableAnnotation extends BaseAnnotation { protected final int visibility; @Nonnull protected final String type; - @Nonnull protected final ImmutableSet<? extends ImmutableAnnotationElement> elements; + @Nonnull protected final Set<? extends ImmutableAnnotationElement> elements; public ImmutableAnnotation(int visibility, @Nonnull String type, @@ -56,7 +56,7 @@ public class ImmutableAnnotation extends BaseAnnotation { public ImmutableAnnotation(int visibility, @Nonnull String type, - @Nullable ImmutableSet<? extends ImmutableAnnotationElement> elements) { + @Nullable Set<? extends ImmutableAnnotationElement> elements) { this.visibility = visibility; this.type = type; this.elements = ImmutableUtils.nullToEmptySet(elements); @@ -74,10 +74,10 @@ public class ImmutableAnnotation extends BaseAnnotation { @Override public int getVisibility() { return visibility; } @Nonnull @Override public String getType() { return type; } - @Nonnull @Override public ImmutableSet<? extends ImmutableAnnotationElement> getElements() { return elements; } + @Nonnull @Override public Set<? extends ImmutableAnnotationElement> getElements() { return elements; } @Nonnull - public static ImmutableSet<ImmutableAnnotation> immutableSetOf(@Nullable Iterable<? extends Annotation> list) { + public static Set<ImmutableAnnotation> immutableSetOf(@Nullable Iterable<? extends Annotation> list) { return CONVERTER.toSet(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableAnnotationElement.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableAnnotationElement.java index b589b1a7..bb2731e1 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableAnnotationElement.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableAnnotationElement.java @@ -36,10 +36,10 @@ import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import com.android.tools.smali.dexlib2.immutable.value.ImmutableEncodedValue; import com.android.tools.smali.dexlib2.immutable.value.ImmutableEncodedValueFactory; import com.android.tools.smali.util.ImmutableConverter; -import com.google.common.collect.ImmutableSet; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Set; public class ImmutableAnnotationElement extends BaseAnnotationElement { @Nonnull protected final String name; @@ -70,7 +70,7 @@ public class ImmutableAnnotationElement extends BaseAnnotationElement { @Nonnull @Override public EncodedValue getValue() { return value; } @Nonnull - public static ImmutableSet<ImmutableAnnotationElement> immutableSetOf( + public static Set<ImmutableAnnotationElement> immutableSetOf( @Nullable Iterable<? extends AnnotationElement> list) { return CONVERTER.toSet(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableClassDef.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableClassDef.java index 7f70a4ad..34298cd8 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableClassDef.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableClassDef.java @@ -30,6 +30,8 @@ package com.android.tools.smali.dexlib2.immutable; +import static java.util.Collections.unmodifiableList; + import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference; import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.ClassDef; @@ -37,31 +39,32 @@ import com.android.tools.smali.dexlib2.iface.Field; import com.android.tools.smali.dexlib2.iface.Method; import com.android.tools.smali.dexlib2.util.FieldUtil; import com.android.tools.smali.dexlib2.util.MethodUtil; +import com.android.tools.smali.util.ChainedIterator; import com.android.tools.smali.util.ImmutableConverter; import com.android.tools.smali.util.ImmutableUtils; +import com.android.tools.smali.util.IteratorUtils; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.AbstractCollection; +import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; + public class ImmutableClassDef extends BaseTypeReference implements ClassDef { @Nonnull protected final String type; protected final int accessFlags; @Nullable protected final String superclass; - @Nonnull protected final ImmutableList<String> interfaces; + @Nonnull protected final List<String> interfaces; @Nullable protected final String sourceFile; - @Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations; - @Nonnull protected final ImmutableSortedSet<? extends ImmutableField> staticFields; - @Nonnull protected final ImmutableSortedSet<? extends ImmutableField> instanceFields; - @Nonnull protected final ImmutableSortedSet<? extends ImmutableMethod> directMethods; - @Nonnull protected final ImmutableSortedSet<? extends ImmutableMethod> virtualMethods; + @Nonnull protected final Set<? extends ImmutableAnnotation> annotations; + @Nonnull protected final SortedSet<? extends ImmutableField> staticFields; + @Nonnull protected final SortedSet<? extends ImmutableField> instanceFields; + @Nonnull protected final SortedSet<? extends ImmutableMethod> directMethods; + @Nonnull protected final SortedSet<? extends ImmutableMethod> virtualMethods; public ImmutableClassDef(@Nonnull String type, int accessFlags, @@ -72,22 +75,22 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef { @Nullable Iterable<? extends Field> fields, @Nullable Iterable<? extends Method> methods) { if (fields == null) { - fields = ImmutableList.of(); + fields = Collections.emptyList(); } if (methods == null) { - methods = ImmutableList.of(); + methods = Collections.emptyList(); } this.type = type; this.accessFlags = accessFlags; this.superclass = superclass; - this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces); + this.interfaces = interfaces == null ? Collections.emptyList() : unmodifiableList(new ArrayList<>(interfaces)); this.sourceFile = sourceFile; this.annotations = ImmutableAnnotation.immutableSetOf(annotations); - this.staticFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC)); - this.instanceFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_INSTANCE)); - this.directMethods = ImmutableMethod.immutableSetOf(Iterables.filter(methods, MethodUtil.METHOD_IS_DIRECT)); - this.virtualMethods = ImmutableMethod.immutableSetOf(Iterables.filter(methods, MethodUtil.METHOD_IS_VIRTUAL)); + this.staticFields = ImmutableField.immutableSetOf(IteratorUtils.filter(fields, FieldUtil.FIELD_IS_STATIC)); + this.instanceFields = ImmutableField.immutableSetOf(IteratorUtils.filter(fields, FieldUtil.FIELD_IS_INSTANCE)); + this.directMethods = ImmutableMethod.immutableSetOf(IteratorUtils.filter(methods, MethodUtil.METHOD_IS_DIRECT)); + this.virtualMethods = ImmutableMethod.immutableSetOf(IteratorUtils.filter(methods, MethodUtil.METHOD_IS_VIRTUAL)); } public ImmutableClassDef(@Nonnull String type, @@ -103,7 +106,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef { this.type = type; this.accessFlags = accessFlags; this.superclass = superclass; - this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces); + this.interfaces = interfaces == null ? Collections.emptyList() : unmodifiableList(new ArrayList<>(interfaces)); this.sourceFile = sourceFile; this.annotations = ImmutableAnnotation.immutableSetOf(annotations); this.staticFields = ImmutableField.immutableSetOf(staticFields); @@ -115,13 +118,13 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef { public ImmutableClassDef(@Nonnull String type, int accessFlags, @Nullable String superclass, - @Nullable ImmutableList<String> interfaces, + @Nullable List<String> interfaces, @Nullable String sourceFile, - @Nullable ImmutableSet<? extends ImmutableAnnotation> annotations, - @Nullable ImmutableSortedSet<? extends ImmutableField> staticFields, - @Nullable ImmutableSortedSet<? extends ImmutableField> instanceFields, - @Nullable ImmutableSortedSet<? extends ImmutableMethod> directMethods, - @Nullable ImmutableSortedSet<? extends ImmutableMethod> virtualMethods) { + @Nullable Set<? extends ImmutableAnnotation> annotations, + @Nullable SortedSet<? extends ImmutableField> staticFields, + @Nullable SortedSet<? extends ImmutableField> instanceFields, + @Nullable SortedSet<? extends ImmutableMethod> directMethods, + @Nullable SortedSet<? extends ImmutableMethod> virtualMethods) { this.type = type; this.accessFlags = accessFlags; this.superclass = superclass; @@ -154,48 +157,28 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef { @Nonnull @Override public String getType() { return type; } @Override public int getAccessFlags() { return accessFlags; } @Nullable @Override public String getSuperclass() { return superclass; } - @Nonnull @Override public ImmutableList<String> getInterfaces() { return interfaces; } + @Nonnull @Override public List<String> getInterfaces() { return interfaces; } @Nullable @Override public String getSourceFile() { return sourceFile; } - @Nonnull @Override public ImmutableSet<? extends ImmutableAnnotation> getAnnotations() { return annotations; } - @Nonnull @Override public ImmutableSet<? extends ImmutableField> getStaticFields() { return staticFields; } - @Nonnull @Override public ImmutableSet<? extends ImmutableField> getInstanceFields() { return instanceFields; } - @Nonnull @Override public ImmutableSet<? extends ImmutableMethod> getDirectMethods() { return directMethods; } - @Nonnull @Override public ImmutableSet<? extends ImmutableMethod> getVirtualMethods() { return virtualMethods; } + @Nonnull @Override public Set<? extends ImmutableAnnotation> getAnnotations() { return annotations; } + @Nonnull @Override public Set<? extends ImmutableField> getStaticFields() { return staticFields; } + @Nonnull @Override public Set<? extends ImmutableField> getInstanceFields() { return instanceFields; } + @Nonnull @Override public Set<? extends ImmutableMethod> getDirectMethods() { return directMethods; } + @Nonnull @Override public Set<? extends ImmutableMethod> getVirtualMethods() { return virtualMethods; } @Nonnull @Override - public Collection<? extends ImmutableField> getFields() { - return new AbstractCollection<ImmutableField>() { - @Nonnull - @Override - public Iterator<ImmutableField> iterator() { - return Iterators.concat(staticFields.iterator(), instanceFields.iterator()); - } - - @Override public int size() { - return staticFields.size() + instanceFields.size(); - } - }; + public Iterable<? extends ImmutableField> getFields() { + return new ChainedIterator(staticFields, instanceFields); } @Nonnull @Override - public Collection<? extends ImmutableMethod> getMethods() { - return new AbstractCollection<ImmutableMethod>() { - @Nonnull - @Override - public Iterator<ImmutableMethod> iterator() { - return Iterators.concat(directMethods.iterator(), virtualMethods.iterator()); - } - - @Override public int size() { - return directMethods.size() + virtualMethods.size(); - } - }; + public Iterable<? extends ImmutableMethod> getMethods() { + return new ChainedIterator(directMethods, virtualMethods); } @Nonnull - public static ImmutableSet<ImmutableClassDef> immutableSetOf(@Nullable Iterable<? extends ClassDef> iterable) { + public static Set<ImmutableClassDef> immutableSetOf(@Nullable Iterable<? extends ClassDef> iterable) { return CONVERTER.toSet(iterable); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableDexFile.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableDexFile.java index 5c9a40c0..d27fdec0 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableDexFile.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableDexFile.java @@ -34,14 +34,14 @@ import com.android.tools.smali.dexlib2.Opcodes; import com.android.tools.smali.dexlib2.iface.ClassDef; import com.android.tools.smali.dexlib2.iface.DexFile; import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableSet; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.Set; public class ImmutableDexFile implements DexFile { - @Nonnull protected final ImmutableSet<? extends ImmutableClassDef> classes; + @Nonnull protected final Set<? extends ImmutableClassDef> classes; @Nonnull private final Opcodes opcodes; public ImmutableDexFile(@Nonnull Opcodes opcodes, @Nullable Collection<? extends ClassDef> classes) { @@ -49,7 +49,7 @@ public class ImmutableDexFile implements DexFile { this.opcodes = opcodes; } - public ImmutableDexFile(@Nonnull Opcodes opcodes, @Nullable ImmutableSet<? extends ImmutableClassDef> classes) { + public ImmutableDexFile(@Nonnull Opcodes opcodes, @Nullable Set<? extends ImmutableClassDef> classes) { this.classes = ImmutableUtils.nullToEmptySet(classes); this.opcodes = opcodes; } @@ -61,6 +61,6 @@ public class ImmutableDexFile implements DexFile { return new ImmutableDexFile(dexFile.getOpcodes(), dexFile.getClasses()); } - @Nonnull @Override public ImmutableSet<? extends ImmutableClassDef> getClasses() { return classes; } + @Nonnull @Override public Set<? extends ImmutableClassDef> getClasses() { return classes; } @Nonnull @Override public Opcodes getOpcodes() { return opcodes; } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableExceptionHandler.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableExceptionHandler.java index e8cd7fa7..ab8f08cf 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableExceptionHandler.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableExceptionHandler.java @@ -33,10 +33,10 @@ package com.android.tools.smali.dexlib2.immutable; import com.android.tools.smali.dexlib2.base.BaseExceptionHandler; import com.android.tools.smali.dexlib2.iface.ExceptionHandler; import com.android.tools.smali.util.ImmutableConverter; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class ImmutableExceptionHandler extends BaseExceptionHandler implements ExceptionHandler { @Nullable protected final String exceptionType; @@ -61,7 +61,7 @@ public class ImmutableExceptionHandler extends BaseExceptionHandler implements E @Override public int getHandlerCodeAddress() { return handlerCodeAddress; } @Nonnull - public static ImmutableList<ImmutableExceptionHandler> immutableListOf( + public static List<ImmutableExceptionHandler> immutableListOf( @Nullable Iterable<? extends ExceptionHandler> list) { return CONVERTER.toList(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableField.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableField.java index d5cb7fc6..3e32aff3 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableField.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableField.java @@ -30,6 +30,8 @@ package com.android.tools.smali.dexlib2.immutable; +import static java.util.Collections.unmodifiableSet; + import com.android.tools.smali.dexlib2.HiddenApiRestriction; import com.android.tools.smali.dexlib2.base.reference.BaseFieldReference; import com.android.tools.smali.dexlib2.iface.Annotation; @@ -37,16 +39,16 @@ import com.android.tools.smali.dexlib2.iface.Field; import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import com.android.tools.smali.dexlib2.immutable.value.ImmutableEncodedValue; import com.android.tools.smali.dexlib2.immutable.value.ImmutableEncodedValueFactory; +import com.android.tools.smali.util.CollectionUtils; import com.android.tools.smali.util.ImmutableConverter; -import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Ordering; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.Set; +import java.util.SortedSet; public class ImmutableField extends BaseFieldReference implements Field { @Nonnull protected final String definingClass; @@ -54,8 +56,8 @@ public class ImmutableField extends BaseFieldReference implements Field { @Nonnull protected final String type; protected final int accessFlags; @Nullable protected final ImmutableEncodedValue initialValue; - @Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations; - @Nonnull protected final ImmutableSet<HiddenApiRestriction> hiddenApiRestrictions; + @Nonnull protected final Set<? extends ImmutableAnnotation> annotations; + @Nonnull protected final Set<HiddenApiRestriction> hiddenApiRestrictions; public ImmutableField(@Nonnull String definingClass, @Nonnull String name, @@ -70,24 +72,8 @@ public class ImmutableField extends BaseFieldReference implements Field { this.accessFlags = accessFlags; this.initialValue = ImmutableEncodedValueFactory.ofNullable(initialValue); this.annotations = ImmutableAnnotation.immutableSetOf(annotations); - this.hiddenApiRestrictions = - hiddenApiRestrictions == null ? ImmutableSet.of() : ImmutableSet.copyOf(hiddenApiRestrictions); - } - - public ImmutableField(@Nonnull String definingClass, - @Nonnull String name, - @Nonnull String type, - int accessFlags, - @Nullable ImmutableEncodedValue initialValue, - @Nullable ImmutableSet<? extends ImmutableAnnotation> annotations, - @Nullable ImmutableSet<HiddenApiRestriction> hiddenApiRestrictions) { - this.definingClass = definingClass; - this.name = name; - this.type = type; - this.accessFlags = accessFlags; - this.initialValue = initialValue; - this.annotations = ImmutableUtils.nullToEmptySet(annotations); - this.hiddenApiRestrictions = ImmutableUtils.nullToEmptySet(hiddenApiRestrictions); + this.hiddenApiRestrictions = hiddenApiRestrictions == null ? Collections.emptySet() + : unmodifiableSet(new HashSet<>(hiddenApiRestrictions)); } public static ImmutableField of(Field field) { @@ -109,12 +95,12 @@ public class ImmutableField extends BaseFieldReference implements Field { @Nonnull @Override public String getType() { return type; } @Override public int getAccessFlags() { return accessFlags; } @Override public EncodedValue getInitialValue() { return initialValue;} - @Nonnull @Override public ImmutableSet<? extends ImmutableAnnotation> getAnnotations() { return annotations; } + @Nonnull @Override public Set<? extends ImmutableAnnotation> getAnnotations() { return annotations; } @Nonnull @Override public Set<HiddenApiRestriction> getHiddenApiRestrictions() { return hiddenApiRestrictions; } @Nonnull - public static ImmutableSortedSet<ImmutableField> immutableSetOf(@Nullable Iterable<? extends Field> list) { - return CONVERTER.toSortedSet(Ordering.natural(), list); + public static SortedSet<ImmutableField> immutableSetOf(@Nullable Iterable<? extends Field> list) { + return CONVERTER.toSortedSet(CollectionUtils.naturalOrdering(), list); } private static final ImmutableConverter<ImmutableField, Field> CONVERTER = diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethod.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethod.java index 09aa81bc..e38da3aa 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethod.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethod.java @@ -30,31 +30,34 @@ package com.android.tools.smali.dexlib2.immutable; +import static java.util.Collections.unmodifiableSet; + import com.android.tools.smali.dexlib2.HiddenApiRestriction; import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference; import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.Method; import com.android.tools.smali.dexlib2.iface.MethodImplementation; import com.android.tools.smali.dexlib2.iface.MethodParameter; +import com.android.tools.smali.util.CollectionUtils; import com.android.tools.smali.util.ImmutableConverter; import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Ordering; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.SortedSet; public class ImmutableMethod extends BaseMethodReference implements Method { @Nonnull protected final String definingClass; @Nonnull protected final String name; - @Nonnull protected final ImmutableList<? extends ImmutableMethodParameter> parameters; + @Nonnull protected final List<? extends ImmutableMethodParameter> parameters; @Nonnull protected final String returnType; protected final int accessFlags; - @Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations; - @Nonnull protected final ImmutableSet<HiddenApiRestriction> hiddenApiRestrictions; + @Nonnull protected final Set<? extends ImmutableAnnotation> annotations; + @Nonnull protected final Set<HiddenApiRestriction> hiddenApiRestrictions; @Nullable protected final ImmutableMethodImplementation methodImplementation; public ImmutableMethod(@Nonnull String definingClass, @@ -72,17 +75,18 @@ public class ImmutableMethod extends BaseMethodReference implements Method { this.accessFlags = accessFlags; this.annotations = ImmutableAnnotation.immutableSetOf(annotations); this.hiddenApiRestrictions = - hiddenApiRestrictions == null ? ImmutableSet.of() : ImmutableSet.copyOf(hiddenApiRestrictions); + hiddenApiRestrictions == null ? Collections.emptySet() : + unmodifiableSet(new HashSet<>(hiddenApiRestrictions)); this.methodImplementation = ImmutableMethodImplementation.of(methodImplementation); } public ImmutableMethod(@Nonnull String definingClass, @Nonnull String name, - @Nullable ImmutableList<? extends ImmutableMethodParameter> parameters, + @Nullable List<? extends ImmutableMethodParameter> parameters, @Nonnull String returnType, int accessFlags, - @Nullable ImmutableSet<? extends ImmutableAnnotation> annotations, - @Nullable ImmutableSet<HiddenApiRestriction> hiddenApiRestrictions, + @Nullable Set<? extends ImmutableAnnotation> annotations, + @Nullable Set<HiddenApiRestriction> hiddenApiRestrictions, @Nullable ImmutableMethodImplementation methodImplementation) { this.definingClass = definingClass; this.name = name; @@ -111,17 +115,17 @@ public class ImmutableMethod extends BaseMethodReference implements Method { @Override @Nonnull public String getDefiningClass() { return definingClass; } @Override @Nonnull public String getName() { return name; } - @Override @Nonnull public ImmutableList<? extends CharSequence> getParameterTypes() { return parameters; } - @Override @Nonnull public ImmutableList<? extends ImmutableMethodParameter> getParameters() { return parameters; } + @Override @Nonnull public List<? extends CharSequence> getParameterTypes() { return parameters; } + @Override @Nonnull public List<? extends ImmutableMethodParameter> getParameters() { return parameters; } @Override @Nonnull public String getReturnType() { return returnType; } @Override public int getAccessFlags() { return accessFlags; } - @Override @Nonnull public ImmutableSet<? extends ImmutableAnnotation> getAnnotations() { return annotations; } + @Override @Nonnull public Set<? extends ImmutableAnnotation> getAnnotations() { return annotations; } @Nonnull @Override public Set<HiddenApiRestriction> getHiddenApiRestrictions() { return hiddenApiRestrictions; } @Override @Nullable public ImmutableMethodImplementation getImplementation() { return methodImplementation; } @Nonnull - public static ImmutableSortedSet<ImmutableMethod> immutableSetOf(@Nullable Iterable<? extends Method> list) { - return CONVERTER.toSortedSet(Ordering.natural(), list); + public static SortedSet<ImmutableMethod> immutableSetOf(@Nullable Iterable<? extends Method> list) { + return CONVERTER.toSortedSet(CollectionUtils.naturalOrdering(), list); } private static final ImmutableConverter<ImmutableMethod, Method> CONVERTER = diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethodImplementation.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethodImplementation.java index 10bc8333..2fdeba99 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethodImplementation.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethodImplementation.java @@ -38,7 +38,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction; import com.android.tools.smali.dexlib2.immutable.debug.ImmutableDebugItem; import com.android.tools.smali.dexlib2.immutable.instruction.ImmutableInstruction; import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -46,9 +45,9 @@ import java.util.List; public class ImmutableMethodImplementation implements MethodImplementation { protected final int registerCount; - @Nonnull protected final ImmutableList<? extends ImmutableInstruction> instructions; - @Nonnull protected final ImmutableList<? extends ImmutableTryBlock> tryBlocks; - @Nonnull protected final ImmutableList<? extends ImmutableDebugItem> debugItems; + @Nonnull protected final List<? extends ImmutableInstruction> instructions; + @Nonnull protected final List<? extends ImmutableTryBlock> tryBlocks; + @Nonnull protected final List<? extends ImmutableDebugItem> debugItems; public ImmutableMethodImplementation(int registerCount, @Nullable Iterable<? extends Instruction> instructions, @@ -61,9 +60,9 @@ public class ImmutableMethodImplementation implements MethodImplementation { } public ImmutableMethodImplementation(int registerCount, - @Nullable ImmutableList<? extends ImmutableInstruction> instructions, - @Nullable ImmutableList<? extends ImmutableTryBlock> tryBlocks, - @Nullable ImmutableList<? extends ImmutableDebugItem> debugItems) { + @Nullable List<? extends ImmutableInstruction> instructions, + @Nullable List<? extends ImmutableTryBlock> tryBlocks, + @Nullable List<? extends ImmutableDebugItem> debugItems) { this.registerCount = registerCount; this.instructions = ImmutableUtils.nullToEmptyList(instructions); this.tryBlocks = ImmutableUtils.nullToEmptyList(tryBlocks); @@ -86,7 +85,7 @@ public class ImmutableMethodImplementation implements MethodImplementation { } @Override public int getRegisterCount() { return registerCount; } - @Nonnull @Override public ImmutableList<? extends ImmutableInstruction> getInstructions() { return instructions; } - @Nonnull @Override public ImmutableList<? extends ImmutableTryBlock> getTryBlocks() { return tryBlocks; } - @Nonnull @Override public ImmutableList<? extends ImmutableDebugItem> getDebugItems() { return debugItems; } + @Nonnull @Override public List<? extends ImmutableInstruction> getInstructions() { return instructions; } + @Nonnull @Override public List<? extends ImmutableTryBlock> getTryBlocks() { return tryBlocks; } + @Nonnull @Override public List<? extends ImmutableDebugItem> getDebugItems() { return debugItems; } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethodParameter.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethodParameter.java index 37d815dd..8dc0a412 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethodParameter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMethodParameter.java @@ -34,17 +34,15 @@ import com.android.tools.smali.dexlib2.base.BaseMethodParameter; import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.MethodParameter; import com.android.tools.smali.util.ImmutableConverter; -import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; import java.util.Set; public class ImmutableMethodParameter extends BaseMethodParameter { @Nonnull protected final String type; - @Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations; + @Nonnull protected final Set<? extends ImmutableAnnotation> annotations; @Nullable protected final String name; public ImmutableMethodParameter(@Nonnull String type, @@ -55,14 +53,6 @@ public class ImmutableMethodParameter extends BaseMethodParameter { this.name = name; } - public ImmutableMethodParameter(@Nonnull String type, - @Nullable ImmutableSet<? extends ImmutableAnnotation> annotations, - @Nullable String name) { - this.type = type; - this.annotations = ImmutableUtils.nullToEmptySet(annotations); - this.name = name; - } - public static ImmutableMethodParameter of(MethodParameter methodParameter) { if (methodParameter instanceof ImmutableMethodParameter) { return (ImmutableMethodParameter)methodParameter; @@ -81,7 +71,7 @@ public class ImmutableMethodParameter extends BaseMethodParameter { @Nullable @Override public String getSignature() { return null; } @Nonnull - public static ImmutableList<ImmutableMethodParameter> immutableListOf( + public static List<ImmutableMethodParameter> immutableListOf( @Nullable Iterable<? extends MethodParameter> list) { return CONVERTER.toList(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMultiDexContainer.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMultiDexContainer.java index 2077bffe..317ab455 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMultiDexContainer.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableMultiDexContainer.java @@ -30,35 +30,37 @@ package com.android.tools.smali.dexlib2.immutable; +import static java.util.Collections.unmodifiableMap; +import static java.util.Collections.unmodifiableList; + import com.android.tools.smali.dexlib2.iface.MultiDexContainer; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; public class ImmutableMultiDexContainer implements MultiDexContainer<ImmutableDexFile> { - private final ImmutableMap<String, ImmutableDexEntry> entries; + private final Map<String, ImmutableDexEntry> entries; public ImmutableMultiDexContainer(Map<String, ImmutableDexFile> entries) { - ImmutableMap.Builder<String, ImmutableDexEntry> builder = ImmutableMap.builder(); + HashMap<String, ImmutableDexEntry> map = new HashMap<>(); for (Map.Entry<String, ImmutableDexFile> entry : entries.entrySet()) { ImmutableDexEntry dexEntry = new ImmutableDexEntry(entry.getKey(), entry.getValue()); - builder.put(dexEntry.getEntryName(), dexEntry); + map.put(dexEntry.getEntryName(), dexEntry); } - this.entries = builder.build(); + this.entries = unmodifiableMap(map); } - @Nonnull @Override public List<String> getDexEntryNames() { - return ImmutableList.copyOf(entries.keySet()); + return unmodifiableList(new ArrayList<>(entries.keySet())); } @Nullable diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableTryBlock.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableTryBlock.java index 9b7ca4aa..cc60b814 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableTryBlock.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/ImmutableTryBlock.java @@ -34,8 +34,6 @@ import com.android.tools.smali.dexlib2.base.BaseTryBlock; import com.android.tools.smali.dexlib2.iface.ExceptionHandler; import com.android.tools.smali.dexlib2.iface.TryBlock; import com.android.tools.smali.util.ImmutableConverter; -import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -44,7 +42,7 @@ import java.util.List; public class ImmutableTryBlock extends BaseTryBlock<ImmutableExceptionHandler> { protected final int startCodeAddress; protected final int codeUnitCount; - @Nonnull protected final ImmutableList<? extends ImmutableExceptionHandler> exceptionHandlers; + @Nonnull protected final List<? extends ImmutableExceptionHandler> exceptionHandlers; public ImmutableTryBlock(int startCodeAddress, int codeUnitCount, @@ -54,14 +52,6 @@ public class ImmutableTryBlock extends BaseTryBlock<ImmutableExceptionHandler> { this.exceptionHandlers = ImmutableExceptionHandler.immutableListOf(exceptionHandlers); } - public ImmutableTryBlock(int startCodeAddress, - int codeUnitCount, - @Nullable ImmutableList<? extends ImmutableExceptionHandler> exceptionHandlers) { - this.startCodeAddress = startCodeAddress; - this.codeUnitCount = codeUnitCount; - this.exceptionHandlers = ImmutableUtils.nullToEmptyList(exceptionHandlers); - } - public static ImmutableTryBlock of(TryBlock<? extends ExceptionHandler> tryBlock) { if (tryBlock instanceof ImmutableTryBlock) { return (ImmutableTryBlock)tryBlock; @@ -75,12 +65,12 @@ public class ImmutableTryBlock extends BaseTryBlock<ImmutableExceptionHandler> { @Override public int getStartCodeAddress() { return startCodeAddress; } @Override public int getCodeUnitCount() { return codeUnitCount; } - @Nonnull @Override public ImmutableList<? extends ImmutableExceptionHandler> getExceptionHandlers() { + @Nonnull @Override public List<? extends ImmutableExceptionHandler> getExceptionHandlers() { return exceptionHandlers; } @Nonnull - public static ImmutableList<ImmutableTryBlock> immutableListOf( + public static List<ImmutableTryBlock> immutableListOf( @Nullable List<? extends TryBlock<? extends ExceptionHandler>> list) { return CONVERTER.toList(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/README.md b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/README.md new file mode 100644 index 00000000..892ac519 --- /dev/null +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/README.md @@ -0,0 +1,4 @@ +## About +This folder contains classes that originally relied on Guava based Immutable collections, thus the +naming. The current implementations rely on the Java unmodifiable collections or on constructor +helpers that produce immutable collections from Java Collections.
\ No newline at end of file diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/debug/ImmutableDebugItem.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/debug/ImmutableDebugItem.java index 6e7c706d..b119b145 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/debug/ImmutableDebugItem.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/debug/ImmutableDebugItem.java @@ -41,10 +41,10 @@ import com.android.tools.smali.dexlib2.iface.debug.SetSourceFile; import com.android.tools.smali.dexlib2.iface.debug.StartLocal; import com.android.tools.smali.util.ExceptionWithContext; import com.android.tools.smali.util.ImmutableConverter; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public abstract class ImmutableDebugItem implements DebugItem { protected final int codeAddress; @@ -81,7 +81,7 @@ public abstract class ImmutableDebugItem implements DebugItem { @Override public int getCodeAddress() { return codeAddress; } @Nonnull - public static ImmutableList<ImmutableDebugItem> immutableListOf(@Nullable Iterable<? extends DebugItem> list) { + public static List<ImmutableDebugItem> immutableListOf(@Nullable Iterable<? extends DebugItem> list) { return CONVERTER.toList(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableArrayPayload.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableArrayPayload.java index c359a6cf..4f815b24 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableArrayPayload.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableArrayPayload.java @@ -30,36 +30,33 @@ package com.android.tools.smali.dexlib2.immutable.instruction; +import static java.util.Collections.unmodifiableList; + import com.android.tools.smali.dexlib2.Format; import com.android.tools.smali.dexlib2.Opcode; import com.android.tools.smali.dexlib2.util.Preconditions; -import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; + import com.android.tools.smali.dexlib2.iface.instruction.formats.ArrayPayload; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; + public class ImmutableArrayPayload extends ImmutableInstruction implements ArrayPayload { public static final Opcode OPCODE = Opcode.ARRAY_PAYLOAD; protected final int elementWidth; - @Nonnull protected final ImmutableList<Number> arrayElements; + @Nonnull protected final List<Number> arrayElements; - public ImmutableArrayPayload(int elementWidth, - @Nullable List<Number> arrayElements) { + public ImmutableArrayPayload(int elementWidth, @Nullable List<Number> arrayElements) { super(OPCODE); this.elementWidth = Preconditions.checkArrayPayloadElementWidth(elementWidth); this.arrayElements = Preconditions.checkArrayPayloadElements(elementWidth, - arrayElements==null ? ImmutableList.<Number>of() : ImmutableList.copyOf(arrayElements)); - } - - public ImmutableArrayPayload(int elementWidth, - @Nullable ImmutableList<Number> arrayElements) { - super(OPCODE); - this.elementWidth = Preconditions.checkArrayPayloadElementWidth(elementWidth); - this.arrayElements = Preconditions.checkArrayPayloadElements(elementWidth, ImmutableUtils.nullToEmptyList(arrayElements)); + arrayElements == null ? Collections.emptyList() + : unmodifiableList(new ArrayList<>(arrayElements))); } @Nonnull diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableInstruction.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableInstruction.java index fda86fa3..f70dcee1 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableInstruction.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableInstruction.java @@ -71,10 +71,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.SparseSwitchPay import com.android.tools.smali.dexlib2.iface.instruction.formats.UnknownInstruction; import com.android.tools.smali.dexlib2.util.Preconditions; import com.android.tools.smali.util.ImmutableConverter; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.iface.instruction.Instruction; import javax.annotation.Nonnull; +import java.util.List; public abstract class ImmutableInstruction implements Instruction { @Nonnull protected final Opcode opcode; @@ -182,7 +182,7 @@ public abstract class ImmutableInstruction implements Instruction { } @Nonnull - public static ImmutableList<ImmutableInstruction> immutableListOf(Iterable<? extends Instruction> list) { + public static List<ImmutableInstruction> immutableListOf(Iterable<? extends Instruction> list) { return CONVERTER.toList(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutablePackedSwitchPayload.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutablePackedSwitchPayload.java index 5ed73e07..6d68f4b2 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutablePackedSwitchPayload.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutablePackedSwitchPayload.java @@ -34,8 +34,6 @@ import com.android.tools.smali.dexlib2.Format; import com.android.tools.smali.dexlib2.Opcode; import com.android.tools.smali.dexlib2.iface.instruction.formats.PackedSwitchPayload; import com.android.tools.smali.dexlib2.util.Preconditions; -import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.iface.instruction.SwitchElement; import javax.annotation.Nonnull; @@ -46,19 +44,13 @@ public class ImmutablePackedSwitchPayload extends ImmutableInstruction implement PackedSwitchPayload { public static final Opcode OPCODE = Opcode.PACKED_SWITCH_PAYLOAD; - @Nonnull protected final ImmutableList<? extends ImmutableSwitchElement> switchElements; + @Nonnull protected final List<? extends ImmutableSwitchElement> switchElements; public ImmutablePackedSwitchPayload(@Nullable List<? extends SwitchElement> switchElements) { super(OPCODE); this.switchElements = Preconditions.checkSequentialOrderedKeys(ImmutableSwitchElement.immutableListOf(switchElements)); } - public ImmutablePackedSwitchPayload( - @Nullable ImmutableList<? extends ImmutableSwitchElement> switchElements) { - super(OPCODE); - this.switchElements = Preconditions.checkSequentialOrderedKeys(ImmutableUtils.nullToEmptyList(switchElements)); - } - @Nonnull public static ImmutablePackedSwitchPayload of(PackedSwitchPayload instruction) { if (instruction instanceof ImmutablePackedSwitchPayload) { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableSparseSwitchPayload.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableSparseSwitchPayload.java index 43e76ac7..d563f6d0 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableSparseSwitchPayload.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableSparseSwitchPayload.java @@ -33,8 +33,6 @@ package com.android.tools.smali.dexlib2.immutable.instruction; import com.android.tools.smali.dexlib2.Format; import com.android.tools.smali.dexlib2.Opcode; import com.android.tools.smali.dexlib2.iface.instruction.formats.SparseSwitchPayload; -import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.iface.instruction.SwitchElement; import javax.annotation.Nonnull; @@ -45,19 +43,13 @@ public class ImmutableSparseSwitchPayload extends ImmutableInstruction implement SparseSwitchPayload { public static final Opcode OPCODE = Opcode.SPARSE_SWITCH_PAYLOAD; - @Nonnull protected final ImmutableList<? extends ImmutableSwitchElement> switchElements; + @Nonnull protected final List<? extends ImmutableSwitchElement> switchElements; public ImmutableSparseSwitchPayload(@Nullable List<? extends SwitchElement> switchElements) { super(OPCODE); this.switchElements = ImmutableSwitchElement.immutableListOf(switchElements); } - public ImmutableSparseSwitchPayload( - @Nullable ImmutableList<? extends ImmutableSwitchElement> switchElements) { - super(OPCODE); - this.switchElements = ImmutableUtils.nullToEmptyList(switchElements); - } - @Nonnull public static ImmutableSparseSwitchPayload of(SparseSwitchPayload instruction) { if (instruction instanceof ImmutableSparseSwitchPayload) { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableSwitchElement.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableSwitchElement.java index 79e10272..e5a2be46 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableSwitchElement.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/instruction/ImmutableSwitchElement.java @@ -31,7 +31,6 @@ package com.android.tools.smali.dexlib2.immutable.instruction; import com.android.tools.smali.util.ImmutableConverter; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.iface.instruction.SwitchElement; import javax.annotation.Nonnull; @@ -62,7 +61,7 @@ public class ImmutableSwitchElement implements SwitchElement { @Override public int getOffset() { return offset; } @Nonnull - public static ImmutableList<ImmutableSwitchElement> immutableListOf(@Nullable List<? extends SwitchElement> list) { + public static List<ImmutableSwitchElement> immutableListOf(@Nullable List<? extends SwitchElement> list) { return CONVERTER.toList(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableCallSiteReference.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableCallSiteReference.java index 62d969b9..67bcf03a 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableCallSiteReference.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableCallSiteReference.java @@ -31,7 +31,6 @@ package com.android.tools.smali.dexlib2.immutable.reference; import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.base.reference.BaseCallSiteReference; import com.android.tools.smali.dexlib2.iface.reference.CallSiteReference; import com.android.tools.smali.dexlib2.iface.reference.MethodHandleReference; @@ -49,7 +48,7 @@ public class ImmutableCallSiteReference extends BaseCallSiteReference implements @Nonnull protected final ImmutableMethodHandleReference methodHandle; @Nonnull protected final String methodName; @Nonnull protected final ImmutableMethodProtoReference methodProto; - @Nonnull protected final ImmutableList<? extends ImmutableEncodedValue> extraArguments; + @Nonnull protected final List<? extends ImmutableEncodedValue> extraArguments; public ImmutableCallSiteReference(@Nonnull String name, @Nonnull MethodHandleReference methodHandle, @Nonnull String methodName, @Nonnull MethodProtoReference methodProto, @@ -63,7 +62,7 @@ public class ImmutableCallSiteReference extends BaseCallSiteReference implements public ImmutableCallSiteReference(@Nonnull String name, @Nonnull ImmutableMethodHandleReference methodHandle, @Nonnull String methodName, @Nonnull ImmutableMethodProtoReference methodProto, - @Nullable ImmutableList<? extends ImmutableEncodedValue> extraArguments) { + @Nullable List<? extends ImmutableEncodedValue> extraArguments) { this.name = name; this.methodHandle = methodHandle; this.methodName = methodName; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableMethodProtoReference.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableMethodProtoReference.java index 5fe4f0f3..bec5c37f 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableMethodProtoReference.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableMethodProtoReference.java @@ -31,7 +31,6 @@ package com.android.tools.smali.dexlib2.immutable.reference; import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.base.reference.BaseMethodProtoReference; import com.android.tools.smali.dexlib2.iface.reference.MethodProtoReference; import com.android.tools.smali.dexlib2.immutable.util.CharSequenceConverter; @@ -41,10 +40,10 @@ import javax.annotation.Nullable; import java.util.List; public class ImmutableMethodProtoReference extends BaseMethodProtoReference implements ImmutableReference { - @Nonnull protected final ImmutableList<String> parameters; + @Nonnull protected final List<String> parameters; @Nonnull protected final String returnType; - public ImmutableMethodProtoReference(@Nullable ImmutableList<String> parameters, + public ImmutableMethodProtoReference(@Nullable List<String> parameters, @Nonnull String returnType) { this.parameters = ImmutableUtils.nullToEmptyList(parameters); this.returnType = returnType; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableMethodReference.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableMethodReference.java index 842d838d..b81337d9 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableMethodReference.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableMethodReference.java @@ -31,18 +31,18 @@ package com.android.tools.smali.dexlib2.immutable.reference; import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; import com.android.tools.smali.dexlib2.immutable.util.CharSequenceConverter; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class ImmutableMethodReference extends BaseMethodReference implements ImmutableReference { @Nonnull protected final String definingClass; @Nonnull protected final String name; - @Nonnull protected final ImmutableList<String> parameters; + @Nonnull protected final List<String> parameters; @Nonnull protected final String returnType; public ImmutableMethodReference(@Nonnull String definingClass, @@ -57,7 +57,7 @@ public class ImmutableMethodReference extends BaseMethodReference implements Imm public ImmutableMethodReference(@Nonnull String definingClass, @Nonnull String name, - @Nullable ImmutableList<String> parameters, + @Nullable List<String> parameters, @Nonnull String returnType) { this.definingClass = definingClass; this.name = name; @@ -79,7 +79,7 @@ public class ImmutableMethodReference extends BaseMethodReference implements Imm @Nonnull @Override public String getDefiningClass() { return definingClass; } @Nonnull @Override public String getName() { return name; } - @Nonnull @Override public ImmutableList<String> getParameterTypes() { return parameters; } + @Nonnull @Override public List<String> getParameterTypes() { return parameters; } @Nonnull @Override public String getReturnType() { return returnType; } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableTypeReference.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableTypeReference.java index 5560bc1d..f2980f58 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableTypeReference.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/reference/ImmutableTypeReference.java @@ -31,7 +31,7 @@ package com.android.tools.smali.dexlib2.immutable.reference; import com.android.tools.smali.util.ImmutableConverter; -import com.google.common.collect.ImmutableList; + import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference; import com.android.tools.smali.dexlib2.iface.reference.TypeReference; @@ -57,7 +57,7 @@ public class ImmutableTypeReference extends BaseTypeReference implements Immutab @Nonnull @Override public String getType() { return type; } @Nonnull - public static ImmutableList<ImmutableTypeReference> immutableListOf(@Nullable List<? extends TypeReference> list) { + public static List<ImmutableTypeReference> immutableListOf(@Nullable List<? extends TypeReference> list) { return CONVERTER.toList(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/util/CharSequenceConverter.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/util/CharSequenceConverter.java index 09020d01..4f2a27ae 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/util/CharSequenceConverter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/util/CharSequenceConverter.java @@ -31,17 +31,17 @@ package com.android.tools.smali.dexlib2.immutable.util; import com.android.tools.smali.util.ImmutableConverter; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public final class CharSequenceConverter { private CharSequenceConverter() { } @Nonnull - public static ImmutableList<String> immutableStringList(@Nullable Iterable<? extends CharSequence> iterable) { + public static List<String> immutableStringList(@Nullable Iterable<? extends CharSequence> iterable) { return CONVERTER.toList(iterable); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableAnnotationEncodedValue.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableAnnotationEncodedValue.java index b42e73d0..10e83cbd 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableAnnotationEncodedValue.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableAnnotationEncodedValue.java @@ -32,7 +32,6 @@ package com.android.tools.smali.dexlib2.immutable.value; import com.android.tools.smali.dexlib2.iface.AnnotationElement; import com.android.tools.smali.util.ImmutableUtils; -import com.google.common.collect.ImmutableSet; import com.android.tools.smali.dexlib2.base.value.BaseAnnotationEncodedValue; import com.android.tools.smali.dexlib2.iface.value.AnnotationEncodedValue; import com.android.tools.smali.dexlib2.immutable.ImmutableAnnotationElement; @@ -40,10 +39,11 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableAnnotationElement; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.Set; public class ImmutableAnnotationEncodedValue extends BaseAnnotationEncodedValue implements ImmutableEncodedValue { @Nonnull protected final String type; - @Nonnull protected final ImmutableSet<? extends ImmutableAnnotationElement> elements; + @Nonnull protected final Set<? extends ImmutableAnnotationElement> elements; public ImmutableAnnotationEncodedValue(@Nonnull String type, @Nullable Collection<? extends AnnotationElement> elements) { @@ -52,7 +52,7 @@ public class ImmutableAnnotationEncodedValue extends BaseAnnotationEncodedValue } public ImmutableAnnotationEncodedValue(@Nonnull String type, - @Nullable ImmutableSet<? extends ImmutableAnnotationElement> elements) { + @Nullable Set<? extends ImmutableAnnotationElement> elements) { this.type = type; this.elements = ImmutableUtils.nullToEmptySet(elements); } @@ -67,5 +67,5 @@ public class ImmutableAnnotationEncodedValue extends BaseAnnotationEncodedValue } @Nonnull @Override public String getType() { return type; } - @Nonnull @Override public ImmutableSet<? extends ImmutableAnnotationElement> getElements() { return elements; } + @Nonnull @Override public Set<? extends ImmutableAnnotationElement> getElements() { return elements; } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableArrayEncodedValue.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableArrayEncodedValue.java index d9025930..cf27be16 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableArrayEncodedValue.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableArrayEncodedValue.java @@ -30,22 +30,22 @@ package com.android.tools.smali.dexlib2.immutable.value; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.base.value.BaseArrayEncodedValue; import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue; import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import javax.annotation.Nonnull; import java.util.Collection; +import java.util.List; public class ImmutableArrayEncodedValue extends BaseArrayEncodedValue implements ImmutableEncodedValue { - @Nonnull protected final ImmutableList<? extends ImmutableEncodedValue> value; + @Nonnull protected final List<? extends ImmutableEncodedValue> value; public ImmutableArrayEncodedValue(@Nonnull Collection<? extends EncodedValue> value) { this.value = ImmutableEncodedValueFactory.immutableListOf(value); } - public ImmutableArrayEncodedValue(@Nonnull ImmutableList<ImmutableEncodedValue> value) { + public ImmutableArrayEncodedValue(@Nonnull List<ImmutableEncodedValue> value) { this.value = value; } @@ -56,5 +56,5 @@ public class ImmutableArrayEncodedValue extends BaseArrayEncodedValue implements return new ImmutableArrayEncodedValue(arrayEncodedValue.getValue()); } - @Nonnull public ImmutableList<? extends ImmutableEncodedValue> getValue() { return value; } + @Nonnull public List<? extends ImmutableEncodedValue> getValue() { return value; } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableEncodedValueFactory.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableEncodedValueFactory.java index e458a1e1..1159b60b 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableEncodedValueFactory.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/immutable/value/ImmutableEncodedValueFactory.java @@ -51,11 +51,10 @@ import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue; import com.android.tools.smali.dexlib2.iface.value.TypeEncodedValue; import com.android.tools.smali.util.ExceptionWithContext; import com.android.tools.smali.util.ImmutableConverter; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class ImmutableEncodedValueFactory { @Nonnull @@ -98,8 +97,7 @@ public class ImmutableEncodedValueFactory { case ValueType.METHOD_TYPE: return ImmutableMethodTypeEncodedValue.of((MethodTypeEncodedValue) encodedValue); default: - Preconditions.checkArgument(false); - return null; + throw new IllegalArgumentException("Invalid value type."); } } @@ -139,7 +137,7 @@ public class ImmutableEncodedValueFactory { } @Nonnull - public static ImmutableList<ImmutableEncodedValue> immutableListOf + public static List<ImmutableEncodedValue> immutableListOf (@Nullable Iterable<? extends EncodedValue> list) { return CONVERTER.toList(list); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/CallSiteReferenceRewriter.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/CallSiteReferenceRewriter.java index d19cebfa..439ff769 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/CallSiteReferenceRewriter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/CallSiteReferenceRewriter.java @@ -30,8 +30,6 @@ package com.android.tools.smali.dexlib2.rewriter; -import com.google.common.base.Function; -import com.google.common.collect.Lists; import com.android.tools.smali.dexlib2.base.reference.BaseCallSiteReference; import com.android.tools.smali.dexlib2.iface.reference.CallSiteReference; import com.android.tools.smali.dexlib2.iface.reference.MethodHandleReference; @@ -40,6 +38,8 @@ import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import javax.annotation.Nonnull; import java.util.List; +import java.util.stream.Collectors; +import java.util.function.Function; public class CallSiteReferenceRewriter implements Rewriter<CallSiteReference> { @Nonnull protected final Rewriters rewriters; @@ -79,12 +79,11 @@ public class CallSiteReferenceRewriter implements Rewriter<CallSiteReference> { } @Override @Nonnull public List<? extends EncodedValue> getExtraArguments() { - return Lists.transform(callSiteReference.getExtraArguments(), - new Function<EncodedValue, EncodedValue>() { - @Nonnull @Override public EncodedValue apply(EncodedValue encodedValue) { - return RewriterUtils.rewriteValue(rewriters, encodedValue); - } - }); + return callSiteReference.getExtraArguments().stream().map(new Function<EncodedValue, EncodedValue>() { + @Nonnull @Override public EncodedValue apply(EncodedValue encodedValue) { + return RewriterUtils.rewriteValue(rewriters, encodedValue); + } + }).collect(Collectors.toList()); } } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/ClassDefRewriter.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/ClassDefRewriter.java index 6117d348..27d2c873 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/ClassDefRewriter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/ClassDefRewriter.java @@ -35,7 +35,7 @@ import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.ClassDef; import com.android.tools.smali.dexlib2.iface.Field; import com.android.tools.smali.dexlib2.iface.Method; -import com.google.common.collect.Iterators; +import com.android.tools.smali.util.ChainedIterator; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -100,7 +100,8 @@ public class ClassDefRewriter implements Rewriter<ClassDef> { @Nonnull @Override public Iterator<Field> iterator() { - return Iterators.concat(getStaticFields().iterator(), getInstanceFields().iterator()); + return new ChainedIterator( + getStaticFields().iterator(), getInstanceFields().iterator()); } }; } @@ -120,7 +121,8 @@ public class ClassDefRewriter implements Rewriter<ClassDef> { @Nonnull @Override public Iterator<Method> iterator() { - return Iterators.concat(getDirectMethods().iterator(), getVirtualMethods().iterator()); + return new ChainedIterator( + getDirectMethods().iterator(), getVirtualMethods().iterator()); } }; } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/MethodReferenceRewriter.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/MethodReferenceRewriter.java index c7b1d8cc..b4209d85 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/MethodReferenceRewriter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/MethodReferenceRewriter.java @@ -32,11 +32,11 @@ package com.android.tools.smali.dexlib2.rewriter; import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; -import com.google.common.base.Function; -import com.google.common.collect.Lists; import javax.annotation.Nonnull; import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; public class MethodReferenceRewriter implements Rewriter<MethodReference> { @Nonnull protected final Rewriters rewriters; @@ -66,12 +66,12 @@ public class MethodReferenceRewriter implements Rewriter<MethodReference> { @Override @Nonnull public List<? extends CharSequence> getParameterTypes() { return RewriterUtils.rewriteList(rewriters.getTypeRewriter(), - Lists.transform(methodReference.getParameterTypes(), + methodReference.getParameterTypes().stream().map( new Function<CharSequence, String>() { @Nonnull @Override public String apply(CharSequence input) { return input.toString(); } - })); + }).collect(Collectors.toList())); } @Override @Nonnull public String getReturnType() { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/RewriterUtils.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/RewriterUtils.java index 652eb46e..a9978b6d 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/RewriterUtils.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/rewriter/RewriterUtils.java @@ -53,14 +53,14 @@ import com.android.tools.smali.dexlib2.iface.value.MethodEncodedValue; import com.android.tools.smali.dexlib2.iface.value.MethodHandleEncodedValue; import com.android.tools.smali.dexlib2.iface.value.MethodTypeEncodedValue; import com.android.tools.smali.dexlib2.iface.value.TypeEncodedValue; -import com.google.common.base.Function; -import com.google.common.collect.Lists; import java.util.AbstractList; import java.util.AbstractSet; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -183,12 +183,11 @@ public class RewriterUtils { return new BaseMethodProtoReference() { @Nonnull @Override public List<? extends CharSequence> getParameterTypes() { return rewriteList(typeRewriter, - Lists.transform(methodProtoReference.getParameterTypes(), + methodProtoReference.getParameterTypes().stream().map( new Function<CharSequence, String>() { @Nonnull @Override public String apply(CharSequence input) { return input.toString(); - } - })); + }}).collect(Collectors.toList())); } @Nonnull @Override public String getReturnType() { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/AnnotatedBytes.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/AnnotatedBytes.java index 9b8e7f62..7fd0c4f6 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/AnnotatedBytes.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/AnnotatedBytes.java @@ -30,18 +30,16 @@ package com.android.tools.smali.dexlib2.util; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - import com.android.tools.smali.util.ExceptionWithContext; import com.android.tools.smali.util.Hex; +import com.android.tools.smali.util.StringUtils; import com.android.tools.smali.util.TwoColumnOutput; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; import java.io.Writer; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -65,7 +63,7 @@ public class AnnotatedBytes { * is the exclusive end point. The range annotation for a range is associated with the first key for that range. * The point annotations for a point are associated with the key at that point. */ - @Nonnull private TreeMap<Integer, AnnotationEndpoint> annotatations = Maps.newTreeMap(); + @Nonnull private TreeMap<Integer, AnnotationEndpoint> annotatations = new TreeMap<>(); private int cursor; private int indentLevel; @@ -250,7 +248,7 @@ public class AnnotatedBytes { private static class AnnotationEndpoint { /** Annotations that are associated with a specific point between bytes */ @Nonnull - public final List<AnnotationItem> pointAnnotations = Lists.newArrayList(); + public final List<AnnotationItem> pointAnnotations = new ArrayList<>(); /** Annotations that are associated with a range of bytes */ @Nullable public AnnotationItem rangeAnnotation = null; @@ -284,7 +282,7 @@ public class AnnotatedBytes { int rightWidth = getAnnotationWidth(); int leftWidth = outputWidth - rightWidth - 1; - String padding = Strings.repeat(" ", 1000); + String padding = StringUtils.repeat(" ", 1000); TwoColumnOutput twoc = new TwoColumnOutput(out, leftWidth, rightWidth, "|"); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/FieldUtil.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/FieldUtil.java index a543b695..835d8a7f 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/FieldUtil.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/FieldUtil.java @@ -31,21 +31,21 @@ package com.android.tools.smali.dexlib2.util; import com.android.tools.smali.dexlib2.iface.Field; -import com.google.common.base.Predicate; import com.android.tools.smali.dexlib2.AccessFlags; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.function.Predicate; public final class FieldUtil { public static Predicate<Field> FIELD_IS_STATIC = new Predicate<Field>() { - @Override public boolean apply(@Nullable Field input) { + @Override public boolean test(@Nullable Field input) { return input!=null && isStatic(input); } }; public static Predicate<Field> FIELD_IS_INSTANCE = new Predicate<Field>() { - @Override public boolean apply(@Nullable Field input) { + @Override public boolean test(@Nullable Field input) { return input!= null && !isStatic(input); } }; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/MethodUtil.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/MethodUtil.java index 2c9812ae..848544a3 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/MethodUtil.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/MethodUtil.java @@ -30,7 +30,6 @@ package com.android.tools.smali.dexlib2.util; -import com.google.common.base.Predicate; import com.android.tools.smali.dexlib2.AccessFlags; import com.android.tools.smali.dexlib2.iface.Method; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; @@ -39,19 +38,20 @@ import com.android.tools.smali.util.CharSequenceUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.function.Predicate; public final class MethodUtil { private static int directMask = AccessFlags.STATIC.getValue() | AccessFlags.PRIVATE.getValue() | AccessFlags.CONSTRUCTOR.getValue(); public static Predicate<Method> METHOD_IS_DIRECT = new Predicate<Method>() { - @Override public boolean apply(@Nullable Method input) { + @Override public boolean test(@Nullable Method input) { return input != null && isDirect(input); } }; public static Predicate<Method> METHOD_IS_VIRTUAL = new Predicate<Method>() { - @Override public boolean apply(@Nullable Method input) { + @Override public boolean test(@Nullable Method input) { return input != null && !isDirect(input); } }; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/SyntheticAccessorResolver.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/SyntheticAccessorResolver.java index dadc9f64..543f2c08 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/SyntheticAccessorResolver.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/util/SyntheticAccessorResolver.java @@ -33,20 +33,22 @@ package com.android.tools.smali.dexlib2.util; import com.android.tools.smali.dexlib2.iface.ClassDef; import com.android.tools.smali.dexlib2.iface.Method; import com.android.tools.smali.dexlib2.iface.MethodImplementation; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import com.android.tools.smali.dexlib2.AccessFlags; import com.android.tools.smali.dexlib2.Opcodes; import com.android.tools.smali.dexlib2.iface.instruction.Instruction; import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; import com.android.tools.smali.dexlib2.iface.reference.Reference; +import com.android.tools.smali.util.IteratorUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; + +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class SyntheticAccessorResolver { public static final int METHOD = 0; @@ -70,17 +72,17 @@ public class SyntheticAccessorResolver { private final SyntheticAccessorFSM syntheticAccessorFSM; private final Map<String, ClassDef> classDefMap; - private final Map<MethodReference, AccessedMember> resolvedAccessors = Maps.newConcurrentMap(); + private final Map<MethodReference, AccessedMember> resolvedAccessors = new ConcurrentHashMap<>(); public SyntheticAccessorResolver(@Nonnull Opcodes opcodes, @Nonnull Iterable<? extends ClassDef> classDefs) { this.syntheticAccessorFSM = new SyntheticAccessorFSM(opcodes); - ImmutableMap.Builder<String, ClassDef> builder = ImmutableMap.builder(); + HashMap<String, ClassDef> classDefMap = new HashMap<>(); for (ClassDef classDef: classDefs) { - builder.put(classDef.getType(), classDef); + classDefMap.put(classDef.getType(), classDef); } - this.classDefMap = builder.build(); + this.classDefMap = Collections.unmodifiableMap(classDefMap); } public static boolean looksLikeSyntheticAccessor(String methodName) { @@ -122,7 +124,8 @@ public class SyntheticAccessorResolver { return null; } - List<Instruction> instructions = ImmutableList.copyOf(matchedMethodImpl.getInstructions()); + List<Instruction> instructions = Collections.unmodifiableList( + IteratorUtils.toList(matchedMethodImpl.getInstructions())); int accessType = syntheticAccessorFSM.test(instructions); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/DebugInfoCache.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/DebugInfoCache.java new file mode 100644 index 00000000..6bdfe55e --- /dev/null +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/DebugInfoCache.java @@ -0,0 +1,30 @@ +package com.android.tools.smali.dexlib2.writer; + +import java.util.Arrays; + +public class DebugInfoCache { + private final byte[] data; + private final int threshold = 128; + + public DebugInfoCache(byte[] data) { + this.data = data; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DebugInfoCache that = (DebugInfoCache) o; + return Arrays.equals(data, that.data); + } + + @Override + public int hashCode() { + int hashSize = Math.min(data.length, threshold); + int result = 0; + for (int i = 0; i < hashSize; i++) { + result = 31 * result + data[i]; + } + return result; + } +} diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/DexWriter.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/DexWriter.java index 205ca2fe..3e28b388 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/DexWriter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/DexWriter.java @@ -90,11 +90,6 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodProtoReference; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; import com.android.tools.smali.dexlib2.iface.reference.StringReference; import com.android.tools.smali.dexlib2.iface.reference.TypeReference; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Ordering; -import com.google.common.primitives.Ints; import com.android.tools.smali.dexlib2.base.BaseAnnotation; import com.android.tools.smali.dexlib2.base.BaseAnnotationElement; import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation; @@ -116,8 +111,12 @@ import com.android.tools.smali.dexlib2.writer.io.DeferredOutputStreamFactory; import com.android.tools.smali.dexlib2.writer.io.DexDataStore; import com.android.tools.smali.dexlib2.writer.io.MemoryDeferredOutputStream; import com.android.tools.smali.dexlib2.writer.util.TryListBuilder; +import com.android.tools.smali.util.ChainedIterator; +import com.android.tools.smali.util.CollectionUtils; import com.android.tools.smali.util.ExceptionWithContext; +import com.android.tools.smali.util.IteratorUtils; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -223,6 +222,8 @@ public abstract class DexWriter< private final IndexSection<?>[] overflowableSections; + private final Map<DebugInfoCache, Integer> debugInfoCaches = new HashMap<>(); + protected DexWriter(Opcodes opcodes) { this.opcodes = opcodes; @@ -263,7 +264,7 @@ public abstract class DexWriter< public int compare(Entry<? extends CallSiteKey, Integer> o1, Entry<? extends CallSiteKey, Integer> o2) { int offset1 = encodedArraySection.getItemOffset(callSiteSection.getEncodedCallSite(o1.getKey())); int offset2 = encodedArraySection.getItemOffset(callSiteSection.getEncodedCallSite(o2.getKey())); - return Ints.compare(offset1, offset2); + return Integer.compare(offset1, offset2); } }; @@ -316,7 +317,7 @@ public abstract class DexWriter< @Nonnull public List<String> getMethodReferences() { - List<String> methodReferences = Lists.newArrayList(); + List<String> methodReferences = new ArrayList<>(); for (Entry<? extends MethodRefKey, Integer> methodReference: methodSection.getItems()) { methodReferences.add(DexFormatter.INSTANCE.getMethodDescriptor(methodReference.getKey())); } @@ -325,7 +326,7 @@ public abstract class DexWriter< @Nonnull public List<String> getFieldReferences() { - List<String> fieldReferences = Lists.newArrayList(); + List<String> fieldReferences = new ArrayList<>(); for (Entry<? extends FieldRefKey, Integer> fieldReference: fieldSection.getItems()) { fieldReferences.add(DexFormatter.INSTANCE.getFieldDescriptor(fieldReference.getKey())); } @@ -334,7 +335,7 @@ public abstract class DexWriter< @Nonnull public List<String> getTypeReferences() { - List<String> classReferences = Lists.newArrayList(); + List<String> classReferences = new ArrayList<>(); for (Entry<? extends TypeKey, Integer> typeReference: typeSection.getItems()) { classReferences.add(typeReference.getKey().toString()); } @@ -470,7 +471,7 @@ public abstract class DexWriter< stringIndexSectionOffset = indexWriter.getPosition(); stringDataSectionOffset = offsetWriter.getPosition(); int index = 0; - List<Entry<? extends StringKey, Integer>> stringEntries = Lists.newArrayList(stringSection.getItems()); + List<Entry<? extends StringKey, Integer>> stringEntries = new ArrayList<>(stringSection.getItems()); Collections.sort(stringEntries, toStringKeyComparator); for (Map.Entry<? extends StringKey, Integer> entry: stringEntries) { @@ -487,7 +488,7 @@ public abstract class DexWriter< typeSectionOffset = writer.getPosition(); int index = 0; - List<Map.Entry<? extends TypeKey, Integer>> typeEntries = Lists.newArrayList(typeSection.getItems()); + List<Map.Entry<? extends TypeKey, Integer>> typeEntries = new ArrayList<>(typeSection.getItems()); Collections.sort(typeEntries, toStringKeyComparator); for (Map.Entry<? extends TypeKey, Integer> entry : typeEntries) { @@ -500,7 +501,7 @@ public abstract class DexWriter< protoSectionOffset = writer.getPosition(); int index = 0; - List<Map.Entry<? extends ProtoRefKey, Integer>> protoEntries = Lists.newArrayList(protoSection.getItems()); + List<Map.Entry<? extends ProtoRefKey, Integer>> protoEntries = new ArrayList<>(protoSection.getItems()); Collections.sort(protoEntries, DexWriter.<ProtoRefKey>comparableKeyComparator()); for (Map.Entry<? extends ProtoRefKey, Integer> entry: protoEntries) { @@ -516,7 +517,7 @@ public abstract class DexWriter< fieldSectionOffset = writer.getPosition(); int index = 0; - List<Map.Entry<? extends FieldRefKey, Integer>> fieldEntries = Lists.newArrayList(fieldSection.getItems()); + List<Map.Entry<? extends FieldRefKey, Integer>> fieldEntries = new ArrayList<>(fieldSection.getItems()); Collections.sort(fieldEntries, DexWriter.<FieldRefKey>comparableKeyComparator()); for (Map.Entry<? extends FieldRefKey, Integer> entry: fieldEntries) { @@ -532,7 +533,7 @@ public abstract class DexWriter< methodSectionOffset = writer.getPosition(); int index = 0; - List<Map.Entry<? extends MethodRefKey, Integer>> methodEntries = Lists.newArrayList(methodSection.getItems()); + List<Map.Entry<? extends MethodRefKey, Integer>> methodEntries = new ArrayList<>(methodSection.getItems()); Collections.sort(methodEntries, DexWriter.<MethodRefKey>comparableKeyComparator()); for (Map.Entry<? extends MethodRefKey, Integer> entry: methodEntries) { @@ -549,7 +550,7 @@ public abstract class DexWriter< classIndexSectionOffset = indexWriter.getPosition(); classDataSectionOffset = offsetWriter.getPosition(); - List<Map.Entry<? extends ClassKey, Integer>> classEntriesKeySorted = Lists.newArrayList(classSection.getItems()); + List<Map.Entry<? extends ClassKey, Integer>> classEntriesKeySorted = new ArrayList<>(classSection.getItems()); Collections.sort(classEntriesKeySorted, DexWriter.<ClassKey>comparableKeyComparator()); int index = 0; @@ -564,7 +565,7 @@ public abstract class DexWriter< offsetWriter.align(); hiddenApiRestrictionsOffset = offsetWriter.getPosition(); - List<Map.Entry<? extends ClassKey, Integer>> classEntriesValueSorted = Lists.newArrayList(classSection.getItems()); + List<Map.Entry<? extends ClassKey, Integer>> classEntriesValueSorted = new ArrayList<>(classSection.getItems()); classEntriesValueSorted.sort(DexWriter.comparableValueComparator()); RestrictionsWriter restrictionsWriter = new RestrictionsWriter(dataStore, offsetWriter, classEntriesValueSorted.size()); @@ -765,7 +766,7 @@ public abstract class DexWriter< callSiteSectionOffset = writer.getPosition(); List<Map.Entry<? extends CallSiteKey, Integer>> callSiteEntries = - Lists.newArrayList(callSiteSection.getItems()); + new ArrayList<>(callSiteSection.getItems()); Collections.sort(callSiteEntries, callSiteComparator); int index = 0; @@ -883,8 +884,8 @@ public abstract class DexWriter< writer.writeUbyte(annotationSection.getVisibility(key)); writer.writeUleb128(typeSection.getItemIndex(annotationSection.getType(key))); - Collection<? extends AnnotationElement> elements = Ordering.from(BaseAnnotationElement.BY_NAME) - .immutableSortedCopy(annotationSection.getElements(key)); + Collection<? extends AnnotationElement> elements = CollectionUtils.immutableSortedCopy( + annotationSection.getElements(key), BaseAnnotationElement.BY_NAME); writer.writeUleb128(elements.size()); @@ -902,9 +903,9 @@ public abstract class DexWriter< writer.writeInt(0); } for (Map.Entry<? extends AnnotationSetKey, Integer> entry: annotationSetSection.getItems()) { - Collection<? extends AnnotationKey> annotations = Ordering.from(BaseAnnotation.BY_TYPE) - .immutableSortedCopy(annotationSetSection.getAnnotations(entry.getKey())); - + Collection<? extends AnnotationKey> annotations = CollectionUtils.immutableSortedCopy( + annotationSetSection.getAnnotations(entry.getKey()), BaseAnnotation.BY_TYPE); + writer.align(); entry.setValue(writer.getPosition()); writer.writeInt(annotations.size()); @@ -917,7 +918,7 @@ public abstract class DexWriter< private void writeAnnotationSetRefs(@Nonnull DexDataWriter writer) throws IOException { writer.align(); annotationSetRefSectionOffset = writer.getPosition(); - HashMap<List<? extends AnnotationSetKey>, Integer> internedItems = Maps.newHashMap(); + HashMap<List<? extends AnnotationSetKey>, Integer> internedItems = new HashMap<>(); for (ClassKey classKey: classSection.getSortedClasses()) { for (MethodKey methodKey: classSection.getSortedMethods(classKey)) { @@ -953,7 +954,7 @@ public abstract class DexWriter< private void writeAnnotationDirectories(@Nonnull DexDataWriter writer) throws IOException { writer.align(); annotationDirectorySectionOffset = writer.getPosition(); - HashMap<AnnotationSetKey, Integer> internedItems = Maps.newHashMap(); + HashMap<AnnotationSetKey, Integer> internedItems = new HashMap<>(); ByteBuffer tempBuffer = ByteBuffer.allocate(65536); tempBuffer.order(ByteOrder.LITTLE_ENDIAN); @@ -1049,18 +1050,17 @@ public abstract class DexWriter< @Nonnull DeferredOutputStream temp) throws IOException { ByteArrayOutputStream ehBuf = new ByteArrayOutputStream(); debugSectionOffset = offsetWriter.getPosition(); - DebugWriter<StringKey, TypeKey> debugWriter = - new DebugWriter<StringKey, TypeKey>(stringSection, typeSection, offsetWriter); DexDataWriter codeWriter = new DexDataWriter(temp, 0); - List<CodeItemOffset<MethodKey>> codeOffsets = Lists.newArrayList(); + List<CodeItemOffset<MethodKey>> codeOffsets = new ArrayList<>(); for (ClassKey classKey: classSection.getSortedClasses()) { Collection<? extends MethodKey> directMethods = classSection.getSortedDirectMethods(classKey); Collection<? extends MethodKey> virtualMethods = classSection.getSortedVirtualMethods(classKey); - Iterable<MethodKey> methods = Iterables.concat(directMethods, virtualMethods); + Iterable<MethodKey> methods = new ChainedIterator<MethodKey>( + (Collection<MethodKey>)directMethods, (Collection<MethodKey>)virtualMethods); for (MethodKey methodKey: methods) { List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = @@ -1091,8 +1091,7 @@ public abstract class DexWriter< } } - int debugItemOffset = writeDebugItem(offsetWriter, debugWriter, - classSection.getParameterNames(methodKey), debugItems); + int debugItemOffset = writeDebugItem(offsetWriter, classSection.getParameterNames(methodKey), debugItems); int codeItemOffset; try { codeItemOffset = writeCodeItem( @@ -1138,13 +1137,12 @@ public abstract class DexWriter< } private int writeDebugItem(@Nonnull DexDataWriter writer, - @Nonnull DebugWriter<StringKey, TypeKey> debugWriter, @Nullable Iterable<? extends StringKey> parameterNames, @Nullable Iterable<? extends DebugItem> debugItems) throws IOException { int parameterCount = 0; int lastNamedParameterIndex = -1; if (parameterNames != null) { - parameterCount = Iterables.size(parameterNames); + parameterCount = IteratorUtils.size(parameterNames); int index = 0; for (StringKey parameterName: parameterNames) { if (parameterName != null) { @@ -1155,12 +1153,11 @@ public abstract class DexWriter< } - if (lastNamedParameterIndex == -1 && (debugItems == null || Iterables.isEmpty(debugItems))) { + if (lastNamedParameterIndex == -1 && (debugItems == null + || !debugItems.iterator().hasNext())) { return NO_OFFSET; } - numDebugInfoItems++; - int debugItemOffset = writer.getPosition(); int startingLineNumber = 0; @@ -1172,9 +1169,14 @@ public abstract class DexWriter< } } } - writer.writeUleb128(startingLineNumber); - writer.writeUleb128(parameterCount); + ByteArrayOutputStream tempByteOutput = new ByteArrayOutputStream(); + DexDataWriter tempDataWriter = new DexDataWriter(tempByteOutput, 0, 64); + DebugWriter tempDebugWriter = new DebugWriter(stringSection, typeSection, tempDataWriter); + + tempDataWriter.writeUleb128(startingLineNumber); + + tempDataWriter.writeUleb128(parameterCount); if (parameterNames != null) { int index = 0; for (StringKey parameterName: parameterNames) { @@ -1182,21 +1184,32 @@ public abstract class DexWriter< break; } index++; - writer.writeUleb128(stringSection.getNullableItemIndex(parameterName) + 1); + tempDataWriter.writeUleb128(stringSection.getNullableItemIndex(parameterName) + 1); } } if (debugItems != null) { - debugWriter.reset(startingLineNumber); + tempDebugWriter.reset(startingLineNumber); for (DebugItem debugItem: debugItems) { - classSection.writeDebugItem(debugWriter, debugItem); + classSection.writeDebugItem(tempDebugWriter, debugItem); } } // write an END_SEQUENCE opcode, to end the debug item - writer.write(0); - - return debugItemOffset; + tempDataWriter.write(0); + + tempDataWriter.flush(); + byte[] debugInfo = tempByteOutput.toByteArray(); + DebugInfoCache wrapBytes = new DebugInfoCache(debugInfo); + int cacheBytes = debugInfoCaches.getOrDefault(wrapBytes, -1); + if (cacheBytes >= 0) { + return cacheBytes; + } else { + writer.write(debugInfo); + debugInfoCaches.put(wrapBytes, debugItemOffset); + numDebugInfoItems++; + return debugItemOffset; + } } private int writeCodeItem(@Nonnull DexDataWriter writer, @@ -1381,7 +1394,7 @@ public abstract class DexWriter< writer.align(); // filter out unique lists of exception handlers - Map<List<? extends ExceptionHandler>, Integer> exceptionHandlerOffsetMap = Maps.newHashMap(); + Map<List<? extends ExceptionHandler>, Integer> exceptionHandlerOffsetMap = new HashMap<>(); for (TryBlock<? extends ExceptionHandler> tryBlock: tryBlocks) { exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), 0); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/EncodedValueWriter.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/EncodedValueWriter.java index 77c647b5..890a13ac 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/EncodedValueWriter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/EncodedValueWriter.java @@ -30,16 +30,19 @@ package com.android.tools.smali.dexlib2.writer; -import com.google.common.collect.Ordering; import com.android.tools.smali.dexlib2.ValueType; import com.android.tools.smali.dexlib2.base.BaseAnnotationElement; import com.android.tools.smali.dexlib2.iface.reference.FieldReference; import com.android.tools.smali.dexlib2.iface.reference.MethodHandleReference; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; +import com.android.tools.smali.util.CollectionUtils; import javax.annotation.Nonnull; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Collection; +import java.util.Collections; public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, AnnotationElement extends com.android.tools.smali.dexlib2.iface.AnnotationElement, @@ -80,8 +83,8 @@ public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends writer.writeUleb128(typeSection.getItemIndex(annotationType)); writer.writeUleb128(elements.size()); - Collection<? extends AnnotationElement> sortedElements = Ordering.from(BaseAnnotationElement.BY_NAME) - .immutableSortedCopy(elements); + List<? extends AnnotationElement> sortedElements = CollectionUtils.immutableSortedCopy( + elements, BaseAnnotationElement.BY_NAME); for (AnnotationElement element: sortedElements) { writer.writeUleb128(stringSection.getItemIndex(annotationSection.getElementName(element))); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/InstructionWriter.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/InstructionWriter.java index 0aa674f3..795e9315 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/InstructionWriter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/InstructionWriter.java @@ -74,18 +74,19 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference; import com.android.tools.smali.dexlib2.iface.reference.Reference; import com.android.tools.smali.dexlib2.iface.reference.StringReference; import com.android.tools.smali.dexlib2.iface.reference.TypeReference; -import com.google.common.collect.Ordering; -import com.google.common.primitives.Ints; import com.android.tools.smali.dexlib2.Opcode; import com.android.tools.smali.dexlib2.Opcodes; import com.android.tools.smali.dexlib2.ReferenceType; import com.android.tools.smali.dexlib2.iface.instruction.DualReferenceInstruction; import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction; import com.android.tools.smali.dexlib2.iface.instruction.SwitchElement; +import com.android.tools.smali.util.CollectionUtils; import com.android.tools.smali.util.ExceptionWithContext; import javax.annotation.Nonnull; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -535,8 +536,9 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend try { writer.writeUbyte(0); writer.writeUbyte(getOpcodeValue(instruction.getOpcode()) >> 8); - List<? extends SwitchElement> elements = Ordering.from(switchElementComparator).immutableSortedCopy( - instruction.getSwitchElements()); + List<? extends SwitchElement> elements = CollectionUtils.immutableSortedCopy( + instruction.getSwitchElements(), switchElementComparator); + writer.writeUshort(elements.size()); for (SwitchElement element: elements) { writer.writeInt(element.getKey()); @@ -551,7 +553,7 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend private final Comparator<SwitchElement> switchElementComparator = new Comparator<SwitchElement>() { @Override public int compare(SwitchElement element1, SwitchElement element2) { - return Ints.compare(element1.getKey(), element2.getKey()); + return Integer.compare(element1.getKey(), element2.getKey()); } }; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationPool.java index 637dd05e..4d3e1072 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationPool.java @@ -32,18 +32,18 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.writer.AnnotationSection; -import com.google.common.collect.Maps; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue; import javax.annotation.Nonnull; import java.util.Collection; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; class BuilderAnnotationPool extends BaseBuilderPool implements AnnotationSection<BuilderStringReference, BuilderTypeReference, BuilderAnnotation, BuilderAnnotationElement, BuilderEncodedValue> { @Nonnull private final ConcurrentMap<Annotation, BuilderAnnotation> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderAnnotationPool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationSet.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationSet.java index ae281301..915e771b 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationSet.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationSet.java @@ -31,16 +31,16 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.DexWriter; -import com.google.common.collect.ImmutableSet; import javax.annotation.Nonnull; import java.util.AbstractSet; +import java.util.Collections; import java.util.Iterator; import java.util.Set; public class BuilderAnnotationSet extends AbstractSet<BuilderAnnotation> { public static final BuilderAnnotationSet EMPTY = - new BuilderAnnotationSet(ImmutableSet.<BuilderAnnotation>of()); + new BuilderAnnotationSet(Collections.emptySet()); @Nonnull final Set<BuilderAnnotation> annotations; int offset = DexWriter.NO_OFFSET; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationSetPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationSetPool.java index eacb472f..f53e9434 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationSetPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderAnnotationSetPool.java @@ -33,22 +33,21 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.writer.AnnotationSetSection; import com.android.tools.smali.dexlib2.writer.DexWriter; -import com.google.common.base.Function; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterators; -import com.google.common.collect.Maps; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.Collections; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; class BuilderAnnotationSetPool extends BaseBuilderPool implements AnnotationSetSection<BuilderAnnotation, BuilderAnnotationSet> { @Nonnull private final ConcurrentMap<Set<? extends Annotation>, BuilderAnnotationSet> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderAnnotationSetPool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); @@ -65,12 +64,9 @@ class BuilderAnnotationSetPool extends BaseBuilderPool } BuilderAnnotationSet annotationSet = new BuilderAnnotationSet( - ImmutableSet.copyOf(Iterators.transform(annotations.iterator(), - new Function<Annotation, BuilderAnnotation>() { - @Nullable @Override public BuilderAnnotation apply(Annotation input) { - return dexBuilder.annotationSection.internAnnotation(input); - } - }))); + Collections.unmodifiableSet(annotations.stream() + .map(annotation -> dexBuilder.annotationSection.internAnnotation(annotation)) + .collect(Collectors.toSet()))); ret = internedItems.putIfAbsent(annotationSet, annotationSet); return ret==null?annotationSet:ret; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderCallSitePool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderCallSitePool.java index df7a1987..23bf45ed 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderCallSitePool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderCallSitePool.java @@ -32,19 +32,19 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.CallSiteSection; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue; -import com.google.common.collect.Maps; import com.android.tools.smali.dexlib2.iface.reference.CallSiteReference; import com.android.tools.smali.dexlib2.writer.util.CallSiteUtil; import javax.annotation.Nonnull; import java.util.Collection; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class BuilderCallSitePool extends BaseBuilderPool implements CallSiteSection<BuilderCallSiteReference, BuilderArrayEncodedValue> { @Nonnull private final ConcurrentMap<CallSiteReference, BuilderCallSiteReference> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderCallSitePool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderCallSiteReference.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderCallSiteReference.java index 75803034..a610e578 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderCallSiteReference.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderCallSiteReference.java @@ -31,7 +31,6 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.DexWriter; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.base.reference.BaseCallSiteReference; import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue; @@ -40,6 +39,7 @@ import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.Build import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderMethodTypeEncodedValue; import javax.annotation.Nonnull; +import java.util.Collections; import java.util.List; public class BuilderCallSiteReference extends BaseCallSiteReference implements BuilderReference { @@ -71,7 +71,7 @@ public class BuilderCallSiteReference extends BaseCallSiteReference implements B @Nonnull @Override public List<? extends BuilderEncodedValue> getExtraArguments() { if (encodedCallSite.elements.size() <= 3) { - return ImmutableList.of(); + return Collections.emptyList(); } return encodedCallSite.elements.subList(3, encodedCallSite.elements.size()); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderClassDef.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderClassDef.java index 43375b1c..b6d0c29a 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderClassDef.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderClassDef.java @@ -33,21 +33,20 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.iface.ClassDef; import com.android.tools.smali.dexlib2.util.MethodUtil; import com.android.tools.smali.dexlib2.writer.DexWriter; -import com.google.common.base.Functions; import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue; +import com.android.tools.smali.util.ArraySortedSet; +import com.android.tools.smali.util.CollectionUtils; +import com.android.tools.smali.util.IteratorUtils; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; -import com.google.common.collect.Lists; -import com.google.common.collect.Ordering; import java.util.AbstractCollection; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.SortedSet; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -78,13 +77,13 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef { @Nullable Iterable<? extends BuilderMethod> methods, @Nullable BuilderArrayEncodedValue staticInitializers) { if (methods == null) { - methods = ImmutableList.of(); + methods = Collections.emptyList(); } if (staticFields == null) { - staticFields = ImmutableSortedSet.of(); + staticFields = Collections.emptySortedSet(); } if (instanceFields == null) { - instanceFields = ImmutableSortedSet.of(); + instanceFields = Collections.emptySortedSet(); } this.type = type; @@ -95,8 +94,10 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef { this.annotations = annotations; this.staticFields = staticFields; this.instanceFields = instanceFields; - this.directMethods = ImmutableSortedSet.copyOf(Iterables.filter(methods, MethodUtil.METHOD_IS_DIRECT)); - this.virtualMethods = ImmutableSortedSet.copyOf(Iterables.filter(methods, MethodUtil.METHOD_IS_VIRTUAL)); + this.directMethods = ArraySortedSet.copyOf(CollectionUtils.naturalOrdering(), IteratorUtils.toList( + (Iterator<? extends BuilderMethod>)IteratorUtils.filter(methods, MethodUtil.METHOD_IS_DIRECT))); + this.virtualMethods = ArraySortedSet.copyOf(CollectionUtils.naturalOrdering(), IteratorUtils.toList( + (Iterator<? extends BuilderMethod>)IteratorUtils.filter(methods, MethodUtil.METHOD_IS_VIRTUAL))); this.staticInitializers = staticInitializers; } @@ -112,15 +113,18 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef { @Nonnull @Override public List<String> getInterfaces() { - return Lists.transform(this.interfaces, Functions.toStringFunction()); + return this.interfaces.stream() + .map(iface -> iface.toString()) + .collect(Collectors.toList()); } @Nonnull @Override public Collection<BuilderField> getFields() { return new AbstractCollection<BuilderField>() { @Nonnull @Override public Iterator<BuilderField> iterator() { - return Iterators.mergeSorted( - ImmutableList.of(staticFields.iterator(), instanceFields.iterator()), - Ordering.natural()); + ArrayList<BuilderField> fields = new ArrayList<>(staticFields); + fields.addAll(instanceFields); + Collections.sort(fields, CollectionUtils.naturalOrdering()); + return fields.iterator(); } @Override public int size() { @@ -132,9 +136,10 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef { @Nonnull @Override public Collection<BuilderMethod> getMethods() { return new AbstractCollection<BuilderMethod>() { @Nonnull @Override public Iterator<BuilderMethod> iterator() { - return Iterators.mergeSorted( - ImmutableList.of(directMethods.iterator(), virtualMethods.iterator()), - Ordering.natural()); + ArrayList<BuilderMethod> methods = new ArrayList<>(directMethods); + methods.addAll(virtualMethods); + Collections.sort(methods, CollectionUtils.naturalOrdering()); + return methods.iterator(); } @Override public int size() { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderClassPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderClassPool.java index 0b6f92e7..25f780fd 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderClassPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderClassPool.java @@ -46,9 +46,8 @@ import com.android.tools.smali.dexlib2.util.EncodedValueUtils; import com.android.tools.smali.dexlib2.writer.ClassSection; import com.android.tools.smali.dexlib2.writer.DebugWriter; import com.android.tools.smali.util.AbstractForwardSequentialList; +import com.android.tools.smali.util.CollectionUtils; import com.android.tools.smali.util.ExceptionWithContext; -import com.google.common.base.Function; -import com.google.common.base.Predicate; import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation; import com.android.tools.smali.dexlib2.iface.instruction.Instruction; import com.android.tools.smali.dexlib2.iface.reference.StringReference; @@ -57,16 +56,17 @@ import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; -import com.google.common.collect.Ordering; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Predicate; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; @@ -77,7 +77,7 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu BuilderTypeReference, BuilderTypeList, BuilderClassDef, BuilderField, BuilderMethod, BuilderAnnotationSet, BuilderArrayEncodedValue> { @Nonnull private final ConcurrentMap<String, BuilderClassDef> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderClassPool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); @@ -91,10 +91,11 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu return classDef; } - private ImmutableList<BuilderClassDef> sortedClasses = null; + private List<BuilderClassDef> sortedClasses = null; @Nonnull @Override public Collection<? extends BuilderClassDef> getSortedClasses() { if (sortedClasses == null) { - sortedClasses = Ordering.natural().immutableSortedCopy(internedItems.values()); + sortedClasses = CollectionUtils.immutableSortedCopy( + internedItems.values(), CollectionUtils.naturalOrdering()); } return sortedClasses; } @@ -147,7 +148,7 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu private static final Predicate<Field> HAS_INITIALIZER = new Predicate<Field>() { @Override - public boolean apply(Field input) { + public boolean test(Field input) { EncodedValue encodedValue = input.getInitialValue(); return encodedValue != null && !EncodedValueUtils.isDefaultValue(encodedValue); } @@ -242,7 +243,7 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu private static final Predicate<BuilderMethodParameter> HAS_PARAMETER_ANNOTATIONS = new Predicate<BuilderMethodParameter>() { @Override - public boolean apply(BuilderMethodParameter input) { + public boolean test(BuilderMethodParameter input) { return input.getAnnotations().size() > 0; } }; @@ -258,13 +259,12 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu @Nullable @Override public List<? extends BuilderAnnotationSet> getParameterAnnotations( @Nonnull final BuilderMethod method) { final List<? extends BuilderMethodParameter> parameters = method.getParameters(); - boolean hasParameterAnnotations = Iterables.any(parameters, HAS_PARAMETER_ANNOTATIONS); + boolean hasParameterAnnotations = parameters.stream().anyMatch(HAS_PARAMETER_ANNOTATIONS); if (hasParameterAnnotations) { return new AbstractForwardSequentialList<BuilderAnnotationSet>() { @Nonnull @Override public Iterator<BuilderAnnotationSet> iterator() { - return FluentIterable.from(parameters) - .transform(PARAMETER_ANNOTATIONS).iterator(); + return parameters.stream().map(PARAMETER_ANNOTATIONS).iterator(); } @Override public int size() { @@ -286,11 +286,8 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu @Nullable @Override public Iterable<? extends BuilderStringReference> getParameterNames(@Nonnull BuilderMethod method) { - return Iterables.transform(method.getParameters(), new Function<BuilderMethodParameter, BuilderStringReference>() { - @Nullable @Override public BuilderStringReference apply(BuilderMethodParameter input) { - return input.name; - } - }); + return method.getParameters().stream().map( + builderMethodParameter -> builderMethodParameter.name).collect(Collectors.toList()); } @Override public int getRegisterCount(@Nonnull BuilderMethod builderMethod) { @@ -314,7 +311,7 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu public List<? extends TryBlock<? extends ExceptionHandler>> getTryBlocks(@Nonnull BuilderMethod builderMethod) { MethodImplementation impl = builderMethod.getImplementation(); if (impl == null) { - return ImmutableList.of(); + return Collections.emptyList(); } return impl.getTryBlocks(); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderEncodedArrayPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderEncodedArrayPool.java index d5a0e468..db390d97 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderEncodedArrayPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderEncodedArrayPool.java @@ -33,19 +33,19 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.EncodedArraySection; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue; -import com.google.common.collect.Maps; import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue; import javax.annotation.Nonnull; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class BuilderEncodedArrayPool extends BaseBuilderPool implements EncodedArraySection<BuilderArrayEncodedValue, BuilderEncodedValue> { @Nonnull private final ConcurrentMap<ArrayEncodedValue, BuilderArrayEncodedValue> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderEncodedArrayPool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderFieldPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderFieldPool.java index 1cba2260..32d00373 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderFieldPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderFieldPool.java @@ -32,19 +32,19 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.immutable.reference.ImmutableFieldReference; import com.android.tools.smali.dexlib2.writer.FieldSection; -import com.google.common.collect.Maps; import com.android.tools.smali.dexlib2.iface.reference.FieldReference; import javax.annotation.Nonnull; import java.util.Collection; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class BuilderFieldPool extends BaseBuilderPool implements FieldSection<BuilderStringReference, BuilderTypeReference, BuilderFieldReference, BuilderField> { @Nonnull private final ConcurrentMap<FieldReference, BuilderFieldReference> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderFieldPool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderMethodHandlePool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderMethodHandlePool.java index e63c9937..76b6b082 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderMethodHandlePool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderMethodHandlePool.java @@ -33,13 +33,13 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.MethodHandleType; import com.android.tools.smali.dexlib2.writer.MethodHandleSection; import com.android.tools.smali.util.ExceptionWithContext; -import com.google.common.collect.Maps; import com.android.tools.smali.dexlib2.iface.reference.FieldReference; import com.android.tools.smali.dexlib2.iface.reference.MethodHandleReference; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; import javax.annotation.Nonnull; import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; import java.util.Map; import java.util.concurrent.ConcurrentMap; @@ -47,7 +47,7 @@ public class BuilderMethodHandlePool extends BaseBuilderPool implements MethodHandleSection<BuilderMethodHandleReference, BuilderFieldReference, BuilderMethodReference> { @Nonnull private final ConcurrentMap<MethodHandleReference, BuilderMethodHandleReference> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>();; public BuilderMethodHandlePool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderMethodPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderMethodPool.java index 725de9ea..cf8ef1e6 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderMethodPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderMethodPool.java @@ -31,7 +31,6 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.MethodSection; -import com.google.common.collect.Maps; import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; @@ -39,12 +38,13 @@ import javax.annotation.Nonnull; import java.util.Collection; import java.util.List; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; class BuilderMethodPool extends BaseBuilderPool implements MethodSection<BuilderStringReference, BuilderTypeReference, BuilderMethodProtoReference, BuilderMethodReference, BuilderMethod> { @Nonnull private final ConcurrentMap<MethodReference, BuilderMethodReference> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderMethodPool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderProtoPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderProtoPool.java index 00f0ed19..027a924e 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderProtoPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderProtoPool.java @@ -33,7 +33,6 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodProtoReference; import com.android.tools.smali.dexlib2.util.MethodUtil; import com.android.tools.smali.dexlib2.writer.ProtoSection; -import com.google.common.collect.Maps; import com.android.tools.smali.dexlib2.iface.reference.MethodProtoReference; import com.android.tools.smali.dexlib2.iface.reference.MethodReference; @@ -41,13 +40,14 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; class BuilderProtoPool extends BaseBuilderPool implements ProtoSection<BuilderStringReference, BuilderTypeReference, BuilderMethodProtoReference, BuilderTypeList> { @Nonnull private final ConcurrentMap<MethodProtoReference, BuilderMethodProtoReference> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderProtoPool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderStringPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderStringPool.java index 406da029..ac2fa64a 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderStringPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderStringPool.java @@ -32,16 +32,16 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.DexWriter; import com.android.tools.smali.dexlib2.writer.StringSection; -import com.google.common.collect.Maps; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; class BuilderStringPool implements StringSection<BuilderStringReference, BuilderStringReference> { - @Nonnull private final ConcurrentMap<String, BuilderStringReference> internedItems = Maps.newConcurrentMap(); + @Nonnull private final ConcurrentMap<String, BuilderStringReference> internedItems = new ConcurrentHashMap<>(); @Nonnull BuilderStringReference internString(@Nonnull String string) { BuilderStringReference ret = internedItems.get(string); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypeList.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypeList.java index 0cb9b7ed..7dbec167 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypeList.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypeList.java @@ -31,14 +31,14 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.DexWriter; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import java.util.AbstractList; +import java.util.Collections; import java.util.List; public class BuilderTypeList extends AbstractList<BuilderTypeReference> { - static final BuilderTypeList EMPTY = new BuilderTypeList(ImmutableList.<BuilderTypeReference>of()); + static final BuilderTypeList EMPTY = new BuilderTypeList(Collections.emptyList()); @Nonnull final List<? extends BuilderTypeReference> types; int offset = DexWriter.NO_OFFSET; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypeListPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypeListPool.java index 4b7942b2..049463e2 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypeListPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypeListPool.java @@ -32,22 +32,21 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.DexWriter; import com.android.tools.smali.dexlib2.writer.TypeListSection; -import com.google.common.base.Function; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; class BuilderTypeListPool extends BaseBuilderPool implements TypeListSection<BuilderTypeReference, BuilderTypeList> { @Nonnull private final ConcurrentMap<List<? extends CharSequence>, BuilderTypeList> internedItems = - Maps.newConcurrentMap(); + new ConcurrentHashMap<>(); public BuilderTypeListPool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); @@ -64,11 +63,10 @@ class BuilderTypeListPool extends BaseBuilderPool implements } BuilderTypeList typeList = new BuilderTypeList( - ImmutableList.copyOf(Iterables.transform(types, new Function<CharSequence, BuilderTypeReference>() { - @Nonnull @Override public BuilderTypeReference apply(CharSequence input) { - return dexBuilder.typeSection.internType(input.toString()); - } - }))); + Collections.unmodifiableList( + types.stream() + .map(type -> dexBuilder.typeSection.internType(type.toString())) + .collect(Collectors.toList()))); ret = internedItems.putIfAbsent(typeList, typeList); return ret==null?typeList:ret; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypePool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypePool.java index dfd6c20d..a14dcaac 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypePool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/BuilderTypePool.java @@ -32,17 +32,17 @@ package com.android.tools.smali.dexlib2.writer.builder; import com.android.tools.smali.dexlib2.writer.DexWriter; import com.android.tools.smali.dexlib2.writer.TypeSection; -import com.google.common.collect.Maps; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; class BuilderTypePool extends BaseBuilderPool implements TypeSection<BuilderStringReference, BuilderTypeReference, BuilderTypeReference> { - @Nonnull private final ConcurrentMap<String, BuilderTypeReference> internedItems = Maps.newConcurrentMap(); + @Nonnull private final ConcurrentMap<String, BuilderTypeReference> internedItems = new ConcurrentHashMap<>(); public BuilderTypePool(@Nonnull DexBuilder dexBuilder) { super(dexBuilder); diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/DexBuilder.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/DexBuilder.java index cd54a6e4..1b1abcc1 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/DexBuilder.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/builder/DexBuilder.java @@ -84,22 +84,24 @@ import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.Build import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderShortEncodedValue; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderStringEncodedValue; import com.android.tools.smali.dexlib2.writer.builder.BuilderEncodedValues.BuilderTypeEncodedValue; +import com.android.tools.smali.util.ArraySortedSet; +import com.android.tools.smali.util.CollectionUtils; import com.android.tools.smali.util.ExceptionWithContext; -import com.google.common.base.Function; +import com.android.tools.smali.util.IteratorUtils; +import com.android.tools.smali.util.TransformedIterator; import com.android.tools.smali.dexlib2.writer.util.StaticInitializerUtil; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; -import com.google.common.collect.Sets; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.SortedSet; +import java.util.function.Function; +import java.util.stream.Collectors; public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference, BuilderTypeReference, BuilderMethodProtoReference, BuilderFieldReference, BuilderMethodReference, @@ -140,7 +142,7 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR @Nonnull Set<HiddenApiRestriction> hiddenApiRestrictions, @Nullable MethodImplementation methodImplementation) { if (parameters == null) { - parameters = ImmutableList.of(); + parameters = Collections.emptyList(); } return new BuilderMethod(methodSection.internMethod(definingClass, name, parameters, returnType), internMethodParameters(parameters), @@ -159,9 +161,9 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR @Nullable Iterable<? extends BuilderField> fields, @Nullable Iterable<? extends BuilderMethod> methods) { if (interfaces == null) { - interfaces = ImmutableList.of(); + interfaces = Collections.emptyList(); } else { - Set<String> interfaces_copy = Sets.newHashSet(interfaces); + Set<String> interfaces_copy = new HashSet<>(interfaces); Iterator<String> interfaceIterator = interfaces.iterator(); while (interfaceIterator.hasNext()) { String iface = interfaceIterator.next(); @@ -173,13 +175,18 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR } } - ImmutableSortedSet<BuilderField> staticFields = null; - ImmutableSortedSet<BuilderField> instanceFields = null; + SortedSet<BuilderField> staticFields = null; + SortedSet<BuilderField> instanceFields = null; BuilderArrayEncodedValue internedStaticInitializers = null; if (fields != null) { - staticFields = ImmutableSortedSet.copyOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC)); - instanceFields = ImmutableSortedSet.copyOf(Iterables.filter(fields, FieldUtil.FIELD_IS_INSTANCE)); - ArrayEncodedValue staticInitializers = StaticInitializerUtil.getStaticInitializers(staticFields); + staticFields = ArraySortedSet.copyOf(CollectionUtils.naturalOrdering(), + IteratorUtils.toList((Iterator<? extends BuilderField>) IteratorUtils + .filter(fields, FieldUtil.FIELD_IS_STATIC))); + instanceFields = ArraySortedSet.copyOf(CollectionUtils.naturalOrdering(), + IteratorUtils.toList((Iterator<? extends BuilderField>) IteratorUtils + .filter(fields, FieldUtil.FIELD_IS_INSTANCE))); + ArrayEncodedValue staticInitializers = StaticInitializerUtil + .getStaticInitializers(staticFields); if (staticInitializers != null) { internedStaticInitializers = encodedArraySection.internArrayEncodedValue(staticInitializers); } @@ -267,14 +274,10 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR @Nonnull private List<BuilderMethodParameter> internMethodParameters( @Nullable List<? extends MethodParameter> methodParameters) { if (methodParameters == null) { - return ImmutableList.of(); + return Collections.emptyList(); } - return ImmutableList.copyOf(Iterators.transform(methodParameters.iterator(), - new Function<MethodParameter, BuilderMethodParameter>() { - @Nullable @Override public BuilderMethodParameter apply(MethodParameter input) { - return internMethodParameter(input); - } - })); + return Collections.unmodifiableList(methodParameters.stream().map(methodParam -> + internMethodParameter(methodParam)).collect(Collectors.toList())); } @Nonnull private BuilderMethodParameter internMethodParameter(@Nonnull MethodParameter methodParameter) { @@ -350,14 +353,8 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR @Nonnull Set<? extends BuilderAnnotationElement> internAnnotationElements( @Nonnull Set<? extends AnnotationElement> elements) { - return ImmutableSet.copyOf( - Iterators.transform(elements.iterator(), - new Function<AnnotationElement, BuilderAnnotationElement>() { - @Nullable @Override - public BuilderAnnotationElement apply(AnnotationElement input) { - return internAnnotationElement(input); - } - })); + return Collections.unmodifiableSet(elements.stream().map(annotationElement -> + internAnnotationElement(annotationElement)).collect(Collectors.toSet())); } @Nonnull private BuilderAnnotationElement internAnnotationElement(@Nonnull AnnotationElement annotationElement) { @@ -423,14 +420,8 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR } @Nonnull private BuilderArrayEncodedValue internArrayEncodedValue(@Nonnull ArrayEncodedValue value) { - return new BuilderArrayEncodedValue( - ImmutableList.copyOf( - Iterators.transform(value.getValue().iterator(), - new Function<EncodedValue, BuilderEncodedValue>() { - @Nullable @Override public BuilderEncodedValue apply(EncodedValue input) { - return internEncodedValue(input); - } - }))); + return new BuilderArrayEncodedValue(Collections.unmodifiableList(value.getValue().stream() + .map(encodedVal -> internEncodedValue(encodedVal)).collect(Collectors.toList()))); } @Nonnull private BuilderEnumEncodedValue internEnumEncodedValue(@Nonnull EnumEncodedValue value) { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/io/FileDeferredOutputStream.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/io/FileDeferredOutputStream.java index c425e297..a89af844 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/io/FileDeferredOutputStream.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/io/FileDeferredOutputStream.java @@ -30,7 +30,7 @@ package com.android.tools.smali.dexlib2.writer.io; -import com.google.common.io.ByteStreams; +import com.android.tools.smali.util.InputStreamUtil; import java.io.BufferedOutputStream; import java.io.File; @@ -71,7 +71,7 @@ public class FileDeferredOutputStream extends DeferredOutputStream { // did we actually write something out to disk? if (count != writtenBytes) { InputStream fis = new FileInputStream(backingFile); - ByteStreams.copy(fis, dest); + InputStreamUtil.copy(fis, dest); backingFile.delete(); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/io/MemoryDeferredOutputStream.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/io/MemoryDeferredOutputStream.java index e9811009..d4392fa9 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/io/MemoryDeferredOutputStream.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/io/MemoryDeferredOutputStream.java @@ -30,11 +30,10 @@ package com.android.tools.smali.dexlib2.writer.io; -import com.google.common.collect.Lists; - import javax.annotation.Nonnull; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.List; /** @@ -43,7 +42,7 @@ import java.util.List; public class MemoryDeferredOutputStream extends DeferredOutputStream { private static final int DEFAULT_BUFFER_SIZE = 16 * 1024; - private final List<byte[]> buffers = Lists.newArrayList(); + private final List<byte[]> buffers = new ArrayList<>(); private byte[] currentBuffer; private int currentPosition; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/BasePool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/BasePool.java index 63c12f2a..c81f9a27 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/BasePool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/BasePool.java @@ -30,15 +30,14 @@ package com.android.tools.smali.dexlib2.writer.pool; -import com.google.common.collect.Maps; - import javax.annotation.Nonnull; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; public class BasePool<Key, Value> implements Markable { @Nonnull protected final DexPool dexPool; - @Nonnull protected final Map<Key, Value> internedItems = Maps.newLinkedHashMap(); + @Nonnull protected final Map<Key, Value> internedItems = new LinkedHashMap<>(); private int markedItemCount = -1; public BasePool(@Nonnull DexPool dexPool) { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/ClassPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/ClassPool.java index a6a6fbb0..be61f1b9 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/ClassPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/ClassPool.java @@ -59,13 +59,9 @@ import com.android.tools.smali.dexlib2.writer.ClassSection; import com.android.tools.smali.dexlib2.writer.DebugWriter; import com.android.tools.smali.dexlib2.writer.util.StaticInitializerUtil; import com.android.tools.smali.util.AbstractForwardSequentialList; +import com.android.tools.smali.util.CollectionUtils; import com.android.tools.smali.util.ExceptionWithContext; -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Ordering; +import com.android.tools.smali.util.TransformedIterator; import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation; import com.android.tools.smali.dexlib2.formatter.DexFormatter; import com.android.tools.smali.dexlib2.iface.instruction.DualReferenceInstruction; @@ -75,12 +71,16 @@ import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue; import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import java.util.AbstractCollection; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; @@ -235,10 +235,11 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe } } - private ImmutableList<PoolClassDef> sortedClasses = null; + private List<PoolClassDef> sortedClasses = null; @Nonnull @Override public Collection<? extends PoolClassDef> getSortedClasses() { if (sortedClasses == null) { - sortedClasses = Ordering.natural().immutableSortedCopy(internedItems.values()); + sortedClasses = CollectionUtils.immutableSortedCopy( + internedItems.values(), CollectionUtils.usingToStringOrdering()); } return sortedClasses; } @@ -360,7 +361,7 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe private static final Predicate<MethodParameter> HAS_PARAMETER_ANNOTATIONS = new Predicate<MethodParameter>() { @Override - public boolean apply(MethodParameter input) { + public boolean test(MethodParameter input) { return input.getAnnotations().size() > 0; } }; @@ -376,13 +377,12 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe @Nullable @Override public List<? extends Set<? extends Annotation>> getParameterAnnotations( @Nonnull final PoolMethod method) { final List<? extends MethodParameter> parameters = method.getParameters(); - boolean hasParameterAnnotations = Iterables.any(parameters, HAS_PARAMETER_ANNOTATIONS); + boolean hasParameterAnnotations = parameters.stream().anyMatch(HAS_PARAMETER_ANNOTATIONS); if (hasParameterAnnotations) { return new AbstractForwardSequentialList<Set<? extends Annotation>>() { @Nonnull @Override public Iterator<Set<? extends Annotation>> iterator() { - return FluentIterable.from(parameters) - .transform(PARAMETER_ANNOTATIONS).iterator(); + return new TransformedIterator<>(parameters.iterator(), PARAMETER_ANNOTATIONS); } @Override public int size() { @@ -402,7 +402,7 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe } @Nullable @Override public Iterable<CharSequence> getParameterNames(@Nonnull PoolMethod method) { - return Iterables.transform(method.getParameters(), new Function<MethodParameter, CharSequence>() { + return new TransformedIterator(method.getParameters(), new Function<MethodParameter, CharSequence>() { @Nullable @Override public CharSequence apply(MethodParameter input) { return input.getName(); } @@ -431,7 +431,7 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe if (impl != null) { return impl.getTryBlocks(); } - return ImmutableList.of(); + return Collections.emptyList(); } @Nullable @Override public CharSequence getExceptionType(@Nonnull ExceptionHandler handler) { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/PoolClassDef.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/PoolClassDef.java index 59e4a5bb..fc146ec0 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/PoolClassDef.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/PoolClassDef.java @@ -30,32 +30,33 @@ package com.android.tools.smali.dexlib2.writer.pool; +import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference; import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.ClassDef; import com.android.tools.smali.dexlib2.iface.Field; -import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference; +import com.android.tools.smali.util.ArraySortedSet; +import com.android.tools.smali.util.CollectionUtils; +import com.android.tools.smali.util.IteratorUtils; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; -import com.google.common.collect.Ordering; import java.util.AbstractCollection; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedSet; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; class PoolClassDef extends BaseTypeReference implements ClassDef { @Nonnull final ClassDef classDef; @Nonnull final TypeListPool.Key<List<String>> interfaces; - @Nonnull final ImmutableSortedSet<Field> staticFields; - @Nonnull final ImmutableSortedSet<Field> instanceFields; - @Nonnull final ImmutableSortedSet<PoolMethod> directMethods; - @Nonnull final ImmutableSortedSet<PoolMethod> virtualMethods; + @Nonnull final SortedSet<Field> staticFields; + @Nonnull final SortedSet<Field> instanceFields; + @Nonnull final SortedSet<PoolMethod> directMethods; + @Nonnull final SortedSet<PoolMethod> virtualMethods; int classDefIndex = DexPool.NO_INDEX; int annotationDirectoryOffset = DexPool.NO_OFFSET; @@ -63,13 +64,17 @@ class PoolClassDef extends BaseTypeReference implements ClassDef { PoolClassDef(@Nonnull ClassDef classDef) { this.classDef = classDef; - interfaces = new TypeListPool.Key<List<String>>(ImmutableList.copyOf(classDef.getInterfaces())); - staticFields = ImmutableSortedSet.copyOf(classDef.getStaticFields()); - instanceFields = ImmutableSortedSet.copyOf(classDef.getInstanceFields()); - directMethods = ImmutableSortedSet.copyOf( - Iterables.transform(classDef.getDirectMethods(), PoolMethod.TRANSFORM)); - virtualMethods = ImmutableSortedSet.copyOf( - Iterables.transform(classDef.getVirtualMethods(), PoolMethod.TRANSFORM)); + interfaces = new TypeListPool.Key<List<String>>(Collections.unmodifiableList(new ArrayList<>(classDef.getInterfaces()))); + staticFields = ArraySortedSet.copyOf(CollectionUtils.naturalOrdering(), + IteratorUtils.toList(classDef.getStaticFields())); + instanceFields = ArraySortedSet.copyOf(CollectionUtils.naturalOrdering(), + IteratorUtils.toList(classDef.getInstanceFields())); + directMethods = ArraySortedSet.copyOf(CollectionUtils.naturalOrdering(), + IteratorUtils.toList(classDef.getDirectMethods()).stream().map(PoolMethod.TRANSFORM) + .collect(Collectors.toList())); + virtualMethods = ArraySortedSet.of(CollectionUtils.naturalOrdering(), + IteratorUtils.toList(classDef.getVirtualMethods()).stream().map(PoolMethod.TRANSFORM) + .collect(Collectors.toList())); } @Nonnull @Override public String getType() { @@ -107,9 +112,10 @@ class PoolClassDef extends BaseTypeReference implements ClassDef { @Nonnull @Override public Collection<Field> getFields() { return new AbstractCollection<Field>() { @Nonnull @Override public Iterator<Field> iterator() { - return Iterators.mergeSorted( - ImmutableList.of(staticFields.iterator(), instanceFields.iterator()), - Ordering.natural()); + ArrayList<Field> fields = new ArrayList<>(staticFields); + fields.addAll(instanceFields); + fields.sort(CollectionUtils.naturalOrdering()); + return fields.iterator(); } @Override public int size() { @@ -129,9 +135,10 @@ class PoolClassDef extends BaseTypeReference implements ClassDef { @Nonnull @Override public Collection<PoolMethod> getMethods() { return new AbstractCollection<PoolMethod>() { @Nonnull @Override public Iterator<PoolMethod> iterator() { - return Iterators.mergeSorted( - ImmutableList.of(directMethods.iterator(), virtualMethods.iterator()), - Ordering.natural()); + ArrayList<PoolMethod> methods = new ArrayList<>(directMethods); + methods.addAll(virtualMethods); + methods.sort(CollectionUtils.naturalOrdering()); + return methods.iterator(); } @Override public int size() { diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/PoolMethod.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/PoolMethod.java index 7594f5e7..7df8be50 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/PoolMethod.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/PoolMethod.java @@ -35,14 +35,13 @@ import com.android.tools.smali.dexlib2.iface.Annotation; import com.android.tools.smali.dexlib2.iface.Method; import com.android.tools.smali.dexlib2.iface.MethodImplementation; import com.android.tools.smali.dexlib2.iface.MethodParameter; -import com.google.common.base.Function; import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Set; - +import java.util.function.Function; class PoolMethod extends BaseMethodReference implements Method { @Nonnull private final Method method; diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/TypeListPool.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/TypeListPool.java index 98e77c08..b36df14f 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/TypeListPool.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/pool/TypeListPool.java @@ -32,12 +32,12 @@ package com.android.tools.smali.dexlib2.writer.pool; import com.android.tools.smali.dexlib2.writer.DexWriter; import com.android.tools.smali.dexlib2.writer.TypeListSection; -import com.google.common.collect.ImmutableList; import com.android.tools.smali.dexlib2.writer.pool.TypeListPool.Key; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; public class TypeListPool extends BaseNullableOffsetPool<Key<? extends Collection<? extends CharSequence>>> @@ -64,7 +64,7 @@ public class TypeListPool extends BaseNullableOffsetPool<Key<? extends Collectio @Nonnull @Override public Collection<? extends CharSequence> getTypes(Key<? extends Collection<? extends CharSequence>> typesKey) { if (typesKey == null) { - return ImmutableList.of(); + return Collections.emptyList(); } return typesKey.types; } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/CallSiteUtil.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/CallSiteUtil.java index b17eddb8..53473a33 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/CallSiteUtil.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/CallSiteUtil.java @@ -31,7 +31,6 @@ package com.android.tools.smali.dexlib2.writer.util; import com.android.tools.smali.dexlib2.immutable.value.ImmutableStringEncodedValue; -import com.google.common.collect.Lists; import com.android.tools.smali.dexlib2.base.value.BaseArrayEncodedValue; import com.android.tools.smali.dexlib2.base.value.BaseMethodHandleEncodedValue; import com.android.tools.smali.dexlib2.base.value.BaseMethodTypeEncodedValue; @@ -42,6 +41,7 @@ import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue; import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import javax.annotation.Nonnull; +import java.util.ArrayList; import java.util.List; public class CallSiteUtil { @@ -50,7 +50,7 @@ public class CallSiteUtil { @Nonnull @Override public List<? extends EncodedValue> getValue() { - List<EncodedValue> encodedCallSite = Lists.newArrayList(); + List<EncodedValue> encodedCallSite = new ArrayList<>(); encodedCallSite.add(new BaseMethodHandleEncodedValue() { @Nonnull diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/StaticInitializerUtil.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/StaticInitializerUtil.java index 1974c95d..11c9a010 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/StaticInitializerUtil.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/StaticInitializerUtil.java @@ -35,15 +35,15 @@ import com.android.tools.smali.dexlib2.immutable.value.ImmutableEncodedValueFact import com.android.tools.smali.dexlib2.util.EncodedValueUtils; import com.android.tools.smali.util.AbstractForwardSequentialList; import com.android.tools.smali.util.CollectionUtils; -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; import com.android.tools.smali.dexlib2.base.value.BaseArrayEncodedValue; import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue; import com.android.tools.smali.dexlib2.iface.value.EncodedValue; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; import java.util.Iterator; import java.util.List; import java.util.SortedSet; @@ -60,9 +60,8 @@ public class StaticInitializerUtil { public List<? extends EncodedValue> getValue() { return new AbstractForwardSequentialList<EncodedValue>() { @Nonnull @Override public Iterator<EncodedValue> iterator() { - return FluentIterable.from(sortedStaticFields) - .limit(lastIndex+1) - .transform(GET_INITIAL_VALUE).iterator(); + return sortedStaticFields.stream().limit(lastIndex + 1) + .map(GET_INITIAL_VALUE).collect(Collectors.toList()).iterator(); } @Override public int size() { @@ -77,7 +76,7 @@ public class StaticInitializerUtil { private static final Predicate<Field> HAS_INITIALIZER = new Predicate<Field>() { @Override - public boolean apply(Field input) { + public boolean test(Field input) { EncodedValue encodedValue = input.getInitialValue(); return encodedValue != null && !EncodedValueUtils.isDefaultValue(encodedValue); } diff --git a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/TryListBuilder.java b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/TryListBuilder.java index 4670d16f..152bbff0 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/TryListBuilder.java +++ b/dexlib2/src/main/java/com/android/tools/smali/dexlib2/writer/util/TryListBuilder.java @@ -34,10 +34,11 @@ import com.android.tools.smali.dexlib2.base.BaseTryBlock; import com.android.tools.smali.dexlib2.iface.ExceptionHandler; import com.android.tools.smali.dexlib2.iface.TryBlock; import com.android.tools.smali.util.ExceptionWithContext; -import com.google.common.collect.Lists; +import com.android.tools.smali.util.IteratorUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; @@ -101,7 +102,7 @@ public class TryListBuilder<EH extends ExceptionHandler> public int startCodeAddress; public int endCodeAddress; - @Nonnull public List<EH> exceptionHandlers = Lists.newArrayList(); + @Nonnull public List<EH> exceptionHandlers = new ArrayList<>(); public MutableTryBlock(int startCodeAddress, int endCodeAddress) { this.startCodeAddress = startCodeAddress; @@ -112,7 +113,7 @@ public class TryListBuilder<EH extends ExceptionHandler> @Nonnull List<EH> exceptionHandlers) { this.startCodeAddress = startCodeAddress; this.endCodeAddress = endCodeAddress; - this.exceptionHandlers = Lists.newArrayList(exceptionHandlers); + this.exceptionHandlers = new ArrayList<>(exceptionHandlers); } @Override public int getStartCodeAddress() { @@ -312,7 +313,7 @@ public class TryListBuilder<EH extends ExceptionHandler> } public List<TryBlock<EH>> getTryBlocks() { - return Lists.newArrayList(new Iterator<TryBlock<EH>>() { + return IteratorUtils.toList(new Iterator<TryBlock<EH>>() { // The next TryBlock to return. This has already been merged, if needed. @Nullable private MutableTryBlock<EH> next; diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/AbstractIterator.java b/dexlib2/src/main/java/com/android/tools/smali/util/AbstractIterator.java new file mode 100644 index 00000000..907a8635 --- /dev/null +++ b/dexlib2/src/main/java/com/android/tools/smali/util/AbstractIterator.java @@ -0,0 +1,108 @@ +/* + * Copyright 2024, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.tools.smali.util; + +import javax.annotation.Nullable; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public abstract class AbstractIterator<T> implements Iterator<T>, Iterable<T> { + /** We have computed the next element and haven't returned it yet. */ + private static final int STATE_READY = 1; + + /** We haven't yet computed or have already returned the element. */ + private static final int STATE_NOT_READY = 2; + + /** We have reached the end of the data and are finished. */ + private static final int STATE_DONE = 3; + + /** We've suffered an exception and are kaputt. */ + private static final int STATE_FAILED = 4; + + private int state = STATE_NOT_READY; + private T next; + + protected final T endOfData() { + state = STATE_DONE; + return null; + } + + @Override + public final boolean hasNext() { + switch (state) { + case STATE_DONE: + return false; + case STATE_READY: + return true; + case STATE_FAILED: + throw new IllegalStateException(); + default: + } + return tryToComputeNext(); + } + + private boolean tryToComputeNext() { + state = STATE_FAILED; // temporary pessimism + next = computeNext(); + if (state != STATE_DONE) { + state = STATE_READY; + return true; + } + return false; + } + + @Override + public final T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + state = STATE_NOT_READY; + T result = next; + next = null; + return result; + } + + @Override + public final Iterator<T> iterator() { + return this; + } + + /** + * Computes next item for the iterator. If the end of the list has been reached, it should call + * endOfData. endOfData has a return value of T, so you can simply {@code return endOfData()} + * + * @return The item that was read. If endOfData was called, the return value is ignored. + */ + + @Nullable + protected abstract T computeNext(); +} + diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/ArraySortedSet.java b/dexlib2/src/main/java/com/android/tools/smali/util/ArraySortedSet.java index 46c90b64..7bc16138 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/ArraySortedSet.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/ArraySortedSet.java @@ -30,31 +30,56 @@ package com.android.tools.smali.util; -import com.google.common.collect.Iterators; - import java.util.Arrays; import java.util.Collection; import java.util.Comparator; +import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedSet; +import java.util.stream.Collectors; import javax.annotation.Nonnull; +/* A sorted set implemented with an underlying array. ArraySortedSet is inmutable. */ public class ArraySortedSet<T> implements SortedSet<T> { @Nonnull private final Comparator<? super T> comparator; @Nonnull private final Object[] arr; private ArraySortedSet(@Nonnull Comparator<? super T> comparator, @Nonnull T[] arr) { - // we assume arr is already sorted by comparator, and all entries are unique this.comparator = comparator; this.arr = arr; + assert assertSorted(); + } + + private ArraySortedSet(@Nonnull Comparator<? super T> comparator, @Nonnull Collection<? extends T> collection) { + this.comparator = comparator; + this.arr = collection.toArray(); + assert assertSorted(); } public static <T> ArraySortedSet<T> of(@Nonnull Comparator<? super T> comparator, @Nonnull T[] arr) { return new ArraySortedSet<T>(comparator, arr); } + public static <T> ArraySortedSet<T> of(@Nonnull Comparator<? super T> comparator, @Nonnull Collection<? extends T> collection) { + return new ArraySortedSet<T>(comparator, collection); + } + + /* Copies without duplicates and sorts the given collection to create an ArraySortedSet from it */ + public static <T> ArraySortedSet<T> copyOf(@Nonnull Comparator<? super T> comparator, @Nonnull Collection<? extends T> collection) { + List<T> tmp = (List<T>)collection.stream().distinct().sorted(comparator).collect(Collectors.toList()); + return new ArraySortedSet<T>(comparator, (T[])tmp.toArray()); + } + + private boolean assertSorted() { + for (int i = 1; i < arr.length; i++) { + assert comparator.compare((T)arr[i - 1], (T)arr[i]) < 0; + } + return true; + } + @Override public int size() { return arr.length; @@ -74,7 +99,7 @@ public class ArraySortedSet<T> implements SortedSet<T> { @Override @SuppressWarnings("unchecked") public Iterator<T> iterator() { - return Iterators.forArray((T[])arr); + return Arrays.asList((T[])arr).iterator(); } @Override @@ -189,7 +214,7 @@ public class ArraySortedSet<T> implements SortedSet<T> { if (arr.length != other.size()) { return false; } - return Iterators.elementsEqual(iterator(), other.iterator()); + return IteratorUtils.elementsEqual(iterator(), other.iterator()); } if (o instanceof Set) { Set other = (Set)o; diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/ChainedIterator.java b/dexlib2/src/main/java/com/android/tools/smali/util/ChainedIterator.java index ed8eab1f..3c342471 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/ChainedIterator.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/ChainedIterator.java @@ -32,7 +32,6 @@ package com.android.tools.smali.util; import java.lang.Iterable; import java.util.Iterator; -import org.checkerframework.checker.nullness.qual.Nullable; /** * Combines two iterators into a single iterator. The returned iterator iterates across the elements @@ -41,7 +40,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; * <p> * The returned iterator does not support {@code remove()}. */ -public class ChainedIterator<T extends @Nullable Object> implements Iterator<T>, Iterable<T> { +public class ChainedIterator<T extends Object> implements Iterator<T>, Iterable<T> { Iterator<T> iteratorA; Iterator<T> iteratorB; @@ -50,6 +49,11 @@ public class ChainedIterator<T extends @Nullable Object> implements Iterator<T>, this.iteratorB = iterableB.iterator(); } + public ChainedIterator(Iterator<T> iteratorA, Iterator<T> iteratorB) { + this.iteratorA = iteratorA; + this.iteratorB = iteratorB; + } + @Override public final boolean hasNext() { return iteratorA.hasNext() || iteratorB.hasNext(); diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/CharSequenceUtils.java b/dexlib2/src/main/java/com/android/tools/smali/util/CharSequenceUtils.java index 587cf2a1..f7b08e32 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/CharSequenceUtils.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/CharSequenceUtils.java @@ -30,21 +30,25 @@ package com.android.tools.smali.util; -import com.google.common.base.Function; -import com.google.common.base.Functions; -import com.google.common.collect.Lists; +import java.util.function.Function; +import java.util.Iterator; import java.util.List; public class CharSequenceUtils { - private static final Function<Object, String> TO_STRING = Functions.toStringFunction(); + private static final Function<Object, String> TO_STRING = new Function<Object,String>() { + @Override + public String apply(Object o) { + return o.toString(); + } + }; public static int listHashCode(List<? extends CharSequence> list) { - return Lists.transform(list, TO_STRING).hashCode(); + return IteratorUtils.toList((Iterator)new TransformedIterator(list.iterator(), TO_STRING)).hashCode(); } public static boolean listEquals(List<? extends CharSequence> list1, List<? extends CharSequence> list2) { - return Lists.transform(list1, TO_STRING).equals( - Lists.transform(list2, TO_STRING)); + return IteratorUtils.toList((Iterator)new TransformedIterator(list1.iterator(), TO_STRING)).equals( + IteratorUtils.toList((Iterator)new TransformedIterator(list2.iterator(), TO_STRING))); } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/CollectionUtils.java b/dexlib2/src/main/java/com/android/tools/smali/util/CollectionUtils.java index 2fe222af..7883dcfa 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/CollectionUtils.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/CollectionUtils.java @@ -30,14 +30,16 @@ package com.android.tools.smali.util; -import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableSortedSet; +import com.android.tools.smali.util.ArraySortedSet; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; +import java.util.List; import java.util.SortedSet; +import java.util.function.Predicate; import javax.annotation.Nonnull; @@ -54,7 +56,7 @@ public class CollectionUtils { int index = 0; int lastMatchingIndex = -1; for (T item: iterable) { - if (predicate.apply(item)) { + if (predicate.test(item)) { lastMatchingIndex = index; } index++; @@ -177,7 +179,7 @@ public class CollectionUtils { } } - return ImmutableSortedSet.copyOf(elementComparator, collection); + return Collections.unmodifiableSortedSet(ArraySortedSet.of(elementComparator, collection)); } @Nonnull @@ -224,6 +226,13 @@ public class CollectionUtils { return 0; } + public static <T> List<T> immutableSortedCopy( + @Nonnull Collection<T> collection, @Nonnull Comparator<? super T> comparator) { + ArrayList<T> copy = new ArrayList<>(collection); + copy.sort(comparator); + return Collections.unmodifiableList(copy); + } + public static <T> Comparator<? super T> usingToStringOrdering() { return UsingToStringOrdering.INSTANCE; } diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/ImmutableConverter.java b/dexlib2/src/main/java/com/android/tools/smali/util/ImmutableConverter.java index a526c74d..5d48d705 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/ImmutableConverter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/ImmutableConverter.java @@ -30,28 +30,34 @@ package com.android.tools.smali.util; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableSet; +import static java.util.Collections.unmodifiableSortedSet; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; import java.util.Iterator; +import java.util.List; +import java.util.Set; import java.util.SortedSet; +import java.util.TreeSet; public abstract class ImmutableConverter<ImmutableItem, Item> { protected abstract boolean isImmutable(@Nonnull Item item); @Nonnull protected abstract ImmutableItem makeImmutable(@Nonnull Item item); @Nonnull - public ImmutableList<ImmutableItem> toList(@Nullable final Iterable<? extends Item> iterable) { + public List<ImmutableItem> toList(@Nullable final Iterable<? extends Item> iterable) { if (iterable == null) { - return ImmutableList.of(); + return Collections.emptyList(); } boolean needsCopy = false; - if (iterable instanceof ImmutableList) { + if (iterable instanceof List) { for (Item element: iterable) { if (!isImmutable(element)) { needsCopy = true; @@ -63,26 +69,27 @@ public abstract class ImmutableConverter<ImmutableItem, Item> { } if (!needsCopy) { - return (ImmutableList<ImmutableItem>)iterable; + return unmodifiableList((List<ImmutableItem>)iterable); } final Iterator<? extends Item> iter = iterable.iterator(); - return ImmutableList.copyOf(new Iterator<ImmutableItem>() { - @Override public boolean hasNext() { return iter.hasNext(); } - @Override public ImmutableItem next() { return makeImmutable(iter.next()); } - @Override public void remove() { iter.remove(); } - }); + ArrayList<ImmutableItem> list = new ArrayList<ImmutableItem>(); + while (iter.hasNext()) { + list.add(makeImmutable(iter.next())); + } + + return unmodifiableList(list); } @Nonnull - public ImmutableSet<ImmutableItem> toSet(@Nullable final Iterable<? extends Item> iterable) { + public Set<ImmutableItem> toSet(@Nullable final Iterable<? extends Item> iterable) { if (iterable == null) { - return ImmutableSet.of(); + return Collections.emptySet(); } boolean needsCopy = false; - if (iterable instanceof ImmutableSet) { + if (iterable instanceof Set) { for (Item element: iterable) { if (!isImmutable(element)) { needsCopy = true; @@ -94,28 +101,28 @@ public abstract class ImmutableConverter<ImmutableItem, Item> { } if (!needsCopy) { - return (ImmutableSet<ImmutableItem>)iterable; + return unmodifiableSet((Set<ImmutableItem>)iterable); } final Iterator<? extends Item> iter = iterable.iterator(); - return ImmutableSet.copyOf(new Iterator<ImmutableItem>() { - @Override public boolean hasNext() { return iter.hasNext(); } - @Override public ImmutableItem next() { return makeImmutable(iter.next()); } - @Override public void remove() { iter.remove(); } - }); + HashSet<ImmutableItem> set = new HashSet<ImmutableItem>(); + while (iter.hasNext()) { + set.add(makeImmutable(iter.next())); + } + return unmodifiableSet(set); } @Nonnull - public ImmutableSortedSet<ImmutableItem> toSortedSet(@Nonnull Comparator<? super ImmutableItem> comparator, + public SortedSet<ImmutableItem> toSortedSet(@Nonnull Comparator<? super ImmutableItem> comparator, @Nullable final Iterable<? extends Item> iterable) { if (iterable == null) { - return ImmutableSortedSet.of(); + return Collections.emptySortedSet(); } boolean needsCopy = false; - if (iterable instanceof ImmutableSortedSet && - ((ImmutableSortedSet)iterable).comparator().equals(comparator)) { + if (iterable instanceof SortedSet && + ((SortedSet)iterable).comparator().equals(comparator)) { for (Item element: iterable) { if (!isImmutable(element)) { needsCopy = true; @@ -127,33 +134,15 @@ public abstract class ImmutableConverter<ImmutableItem, Item> { } if (!needsCopy) { - return (ImmutableSortedSet<ImmutableItem>)iterable; + return unmodifiableSortedSet((SortedSet<ImmutableItem>)iterable); } final Iterator<? extends Item> iter = iterable.iterator(); - - return ImmutableSortedSet.copyOf(comparator, new Iterator<ImmutableItem>() { - @Override public boolean hasNext() { return iter.hasNext(); } - @Override public ImmutableItem next() { return makeImmutable(iter.next()); } - @Override public void remove() { iter.remove(); } - }); - } - - @Nonnull - public SortedSet<ImmutableItem> toSortedSet(@Nonnull Comparator<? super ImmutableItem> comparator, - @Nullable final SortedSet<? extends Item> sortedSet) { - if (sortedSet == null || sortedSet.size() == 0) { - return ImmutableSortedSet.of(); - } - - @SuppressWarnings("unchecked") - ImmutableItem[] newItems = (ImmutableItem[])new Object[sortedSet.size()]; - int index = 0; - for (Item item: sortedSet) { - newItems[index++] = makeImmutable(item); + TreeSet<ImmutableItem> treeSet = new TreeSet<ImmutableItem>(comparator); + while (iter.hasNext()) { + treeSet.add(makeImmutable(iter.next())); } - - return ArraySortedSet.of(comparator, newItems); + return unmodifiableSortedSet(treeSet); } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/ImmutableUtils.java b/dexlib2/src/main/java/com/android/tools/smali/util/ImmutableUtils.java index fbd67e3d..0107f856 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/ImmutableUtils.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/ImmutableUtils.java @@ -30,32 +30,36 @@ package com.android.tools.smali.util; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; +import static java.util.Collections.unmodifiableSet; +import static java.util.Collections.unmodifiableSortedSet; +import static java.util.Collections.unmodifiableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; public class ImmutableUtils { - @Nonnull public static <T> ImmutableList<T> nullToEmptyList(@Nullable ImmutableList<T> list) { + @Nonnull public static <T> List<T> nullToEmptyList(@Nullable List<T> list) { if (list == null) { - return ImmutableList.of(); + return Collections.emptyList(); } - return list; + return unmodifiableList(list); } - @Nonnull public static <T> ImmutableSet<T> nullToEmptySet(@Nullable ImmutableSet<T> set) { + @Nonnull public static <T> Set<T> nullToEmptySet(@Nullable Set<T> set) { if (set == null) { - return ImmutableSet.of(); + return Collections.emptySet(); } - return set; + return unmodifiableSet(set); } - @Nonnull public static <T> ImmutableSortedSet<T> nullToEmptySortedSet(@Nullable ImmutableSortedSet<T> set) { + @Nonnull public static <T> SortedSet<T> nullToEmptySortedSet(@Nullable SortedSet<T> set) { if (set == null) { - return ImmutableSortedSet.of(); + return Collections.emptySortedSet(); } - return set; + return unmodifiableSortedSet(set); } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/InputStreamUtil.java b/dexlib2/src/main/java/com/android/tools/smali/util/InputStreamUtil.java index 46f696a1..0532f0c2 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/InputStreamUtil.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/InputStreamUtil.java @@ -38,6 +38,7 @@ import java.io.DataInput; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Queue; @@ -259,4 +260,30 @@ public final class InputStreamUtil { } return total; } + + /** + * Copies all bytes from the input stream to the output stream. Does not close or flush either + * stream. + * + * @param from the input stream to read from + * @param to the output stream to write to + * @return the number of bytes copied + * @throws IOException if an I/O error occurs + */ + public static long copy(InputStream from, OutputStream to) throws IOException { + if (from == null || to == null) { + throw new NullPointerException(); + } + byte[] buf = new byte[BUFFER_SIZE]; + long total = 0; + while (true) { + int r = from.read(buf); + if (r == -1) { + break; + } + to.write(buf, 0, r); + total += r; + } + return total; + } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/IteratorUtils.java b/dexlib2/src/main/java/com/android/tools/smali/util/IteratorUtils.java index 6f6c8576..4894d5a6 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/IteratorUtils.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/IteratorUtils.java @@ -30,13 +30,16 @@ package com.android.tools.smali.util; +import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; - -import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; public final class IteratorUtils { - public static <T extends @Nullable Object> T getLast(Iterator<T> iterator) { + public static <T extends Object> T getLast(Iterator<T> iterator) { while (true) { T current = iterator.next(); if (!iterator.hasNext()) { @@ -44,4 +47,67 @@ public final class IteratorUtils { } } } + + public static <T extends Object> AbstractIterator<T> filter( + Iterable<T> unfiltered, Predicate<? super T> retainIfTrue) { + return filter(unfiltered.iterator(), retainIfTrue); + } + + public static <T extends Object> AbstractIterator<T> filter( + Iterator<T> unfiltered, Predicate<? super T> retainIfTrue) { + return new AbstractIterator<T>() { + @Override + protected T computeNext() { + while (unfiltered.hasNext()) { + T next = unfiltered.next(); + if (retainIfTrue.test(next)) { + return next; + } + } + return endOfData(); + } + }; + } + + public static <T extends Object> List<T> toList(Iterable<T> iterable) { + return toList(iterable.iterator()); + } + + public static <T extends Object> List<T> toList(Iterator<T> iterator) { + ArrayList<T> list = new ArrayList<T>(); + while (iterator.hasNext()) { + list.add(iterator.next()); + } + return list; + } + + public static <T extends Object> void addAll(Collection<T> collection, Iterator<T> iterator) { + while (iterator.hasNext()) { + collection.add(iterator.next()); + } + } + + public static boolean elementsEqual(Iterator<?> iterator1, Iterator<?> iterator2) { + while (iterator1.hasNext()) { + if (!iterator2.hasNext()) { + return false; + } + Object o1 = iterator1.next(); + Object o2 = iterator2.next(); + if (!Objects.equals(o1, o2)) { + return false; + } + } + return !iterator2.hasNext(); + } + + public static int size(Iterable<?> iterable) { + Iterator<?> iterator = iterable.iterator(); + int count = 0; + while (iterator.hasNext()) { + count++; + iterator.next(); + } + return count; + } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/Range.java b/dexlib2/src/main/java/com/android/tools/smali/util/Range.java new file mode 100644 index 00000000..f74377f9 --- /dev/null +++ b/dexlib2/src/main/java/com/android/tools/smali/util/Range.java @@ -0,0 +1,297 @@ +/* + * Copyright 2024, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.tools.smali.util; + +import java.util.Comparator; +import java.util.Objects; + +/* + * Represents a Range of values of type C. It can have open bounds if the range doesn't include the + * bound value. It can also be unbounded on the lower or upper side. Simplified version of a guava + * Range. + */ +public class Range<C extends Comparable> { + public static final Comparator<Range<?>> RANGE_LEX_COMPARATOR = new Comparator<Range<?>>() { + @Override + public int compare(Range<?> left, Range<?> right) { + int cmp = 0; + if (!left.hasLowerBound() && right.hasLowerBound()) { + return -1; + } else if (!right.hasLowerBound() && left.hasLowerBound()) { + return 1; + } else if (left.hasLowerBound() && right.hasLowerBound()) { + cmp = left.lowerBound.compareTo(right.lowerBound); + } + + if (cmp != 0) { + return cmp; + } + if (!left.hasUpperBound() && right.hasUpperBound()) { + return 1; + } else if (!right.hasUpperBound() && left.hasUpperBound()) { + return -1; + } else if (left.hasUpperBound() && right.hasUpperBound()) { + cmp = left.upperBound.compareTo(right.upperBound); + } + return cmp; + } + }; + + private C lowerBound; + private C upperBound; + private boolean lowerOpen; + private boolean upperOpen; + private boolean allValues; + + public static <C extends Comparable> Range<C> closed(C lowerBound, C upperBound) { + if (lowerBound == null || upperBound == null) { + throw new NullPointerException(); + } + if (lowerBound.compareTo(upperBound) > 0) { + throw new IllegalArgumentException("lowerBound must be <= upperBound"); + } + return new Range<>(lowerBound, upperBound, false, false); + } + + public static <C extends Comparable> Range<C> open(C lowerBound, C upperBound) { + if (lowerBound == null || upperBound == null) { + throw new NullPointerException(); + } + if (lowerBound.compareTo(upperBound) > 0) { + throw new IllegalArgumentException("lowerBound must be <= upperBound"); + } + return new Range<>(lowerBound, upperBound, true, true); + } + + public static <C extends Comparable> Range<C> openClosed(C lowerBound, C upperBound) { + if (lowerBound == null || upperBound == null) { + throw new NullPointerException(); + } + if (lowerBound.compareTo(upperBound) > 0) { + throw new IllegalArgumentException("lowerBound must be <= upperBound"); + } + return new Range<>(lowerBound, upperBound, true, false); + } + + public static <C extends Comparable> Range<C> closedOpen(C lowerBound, C upperBound) { + if (lowerBound == null || upperBound == null) { + throw new NullPointerException(); + } + if (lowerBound.compareTo(upperBound) > 0) { + throw new IllegalArgumentException("lowerBound must be <= upperBound"); + } + return new Range<>(lowerBound, upperBound, false, true); + } + + public static <C extends Comparable> Range<C> atLeast(C lowerBound) { + if (lowerBound == null) { + throw new NullPointerException(); + } + return new Range<>(lowerBound, null, false, false); + } + + public static <C extends Comparable> Range<C> atMost(C upperBound) { + if (upperBound == null) { + throw new NullPointerException(); + } + return new Range<>(null, upperBound, false, false); + } + + public static <C extends Comparable> Range<C> allValues() { + return new Range<>(); + } + + private Range(C lowerBound, C upperBound, boolean lowerOpen, boolean upperOpen) { + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.lowerOpen = lowerOpen; + this.upperOpen = upperOpen; + allValues = false; + } + + private Range() { + allValues = true; + lowerBound = null; + upperBound = null; + lowerOpen = false; + upperOpen = false; + } + + public boolean isEmpty() { + return !allValues + && Objects.equals(lowerBound, upperBound) + && (lowerOpen || upperOpen); + } + + public C getLowerBound() { + return lowerBound; + } + + public C getUpperBound() { + return upperBound; + } + + public boolean openLowerBound() { + return lowerOpen; + } + + public boolean openUpperBound() { + return upperOpen; + } + + public boolean hasAllValues() { + return allValues; + } + + public boolean hasLowerBound() { + return lowerBound != null; + } + + public boolean hasUpperBound() { + return upperBound != null; + } + + /* Returns true if value is included in the Range */ + public boolean contains(C value) { + if (value == null) { + return false; + } + if (allValues) { + return true; + } + + if (lowerBound != null) { + if (lowerOpen && value.compareTo(lowerBound) == 0) { + return false; + } + if (value.compareTo(lowerBound) < 0) { + return false; + } + } + if (upperBound != null) { + if (upperOpen && value.compareTo(upperBound) == 0) { + return false; + } + if (value.compareTo(upperBound) > 0) { + return false; + } + } + return true; + } + + /* + * Returns true if there exists a (possibly empty) range which is enclosed by both this range + * and other. + */ + public boolean isConnected(Range<C> other) { + return (!hasLowerBound() || !other.hasUpperBound() + || lowerBound.compareTo(other.getUpperBound()) <= 0) + && (!hasUpperBound() || !other.hasLowerBound() + || other.getLowerBound().compareTo(upperBound) <= 0); + } + + /* Returns the maximal range enclosed by both this range and other, if such a range exists. */ + public Range<C> intersection(Range<C> other) { + if (!isConnected(other)) { + return null; + } + + // select the max of the lowerBounds. If they're equal, + // choose the range that has an open lower bound + Range<C> lowerBoundRange; + if (!hasLowerBound() || !other.hasLowerBound()) { + lowerBoundRange = hasLowerBound() ? this : other; + } else if (Objects.equals(lowerBound, other.getLowerBound())) { + lowerBoundRange = lowerOpen ? this : other; + } else { + lowerBoundRange = lowerBound.compareTo(other.getLowerBound()) > 0 ? this : other; + } + + // and the min of the upperBounds, or the open upper bound if they're equal + Range<C> upperBoundRange; + if (!hasUpperBound() || !other.hasUpperBound()) { + upperBoundRange = hasUpperBound() ? this : other; + } else if (Objects.equals(upperBound, other.getUpperBound())) { + upperBoundRange = upperOpen ? this : other; + } else { + upperBoundRange = upperBound.compareTo(other.getUpperBound()) < 0 ? this : other; + } + + return new Range<C>( + lowerBoundRange.getLowerBound(), + upperBoundRange.getUpperBound(), + lowerBoundRange.openLowerBound(), + upperBoundRange.openUpperBound()); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Range)) { + return false; + } + Range<?> other = (Range<?>) o; + + if (allValues != other.hasAllValues()) { + return false; + } + + return Objects.equals(lowerBound, other.lowerBound) + && Objects.equals(upperBound, other.upperBound) + && lowerOpen == other.openLowerBound() + && upperOpen == other.openUpperBound(); + } + + @Override + public String toString() { + if (allValues) { + return "[*]"; + } + String sb = ""; + if (lowerOpen) { + sb += "("; + } else { + sb += "["; + } + sb += lowerBound; + sb += ", "; + sb += upperBound; + if (upperOpen) { + sb += ")"; + } else { + sb += "]"; + } + return sb; + } + +} diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/StringUtils.java b/dexlib2/src/main/java/com/android/tools/smali/util/StringUtils.java index 730caa8f..767c6ddf 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/StringUtils.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/StringUtils.java @@ -31,15 +31,18 @@ package com.android.tools.smali.util; import com.android.tools.smali.dexlib2.formatter.DexFormattedWriter; +import com.android.tools.smali.dexlib2.iface.value.CharEncodedValue; + import java.io.IOException; import java.io.Writer; +import java.util.Collection; import java.util.Iterator; -import java.util.List; public class StringUtils { /** - * @deprecated Use {@link com.android.tools.smali.baksmali.formatter.BaksmaliWriter#writeCharEncodedValue} + * @deprecated Use @see + * com.android.tools.smali.baksmali.formatter.BaksmaliWriter}#writeCharEncodedValue() */ @Deprecated public static void writeEscapedChar(Writer writer, char c) throws IOException { @@ -51,9 +54,15 @@ public class StringUtils { return; } else if (c <= 0x7f) { switch (c) { - case '\n': writer.write("\\n"); return; - case '\r': writer.write("\\r"); return; - case '\t': writer.write("\\t"); return; + case '\n': + writer.write("\\n"); + return; + case '\r': + writer.write("\\r"); + return; + case '\t': + writer.write("\\t"); + return; } } @@ -80,9 +89,15 @@ public class StringUtils { continue; } else if (c <= 0x7f) { switch (c) { - case '\n': writer.write("\\n"); continue; - case '\r': writer.write("\\r"); continue; - case '\t': writer.write("\\t"); continue; + case '\n': + writer.write("\\n"); + continue; + case '\r': + writer.write("\\r"); + continue; + case '\t': + writer.write("\\t"); + continue; } } @@ -109,9 +124,15 @@ public class StringUtils { continue; } else if (c <= 0x7f) { switch (c) { - case '\n': sb.append("\\n"); continue; - case '\r': sb.append("\\r"); continue; - case '\t': sb.append("\\t"); continue; + case '\n': + sb.append("\\n"); + continue; + case '\r': + sb.append("\\r"); + continue; + case '\t': + sb.append("\\t"); + continue; } } @@ -125,7 +146,7 @@ public class StringUtils { return sb.toString(); } - public static String join(List<? extends Object> parts, String separator) { + public static String join(Collection<? extends Object> parts, String separator) { StringBuilder builder = new StringBuilder(); Iterator<? extends Object> it = parts.iterator(); if (it.hasNext()) { @@ -137,4 +158,35 @@ public class StringUtils { } return builder.toString(); } + + // Base on the repeat method in guava Strings, of the same signature. + public static String repeat(String string, int count) { + if (string == null) { + throw new NullPointerException("string == null"); + } + + if (count <= 1) { + if (count >= 0) { + throw new IllegalArgumentException("invalid count: " + count); + } + return (count == 0) ? "" : string; + } + + final int len = string.length(); + final long longSize = (long) len * (long) count; + final int size = (int) longSize; + if (size != longSize) { + throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize); + } + + final char[] array = new char[size]; + string.getChars(0, len, array, 0); + int n; + for (n = len; n < size - n; n <<= 1) { + System.arraycopy(array, 0, array, n, n); + } + System.arraycopy(array, 0, array, n, size - n); + return new String(array); + + } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/TransformedIterator.java b/dexlib2/src/main/java/com/android/tools/smali/util/TransformedIterator.java index bf89ea99..ab5179a1 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/TransformedIterator.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/TransformedIterator.java @@ -32,7 +32,6 @@ package com.android.tools.smali.util; import java.util.Iterator; import java.util.function.Function; -import org.checkerframework.checker.nullness.qual.Nullable; /** * An iterator that will return the results of applying {@code transformFunction} to each element of @@ -40,11 +39,17 @@ import org.checkerframework.checker.nullness.qual.Nullable; * <p> * The returned iterator supports {@code remove()} if {@code backingIterator} does. */ -public class TransformedIterator<F extends @Nullable Object, T extends @Nullable Object> - implements Iterator<T> { +public class TransformedIterator<F extends Object, T extends Object> + implements Iterator<T>, Iterable<T> { final Iterator<? extends F> backingIterator; final Function<F, T> transformFunction; + public TransformedIterator(Iterable<? extends F> backingIterable, + Function<F, T> transformFunction) { + this.backingIterator = backingIterable.iterator(); + this.transformFunction = transformFunction; + } + public TransformedIterator(Iterator<? extends F> backingIterator, Function<F, T> transformFunction) { this.backingIterator = backingIterator; @@ -65,4 +70,9 @@ public class TransformedIterator<F extends @Nullable Object, T extends @Nullable public final void remove() { backingIterator.remove(); } + + @Override + public final Iterator<T> iterator() { + return this; + } } diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/UnmodifiableRangeMap.java b/dexlib2/src/main/java/com/android/tools/smali/util/UnmodifiableRangeMap.java new file mode 100644 index 00000000..eed14b63 --- /dev/null +++ b/dexlib2/src/main/java/com/android/tools/smali/util/UnmodifiableRangeMap.java @@ -0,0 +1,205 @@ +/* + * Copyright 2024, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.tools.smali.util; + +import javax.annotation.CheckForNull; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/* + * Based on guava's ImmutableRangeMap + */ +public class UnmodifiableRangeMap<K extends Comparable<?>, V> { + private static final UnmodifiableRangeMap<Comparable<?>, Object> EMPTY = new UnmodifiableRangeMap<>( + Collections.emptyList(), Collections.emptyList()); + + /** Returns a new builder for an immutable range map. */ + public static <K extends Comparable<?>, V> Builder<K, V> builder() { + return new Builder<>(); + } + + /** + * Returns an empty immutable range map. + * <p> + * <b>Performance note:</b> the instance returned is a singleton. + */ + public static <K extends Comparable<?>, V> UnmodifiableRangeMap<K, V> of() { + return (UnmodifiableRangeMap<K, V>) EMPTY; + } + + /** + * A builder for immutable range maps. Overlapping ranges are prohibited. + * + * @since 14.0 + */ + public static final class Builder<K extends Comparable<?>, V> { + + private final List<Entry<Range<K>, V>> entries; + + public Builder() { + this.entries = new ArrayList<>(); + } + + /** + * Associates the specified range with the specified value. + * + * @throws IllegalArgumentException if {@code range} is empty + */ + public Builder<K, V> put(Range<K> range, V value) { + if (range == null || value == null) { + throw new NullPointerException("Both range and value must be non-null"); + } + + if (range.isEmpty()) { + throw new IllegalArgumentException("Ranges cannot be empty"); + } + entries.add(new UnmodifiableEntry(range, value)); + return this; + } + + /** + * Returns an {@code ImmutableRangeMap} containing the associations previously added to this + * builder. + * + * @throws IllegalArgumentException if any two ranges inserted into this builder overlap + */ + public UnmodifiableRangeMap<K, V> build() { + Collections.sort(entries, + (e1, e2) -> Range.RANGE_LEX_COMPARATOR.compare(e1.getKey(), e2.getKey())); + ArrayList<Range<K>> rangesList = new ArrayList<>(entries.size()); + ArrayList<V> valuesList = new ArrayList<>(entries.size()); + for (int i = 0; i < entries.size(); i++) { + Range<K> range = entries.get(i).getKey(); + if (i > 0) { + Range<K> prevRange = entries.get(i - 1).getKey(); + if (range.isConnected(prevRange) && !range.intersection(prevRange).isEmpty()) { + throw new IllegalArgumentException( + "Overlapping ranges: range " + prevRange + " overlaps with entry " + + range); + } + } + rangesList.add(range); + valuesList.add(entries.get(i).getValue()); + } + return new UnmodifiableRangeMap(rangesList, valuesList); + } + } + + private final transient List<Range<K>> ranges; + private final transient List<V> values; + + private UnmodifiableRangeMap(List<Range<K>> ranges, List<V> values) { + this.ranges = Collections.unmodifiableList(ranges); + this.values = Collections.unmodifiableList(values); + } + + @CheckForNull + public V get(K key) { + if (key == null) { + return null; + } + + int index = rangeBinarySearch(ranges, key); + if (index == -1) { + return null; + } else { + Range<K> range = ranges.get(index); + return range.contains(key) ? values.get(index) : null; + } + } + + @CheckForNull + public Entry<Range<K>, V> getEntry(K key) { + if (key == null) { + return null; + } + + int index = rangeBinarySearch(ranges, key); + if (index == -1) { + return null; + } else { + Range<K> range = ranges.get(index); + return range.contains(key) ? new UnmodifiableEntry(range, values.get(index)) : null; + } + } + + private static <T extends Comparable> int rangeBinarySearch(List<Range<T>> l, T key) { + int low = 0; + int high = l.size() - 1; + + while (low <= high) { + int mid = (low + high) >>> 1; + Range<T> midRange = l.get(mid); + if (midRange.contains(key)) { + return mid; + } + + int cmp = midRange.hasLowerBound() ? key.compareTo(midRange.getLowerBound()) + : key.compareTo(midRange.getUpperBound()); + + if (cmp > 0) + low = mid + 1; + else if (cmp < 0) + high = mid - 1; + else + return mid; // key found + } + return -1; // key not found + } + + public static class UnmodifiableEntry<K, V> implements Map.Entry<K, V> { + private final K key; + private final V value; + + public UnmodifiableEntry(K key, V value) { + this.key = key; + this.value = value; + } + + @Override + public K getKey() { + return key; + } + + @Override + public V getValue() { + return value; + } + + @Override + public V setValue(V value) { + throw new UnsupportedOperationException(); + } + } +} diff --git a/dexlib2/src/main/java/com/android/tools/smali/util/WrappedIndentingWriter.java b/dexlib2/src/main/java/com/android/tools/smali/util/WrappedIndentingWriter.java index bf1798e1..16873e93 100644 --- a/dexlib2/src/main/java/com/android/tools/smali/util/WrappedIndentingWriter.java +++ b/dexlib2/src/main/java/com/android/tools/smali/util/WrappedIndentingWriter.java @@ -30,8 +30,6 @@ package com.android.tools.smali.util; -import com.google.common.collect.Lists; - import java.io.FilterWriter; import java.io.IOException; import java.io.Writer; @@ -76,7 +74,8 @@ public class WrappedIndentingWriter extends FilterWriter { } private void wrapLine() throws IOException { - List<String> wrapped = Lists.newArrayList(StringWrapper.wrapStringOnBreaks(line.toString(), maxWidth)); + List<String> wrapped = IteratorUtils.toList( + StringWrapper.wrapStringOnBreaks(line.toString(), maxWidth)); out.write(wrapped.get(0), 0, wrapped.get(0).length()); out.write('\n'); diff --git a/dexlib2/src/test/java/com/android/tools/smali/dexlib2/util/RangeTest.java b/dexlib2/src/test/java/com/android/tools/smali/dexlib2/util/RangeTest.java new file mode 100644 index 00000000..23fea452 --- /dev/null +++ b/dexlib2/src/test/java/com/android/tools/smali/dexlib2/util/RangeTest.java @@ -0,0 +1,499 @@ + +/* + * Copyright 2024, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.tools.smali.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import com.android.tools.smali.util.Range; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +public class RangeTest { + + @Test + public void testClosed() { + Range<Integer> range = Range.closed(1, 10); + assertTrue(range.contains(1)); + assertTrue(range.contains(10)); + assertTrue(range.contains(5)); + assertFalse(range.contains(0)); + assertFalse(range.contains(11)); + } + + @Test + public void testOpenClosed() { + Range<Integer> range = Range.openClosed(1, 10); + assertTrue(range.contains(10)); + assertFalse(range.contains(1)); + assertTrue(range.contains(5)); + assertFalse(range.contains(0)); + assertFalse(range.contains(11)); + } + + @Test + public void testClosedOpen() { + Range<Integer> range = Range.closedOpen(1, 10); + assertFalse(range.contains(10)); + assertTrue(range.contains(1)); + assertTrue(range.contains(5)); + assertFalse(range.contains(0)); + assertFalse(range.contains(11)); + } + + @Test + public void testOpen() { + Range<Integer> range = Range.open(1, 10); + assertFalse(range.contains(10)); + assertFalse(range.contains(1)); + assertTrue(range.contains(5)); + assertFalse(range.contains(11)); + assertFalse(range.contains(0)); + } + + @Test + public void testAtLeast() { + Range<Integer> range = Range.atLeast(1); + assertTrue(range.contains(1)); + assertTrue(range.contains(10)); + assertFalse(range.contains(0)); + } + + @Test + public void testAtMost() { + Range<Integer> range = Range.atMost(10); + assertFalse(range.contains(11)); + assertTrue(range.contains(10)); + assertTrue(range.contains(5)); + } + + @Test + public void testAllValues() { + Range<Integer> range = Range.allValues(); + assertTrue(range.contains(1)); + assertTrue(range.contains(10)); + assertTrue(range.contains(0)); + assertTrue(range.contains(11)); + } + + @Test + public void testEquals() { + Range<Integer> range1 = Range.closed(1, 10); + Range<Integer> range2 = Range.closed(1, 10); + assertTrue(range1.equals(range2)); + + range1 = Range.open(1, 10); + range2 = Range.open(1, 10); + assertTrue(range1.equals(range2)); + + range1 = Range.closedOpen(1, 10); + range2 = Range.closedOpen(1, 10); + assertTrue(range1.equals(range2)); + + range1 = Range.openClosed(1, 10); + range2 = Range.openClosed(1, 10); + assertTrue(range1.equals(range2)); + + range1 = Range.atLeast(1); + range2 = Range.atLeast(1); + assertTrue(range1.equals(range2)); + + range1 = Range.atMost(10); + range2 = Range.atMost(10); + assertTrue(range1.equals(range2)); + + range1 = Range.allValues(); + range2 = Range.allValues(); + assertTrue(range1.equals(range2)); + + range1 = Range.closed(1, 10); + range2 = Range.closed(1, 11); + assertFalse(range1.equals(range2)); + + range1 = Range.open(1, 10); + range2 = Range.open(0, 10); + assertFalse(range1.equals(range2)); + + range1 = Range.closed(1, 10); + range2 = Range.open(1, 10); + assertFalse(range1.equals(range2)); + + range1 = Range.closed(1, 10); + range2 = Range.closedOpen(1, 10); + assertFalse(range1.equals(range2)); + + range1 = Range.closedOpen(1, 10); + range2 = Range.openClosed(1, 10); + assertFalse(range1.equals(range2)); + + range1 = Range.closed(1, 10); + range2 = Range.atLeast(1); + assertFalse(range1.equals(range2)); + + range1 = Range.closed(1, 10); + range2 = Range.atMost(10); + assertFalse(range1.equals(range2)); + + range1 = Range.closed(1, 10); + range2 = Range.allValues(); + assertFalse(range1.equals(range2)); + + range1 = Range.open(1, 10); + range2 = Range.closedOpen(1, 10); + assertFalse(range1.equals(range2)); + + range1 = Range.open(1, 10); + range2 = Range.openClosed(1, 10); + assertFalse(range1.equals(range2)); + + range1 = Range.open(1, 10); + range2 = Range.atLeast(1); + assertFalse(range1.equals(range2)); + + range1 = Range.open(1, 10); + range2 = Range.atMost(10); + assertFalse(range1.equals(range2)); + + range1 = Range.open(1, 10); + range2 = Range.allValues(); + assertFalse(range1.equals(range2)); + + range1 = Range.closedOpen(1, 10); + range2 = Range.openClosed(1, 10); + assertFalse(range1.equals(range2)); + + range1 = Range.closedOpen(1, 10); + range2 = Range.atLeast(1); + assertFalse(range1.equals(range2)); + + range1 = Range.closedOpen(1, 10); + range2 = Range.atMost(10); + assertFalse(range1.equals(range2)); + + range1 = Range.closedOpen(1, 10); + range2 = Range.allValues(); + assertFalse(range1.equals(range2)); + + range1 = Range.openClosed(1, 10); + range2 = Range.atLeast(1); + assertFalse(range1.equals(range2)); + + range1 = Range.openClosed(1, 10); + range2 = Range.atMost(10); + assertFalse(range1.equals(range2)); + + range1 = Range.openClosed(1, 10); + range2 = Range.allValues(); + assertFalse(range1.equals(range2)); + + range1 = Range.atLeast(1); + range2 = Range.atMost(1); + assertFalse(range1.equals(range2)); + + range1 = Range.atLeast(1); + range2 = Range.allValues(); + assertFalse(range1.equals(range2)); + + range1 = Range.atMost(10); + range2 = Range.allValues(); + assertFalse(range1.equals(range2)); + } + + @Test + public void testIsEmpty() { + Range<Integer> range = Range.closed(1, 1); + assertFalse(range.isEmpty()); + + range = Range.openClosed(2, 2); + assertTrue(range.isEmpty()); + + range = Range.closedOpen(3, 3); + assertTrue(range.isEmpty()); + + range = Range.open(4, 4); + assertTrue(range.isEmpty()); + + range = Range.open(4, 5); + assertFalse(range.isEmpty()); + + range = Range.atMost(10); + assertFalse(range.isEmpty()); + + range = Range.atLeast(10); + assertFalse(range.isEmpty()); + + range = Range.allValues(); + assertFalse(range.isEmpty()); + } + + @Test + public void testGetLowerBound() { + Range<Integer> range = Range.closed(1, 10); + assertEquals((Integer) 1, range.getLowerBound()); + } + + @Test + public void testGetUpperBound() { + Range<Integer> range = Range.closed(1, 10); + assertEquals((Integer) 10, range.getUpperBound()); + } + + @Test + public void testHasLowerBound() { + assertTrue(Range.closed(1, 10).hasLowerBound()); + assertTrue(Range.open(1, 10).hasLowerBound()); + assertTrue(Range.openClosed(1, 10).hasLowerBound()); + assertTrue(Range.closedOpen(1, 10).hasLowerBound()); + assertTrue(Range.atLeast(1).hasLowerBound()); + assertFalse(Range.atMost(10).hasLowerBound()); + assertFalse(Range.allValues().hasLowerBound()); + } + + @Test + public void testHasUpperBound() { + assertTrue(Range.closed(1, 10).hasUpperBound()); + assertTrue(Range.open(1, 10).hasUpperBound()); + assertTrue(Range.openClosed(1, 10).hasUpperBound()); + assertTrue(Range.closedOpen(1, 10).hasUpperBound()); + assertFalse(Range.atLeast(1).hasUpperBound()); + assertTrue(Range.atMost(10).hasUpperBound()); + assertFalse(Range.allValues().hasUpperBound()); + } + + @Test + public void testIsConnected() { + Range<Integer> range1 = Range.closed(1, 5); + Range<Integer> range2 = Range.closed(3, 7); + assertTrue(range1.isConnected(range2)); + assertTrue(range2.isConnected(range1)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(6, 7); + assertFalse(range1.isConnected(range2)); + assertFalse(range2.isConnected(range1)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(0, 2); + assertTrue(range1.isConnected(range2)); + assertTrue(range2.isConnected(range1)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(10, 20); + assertFalse(range1.isConnected(range2)); + assertFalse(range2.isConnected(range1)); + } + + @Test + public void testIsConnected_edgeConnection() { + Range<Integer> range1 = Range.closed(1, 5); + Range<Integer> range2 = Range.closed(5, 7); + assertTrue(range1.isConnected(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(3, 5); + assertTrue(range1.isConnected(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(1, 3); + assertTrue(range1.isConnected(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(1, 5); + assertTrue(range1.isConnected(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(5, 5); + assertTrue(range1.isConnected(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.openClosed(5, 10); + assertTrue(range1.isConnected(range2)); + } + + @Test + public void testIntersection() { + Range<Integer> range1 = Range.closed(1, 5); + Range<Integer> range2 = Range.closed(3, 7); + assertEquals(Range.closed(3, 5), range1.intersection(range2)); + assertEquals(Range.closed(3, 5), range2.intersection(range1)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(6, 7); + assertNull(range1.intersection(range2)); + assertNull(range2.intersection(range1)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(0, 2); + assertEquals(Range.closed(1, 2), range1.intersection(range2)); + assertEquals(Range.closed(1, 2), range2.intersection(range1)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(5, 7); + assertEquals(Range.closed(5, 5), range1.intersection(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(3, 5); + assertEquals(Range.closed(3, 5), range1.intersection(range2)); + assertEquals(Range.closed(3, 5), range2.intersection(range1)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(2, 4); + assertEquals(Range.closed(2, 4), range1.intersection(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(1, 3); + assertEquals(Range.closed(1, 3), range1.intersection(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(1, 5); + assertEquals(Range.closed(1, 5), range1.intersection(range2)); + + range1 = Range.closed(1, 5); + range2 = Range.closed(5, 5); + assertEquals(Range.closed(5, 5), range1.intersection(range2)); + } + + @Test + public void testIntersection_openBounds() { + Range<Integer> range1 = Range.openClosed(1, 5); + Range<Integer> range2 = Range.closed(3, 7); + assertEquals(Range.closed(3, 5), range1.intersection(range2)); + + range1 = Range.openClosed(1, 5); + range2 = Range.closed(6, 7); + assertNull(range1.intersection(range2)); + + range1 = Range.openClosed(1, 5); + range2 = Range.closed(5, 7); + assertEquals(Range.closed(5, 5), range1.intersection(range2)); + + range1 = Range.openClosed(4, 6); + range2 = Range.closed(1, 5); + assertEquals(Range.openClosed(4, 5), range1.intersection(range2)); + + range1 = Range.closedOpen(1, 5); + range2 = Range.closed(3, 5); + assertEquals(Range.closedOpen(3, 5), range1.intersection(range2)); + + range1 = Range.openClosed(1, 5); + range2 = Range.closed(2, 4); + assertEquals(Range.closed(2, 4), range1.intersection(range2)); + + range1 = Range.open(1, 5); + range2 = Range.closed(1, 3); + assertEquals(Range.openClosed(1, 3), range1.intersection(range2)); + + range1 = Range.open(1, 5); + range2 = Range.closed(1, 5); + assertEquals(Range.open(1, 5), range1.intersection(range2)); + + range1 = Range.closed(1, 10); + range2 = Range.open(2, 4); + assertEquals(Range.open(2, 4), range1.intersection(range2)); + + range1 = Range.open(1, 10); + range2 = Range.closed(2, 5); + assertEquals(Range.closed(2, 5), range1.intersection(range2)); + + range1 = Range.openClosed(1, 5); + range2 = Range.closed(1, 5); + assertEquals(Range.openClosed(1, 5), range1.intersection(range2)); + + range1 = Range.closedOpen(1, 5); + range2 = Range.closed(1, 5); + assertEquals(Range.closedOpen(1, 5), range1.intersection(range2)); + } + + @Test + public void testIntersection_atLeastAtMost(){ + Range<Integer> range1 = Range.atLeast(1); + Range<Integer> range2 = Range.atLeast(5); + assertEquals(Range.atLeast(5), range1.intersection(range2)); + + range1 = Range.atMost(1); + range2 = Range.atMost(5); + assertEquals(Range.atMost(1), range1.intersection(range2)); + } + + @Test + public void testRangeLexComparator() { + List<Range<Integer>> ranges = Arrays.asList( + Range.closed(1, 3), + Range.closed(2, 4), + Range.closed(1, 4), + Range.closed(2, 3), + Range.closed(7, 10), + Range.closed(3, 4), + Range.closed(1, 2)); + ranges.sort(Range.RANGE_LEX_COMPARATOR); + assertEquals( + Arrays.asList( + Range.closed(1, 2), + Range.closed(1, 3), + Range.closed(1, 4), + Range.closed(2, 3), + Range.closed(2, 4), + Range.closed(3, 4), + Range.closed(7, 10)), + ranges); + } + + @Test + public void testRangeLexComparator_openBounds() { + List<Range<Integer>> ranges = Arrays.asList( + Range.closed(2, 4), + Range.closed(1, 4), + Range.closed(2, 3), + Range.atLeast(7), + Range.atMost(3), + Range.closed(3, 4), + Range.closed(1, 2)); + ranges.sort(Range.RANGE_LEX_COMPARATOR); + assertEquals( + Arrays.asList( + Range.atMost(3), + Range.closed(1, 2), + Range.closed(1, 4), + Range.closed(2, 3), + Range.closed(2, 4), + Range.closed(3, 4), + Range.atLeast(7)), + ranges); + } +} diff --git a/dexlib2/src/test/java/com/android/tools/smali/dexlib2/util/UnmodifiableRangeMapTest.java b/dexlib2/src/test/java/com/android/tools/smali/dexlib2/util/UnmodifiableRangeMapTest.java new file mode 100644 index 00000000..dead33e4 --- /dev/null +++ b/dexlib2/src/test/java/com/android/tools/smali/dexlib2/util/UnmodifiableRangeMapTest.java @@ -0,0 +1,166 @@ +/* + * Copyright 2024, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.tools.smali.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import com.android.tools.smali.util.Range; +import com.android.tools.smali.util.UnmodifiableRangeMap; + +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +public class UnmodifiableRangeMapTest { + + @Test + public void testEmpty() { + UnmodifiableRangeMap<Integer, String> map = UnmodifiableRangeMap.of(); + Assert.assertNull(map.get(0)); + Assert.assertNull(map.getEntry(0)); + } + + @Test + public void testBuilder() { + UnmodifiableRangeMap<Integer, String> rangeMap = + UnmodifiableRangeMap.<Integer, String>builder() + .put(Range.closed(1, 3), "a") + .put(Range.closed(4, 6), "b") + .build(); + assertEquals("a", rangeMap.get(2)); + assertEquals("b", rangeMap.get(5)); + assertNull(rangeMap.get(0)); + assertNull(rangeMap.get(7)); + assertNull(rangeMap.get(null)); + } + + @Test(expected = IllegalArgumentException.class) + public void testBuilderEmptyRange() { + UnmodifiableRangeMap.<Integer, String>builder().put(Range.open(1, 1), "a").build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testBuilderOverlappingRanges() { + UnmodifiableRangeMap.<Integer, String>builder() + .put(Range.closed(1, 3), "a") + .put(Range.closed(2, 4), "b") + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testBuilderEdgeOverlappingRanges() { + UnmodifiableRangeMap.<Integer, String>builder() + .put(Range.closed(1, 3), "a") + .put(Range.closed(3, 7), "b") + .build(); + } + + @Test + public void testGet_oddSizeMap() { + UnmodifiableRangeMap<Integer, String> rangeMap = + UnmodifiableRangeMap.<Integer, String>builder() + .put(Range.closed(1, 3), "a") + .put(Range.closed(4, 6), "b") + .put(Range.closed(11, 20), "c") + .build(); + assertEquals("a", rangeMap.get(2)); + assertEquals("c", rangeMap.get(15)); + assertNull(rangeMap.get(0)); + assertNull(rangeMap.get(7)); + } + + @Test + public void testGet_evenSizeMap() { + UnmodifiableRangeMap<Integer, String> rangeMap = + UnmodifiableRangeMap.<Integer, String>builder() + .put(Range.closed(1, 3), "a") + .put(Range.closed(4, 6), "b") + .put(Range.closed(11, 20), "c") + .put(Range.closed(21, 30), "d") + .build(); + assertEquals("a", rangeMap.get(2)); + assertEquals("b", rangeMap.get(6)); + assertEquals("c", rangeMap.get(15)); + assertEquals("d", rangeMap.get(23)); + assertNull(rangeMap.get(0)); + assertNull(rangeMap.get(7)); + } + + @Test + public void testEntry() { + UnmodifiableRangeMap<Integer, String> rangeMap = + UnmodifiableRangeMap.<Integer, String>builder() + .put(Range.closed(1, 3), "a") + .put(Range.closed(4, 6), "b") + .put(Range.closed(10, 15), "c") + .build(); + Map.Entry<Range<Integer>, String> entry = rangeMap.getEntry(2); + assertEquals(Range.closed(1, 3), entry.getKey()); + assertEquals("a", entry.getValue()); + assertNull(rangeMap.getEntry(null)); + } + + @Test + public void testRanges_AtMostAtLeast() { + UnmodifiableRangeMap<Integer, String> rangeMap = + UnmodifiableRangeMap.<Integer, String>builder() + .put(Range.atMost(3), "a") + .put(Range.closed(10, 15), "b") + .put(Range.atLeast(25), "c") + .build(); + assertEquals("a", rangeMap.get(2)); + assertNull(rangeMap.get(5)); + assertEquals("b", rangeMap.get(12)); + assertEquals("c", rangeMap.get(30)); + assertNull(rangeMap.get(null)); + } + + @Test + public void testRanges_openBounds() { + UnmodifiableRangeMap<Integer, String> rangeMap = + UnmodifiableRangeMap.<Integer, String>builder() + .put(Range.openClosed(1, 3), "a") + .put(Range.open(10, 15), "b") + .put(Range.closedOpen(25, 30), "c") + .build(); + + assertNull(rangeMap.get(0)); + assertNull(rangeMap.get(1)); + assertEquals("a", rangeMap.get(2)); + assertEquals("b", rangeMap.get(12)); + assertNull(rangeMap.get(5)); + assertNull(rangeMap.get(15)); + assertEquals("c", rangeMap.get(25)); + assertEquals("c", rangeMap.get(25)); + } +}
\ No newline at end of file diff --git a/dexlib2/src/test/java/com/android/tools/smali/util/ArraySortedSetTest.java b/dexlib2/src/test/java/com/android/tools/smali/util/ArraySortedSetTest.java new file mode 100644 index 00000000..658ad4dd --- /dev/null +++ b/dexlib2/src/test/java/com/android/tools/smali/util/ArraySortedSetTest.java @@ -0,0 +1,179 @@ +/* + * Copyright 2024, Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.tools.smali.util; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Iterator; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ArraySortedSetTest { + @Test + public void testOf() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), new Integer[] { + 1, 2, 3 + }); + Assert.assertEquals(set.size(), 3); + Assert.assertTrue(set.contains(1)); + Assert.assertTrue(set.contains(2)); + Assert.assertTrue(set.contains(3)); + Assert.assertFalse(set.contains(4)); + } + + @Test + public void testOfCollection() { + List<Integer> list = Arrays.asList(1, 2, 3); + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), list); + Assert.assertEquals(set.size(), 3); + Assert.assertTrue(set.contains(1)); + Assert.assertTrue(set.contains(2)); + Assert.assertTrue(set.contains(3)); + Assert.assertFalse(set.contains(4)); + } + + @Test(expected = AssertionError.class) + public void testOfUnsorted() { + ArraySortedSet.of(Comparator.naturalOrder(), new Integer[] { + 3, 1, 2 + }); + } + + @Test(expected = AssertionError.class) + public void testOfCollectionUnsorted() { + ArraySortedSet.of(Comparator.naturalOrder(), Arrays.asList(3, 1, 2)); + } + + @Test + public void testIterator() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + Iterator<Integer> it = set.iterator(); + Assert.assertEquals(it.next(), (Integer) 1); + Assert.assertEquals(it.next(), (Integer) 2); + Assert.assertEquals(it.next(), (Integer) 3); + } + + @Test + public void testToArray() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + Assert.assertArrayEquals(set.toArray(), new Integer[] { + 1, 2, 3 + }); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAdd() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + set.add(4); + } + + @Test(expected = UnsupportedOperationException.class) + public void testRemove() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + set.remove(2); + } + + @Test + public void testContainsAll() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + Assert.assertTrue(set.containsAll(Arrays.asList(1, 2))); + Assert.assertTrue(set.containsAll(Arrays.asList(1, 2, 3))); + Assert.assertFalse(set.containsAll(Arrays.asList(1, 2, 3, 4))); + } + + @Test(expected = UnsupportedOperationException.class) + public void testAddAll() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + set.addAll(Arrays.asList(4)); + } + + @Test(expected = UnsupportedOperationException.class) + public void testRemoveAll() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + set.removeAll(Arrays.asList(2)); + } + + @Test(expected = UnsupportedOperationException.class) + public void testClear() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + set.clear(); + } + + @Test + public void testComparator() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + Assert.assertEquals(set.comparator(), Comparator.naturalOrder()); + } + + @Test + public void testFirst() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + Assert.assertEquals(set.first(), (Integer) 1); + } + + @Test + public void testLast() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + Assert.assertEquals(set.last(), (Integer) 3); + } + + @Test + public void testHashCode() { + ArraySortedSet<Integer> set = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + Assert.assertEquals(set.hashCode(), 6); + } + + @Test + public void testEquals() { + ArraySortedSet<Integer> set1 = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + ArraySortedSet<Integer> set2 = ArraySortedSet.of(Comparator.naturalOrder(), + Arrays.asList(1, 2, 3)); + Assert.assertTrue(set1.equals(set2)); + } +} diff --git a/smali/Android.bp b/smali/Android.bp index 73ec6520..4184deb5 100644 --- a/smali/Android.bp +++ b/smali/Android.bp @@ -34,6 +34,7 @@ java_binary_host { manifest: "manifest.txt", static_libs: [ + "guava", "antlr-runtime", "jcommander", "smali-dexlib2", @@ -43,4 +44,4 @@ java_binary_host { java_resources: [":android-smali_version"], wrapper: ":android-smali_script", -}
\ No newline at end of file +} |