From 2c97de2894171a8e7825026fc3bf8e61b0ac8599 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 14 Dec 2025 03:17:33 +0100 Subject: [PATCH] Use Kotlin Multiplatform, update to new binary compatibility plugin, more or less finish composite api, modularize project for separation of APIs, update Gradle wrapper, add new handy declarative predicate APIs, use new publishing plugin, simplify/modernize build system, standardize gitignore, and optimize build properties for performance --- .editorconfig | 3 - .gitignore | 133 +- build.gradle.kts | 122 +- .../api/android/core.api | 1227 ++++++++--------- core/api/jvm/core.api | 1108 +++++++++++++++ core/build.gradle.kts | 109 ++ .../revanced/patcher/patch/Patch.android.kt | 32 + .../kotlin/collections/MutableMap.android.kt | 7 + .../kotlin/java/io/File.android.kt | 8 + .../app/revanced/patcher/Fingerprint.kt | 598 ++++++++ .../app/revanced/patcher/InternalApi.kt | 0 .../kotlin/app/revanced/patcher/Matching.kt | 814 +++++++++++ .../app/revanced/patcher/PackageMetadata.kt | 0 .../kotlin/app/revanced/patcher/Patcher.kt | 11 +- .../app/revanced/patcher/PatcherConfig.kt | 5 +- .../app/revanced/patcher/PatcherContext.kt | 0 .../app/revanced/patcher/PatcherResult.kt | 0 .../patcher/extensions/Instruction.kt | 82 +- .../app/revanced/patcher/extensions/Method.kt | 14 +- .../patcher/patch/BytecodePatchContext.kt | 287 ++++ .../app/revanced/patcher/patch/Option.kt | 7 +- .../app/revanced/patcher/patch/Patch.kt | 207 +-- .../patcher/patch/ResourcePatchContext.kt | 4 +- .../app/revanced/patcher/util/ClassMerger.kt | 23 +- .../app/revanced/patcher/util/Document.kt | 13 +- .../revanced/patcher/util/MethodNavigator.kt | 20 +- .../kotlin/collections/MutableMap.kt | 13 + .../value}/MutableAnnotationEncodedValue.kt | 14 +- .../iface/value/MutableArrayEncodedValue.kt | 16 + .../value}/MutableBooleanEncodedValue.kt | 7 +- .../iface/value}/MutableByteEncodedValue.kt | 11 +- .../iface/value}/MutableCharEncodedValue.kt | 11 +- .../iface/value}/MutableDoubleEncodedValue.kt | 7 +- .../iface/value}/MutableEncodedValue.kt | 3 +- .../iface/value}/MutableEnumEncodedValue.kt | 11 +- .../iface/value}/MutableFieldEncodedValue.kt | 15 +- .../iface/value}/MutableFloatEncodedValue.kt | 11 +- .../iface/value}/MutableIntEncodedValue.kt | 11 +- .../iface/value}/MutableLongEncodedValue.kt | 11 +- .../iface/value}/MutableMethodEncodedValue.kt | 7 +- .../value}/MutableMethodHandleEncodedValue.kt | 7 +- .../value}/MutableMethodTypeEncodedValue.kt | 11 +- .../iface/value/MutableNullEncodedValue.kt | 9 + .../iface/value}/MutableShortEncodedValue.kt | 7 +- .../iface/value}/MutableStringEncodedValue.kt | 8 +- .../iface/value}/MutableTypeEncodedValue.kt | 11 +- .../dexlib2}/mutable/MutableAnnotation.kt | 12 +- .../mutable/MutableAnnotationElement.kt | 13 +- .../smali/dexlib2}/mutable/MutableClassDef.kt | 40 +- .../smali/dexlib2}/mutable/MutableField.kt | 29 +- .../smali/dexlib2}/mutable/MutableMethod.kt | 33 +- .../dexlib2/mutable/MutableMethodParameter.kt | 26 + core/src/commonMain/kotlin/java/io/File.kt | 17 + .../app/revanced/patcher/patch/Patch.jvm.kt | 26 + .../kotlin/collections/MutableMap.jvm.kt | 7 + core/src/jvmMain/kotlin/java/io/File.jvm.kt | 9 + .../app/revanced/patcher/ExtensionsTest.kt | 4 +- .../app/revanced/patcher/PatcherTest.kt | 225 +-- .../revanced/patcher/patch/PatchLoaderTest.kt | 34 +- .../app/revanced/patcher/patch/PatchTest.kt | 0 .../patcher/patch/options/OptionsTest.kt | 0 .../app/revanced/patcher/util/SmaliTest.kt | 2 +- gradle.properties | 14 +- gradle/libs.versions.toml | 15 +- gradle/wrapper/gradle-wrapper.jar | Bin 43504 -> 45633 bytes gradlew | 12 +- gradlew.bat | 3 +- settings.gradle.kts | 23 + .../app/revanced/patcher/Fingerprint.kt | 784 ----------- .../app/revanced/patcher/InstructionFilter.kt | 1075 --------------- .../kotlin/app/revanced/patcher/Matching.kt | 582 -------- .../dex/mutable/MutableMethodParameter.kt | 29 - .../encodedValue/MutableArrayEncodedValue.kt | 20 - .../encodedValue/MutableNullEncodedValue.kt | 12 - .../patcher/patch/BytecodePatchContext.kt | 228 --- .../app/revanced/patcher/version.properties | 1 - 76 files changed, 4120 insertions(+), 4190 deletions(-) delete mode 100644 .editorconfig rename api/revanced-patcher.api => core/api/android/core.api (56%) create mode 100644 core/api/jvm/core.api create mode 100644 core/build.gradle.kts create mode 100644 core/src/androidMain/kotlin/app/revanced/patcher/patch/Patch.android.kt create mode 100644 core/src/androidMain/kotlin/collections/MutableMap.android.kt create mode 100644 core/src/androidMain/kotlin/java/io/File.android.kt create mode 100644 core/src/commonMain/kotlin/app/revanced/patcher/Fingerprint.kt rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/InternalApi.kt (100%) create mode 100644 core/src/commonMain/kotlin/app/revanced/patcher/Matching.kt rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/PackageMetadata.kt (100%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/Patcher.kt (95%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/PatcherConfig.kt (96%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/PatcherContext.kt (100%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/PatcherResult.kt (100%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/extensions/Instruction.kt (60%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/extensions/Method.kt (96%) create mode 100644 core/src/commonMain/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/patch/Option.kt (99%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/patch/Patch.kt (75%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt (99%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/util/ClassMerger.kt (90%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/util/Document.kt (80%) rename {src/main => core/src/commonMain}/kotlin/app/revanced/patcher/util/MethodNavigator.kt (86%) create mode 100644 core/src/commonMain/kotlin/collections/MutableMap.kt rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableAnnotationEncodedValue.kt (50%) create mode 100644 core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableBooleanEncodedValue.kt (80%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableByteEncodedValue.kt (70%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableCharEncodedValue.kt (70%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableDoubleEncodedValue.kt (80%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableEncodedValue.kt (94%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableEnumEncodedValue.kt (74%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableFieldEncodedValue.kt (77%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableFloatEncodedValue.kt (70%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableIntEncodedValue.kt (70%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableLongEncodedValue.kt (70%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableMethodEncodedValue.kt (82%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableMethodHandleEncodedValue.kt (83%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableMethodTypeEncodedValue.kt (72%) create mode 100644 core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableShortEncodedValue.kt (80%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableStringEncodedValue.kt (72%) rename {src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value}/MutableTypeEncodedValue.kt (62%) rename {src/main/kotlin/app/revanced/patcher/dex => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2}/mutable/MutableAnnotation.kt (52%) rename {src/main/kotlin/app/revanced/patcher/dex => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2}/mutable/MutableAnnotationElement.kt (52%) rename {src/main/kotlin/app/revanced/patcher/dex => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2}/mutable/MutableClassDef.kt (52%) rename {src/main/kotlin/app/revanced/patcher/dex => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2}/mutable/MutableField.kt (51%) rename {src/main/kotlin/app/revanced/patcher/dex => core/src/commonMain/kotlin/com/android/tools/smali/dexlib2}/mutable/MutableMethod.kt (52%) create mode 100644 core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt create mode 100644 core/src/commonMain/kotlin/java/io/File.kt create mode 100644 core/src/jvmMain/kotlin/app/revanced/patcher/patch/Patch.jvm.kt create mode 100644 core/src/jvmMain/kotlin/collections/MutableMap.jvm.kt create mode 100644 core/src/jvmMain/kotlin/java/io/File.jvm.kt rename {src/test => core/src/jvmTest}/kotlin/app/revanced/patcher/ExtensionsTest.kt (98%) rename {src/test => core/src/jvmTest}/kotlin/app/revanced/patcher/PatcherTest.kt (67%) rename {src/test => core/src/jvmTest}/kotlin/app/revanced/patcher/patch/PatchLoaderTest.kt (52%) rename {src/test => core/src/jvmTest}/kotlin/app/revanced/patcher/patch/PatchTest.kt (100%) rename {src/test => core/src/jvmTest}/kotlin/app/revanced/patcher/patch/options/OptionsTest.kt (100%) rename {src/test => core/src/jvmTest}/kotlin/app/revanced/patcher/util/SmaliTest.kt (97%) delete mode 100644 src/main/kotlin/app/revanced/patcher/Fingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patcher/InstructionFilter.kt delete mode 100644 src/main/kotlin/app/revanced/patcher/Matching.kt delete mode 100644 src/main/kotlin/app/revanced/patcher/dex/mutable/MutableMethodParameter.kt delete mode 100644 src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableArrayEncodedValue.kt delete mode 100644 src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableNullEncodedValue.kt delete mode 100644 src/main/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt delete mode 100644 src/main/resources/app/revanced/patcher/version.properties diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 2d6d258..0000000 --- a/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -[*.{kt,kts}] -ktlint_code_style = intellij_idea -ktlint_standard_no-wildcard-imports = disabled \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9dbd27a..adfa9bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,124 +1,19 @@ -### Java template -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -### JetBrains template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -.idea/artifacts -.idea/compiler.xml -.idea/jarRepositories.xml -.idea/modules.xml -.idea/*.iml -.idea/modules *.iml -*.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ -.idea/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Gradle template +.kotlin .gradle **/build/ +xcuserdata !src/**/build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Cache of project -.gradletasknamecache - -# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 -# gradle/wrapper/gradle-wrapper.properties - -# Avoid ignoring test resources -!src/test/resources/* - -# Dependency directories +local.properties +.idea +.DS_Store +captures +.externalNativeBuild +.cxx +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcodeproj/project.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +**/xcshareddata/WorkspaceSettings.xcsettings node_modules/ - -# Gradle props, to avoid sharing the gpr key -gradle.properties diff --git a/build.gradle.kts b/build.gradle.kts index b6fc031..7728dea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,119 +1,5 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - alias(libs.plugins.kotlin) - alias(libs.plugins.binary.compatibility.validator) - `maven-publish` - signing -} - -group = "app.revanced" - -tasks { - processResources { - expand("projectVersion" to project.version) - } - - test { - useJUnitPlatform() - testLogging { - events("PASSED", "SKIPPED", "FAILED") - } - } -} - -repositories { - mavenCentral() - google() - maven { - // A repository must be specified for some reason. "registry" is a dummy. - url = uri("https://maven.pkg.github.com/revanced/registry") - credentials { - username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR") - password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN") - } - } -} - -dependencies { - // TODO: Convert project to KMP. - compileOnly(libs.android) { - // Exclude, otherwise the org.w3c.dom API breaks. - exclude(group = "xerces", module = "xmlParserAPIs") - } - - implementation(libs.apktool.lib) - implementation(libs.kotlin.reflect) - implementation(libs.kotlinx.coroutines.core) - implementation(libs.multidexlib2) - implementation(libs.smali) - implementation(libs.xpp3) - - testImplementation(libs.mockk) - testImplementation(libs.kotlin.test) -} - -kotlin { - compilerOptions { - jvmTarget.set(JvmTarget.JVM_11) - - freeCompilerArgs = listOf("-Xcontext-parameters") - } -} - -java { - targetCompatibility = JavaVersion.VERSION_11 - - withSourcesJar() -} - -publishing { - repositories { - maven { - name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/revanced/revanced-patcher") - credentials { - username = System.getenv("GITHUB_ACTOR") - password = System.getenv("GITHUB_TOKEN") - } - } - } - - publications { - create("revanced-patcher-publication") { - from(components["java"]) - - version = project.version.toString() - - pom { - name = "ReVanced Patcher" - description = "Patcher used by ReVanced." - url = "https://revanced.app" - - licenses { - license { - name = "GNU General Public License v3.0" - url = "https://www.gnu.org/licenses/gpl-3.0.en.html" - } - } - developers { - developer { - id = "ReVanced" - name = "ReVanced" - email = "contact@revanced.app" - } - } - scm { - connection = "scm:git:git://github.com/revanced/revanced-patcher.git" - developerConnection = "scm:git:git@github.com:revanced/revanced-patcher.git" - url = "https://github.com/revanced/revanced-patcher" - } - } - } - } -} - -signing { - useGpgCmd() - sign(publishing.publications["revanced-patcher-publication"]) -} + alias(libs.plugins.android.kotlin.multiplatform.library) apply false + alias(libs.plugins.kotlinMultiplatform) apply false + alias(libs.plugins.vanniktech.mavenPublish) apply false +} \ No newline at end of file diff --git a/api/revanced-patcher.api b/core/api/android/core.api similarity index 56% rename from api/revanced-patcher.api rename to core/api/android/core.api index 689e331..059d0c4 100644 --- a/api/revanced-patcher.api +++ b/core/api/android/core.api @@ -1,29 +1,27 @@ -public final class app/revanced/patcher/AnyInstruction : app/revanced/patcher/InstructionFilter { - public fun getLocation ()Lapp/revanced/patcher/InstructionLocation; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z +public final class app/revanced/patcher/CachedReadOnlyProperty : kotlin/properties/ReadOnlyProperty { + public fun getValue (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/reflect/KProperty;)Ljava/lang/Object; + public synthetic fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object; } -public final class app/revanced/patcher/CheckCastFilter : app/revanced/patcher/OpcodeFilter { - public final fun getComparison ()Lapp/revanced/patcher/StringComparisonType; - public final fun getType ()Lkotlin/jvm/functions/Function0; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z +public final class app/revanced/patcher/Composition { + public final fun getIndices ()Ljava/util/List; + public final fun getMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun getMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun getStrings ()Ljava/util/List; } -public final class app/revanced/patcher/FieldAccessFilter : app/revanced/patcher/OpcodesFilter { - public final fun getDefiningClass ()Ljava/lang/String; - public final fun getName ()Ljava/lang/String; - public final fun getType ()Ljava/lang/String; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z +public final class app/revanced/patcher/DeclarativePredicateBuilder { + public final fun all (Ljava/lang/Object;)Z + public final fun any (Ljava/lang/Object;)Z + public final fun anyOf (Lkotlin/jvm/functions/Function1;)V + public final fun predicate (Lkotlin/jvm/functions/Function1;)V } public final class app/revanced/patcher/Fingerprint { - public final fun clearMatch ()V - public final fun getClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; - public final fun getClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; - public final fun getInstructionMatches (Lapp/revanced/patcher/patch/BytecodePatchContext;)Ljava/util/List; - public final fun getInstructionMatchesOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Ljava/util/List; - public final fun getMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/dex/mutable/MutableMethod; - public final fun getMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/dex/mutable/MutableMethod; + public final fun getClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public final fun getClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public final fun getMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun getMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; public final fun getOriginalClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; public final fun getOriginalClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; public final fun getOriginalMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/Method; @@ -32,24 +30,19 @@ public final class app/revanced/patcher/Fingerprint { public final fun getPatternMatchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/Match$PatternMatch; public final fun getStringMatches (Lapp/revanced/patcher/patch/BytecodePatchContext;)Ljava/util/List; public final fun getStringMatchesOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Ljava/util/List; - public final fun match (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/Match; public final fun match (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/Match; public final fun match (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/Match; public final fun match (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/Match; - public final fun matchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/Match; public final fun matchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/Match; - public final fun matchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/Match; public final fun matchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/Match; - public final fun patchException ()Lapp/revanced/patcher/patch/PatchException; + public final fun matchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/Match; } public final class app/revanced/patcher/FingerprintBuilder { public fun ()V public final fun accessFlags (I)V public final fun accessFlags ([Lcom/android/tools/smali/dexlib2/AccessFlags;)V - public final fun build ()Lapp/revanced/patcher/Fingerprint; public final fun custom (Lkotlin/jvm/functions/Function2;)V - public final fun instructions ([Lapp/revanced/patcher/InstructionFilter;)V public final fun opcodes (Ljava/lang/String;)V public final fun opcodes ([Lcom/android/tools/smali/dexlib2/Opcode;)V public final fun parameters ([Ljava/lang/String;)V @@ -58,159 +51,39 @@ public final class app/revanced/patcher/FingerprintBuilder { } public final class app/revanced/patcher/FingerprintKt { - public static final fun fingerprint (Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/Fingerprint; + public static final fun fingerprint (ILkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/Fingerprint; + public static synthetic fun fingerprint$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/Fingerprint; } public final class app/revanced/patcher/IndexedMatcher : app/revanced/patcher/Matcher { public fun ()V - public final fun after (IILkotlin/jvm/functions/Function1;)Z - public static synthetic fun after$default (Lapp/revanced/patcher/IndexedMatcher;IILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Z public final fun contains (Ljava/lang/Object;)Z - public fun contains (Lkotlin/jvm/functions/Function1;)Z - public final fun first (Lkotlin/jvm/functions/Function1;)Z + public fun contains (Lkotlin/jvm/functions/Function3;)Z public final fun getIndices ()Ljava/util/List; + public final fun getNextIndex ()Ljava/lang/Integer; public final fun indexOf (Ljava/lang/Object;)I - public fun indexOf (Lkotlin/jvm/functions/Function1;)I + public fun indexOf (Lkotlin/jvm/functions/Function3;)I public fun invoke (Ljava/lang/Iterable;)Z public final fun lastIndexOf (Ljava/lang/Object;)I - public fun lastIndexOf (Lkotlin/jvm/functions/Function1;)I - public final fun remove (I)Lkotlin/jvm/functions/Function1; + public fun lastIndexOf (Lkotlin/jvm/functions/Function3;)I + public final fun remove (I)Lkotlin/jvm/functions/Function3; public final fun remove (Ljava/lang/Object;)Z - public fun remove (Lkotlin/jvm/functions/Function1;)Z - public fun removeAt (I)Lkotlin/jvm/functions/Function1; -} - -public abstract interface class app/revanced/patcher/InstructionFilter { - public fun getLocation ()Lapp/revanced/patcher/InstructionLocation; - public abstract fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z -} - -public final class app/revanced/patcher/InstructionFilter$DefaultImpls { - public static fun getLocation (Lapp/revanced/patcher/InstructionFilter;)Lapp/revanced/patcher/InstructionLocation; -} - -public final class app/revanced/patcher/InstructionFilterKt { - public static final fun anyInstruction ([Lapp/revanced/patcher/InstructionFilter;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/AnyInstruction; - public static synthetic fun anyInstruction$default ([Lapp/revanced/patcher/InstructionFilter;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/AnyInstruction; - public static final fun checkCast (Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/CheckCastFilter; - public static final fun checkCast (Ljava/lang/String;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/CheckCastFilter; - public static final fun checkCast (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/CheckCastFilter; - public static final fun checkCast (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/CheckCastFilter; - public static synthetic fun checkCast$default (Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/CheckCastFilter; - public static synthetic fun checkCast$default (Ljava/lang/String;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/CheckCastFilter; - public static synthetic fun checkCast$default (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/CheckCastFilter; - public static synthetic fun checkCast$default (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/CheckCastFilter; - public static final fun fieldAccess (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/FieldAccessFilter; - public static final fun fieldAccess (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/FieldAccessFilter; - public static final fun fieldAccess (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/FieldAccessFilter; - public static final fun fieldAccess (Ljava/lang/String;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/FieldAccessFilter; - public static synthetic fun fieldAccess$default (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/FieldAccessFilter; - public static synthetic fun fieldAccess$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/FieldAccessFilter; - public static synthetic fun fieldAccess$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/FieldAccessFilter; - public static synthetic fun fieldAccess$default (Ljava/lang/String;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/FieldAccessFilter; - public static final fun literal (DLjava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/LiteralFilter; - public static final fun literal (FLjava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/LiteralFilter; - public static final fun literal (ILjava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/LiteralFilter; - public static final fun literal (JLjava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/LiteralFilter; - public static final fun literal (Lkotlin/jvm/functions/Function0;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/LiteralFilter; - public static synthetic fun literal$default (DLjava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/LiteralFilter; - public static synthetic fun literal$default (FLjava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/LiteralFilter; - public static synthetic fun literal$default (ILjava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/LiteralFilter; - public static synthetic fun literal$default (JLjava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/LiteralFilter; - public static synthetic fun literal$default (Lkotlin/jvm/functions/Function0;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/LiteralFilter; - public static final fun methodCall (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/MethodCallFilter; - public static final fun methodCall (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/MethodCallFilter; - public static final fun methodCall (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/MethodCallFilter; - public static final fun methodCall (Ljava/lang/String;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/MethodCallFilter; - public static synthetic fun methodCall$default (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/MethodCallFilter; - public static synthetic fun methodCall$default (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/MethodCallFilter; - public static synthetic fun methodCall$default (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/MethodCallFilter; - public static synthetic fun methodCall$default (Ljava/lang/String;Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/MethodCallFilter; - public static final fun newInstance (Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/NewInstanceFilter; - public static final fun newInstance (Ljava/lang/String;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/NewInstanceFilter; - public static final fun newInstance (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/NewInstanceFilter; - public static final fun newInstance (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/NewInstanceFilter; - public static synthetic fun newInstance$default (Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/NewInstanceFilter; - public static synthetic fun newInstance$default (Ljava/lang/String;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/NewInstanceFilter; - public static synthetic fun newInstance$default (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/NewInstanceFilter; - public static synthetic fun newInstance$default (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/NewInstanceFilter; - public static final fun opcode (Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/OpcodeFilter; - public static synthetic fun opcode$default (Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/OpcodeFilter; - public static final fun string (Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/StringFilter; - public static final fun string (Ljava/lang/String;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/StringFilter; - public static final fun string (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/StringFilter; - public static final fun string (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;)Lapp/revanced/patcher/StringFilter; - public static synthetic fun string$default (Ljava/lang/String;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/StringFilter; - public static synthetic fun string$default (Ljava/lang/String;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/StringFilter; - public static synthetic fun string$default (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/StringFilter; - public static synthetic fun string$default (Lkotlin/jvm/functions/Function0;Lapp/revanced/patcher/StringComparisonType;Lapp/revanced/patcher/InstructionLocation;ILjava/lang/Object;)Lapp/revanced/patcher/StringFilter; -} - -public abstract interface class app/revanced/patcher/InstructionLocation { - public abstract fun indexIsValidForMatching (II)Z -} - -public final class app/revanced/patcher/InstructionLocation$MatchAfterAnywhere : app/revanced/patcher/InstructionLocation { - public fun ()V - public fun indexIsValidForMatching (II)Z -} - -public final class app/revanced/patcher/InstructionLocation$MatchAfterAtLeast : app/revanced/patcher/InstructionLocation { - public fun (I)V - public final fun getMinimumDistanceFromLastInstruction ()I - public fun indexIsValidForMatching (II)Z - public final fun setMinimumDistanceFromLastInstruction (I)V -} - -public final class app/revanced/patcher/InstructionLocation$MatchAfterImmediately : app/revanced/patcher/InstructionLocation { - public fun ()V - public fun indexIsValidForMatching (II)Z -} - -public final class app/revanced/patcher/InstructionLocation$MatchAfterRange : app/revanced/patcher/InstructionLocation { - public fun (II)V - public final fun getMaximumDistanceFromLastInstruction ()I - public final fun getMinimumDistanceFromLastInstruction ()I - public fun indexIsValidForMatching (II)Z -} - -public final class app/revanced/patcher/InstructionLocation$MatchAfterWithin : app/revanced/patcher/InstructionLocation { - public fun (I)V - public final fun getMatchDistance ()I - public fun indexIsValidForMatching (II)Z -} - -public final class app/revanced/patcher/InstructionLocation$MatchFirst : app/revanced/patcher/InstructionLocation { - public fun ()V - public fun indexIsValidForMatching (II)Z + public fun remove (Lkotlin/jvm/functions/Function3;)Z + public fun removeAt (I)Lkotlin/jvm/functions/Function3; + public final fun setNextIndex (Ljava/lang/Integer;)V } public abstract interface annotation class app/revanced/patcher/InternalApi : java/lang/annotation/Annotation { } -public final class app/revanced/patcher/LiteralFilter : app/revanced/patcher/OpcodesFilter { - public final fun getLiteral ()Lkotlin/jvm/functions/Function0; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z -} - public final class app/revanced/patcher/Match { - public final fun getClassDef ()Lapp/revanced/patcher/dex/mutable/MutableClassDef; + public final fun getClassDef ()Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; public final fun getContext ()Lapp/revanced/patcher/patch/BytecodePatchContext; - public final fun getInstructionMatches ()Ljava/util/List; - public final fun getInstructionMatchesOrNull ()Ljava/util/List; - public final fun getMethod ()Lapp/revanced/patcher/dex/mutable/MutableMethod; + public final fun getMethod ()Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; public final fun getOriginalClassDef ()Lcom/android/tools/smali/dexlib2/iface/ClassDef; public final fun getOriginalMethod ()Lcom/android/tools/smali/dexlib2/iface/Method; public final fun getPatternMatch ()Lapp/revanced/patcher/Match$PatternMatch; public final fun getStringMatches ()Ljava/util/List; - public final fun getStringMatchesOrNull ()Ljava/util/List; -} - -public final class app/revanced/patcher/Match$InstructionMatch { - public final fun getFilter ()Lapp/revanced/patcher/InstructionFilter; - public final fun getIndex ()I - public final fun getInstruction ()Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction; - public final fun getInstruction ()Ljava/lang/Object; } public final class app/revanced/patcher/Match$PatternMatch { @@ -255,31 +128,13 @@ public abstract class app/revanced/patcher/Matcher : java/util/List, kotlin/jvm/ public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; } -public final class app/revanced/patcher/Matcher$MatchContext : java/util/Map, kotlin/jvm/internal/markers/KMutableMap { - public fun clear ()V - public final fun containsKey (Ljava/lang/Object;)Z - public fun containsKey (Ljava/lang/String;)Z - public fun containsValue (Ljava/lang/Object;)Z - public final fun entrySet ()Ljava/util/Set; - public final fun get (Ljava/lang/Object;)Ljava/lang/Object; - public fun get (Ljava/lang/String;)Ljava/lang/Object; - public fun getEntries ()Ljava/util/Set; - public fun getKeys ()Ljava/util/Set; - public fun getSize ()I - public fun getValues ()Ljava/util/Collection; - public fun isEmpty ()Z - public final fun keySet ()Ljava/util/Set; - public synthetic fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun put (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; - public fun putAll (Ljava/util/Map;)V - public final fun remove (Ljava/lang/Object;)Ljava/lang/Object; - public fun remove (Ljava/lang/String;)Ljava/lang/Object; - public final fun size ()I - public final fun values ()Ljava/util/Collection; -} - public final class app/revanced/patcher/MatchingKt { - public static final fun a (Lapp/revanced/patcher/patch/BytecodePatchContext;)V + public static final fun accessFlags (Lapp/revanced/patcher/DeclarativePredicateBuilder;[Lcom/android/tools/smali/dexlib2/AccessFlags;)V + public static final fun after (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun after (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; + public static synthetic fun after$default (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun after$default (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun allOf ([Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; public static final fun anyAnnotation (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z public static final fun anyAnnotation (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z public static final fun anyClassDef (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Z @@ -292,101 +147,142 @@ public final class app/revanced/patcher/MatchingKt { public static final fun anyInstruction (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Z public static final fun anyInterface (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z public static final fun anyMethod (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyOf ([Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; public static final fun anyParameter (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z public static final fun anyParameterType (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z public static final fun anyStaticField (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z public static final fun anyTryBlock (Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;Lkotlin/jvm/functions/Function1;)Z public static final fun anyVirtualMethod (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun custom (Lapp/revanced/patcher/DeclarativePredicateBuilder;Lkotlin/jvm/functions/Function1;)V + public static final fun declarativePredicate (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public static final fun field (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun field (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun field$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun field$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; public static final fun firstClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; public static final fun firstClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; public static synthetic fun firstClassDef$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; - public static final fun firstClassDefMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; - public static final fun firstClassDefMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; - public static synthetic fun firstClassDefMutable$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; - public static final fun firstClassDefMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; - public static final fun firstClassDefMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; - public static synthetic fun firstClassDefMutableOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; + public static final fun firstClassDefByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static synthetic fun firstClassDefMutable$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static synthetic fun firstClassDefMutableOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; public static final fun firstClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; public static final fun firstClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; public static synthetic fun firstClassDefOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; public static final fun firstMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; public static final fun firstMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; - public static final fun firstMethod (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; public static synthetic fun firstMethod$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/iface/Method; - public static final fun firstMethodMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableMethod; - public static final fun firstMethodMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableMethod; - public static final fun firstMethodMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableMethod; - public static synthetic fun firstMethodMutable$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/dex/mutable/MutableMethod; - public static final fun firstMethodMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableMethod; - public static final fun firstMethodMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableMethod; - public static final fun firstMethodMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/dex/mutable/MutableMethod; - public static synthetic fun firstMethodMutableOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/dex/mutable/MutableMethod; + public static final fun firstMethodByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodComposite ([Ljava/lang/String;Lkotlin/jvm/functions/Function5;)Lapp/revanced/patcher/Composition; + public static final fun firstMethodMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static synthetic fun firstMethodMutable$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static synthetic fun firstMethodMutableOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; public static final fun firstMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; public static final fun firstMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; - public static final fun firstMethodOrNull (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; public static synthetic fun firstMethodOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/iface/Method; - public static final fun gettingFirstClassDef (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstClassDef (Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun gettingFirstClassDef$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstClassDefMutable (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstClassDefMutable (Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun gettingFirstClassDefMutable$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstClassDefMutableOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstClassDefMutableOrNull (Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun gettingFirstClassDefMutableOrNull$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstClassDefOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstClassDefOrNull (Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun gettingFirstClassDefOrNull$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstMethod (Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstMethod ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun gettingFirstMethod$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstMethodMutable (Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstMethodMutable ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun gettingFirstMethodMutable$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstMethodMutableOrNull (Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstMethodMutableOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun gettingFirstMethodMutableOrNull$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstMethodOrNull (Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static final fun gettingFirstMethodOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun gettingFirstMethodOrNull$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun getM ()Lapp/revanced/patcher/Composition; + public static final fun gettingFirstClassDef (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDef (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstClassDef$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefByDeclarativePredicate (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefByDeclarativePredicate (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefByDeclarativePredicateOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefByDeclarativePredicateOrNull (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutable (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutable (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstClassDefMutable$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableByDeclarativePredicate (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableByDeclarativePredicate (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableByDeclarativePredicateOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableByDeclarativePredicateOrNull (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableOrNull (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstClassDefMutableOrNull$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefOrNull (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstClassDefOrNull$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethod (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethod ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstMethod$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodByDeclarativePredicate (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodByDeclarativePredicate ([Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodByDeclarativePredicateOrNull (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodByDeclarativePredicateOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutable (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutable ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstMethodMutable$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableByDeclarativePredicate (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableByDeclarativePredicate ([Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableByDeclarativePredicateOrNull (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableByDeclarativePredicateOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableOrNull (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstMethodMutableOrNull$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodOrNull (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstMethodOrNull$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun head (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun head (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; public static final fun implementation (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z public static final fun indexedMatcher ()Lapp/revanced/patcher/IndexedMatcher; public static final fun indexedMatcher (Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/IndexedMatcher; - public static final fun invoke (Lapp/revanced/patcher/Matcher$MatchContext;Lapp/revanced/patcher/IndexedMatcher;Ljava/lang/Iterable;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Z - public static final fun matchIndexed (Lapp/revanced/patcher/Matcher$MatchContext;Ljava/lang/Iterable;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Z + public static final fun instruction (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun instructions (Lapp/revanced/patcher/IndexedMatcher;Lapp/revanced/patcher/DeclarativePredicateBuilder;Lkotlin/jvm/functions/Function1;)V + public static final fun instructions (Lapp/revanced/patcher/IndexedMatcher;Lapp/revanced/patcher/DeclarativePredicateBuilder;[Lkotlin/jvm/functions/Function3;)V + public static final fun invoke (Lcom/android/tools/smali/dexlib2/Opcode;)Lkotlin/jvm/functions/Function3; + public static final fun invoke (Ljava/util/List;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static synthetic fun invoke$default (Ljava/util/List;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun literal (JLkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun literal (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun literal$default (JLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun literal$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; public static final fun matchIndexed (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Z - public static final fun matchers (Lapp/revanced/patcher/patch/BytecodePatchContext;)V -} - -public final class app/revanced/patcher/MethodCallFilter : app/revanced/patcher/OpcodesFilter { - public final fun getDefiningClass ()Ljava/lang/String; - public final fun getName ()Ljava/lang/String; - public final fun getParameters ()Ljava/util/List; - public final fun getReturnType ()Ljava/lang/String; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z -} - -public final class app/revanced/patcher/NewInstanceFilter : app/revanced/patcher/OpcodesFilter { - public final fun getComparison ()Lapp/revanced/patcher/StringComparisonType; - public final fun getType ()Lkotlin/jvm/functions/Function0; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z -} - -public class app/revanced/patcher/OpcodeFilter : app/revanced/patcher/InstructionFilter { - public fun (Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;)V - public synthetic fun (Lcom/android/tools/smali/dexlib2/Opcode;Lapp/revanced/patcher/InstructionLocation;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun getLocation ()Lapp/revanced/patcher/InstructionLocation; - public final fun getOpcode ()Lcom/android/tools/smali/dexlib2/Opcode; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z -} - -public class app/revanced/patcher/OpcodesFilter : app/revanced/patcher/InstructionFilter { - protected fun (Ljava/util/EnumSet;Lapp/revanced/patcher/InstructionLocation;)V - public synthetic fun (Ljava/util/EnumSet;Lapp/revanced/patcher/InstructionLocation;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - protected fun (Ljava/util/List;Lapp/revanced/patcher/InstructionLocation;)V - public fun getLocation ()Lapp/revanced/patcher/InstructionLocation; - public final fun getOpcodes ()Ljava/util/EnumSet; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z + public static final fun method (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun method (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun method$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun method$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun noneOf ([Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; + public static final fun parameterTypes (Lapp/revanced/patcher/DeclarativePredicateBuilder;[Ljava/lang/String;)V + public static final fun reference (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun reference (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun reference$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun reference$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun registers (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun registers ([ILkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static synthetic fun registers$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun registers$default ([ILkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun rememberedDeclarativePredicate (Lapp/revanced/patcher/PredicateContext;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public static final fun rememberedMatchIndexed (Lapp/revanced/patcher/PredicateContext;Ljava/lang/Iterable;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public static final fun returns (Lapp/revanced/patcher/DeclarativePredicateBuilder;Ljava/lang/String;)V + public static final fun string (Ljava/util/List;Lapp/revanced/patcher/DeclarativePredicateBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun string (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun string$default (Ljava/util/List;Lapp/revanced/patcher/DeclarativePredicateBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun string$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun type (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun type (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun type$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun type$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun unaryPlus (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/jvm/functions/Function3;)Z } public final class app/revanced/patcher/PackageMetadata { @@ -432,348 +328,23 @@ public final class app/revanced/patcher/PatcherResult$PatchedResources { public final fun getResourcesApk ()Ljava/io/File; } -public final class app/revanced/patcher/StringComparisonType : java/lang/Enum { - public static final field CONTAINS Lapp/revanced/patcher/StringComparisonType; - public static final field ENDS_WITH Lapp/revanced/patcher/StringComparisonType; - public static final field EQUALS Lapp/revanced/patcher/StringComparisonType; - public static final field STARTS_WITH Lapp/revanced/patcher/StringComparisonType; - public final fun compare (Ljava/lang/String;Ljava/lang/String;)Z - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lapp/revanced/patcher/StringComparisonType; - public static fun values ()[Lapp/revanced/patcher/StringComparisonType; -} - -public final class app/revanced/patcher/StringFilter : app/revanced/patcher/OpcodesFilter { - public final fun getComparison ()Lapp/revanced/patcher/StringComparisonType; - public final fun getString ()Lkotlin/jvm/functions/Function0; - public fun matches (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Z -} - -public final class app/revanced/patcher/dex/mutable/MutableAnnotation : com/android/tools/smali/dexlib2/base/BaseAnnotation { - public static final field Companion Lapp/revanced/patcher/dex/mutable/MutableAnnotation$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/Annotation;)V - public fun getElements ()Ljava/util/Set; - public fun getType ()Ljava/lang/String; - public fun getVisibility ()I -} - -public final class app/revanced/patcher/dex/mutable/MutableAnnotation$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Annotation;)Lapp/revanced/patcher/dex/mutable/MutableAnnotation; -} - -public final class app/revanced/patcher/dex/mutable/MutableAnnotationElement : com/android/tools/smali/dexlib2/base/BaseAnnotationElement { - public static final field Companion Lapp/revanced/patcher/dex/mutable/MutableAnnotationElement$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)V - public fun getName ()Ljava/lang/String; - public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue; - public final fun setName (Ljava/lang/String;)V - public final fun setValue (Lapp/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue;)V -} - -public final class app/revanced/patcher/dex/mutable/MutableAnnotationElement$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)Lapp/revanced/patcher/dex/mutable/MutableAnnotationElement; -} - -public final class app/revanced/patcher/dex/mutable/MutableClassDef : com/android/tools/smali/dexlib2/base/reference/BaseTypeReference, com/android/tools/smali/dexlib2/iface/ClassDef { - public static final field Companion Lapp/revanced/patcher/dex/mutable/MutableClassDef$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)V - public final fun charAt (I)C - public fun get (I)C - public fun getAccessFlags ()I - public fun getAnnotations ()Ljava/util/Set; - public synthetic fun getDirectMethods ()Ljava/lang/Iterable; - public fun getDirectMethods ()Ljava/util/Set; - public synthetic fun getFields ()Ljava/lang/Iterable; - public fun getFields ()Ljava/util/Set; - public synthetic fun getInstanceFields ()Ljava/lang/Iterable; - public fun getInstanceFields ()Ljava/util/Set; - public fun getInterfaces ()Ljava/util/List; - public fun getLength ()I - public synthetic fun getMethods ()Ljava/lang/Iterable; - public fun getMethods ()Ljava/util/Set; - public fun getSourceFile ()Ljava/lang/String; - public synthetic fun getStaticFields ()Ljava/lang/Iterable; - public fun getStaticFields ()Ljava/util/Set; - public fun getSuperclass ()Ljava/lang/String; - public fun getType ()Ljava/lang/String; - public synthetic fun getVirtualMethods ()Ljava/lang/Iterable; - public fun getVirtualMethods ()Ljava/util/Set; - public final fun length ()I - public final fun setAccessFlags (I)V - public final fun setSourceFile (Ljava/lang/String;)V - public final fun setSuperClass (Ljava/lang/String;)V - public final fun setType (Ljava/lang/String;)V -} - -public final class app/revanced/patcher/dex/mutable/MutableClassDef$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; -} - -public final class app/revanced/patcher/dex/mutable/MutableField : com/android/tools/smali/dexlib2/base/reference/BaseFieldReference, com/android/tools/smali/dexlib2/iface/Field { - public static final field Companion Lapp/revanced/patcher/dex/mutable/MutableField$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/Field;)V - public fun getAccessFlags ()I - public fun getAnnotations ()Ljava/util/Set; - public fun getDefiningClass ()Ljava/lang/String; - public fun getHiddenApiRestrictions ()Ljava/util/Set; - public fun getInitialValue ()Lapp/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue; - public synthetic fun getInitialValue ()Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue; - public fun getName ()Ljava/lang/String; - public fun getType ()Ljava/lang/String; - public final fun setAccessFlags (I)V - public final fun setDefiningClass (Ljava/lang/String;)V - public final fun setInitialValue (Lapp/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue;)V - public final fun setName (Ljava/lang/String;)V - public final fun setType (Ljava/lang/String;)V -} - -public final class app/revanced/patcher/dex/mutable/MutableField$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Field;)Lapp/revanced/patcher/dex/mutable/MutableField; -} - -public final class app/revanced/patcher/dex/mutable/MutableMethod : com/android/tools/smali/dexlib2/base/reference/BaseMethodReference, com/android/tools/smali/dexlib2/iface/Method { - public static final field Companion Lapp/revanced/patcher/dex/mutable/MutableMethod$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/Method;)V - public fun getAccessFlags ()I - public fun getAnnotations ()Ljava/util/Set; - public fun getDefiningClass ()Ljava/lang/String; - public fun getHiddenApiRestrictions ()Ljava/util/Set; - public fun getImplementation ()Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation; - public synthetic fun getImplementation ()Lcom/android/tools/smali/dexlib2/iface/MethodImplementation; - public fun getName ()Ljava/lang/String; - public fun getParameterTypes ()Ljava/util/List; - public fun getParameters ()Ljava/util/List; - public fun getReturnType ()Ljava/lang/String; - public final fun setAccessFlags (I)V - public final fun setDefiningClass (Ljava/lang/String;)V - public final fun setName (Ljava/lang/String;)V - public final fun setReturnType (Ljava/lang/String;)V -} - -public final class app/revanced/patcher/dex/mutable/MutableMethod$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/dex/mutable/MutableMethod; -} - -public final class app/revanced/patcher/dex/mutable/MutableMethodParameter : com/android/tools/smali/dexlib2/base/BaseMethodParameter, com/android/tools/smali/dexlib2/iface/MethodParameter { - public static final field Companion Lapp/revanced/patcher/dex/mutable/MutableMethodParameter$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)V - public final fun charAt (I)C - public fun get (I)C - public fun getAnnotations ()Ljava/util/Set; - public fun getLength ()I - public fun getName ()Ljava/lang/String; - public fun getSignature ()Ljava/lang/String; - public fun getType ()Ljava/lang/String; - public final fun length ()I -} - -public final class app/revanced/patcher/dex/mutable/MutableMethodParameter$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)Lapp/revanced/patcher/dex/mutable/MutableMethodParameter; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableAnnotationEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseAnnotationEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableAnnotationEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)V - public fun getElements ()Ljava/util/Set; - public fun getType ()Ljava/lang/String; - public final fun setType (Ljava/lang/String;)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableAnnotationEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableAnnotationEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableArrayEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseArrayEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableArrayEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)V - public fun getValue ()Ljava/util/List; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableArrayEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableArrayEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableBooleanEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseBooleanEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableBooleanEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)V - public fun getValue ()Z - public final fun setValue (Z)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableBooleanEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableBooleanEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseByteEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)V - public fun getValue ()B - public final fun setValue (B)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableCharEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseCharEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableCharEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)V - public fun getValue ()C - public final fun setValue (C)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableCharEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableCharEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableDoubleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseDoubleEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableDoubleEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)V - public fun getValue ()D - public final fun setValue (D)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableDoubleEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableDoubleEncodedValue; -} - -public abstract interface class app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue : com/android/tools/smali/dexlib2/iface/value/EncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue$Companion; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableEnumEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseEnumEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableEnumEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)V - public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference; - public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableEnumEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableEnumEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableFieldEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFieldEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableFieldEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)V - public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference; - public fun getValueType ()I - public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableFieldEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableFieldEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableFloatEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFloatEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableFloatEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)V - public fun getValue ()F - public final fun setValue (F)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableFloatEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableFloatEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableIntEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseIntEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableIntEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)V - public fun getValue ()I - public final fun setValue (I)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableIntEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableIntEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableLongEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseLongEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableLongEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)V - public fun getValue ()J - public final fun setValue (J)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableLongEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableLongEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableMethodEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableMethodEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)V - public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference; - public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference;)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableMethodEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableMethodEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableMethodHandleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodHandleEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableMethodHandleEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)V - public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodHandleReference; - public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodHandleReference;)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableMethodHandleEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableMethodHandleEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableMethodTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodTypeEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableMethodTypeEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)V - public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodProtoReference; - public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodProtoReference;)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableMethodTypeEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableMethodTypeEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableNullEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseNullEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableNullEncodedValue$Companion; - public fun ()V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableNullEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableShortEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseShortEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableShortEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)V - public fun getValue ()S - public final fun setValue (S)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableShortEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableShortEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableStringEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseStringEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableStringEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/StringEncodedValue;)V - public fun getValue ()Ljava/lang/String; - public final fun setValue (Ljava/lang/String;)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableStringEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue; -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseTypeEncodedValue, app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue { - public static final field Companion Lapp/revanced/patcher/dex/mutable/encodedValue/MutableTypeEncodedValue$Companion; - public fun (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)V - public fun getValue ()Ljava/lang/String; - public final fun setValue (Ljava/lang/String;)V -} - -public final class app/revanced/patcher/dex/mutable/encodedValue/MutableTypeEncodedValue$Companion { - public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)Lapp/revanced/patcher/dex/mutable/encodedValue/MutableTypeEncodedValue; +public final class app/revanced/patcher/PredicateContext : java/util/Map, kotlin/jvm/internal/markers/KMutableMap { + public fun clear ()V + public fun containsKey (Ljava/lang/Object;)Z + public fun containsValue (Ljava/lang/Object;)Z + public final fun entrySet ()Ljava/util/Set; + public fun get (Ljava/lang/Object;)Ljava/lang/Object; + public fun getEntries ()Ljava/util/Set; + public fun getKeys ()Ljava/util/Set; + public fun getSize ()I + public fun getValues ()Ljava/util/Collection; + public fun isEmpty ()Z + public final fun keySet ()Ljava/util/Set; + public fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun putAll (Ljava/util/Map;)V + public fun remove (Ljava/lang/Object;)Ljava/lang/Object; + public final fun size ()I + public final fun values ()Ljava/util/Collection; } public final class app/revanced/patcher/extensions/ExternalLabel { @@ -786,66 +357,58 @@ public final class app/revanced/patcher/extensions/ExternalLabel { } public final class app/revanced/patcher/extensions/InstructionKt { - public static final fun fieldReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Ljava/lang/String;)Z - public static final fun fieldReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Lkotlin/jvm/functions/Function1;)Z public static final fun getFieldReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference; public static final fun getMethodReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference; public static final fun getReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/Reference; + public static final fun getString (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Ljava/lang/String; public static final fun getStringReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/StringReference; + public static final fun getType (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Ljava/lang/String; public static final fun getTypeReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/TypeReference; public static final fun getWideLiteral (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Ljava/lang/Long; - public static final fun methodReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference;)Z - public static final fun methodReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Lkotlin/jvm/functions/Function1;)Z - public static final fun opcode (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Lcom/android/tools/smali/dexlib2/Opcode;)Z - public static final fun reference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Lkotlin/jvm/functions/Function1;)Z - public static final fun reference2 (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Lkotlin/jvm/functions/Function1;)Z - public static final fun string (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Ljava/lang/String;)Z - public static final fun string (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Lkotlin/jvm/functions/Function1;)Z - public static final fun type (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Ljava/lang/String;)Z - public static final fun type (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;Lkotlin/jvm/functions/Function1;)Z - public static final fun wideLiteral (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;J)Z + public static final fun toInstructions (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;)Ljava/util/List; + public static synthetic fun toInstructions$default (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/Object;)Ljava/util/List; } public final class app/revanced/patcher/extensions/MethodKt { public static final fun accessFlags (Lcom/android/tools/smali/dexlib2/iface/Method;[Lcom/android/tools/smali/dexlib2/AccessFlags;)Z - public static final fun addInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V - public static final fun addInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILjava/lang/String;)V - public static final fun addInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V - public static final fun addInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;Ljava/lang/String;)V - public static final fun addInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILjava/lang/String;)V - public static final fun addInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILjava/util/List;)V - public static final fun addInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;Ljava/lang/String;)V - public static final fun addInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;Ljava/util/List;)V + public static final fun addInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V + public static final fun addInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;)V + public static final fun addInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V + public static final fun addInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;Ljava/lang/String;)V public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;ILjava/util/List;)V public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;Ljava/util/List;)V - public static final fun addInstructionsWithLabels (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILjava/lang/String;[Lapp/revanced/patcher/extensions/ExternalLabel;)V - public static final fun getInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction; - public static final fun getInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;I)Ljava/lang/Object; + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/util/List;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;Ljava/lang/String;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;Ljava/util/List;)V + public static final fun addInstructionsWithLabels (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;[Lapp/revanced/patcher/extensions/ExternalLabel;)V public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction; public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)Ljava/lang/Object; public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;I)Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction; public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;I)Ljava/lang/Object; public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;I)Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction; public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;I)Ljava/lang/Object; - public static final fun getInstructionOrNull (Lapp/revanced/patcher/dex/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction; - public static final fun getInstructionOrNull (Lapp/revanced/patcher/dex/mutable/MutableMethod;I)Ljava/lang/Object; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Ljava/lang/Object; public static final fun getInstructionOrNull (Lcom/android/tools/smali/dexlib2/iface/Method;I)Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction; public static final fun getInstructionOrNull (Lcom/android/tools/smali/dexlib2/iface/Method;I)Ljava/lang/Object; - public static final fun getInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;)Ljava/util/List; + public static final fun getInstructionOrNull (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction; + public static final fun getInstructionOrNull (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Ljava/lang/Object; public static final fun getInstructions (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Iterable; - public static final fun getInstructionsOrNull (Lapp/revanced/patcher/dex/mutable/MutableMethod;)Ljava/util/List; + public static final fun getInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;)Ljava/util/List; public static final fun getInstructionsOrNull (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Iterable; - public static final fun newLabel (Lapp/revanced/patcher/dex/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/Label; - public static final fun removeInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;I)V - public static final fun removeInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;I)V - public static final fun removeInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;II)V + public static final fun getInstructionsOrNull (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;)Ljava/util/List; + public static final fun newLabel (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/Label; + public static final fun removeInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)V public static final fun removeInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)V public static final fun removeInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;II)V - public static final fun replaceInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V - public static final fun replaceInstruction (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILjava/lang/String;)V - public static final fun replaceInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILjava/lang/String;)V - public static final fun replaceInstructions (Lapp/revanced/patcher/dex/mutable/MutableMethod;ILjava/util/List;)V + public static final fun removeInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)V + public static final fun removeInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;II)V + public static final fun replaceInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V + public static final fun replaceInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;)V public static final fun replaceInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;ILjava/util/List;)V + public static final fun replaceInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;)V + public static final fun replaceInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/util/List;)V } public final class app/revanced/patcher/patch/BytecodePatch : app/revanced/patcher/patch/Patch { @@ -854,7 +417,7 @@ public final class app/revanced/patcher/patch/BytecodePatch : app/revanced/patch } public final class app/revanced/patcher/patch/BytecodePatchBuilder : app/revanced/patcher/patch/PatchBuilder { - public synthetic fun build$revanced_patcher ()Lapp/revanced/patcher/patch/Patch; + public synthetic fun build$core ()Lapp/revanced/patcher/patch/Patch; public final fun extendWith (Ljava/lang/String;)Lapp/revanced/patcher/patch/BytecodePatchBuilder; public final fun getExtensionInputStream ()Ljava/util/function/Supplier; public final fun setExtensionInputStream (Ljava/util/function/Supplier;)V @@ -864,11 +427,35 @@ public final class app/revanced/patcher/patch/BytecodePatchContext : app/revance public fun close ()V public synthetic fun get ()Ljava/lang/Object; public fun get ()Ljava/util/Set; - public final fun getClassDefs ()Ljava/util/Set; - public final fun mutable (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/dex/mutable/MutableClassDef; + public final fun getClassDefs ()Lapp/revanced/patcher/patch/BytecodePatchContext$ClassDefs; public final fun navigate (Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference;)Lapp/revanced/patcher/util/MethodNavigator; } +public final class app/revanced/patcher/patch/BytecodePatchContext$ClassDefs : java/util/Set, kotlin/jvm/internal/markers/KMutableSet { + public fun (Lapp/revanced/patcher/patch/BytecodePatchContext;)V + public fun add (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z + public synthetic fun add (Ljava/lang/Object;)Z + public fun addAll (Ljava/util/Collection;)Z + public fun clear ()V + public fun contains (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z + public final fun contains (Ljava/lang/Object;)Z + public fun containsAll (Ljava/util/Collection;)Z + public final fun get (Ljava/lang/String;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public final fun getMethodsByString ()Ljava/util/Map; + public final fun getOrReplaceMutable (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public fun getSize ()I + public fun isEmpty ()Z + public fun iterator ()Ljava/util/Iterator; + public fun remove (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z + public final fun remove (Ljava/lang/Object;)Z + public fun removeAll (Ljava/util/Collection;)Z + public fun removeIf (Ljava/util/function/Predicate;)Z + public fun retainAll (Ljava/util/Collection;)Z + public final fun size ()I + public fun toArray ()[Ljava/lang/Object; + public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; +} + public final class app/revanced/patcher/patch/Option { public fun (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/reflect/KType;Lkotlin/jvm/functions/Function2;)V public synthetic fun (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/reflect/KType;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -1048,18 +635,23 @@ public final class app/revanced/patcher/patch/PatchKt { public static synthetic fun gettingRawResourcePatch$default (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static final fun gettingResourcePatch (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun gettingResourcePatch$default (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun loadPatchesFromDex (Ljava/util/Set;Ljava/io/File;)Lapp/revanced/patcher/patch/PatchLoader$Dex; - public static synthetic fun loadPatchesFromDex$default (Ljava/util/Set;Ljava/io/File;ILjava/lang/Object;)Lapp/revanced/patcher/patch/PatchLoader$Dex; - public static final fun loadPatchesFromJar (Ljava/util/Set;)Lapp/revanced/patcher/patch/PatchLoader$Jar; public static final fun rawResourcePatch (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/RawResourcePatch; public static synthetic fun rawResourcePatch$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/RawResourcePatch; public static final fun resourcePatch (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch; public static synthetic fun resourcePatch$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch; } -public abstract class app/revanced/patcher/patch/PatchLoader : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { - public synthetic fun (Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Ljava/util/Set;Lkotlin/jvm/functions/Function1;Ljava/lang/ClassLoader;Lkotlin/jvm/internal/DefaultConstructorMarker;)V +public final class app/revanced/patcher/patch/PatchResult { + public final fun getException ()Lapp/revanced/patcher/patch/PatchException; + public final fun getPatch ()Lapp/revanced/patcher/patch/Patch; +} + +public final class app/revanced/patcher/patch/Patch_androidKt { + public static final fun isPatch (Ljava/lang/Class;)Z + public static final fun loadPatches (Ljava/util/Set;)Lapp/revanced/patcher/patch/Patches; +} + +public final class app/revanced/patcher/patch/Patches : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { public fun add (Lapp/revanced/patcher/patch/Patch;)Z public synthetic fun add (Ljava/lang/Object;)Z public fun addAll (Ljava/util/Collection;)Z @@ -1067,7 +659,7 @@ public abstract class app/revanced/patcher/patch/PatchLoader : java/util/Set, ko public fun contains (Lapp/revanced/patcher/patch/Patch;)Z public final fun contains (Ljava/lang/Object;)Z public fun containsAll (Ljava/util/Collection;)Z - public final fun getByPatchesFile ()Ljava/util/Map; + public final fun getPatchesByFile ()Ljava/util/Map; public fun getSize ()I public fun isEmpty ()Z public fun iterator ()Ljava/util/Iterator; @@ -1079,26 +671,12 @@ public abstract class app/revanced/patcher/patch/PatchLoader : java/util/Set, ko public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; } -public final class app/revanced/patcher/patch/PatchLoader$Dex : app/revanced/patcher/patch/PatchLoader { - public fun (Ljava/util/Set;Ljava/io/File;)V - public synthetic fun (Ljava/util/Set;Ljava/io/File;ILkotlin/jvm/internal/DefaultConstructorMarker;)V -} - -public final class app/revanced/patcher/patch/PatchLoader$Jar : app/revanced/patcher/patch/PatchLoader { - public fun (Ljava/util/Set;)V -} - -public final class app/revanced/patcher/patch/PatchResult { - public final fun getException ()Lapp/revanced/patcher/patch/PatchException; - public final fun getPatch ()Lapp/revanced/patcher/patch/Patch; -} - public final class app/revanced/patcher/patch/RawResourcePatch : app/revanced/patcher/patch/Patch { public fun toString ()Ljava/lang/String; } public final class app/revanced/patcher/patch/RawResourcePatchBuilder : app/revanced/patcher/patch/PatchBuilder { - public synthetic fun build$revanced_patcher ()Lapp/revanced/patcher/patch/Patch; + public synthetic fun build$core ()Lapp/revanced/patcher/patch/Patch; } public final class app/revanced/patcher/patch/ResourcePatch : app/revanced/patcher/patch/Patch { @@ -1106,7 +684,7 @@ public final class app/revanced/patcher/patch/ResourcePatch : app/revanced/patch } public final class app/revanced/patcher/patch/ResourcePatchBuilder : app/revanced/patcher/patch/PatchBuilder { - public synthetic fun build$revanced_patcher ()Lapp/revanced/patcher/patch/Patch; + public synthetic fun build$core ()Lapp/revanced/patcher/patch/Patch; } public final class app/revanced/patcher/patch/ResourcePatchContext : app/revanced/patcher/patch/PatchContext { @@ -1192,16 +770,339 @@ public final class app/revanced/patcher/util/Document : java/io/Closeable, org/w } public final class app/revanced/patcher/util/MethodNavigator { - public final fun getValue (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/reflect/KProperty;)Lapp/revanced/patcher/dex/mutable/MutableMethod; + public final fun getValue (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/reflect/KProperty;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; public final fun original (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/Method; - public final fun stop (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/dex/mutable/MutableMethod; + public final fun stop (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; public final fun to (Lapp/revanced/patcher/patch/BytecodePatchContext;ILkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/util/MethodNavigator; public final fun to (Lapp/revanced/patcher/patch/BytecodePatchContext;[I)Lapp/revanced/patcher/util/MethodNavigator; public static synthetic fun to$default (Lapp/revanced/patcher/util/MethodNavigator;Lapp/revanced/patcher/patch/BytecodePatchContext;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/util/MethodNavigator; } -public final class app/revanced/patcher/util/SmaliKt { - public static final fun toInstructions (Ljava/lang/String;Lapp/revanced/patcher/dex/mutable/MutableMethod;)Ljava/util/List; - public static synthetic fun toInstructions$default (Ljava/lang/String;Lapp/revanced/patcher/dex/mutable/MutableMethod;ILjava/lang/Object;)Ljava/util/List; +public final class com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseAnnotationEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)V + public fun getElements ()Ljava/util/Set; + public fun getType ()Ljava/lang/String; + public final fun setType (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseArrayEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)V + public fun getValue ()Ljava/util/List; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseBooleanEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)V + public fun getValue ()Z + public final fun setValue (Z)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseByteEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)V + public fun getValue ()B + public final fun setValue (B)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseCharEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)V + public fun getValue ()C + public final fun setValue (C)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseDoubleEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)V + public fun getValue ()D + public final fun setValue (D)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue; +} + +public abstract interface class com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue : com/android/tools/smali/dexlib2/iface/value/EncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue$Companion; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseEnumEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference; + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFieldEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference; + public fun getValueType ()I + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFloatEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)V + public fun getValue ()F + public final fun setValue (F)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseIntEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)V + public fun getValue ()I + public final fun setValue (I)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseLongEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)V + public fun getValue ()J + public final fun setValue (J)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference; + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodHandleEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodHandleReference; + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodHandleReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodTypeEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodProtoReference; + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodProtoReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseNullEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue$Companion; + public fun ()V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseShortEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)V + public fun getValue ()S + public final fun setValue (S)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseStringEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/StringEncodedValue;)V + public fun getValue ()Ljava/lang/String; + public final fun setValue (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseTypeEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)V + public fun getValue ()Ljava/lang/String; + public final fun setValue (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableAnnotation : com/android/tools/smali/dexlib2/base/BaseAnnotation { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableAnnotation$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/Annotation;)V + public fun getElements ()Ljava/util/Set; + public fun getType ()Ljava/lang/String; + public fun getVisibility ()I +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableAnnotation$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Annotation;)Lcom/android/tools/smali/dexlib2/mutable/MutableAnnotation; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement : com/android/tools/smali/dexlib2/base/BaseAnnotationElement { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableAnnotationElement$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)V + public fun getName ()Ljava/lang/String; + public synthetic fun getValue ()Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue; + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue; + public final fun setName (Ljava/lang/String;)V + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue;)V +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)Lcom/android/tools/smali/dexlib2/mutable/MutableAnnotationElement; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableClassDef : com/android/tools/smali/dexlib2/base/reference/BaseTypeReference, com/android/tools/smali/dexlib2/iface/ClassDef { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)V + public final fun charAt (I)C + public fun get (I)C + public fun getAccessFlags ()I + public fun getAnnotations ()Ljava/util/Set; + public synthetic fun getDirectMethods ()Ljava/lang/Iterable; + public fun getDirectMethods ()Ljava/util/Set; + public synthetic fun getFields ()Ljava/lang/Iterable; + public fun getFields ()Ljava/util/Set; + public synthetic fun getInstanceFields ()Ljava/lang/Iterable; + public fun getInstanceFields ()Ljava/util/Set; + public fun getInterfaces ()Ljava/util/List; + public fun getLength ()I + public synthetic fun getMethods ()Ljava/lang/Iterable; + public fun getMethods ()Ljava/util/Set; + public fun getSourceFile ()Ljava/lang/String; + public synthetic fun getStaticFields ()Ljava/lang/Iterable; + public fun getStaticFields ()Ljava/util/Set; + public fun getSuperclass ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public synthetic fun getVirtualMethods ()Ljava/lang/Iterable; + public fun getVirtualMethods ()Ljava/util/Set; + public final fun length ()I + public final fun setAccessFlags (I)V + public final fun setSourceFile (Ljava/lang/String;)V + public final fun setSuperClass (Ljava/lang/String;)V + public final fun setType (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableClassDef$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableField : com/android/tools/smali/dexlib2/base/reference/BaseFieldReference, com/android/tools/smali/dexlib2/iface/Field { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableField$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/Field;)V + public fun getAccessFlags ()I + public fun getAnnotations ()Ljava/util/Set; + public fun getDefiningClass ()Ljava/lang/String; + public fun getHiddenApiRestrictions ()Ljava/util/Set; + public synthetic fun getInitialValue ()Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue; + public fun getInitialValue ()Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue; + public fun getName ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public final fun setAccessFlags (I)V + public final fun setDefiningClass (Ljava/lang/String;)V + public final fun setInitialValue (Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue;)V + public final fun setName (Ljava/lang/String;)V + public final fun setType (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableField$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Field;)Lcom/android/tools/smali/dexlib2/mutable/MutableField; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableMethod : com/android/tools/smali/dexlib2/base/reference/BaseMethodReference, com/android/tools/smali/dexlib2/iface/Method { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableMethod$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/Method;)V + public fun getAccessFlags ()I + public fun getAnnotations ()Ljava/util/Set; + public fun getDefiningClass ()Ljava/lang/String; + public fun getHiddenApiRestrictions ()Ljava/util/Set; + public fun getImplementation ()Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation; + public synthetic fun getImplementation ()Lcom/android/tools/smali/dexlib2/iface/MethodImplementation; + public fun getName ()Ljava/lang/String; + public fun getParameterTypes ()Ljava/util/List; + public fun getParameters ()Ljava/util/List; + public fun getReturnType ()Ljava/lang/String; + public final fun setAccessFlags (I)V + public final fun setDefiningClass (Ljava/lang/String;)V + public final fun setName (Ljava/lang/String;)V + public final fun setReturnType (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableMethod$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Method;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableMethodParameter : com/android/tools/smali/dexlib2/base/BaseMethodParameter, com/android/tools/smali/dexlib2/iface/MethodParameter { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableMethodParameter$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)V + public final fun charAt (I)C + public fun get (I)C + public fun getAnnotations ()Ljava/util/Set; + public fun getLength ()I + public fun getName ()Ljava/lang/String; + public fun getSignature ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public final fun length ()I +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableMethodParameter$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethodParameter; } diff --git a/core/api/jvm/core.api b/core/api/jvm/core.api new file mode 100644 index 0000000..b11a860 --- /dev/null +++ b/core/api/jvm/core.api @@ -0,0 +1,1108 @@ +public final class app/revanced/patcher/CachedReadOnlyProperty : kotlin/properties/ReadOnlyProperty { + public fun getValue (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/reflect/KProperty;)Ljava/lang/Object; + public synthetic fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object; +} + +public final class app/revanced/patcher/Composition { + public final fun getIndices ()Ljava/util/List; + public final fun getMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun getMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun getStrings ()Ljava/util/List; +} + +public final class app/revanced/patcher/DeclarativePredicateBuilder { + public final fun all (Ljava/lang/Object;)Z + public final fun any (Ljava/lang/Object;)Z + public final fun anyOf (Lkotlin/jvm/functions/Function1;)V + public final fun predicate (Lkotlin/jvm/functions/Function1;)V +} + +public final class app/revanced/patcher/Fingerprint { + public final fun getClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public final fun getClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public final fun getMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun getMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun getOriginalClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public final fun getOriginalClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public final fun getOriginalMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/Method; + public final fun getOriginalMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/Method; + public final fun getPatternMatch (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/Match$PatternMatch; + public final fun getPatternMatchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lapp/revanced/patcher/Match$PatternMatch; + public final fun getStringMatches (Lapp/revanced/patcher/patch/BytecodePatchContext;)Ljava/util/List; + public final fun getStringMatchesOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;)Ljava/util/List; + public final fun match (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/Match; + public final fun match (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/Match; + public final fun match (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/Match; + public final fun matchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/Match; + public final fun matchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/Match; + public final fun matchOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/Match; +} + +public final class app/revanced/patcher/FingerprintBuilder { + public fun ()V + public final fun accessFlags (I)V + public final fun accessFlags ([Lcom/android/tools/smali/dexlib2/AccessFlags;)V + public final fun custom (Lkotlin/jvm/functions/Function2;)V + public final fun opcodes (Ljava/lang/String;)V + public final fun opcodes ([Lcom/android/tools/smali/dexlib2/Opcode;)V + public final fun parameters ([Ljava/lang/String;)V + public final fun returns (Ljava/lang/String;)V + public final fun strings ([Ljava/lang/String;)V +} + +public final class app/revanced/patcher/FingerprintKt { + public static final fun fingerprint (ILkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/Fingerprint; + public static synthetic fun fingerprint$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/Fingerprint; +} + +public final class app/revanced/patcher/IndexedMatcher : app/revanced/patcher/Matcher { + public fun ()V + public final fun contains (Ljava/lang/Object;)Z + public fun contains (Lkotlin/jvm/functions/Function3;)Z + public final fun getIndices ()Ljava/util/List; + public final fun getNextIndex ()Ljava/lang/Integer; + public final fun indexOf (Ljava/lang/Object;)I + public fun indexOf (Lkotlin/jvm/functions/Function3;)I + public fun invoke (Ljava/lang/Iterable;)Z + public final fun lastIndexOf (Ljava/lang/Object;)I + public fun lastIndexOf (Lkotlin/jvm/functions/Function3;)I + public final fun remove (I)Lkotlin/jvm/functions/Function3; + public final fun remove (Ljava/lang/Object;)Z + public fun remove (Lkotlin/jvm/functions/Function3;)Z + public fun removeAt (I)Lkotlin/jvm/functions/Function3; + public final fun setNextIndex (Ljava/lang/Integer;)V +} + +public abstract interface annotation class app/revanced/patcher/InternalApi : java/lang/annotation/Annotation { +} + +public final class app/revanced/patcher/Match { + public final fun getClassDef ()Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public final fun getContext ()Lapp/revanced/patcher/patch/BytecodePatchContext; + public final fun getMethod ()Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun getOriginalClassDef ()Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public final fun getOriginalMethod ()Lcom/android/tools/smali/dexlib2/iface/Method; + public final fun getPatternMatch ()Lapp/revanced/patcher/Match$PatternMatch; + public final fun getStringMatches ()Ljava/util/List; +} + +public final class app/revanced/patcher/Match$PatternMatch { + public final fun getEndIndex ()I + public final fun getStartIndex ()I +} + +public final class app/revanced/patcher/Match$StringMatch { + public final fun getIndex ()I + public final fun getString ()Ljava/lang/String; +} + +public abstract class app/revanced/patcher/Matcher : java/util/List, kotlin/jvm/internal/markers/KMutableList { + public fun ()V + public fun add (ILjava/lang/Object;)V + public fun add (Ljava/lang/Object;)Z + public fun addAll (ILjava/util/Collection;)Z + public fun addAll (Ljava/util/Collection;)Z + public fun clear ()V + public fun contains (Ljava/lang/Object;)Z + public fun containsAll (Ljava/util/Collection;)Z + public fun get (I)Ljava/lang/Object; + public final fun getMatchIndex ()I + public fun getSize ()I + public fun indexOf (Ljava/lang/Object;)I + public abstract fun invoke (Ljava/lang/Iterable;)Z + public fun isEmpty ()Z + public fun iterator ()Ljava/util/Iterator; + public fun lastIndexOf (Ljava/lang/Object;)I + public fun listIterator ()Ljava/util/ListIterator; + public fun listIterator (I)Ljava/util/ListIterator; + public final fun remove (I)Ljava/lang/Object; + public fun remove (Ljava/lang/Object;)Z + public fun removeAll (Ljava/util/Collection;)Z + public fun removeAt (I)Ljava/lang/Object; + public fun retainAll (Ljava/util/Collection;)Z + public fun set (ILjava/lang/Object;)Ljava/lang/Object; + protected final fun setMatchIndex (I)V + public final fun size ()I + public fun subList (II)Ljava/util/List; + public fun toArray ()[Ljava/lang/Object; + public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; +} + +public final class app/revanced/patcher/MatchingKt { + public static final fun accessFlags (Lapp/revanced/patcher/DeclarativePredicateBuilder;[Lcom/android/tools/smali/dexlib2/AccessFlags;)V + public static final fun after (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun after (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; + public static synthetic fun after$default (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun after$default (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/ranges/IntRange;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun allOf ([Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; + public static final fun anyAnnotation (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyAnnotation (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyClassDef (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyDebugItem (Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyDirectMethod (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyField (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyHiddenApiRestriction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyInstanceField (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyInstruction (Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyInstruction (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyInterface (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyMethod (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyOf ([Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; + public static final fun anyParameter (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyParameterType (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyStaticField (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyTryBlock (Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;Lkotlin/jvm/functions/Function1;)Z + public static final fun anyVirtualMethod (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lkotlin/jvm/functions/Function1;)Z + public static final fun custom (Lapp/revanced/patcher/DeclarativePredicateBuilder;Lkotlin/jvm/functions/Function1;)V + public static final fun declarativePredicate (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public static final fun field (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun field (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun field$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun field$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun firstClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDef (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static synthetic fun firstClassDef$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static synthetic fun firstClassDefMutable$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static synthetic fun firstClassDefMutableOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public static final fun firstClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstClassDefOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static synthetic fun firstClassDefOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public static final fun firstMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethod (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static synthetic fun firstMethod$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodComposite ([Ljava/lang/String;Lkotlin/jvm/functions/Function5;)Lapp/revanced/patcher/Composition; + public static final fun firstMethodMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutable (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static synthetic fun firstMethodMutable$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableByDeclarativePredicate (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableByDeclarativePredicateOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodMutableOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static synthetic fun firstMethodMutableOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public static final fun firstMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun firstMethodOrNull (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static synthetic fun firstMethodOrNull$default (Lapp/revanced/patcher/patch/BytecodePatchContext;[Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/iface/Method; + public static final fun getM ()Lapp/revanced/patcher/Composition; + public static final fun gettingFirstClassDef (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDef (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstClassDef$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefByDeclarativePredicate (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefByDeclarativePredicate (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefByDeclarativePredicateOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefByDeclarativePredicateOrNull (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutable (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutable (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstClassDefMutable$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableByDeclarativePredicate (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableByDeclarativePredicate (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableByDeclarativePredicateOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableByDeclarativePredicateOrNull (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefMutableOrNull (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstClassDefMutableOrNull$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefOrNull (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstClassDefOrNull (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstClassDefOrNull$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethod (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethod ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstMethod$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodByDeclarativePredicate (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodByDeclarativePredicate ([Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodByDeclarativePredicateOrNull (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodByDeclarativePredicateOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutable (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutable ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstMethodMutable$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableByDeclarativePredicate (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableByDeclarativePredicate ([Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableByDeclarativePredicateOrNull (Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableByDeclarativePredicateOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function3;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableOrNull (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodMutableOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstMethodMutableOrNull$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodOrNull (Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun gettingFirstMethodOrNull ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static synthetic fun gettingFirstMethodOrNull$default ([Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/CachedReadOnlyProperty; + public static final fun head (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun head (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; + public static final fun implementation (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Z + public static final fun indexedMatcher ()Lapp/revanced/patcher/IndexedMatcher; + public static final fun indexedMatcher (Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/IndexedMatcher; + public static final fun instruction (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun instructions (Lapp/revanced/patcher/IndexedMatcher;Lapp/revanced/patcher/DeclarativePredicateBuilder;Lkotlin/jvm/functions/Function1;)V + public static final fun instructions (Lapp/revanced/patcher/IndexedMatcher;Lapp/revanced/patcher/DeclarativePredicateBuilder;[Lkotlin/jvm/functions/Function3;)V + public static final fun invoke (Lcom/android/tools/smali/dexlib2/Opcode;)Lkotlin/jvm/functions/Function3; + public static final fun invoke (Ljava/util/List;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static synthetic fun invoke$default (Ljava/util/List;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun literal (JLkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun literal (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun literal$default (JLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun literal$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun matchIndexed (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Z + public static final fun method (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun method (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun method$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun method$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun noneOf ([Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; + public static final fun parameterTypes (Lapp/revanced/patcher/DeclarativePredicateBuilder;[Ljava/lang/String;)V + public static final fun reference (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun reference (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun reference$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun reference$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun registers (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun registers ([ILkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static synthetic fun registers$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun registers$default ([ILkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun rememberedDeclarativePredicate (Lapp/revanced/patcher/PredicateContext;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public static final fun rememberedMatchIndexed (Lapp/revanced/patcher/PredicateContext;Ljava/lang/Iterable;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public static final fun returns (Lapp/revanced/patcher/DeclarativePredicateBuilder;Ljava/lang/String;)V + public static final fun string (Ljava/util/List;Lapp/revanced/patcher/DeclarativePredicateBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun string (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun string$default (Ljava/util/List;Lapp/revanced/patcher/DeclarativePredicateBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun string$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun type (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function3; + public static final fun type (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static synthetic fun type$default (Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static synthetic fun type$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun unaryPlus (Lapp/revanced/patcher/IndexedMatcher;Lkotlin/jvm/functions/Function3;)Z +} + +public final class app/revanced/patcher/PackageMetadata { + public final fun getPackageName ()Ljava/lang/String; + public final fun getPackageVersion ()Ljava/lang/String; +} + +public final class app/revanced/patcher/Patcher : java/io/Closeable { + public fun (Lapp/revanced/patcher/PatcherConfig;)V + public fun close ()V + public final fun get ()Lapp/revanced/patcher/PatcherResult; + public final fun getContext ()Lapp/revanced/patcher/PatcherContext; + public final fun invoke ()Lkotlinx/coroutines/flow/Flow; + public final fun plusAssign (Ljava/util/Set;)V +} + +public final class app/revanced/patcher/PatcherConfig { + public fun (Ljava/io/File;Ljava/io/File;Ljava/io/File;Ljava/lang/String;)V + public synthetic fun (Ljava/io/File;Ljava/io/File;Ljava/io/File;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;)V + public synthetic fun (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V +} + +public final class app/revanced/patcher/PatcherContext : java/io/Closeable { + public fun close ()V + public final fun getPackageMetadata ()Lapp/revanced/patcher/PackageMetadata; +} + +public final class app/revanced/patcher/PatcherResult { + public final fun getDexFiles ()Ljava/util/Set; + public final fun getResources ()Lapp/revanced/patcher/PatcherResult$PatchedResources; +} + +public final class app/revanced/patcher/PatcherResult$PatchedDexFile { + public final fun getName ()Ljava/lang/String; + public final fun getStream ()Ljava/io/InputStream; +} + +public final class app/revanced/patcher/PatcherResult$PatchedResources { + public final fun getDeleteResources ()Ljava/util/Set; + public final fun getDoNotCompress ()Ljava/util/Set; + public final fun getOtherResources ()Ljava/io/File; + public final fun getResourcesApk ()Ljava/io/File; +} + +public final class app/revanced/patcher/PredicateContext : java/util/Map, kotlin/jvm/internal/markers/KMutableMap { + public fun clear ()V + public fun containsKey (Ljava/lang/Object;)Z + public fun containsValue (Ljava/lang/Object;)Z + public final fun entrySet ()Ljava/util/Set; + public fun get (Ljava/lang/Object;)Ljava/lang/Object; + public fun getEntries ()Ljava/util/Set; + public fun getKeys ()Ljava/util/Set; + public fun getSize ()I + public fun getValues ()Ljava/util/Collection; + public fun isEmpty ()Z + public final fun keySet ()Ljava/util/Set; + public fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun putAll (Ljava/util/Map;)V + public fun remove (Ljava/lang/Object;)Ljava/lang/Object; + public final fun size ()I + public final fun values ()Ljava/util/Collection; +} + +public final class app/revanced/patcher/extensions/ExternalLabel { + public fun (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)V + public final fun copy (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lapp/revanced/patcher/extensions/ExternalLabel; + public static synthetic fun copy$default (Lapp/revanced/patcher/extensions/ExternalLabel;Ljava/lang/String;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;ILjava/lang/Object;)Lapp/revanced/patcher/extensions/ExternalLabel; + public fun equals (Ljava/lang/Object;)Z + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class app/revanced/patcher/extensions/InstructionKt { + public static final fun getFieldReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference; + public static final fun getMethodReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference; + public static final fun getReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/Reference; + public static final fun getString (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Ljava/lang/String; + public static final fun getStringReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/StringReference; + public static final fun getType (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Ljava/lang/String; + public static final fun getTypeReference (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lcom/android/tools/smali/dexlib2/iface/reference/TypeReference; + public static final fun getWideLiteral (Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Ljava/lang/Long; + public static final fun toInstructions (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;)Ljava/util/List; + public static synthetic fun toInstructions$default (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/Object;)Ljava/util/List; +} + +public final class app/revanced/patcher/extensions/MethodKt { + public static final fun accessFlags (Lcom/android/tools/smali/dexlib2/iface/Method;[Lcom/android/tools/smali/dexlib2/AccessFlags;)Z + public static final fun addInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V + public static final fun addInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;)V + public static final fun addInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V + public static final fun addInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;Ljava/lang/String;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;ILjava/util/List;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;Ljava/util/List;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/util/List;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;Ljava/lang/String;)V + public static final fun addInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;Ljava/util/List;)V + public static final fun addInstructionsWithLabels (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;[Lapp/revanced/patcher/extensions/ExternalLabel;)V + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)Ljava/lang/Object; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;I)Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;I)Ljava/lang/Object; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;I)Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;I)Ljava/lang/Object; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction; + public static final fun getInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Ljava/lang/Object; + public static final fun getInstructionOrNull (Lcom/android/tools/smali/dexlib2/iface/Method;I)Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction; + public static final fun getInstructionOrNull (Lcom/android/tools/smali/dexlib2/iface/Method;I)Ljava/lang/Object; + public static final fun getInstructionOrNull (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction; + public static final fun getInstructionOrNull (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Ljava/lang/Object; + public static final fun getInstructions (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Iterable; + public static final fun getInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;)Ljava/util/List; + public static final fun getInstructionsOrNull (Lcom/android/tools/smali/dexlib2/iface/Method;)Ljava/lang/Iterable; + public static final fun getInstructionsOrNull (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;)Ljava/util/List; + public static final fun newLabel (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/Label; + public static final fun removeInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)V + public static final fun removeInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)V + public static final fun removeInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;II)V + public static final fun removeInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;I)V + public static final fun removeInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;II)V + public static final fun replaceInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V + public static final fun replaceInstruction (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;)V + public static final fun replaceInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;ILjava/util/List;)V + public static final fun replaceInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/lang/String;)V + public static final fun replaceInstructions (Lcom/android/tools/smali/dexlib2/mutable/MutableMethod;ILjava/util/List;)V +} + +public final class app/revanced/patcher/patch/BytecodePatch : app/revanced/patcher/patch/Patch { + public final fun getExtensionInputStream ()Ljava/util/function/Supplier; + public fun toString ()Ljava/lang/String; +} + +public final class app/revanced/patcher/patch/BytecodePatchBuilder : app/revanced/patcher/patch/PatchBuilder { + public synthetic fun build$core ()Lapp/revanced/patcher/patch/Patch; + public final fun extendWith (Ljava/lang/String;)Lapp/revanced/patcher/patch/BytecodePatchBuilder; + public final fun getExtensionInputStream ()Ljava/util/function/Supplier; + public final fun setExtensionInputStream (Ljava/util/function/Supplier;)V +} + +public final class app/revanced/patcher/patch/BytecodePatchContext : app/revanced/patcher/patch/PatchContext, java/io/Closeable { + public fun close ()V + public synthetic fun get ()Ljava/lang/Object; + public fun get ()Ljava/util/Set; + public final fun getClassDefs ()Lapp/revanced/patcher/patch/BytecodePatchContext$ClassDefs; + public final fun navigate (Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference;)Lapp/revanced/patcher/util/MethodNavigator; +} + +public final class app/revanced/patcher/patch/BytecodePatchContext$ClassDefs : java/util/Set, kotlin/jvm/internal/markers/KMutableSet { + public fun (Lapp/revanced/patcher/patch/BytecodePatchContext;)V + public fun add (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z + public synthetic fun add (Ljava/lang/Object;)Z + public fun addAll (Ljava/util/Collection;)Z + public fun clear ()V + public fun contains (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z + public final fun contains (Ljava/lang/Object;)Z + public fun containsAll (Ljava/util/Collection;)Z + public final fun get (Ljava/lang/String;)Lcom/android/tools/smali/dexlib2/iface/ClassDef; + public final fun getMethodsByString ()Ljava/util/Map; + public final fun getOrReplaceMutable (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; + public fun getSize ()I + public fun isEmpty ()Z + public fun iterator ()Ljava/util/Iterator; + public fun remove (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z + public final fun remove (Ljava/lang/Object;)Z + public fun removeAll (Ljava/util/Collection;)Z + public fun removeIf (Ljava/util/function/Predicate;)Z + public fun retainAll (Ljava/util/Collection;)Z + public final fun size ()I + public fun toArray ()[Ljava/lang/Object; + public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; +} + +public final class app/revanced/patcher/patch/Option { + public fun (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/reflect/KType;Lkotlin/jvm/functions/Function2;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/reflect/KType;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/lang/String;ZLkotlin/reflect/KType;Lkotlin/jvm/functions/Function2;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/Object;Ljava/util/Map;Ljava/lang/String;ZLkotlin/reflect/KType;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getDefault ()Ljava/lang/Object; + public final fun getDescription ()Ljava/lang/String; + public final fun getKey ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getRequired ()Z + public final fun getTitle ()Ljava/lang/String; + public final fun getType ()Lkotlin/reflect/KType; + public final fun getValidator ()Lkotlin/jvm/functions/Function2; + public final fun getValue ()Ljava/lang/Object; + public final fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object; + public final fun getValues ()Ljava/util/Map; + public final fun reset ()V + public final fun setValue (Ljava/lang/Object;)V + public final fun setValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;Ljava/lang/Object;)V + public fun toString ()Ljava/lang/String; +} + +public abstract class app/revanced/patcher/patch/OptionException : java/lang/Exception { + public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V +} + +public final class app/revanced/patcher/patch/OptionException$InvalidValueTypeException : app/revanced/patcher/patch/OptionException { + public fun (Ljava/lang/String;Ljava/lang/String;)V +} + +public final class app/revanced/patcher/patch/OptionException$OptionNotFoundException : app/revanced/patcher/patch/OptionException { + public fun (Ljava/lang/String;)V +} + +public final class app/revanced/patcher/patch/OptionException$ValueRequiredException : app/revanced/patcher/patch/OptionException { + public fun (Lapp/revanced/patcher/patch/Option;)V +} + +public final class app/revanced/patcher/patch/OptionException$ValueValidationException : app/revanced/patcher/patch/OptionException { + public fun (Ljava/lang/Object;Lapp/revanced/patcher/patch/Option;)V +} + +public final class app/revanced/patcher/patch/OptionKt { + public static final fun booleanOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun booleanOption (Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun booleanOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun booleanOption$default (Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun booleansOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun booleansOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun booleansOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun booleansOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun floatOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun floatOption (Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun floatOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun floatOption$default (Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun floatsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun floatsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun intOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun intOption (Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun intOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun intOption$default (Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun intsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun intsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun intsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun intsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun longOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun longOption (Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun longOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun longOption$default (Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun longsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun longsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun longsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun longsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun stringOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun stringOption (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun stringOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun stringOption$default (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static final fun stringsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static final fun stringsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun stringsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public static synthetic fun stringsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option; +} + +public final class app/revanced/patcher/patch/Options : java/util/Map, kotlin/jvm/internal/markers/KMappedMarker { + public fun clear ()V + public synthetic fun compute (Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; + public fun compute (Ljava/lang/String;Ljava/util/function/BiFunction;)Lapp/revanced/patcher/patch/Option; + public synthetic fun computeIfAbsent (Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object; + public fun computeIfAbsent (Ljava/lang/String;Ljava/util/function/Function;)Lapp/revanced/patcher/patch/Option; + public synthetic fun computeIfPresent (Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; + public fun computeIfPresent (Ljava/lang/String;Ljava/util/function/BiFunction;)Lapp/revanced/patcher/patch/Option; + public final fun containsKey (Ljava/lang/Object;)Z + public fun containsKey (Ljava/lang/String;)Z + public fun containsValue (Lapp/revanced/patcher/patch/Option;)Z + public final fun containsValue (Ljava/lang/Object;)Z + public final fun entrySet ()Ljava/util/Set; + public final fun get (Ljava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public final synthetic fun get (Ljava/lang/Object;)Ljava/lang/Object; + public fun get (Ljava/lang/String;)Lapp/revanced/patcher/patch/Option; + public fun getEntries ()Ljava/util/Set; + public fun getKeys ()Ljava/util/Set; + public fun getSize ()I + public fun getValues ()Ljava/util/Collection; + public fun isEmpty ()Z + public final fun keySet ()Ljava/util/Set; + public synthetic fun merge (Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; + public fun merge (Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Ljava/util/function/BiFunction;)Lapp/revanced/patcher/patch/Option; + public synthetic fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun put (Ljava/lang/String;Lapp/revanced/patcher/patch/Option;)Lapp/revanced/patcher/patch/Option; + public fun putAll (Ljava/util/Map;)V + public synthetic fun putIfAbsent (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun putIfAbsent (Ljava/lang/String;Lapp/revanced/patcher/patch/Option;)Lapp/revanced/patcher/patch/Option; + public fun remove (Ljava/lang/Object;)Lapp/revanced/patcher/patch/Option; + public synthetic fun remove (Ljava/lang/Object;)Ljava/lang/Object; + public fun remove (Ljava/lang/Object;Ljava/lang/Object;)Z + public synthetic fun replace (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public synthetic fun replace (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z + public fun replace (Ljava/lang/String;Lapp/revanced/patcher/patch/Option;)Lapp/revanced/patcher/patch/Option; + public fun replace (Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lapp/revanced/patcher/patch/Option;)Z + public fun replaceAll (Ljava/util/function/BiFunction;)V + public final fun set (Ljava/lang/String;Ljava/lang/Object;)V + public final fun size ()I + public final fun values ()Ljava/util/Collection; +} + +public abstract class app/revanced/patcher/patch/Patch { + public synthetic fun (Ljava/lang/String;Ljava/lang/String;ZLjava/util/Set;Ljava/util/Set;Ljava/util/Set;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun execute (Lapp/revanced/patcher/patch/PatchContext;)V + public final fun finalize (Lapp/revanced/patcher/patch/PatchContext;)V + public final fun getCompatiblePackages ()Ljava/util/Set; + public final fun getDependencies ()Ljava/util/Set; + public final fun getDescription ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getOptions ()Lapp/revanced/patcher/patch/Options; + public final fun getUse ()Z + public fun toString ()Ljava/lang/String; +} + +public abstract class app/revanced/patcher/patch/PatchBuilder { + public synthetic fun (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun compatibleWith ([Ljava/lang/String;)V + public final fun compatibleWith ([Lkotlin/Pair;)V + public final fun dependsOn ([Lapp/revanced/patcher/patch/Patch;)V + public final fun execute (Lkotlin/jvm/functions/Function1;)V + public final fun finalize (Lkotlin/jvm/functions/Function1;)V + protected final fun getCompatiblePackages ()Ljava/util/Set; + protected final fun getDependencies ()Ljava/util/Set; + protected final fun getDescription ()Ljava/lang/String; + protected final fun getExecutionBlock ()Lkotlin/jvm/functions/Function1; + protected final fun getFinalizeBlock ()Lkotlin/jvm/functions/Function1; + protected final fun getName ()Ljava/lang/String; + protected final fun getOptions ()Ljava/util/Set; + protected final fun getUse ()Z + public final fun invoke (Lapp/revanced/patcher/patch/Option;)Lapp/revanced/patcher/patch/Option; + public final fun invoke (Ljava/lang/String;[Ljava/lang/String;)Lkotlin/Pair; + protected final fun setCompatiblePackages (Ljava/util/Set;)V + protected final fun setDependencies (Ljava/util/Set;)V + protected final fun setExecutionBlock (Lkotlin/jvm/functions/Function1;)V + protected final fun setFinalizeBlock (Lkotlin/jvm/functions/Function1;)V +} + +public abstract interface class app/revanced/patcher/patch/PatchContext : java/util/function/Supplier { +} + +public final class app/revanced/patcher/patch/PatchException : java/lang/Exception { + public fun (Ljava/lang/String;)V + public fun (Ljava/lang/String;Ljava/lang/Throwable;)V + public fun (Ljava/lang/Throwable;)V +} + +public final class app/revanced/patcher/patch/PatchKt { + public static final fun bytecodePatch (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch; + public static synthetic fun bytecodePatch$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch; + public static final fun gettingBytecodePatch (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun gettingBytecodePatch$default (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun gettingRawResourcePatch (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun gettingRawResourcePatch$default (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun gettingResourcePatch (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun gettingResourcePatch$default (Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun rawResourcePatch (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/RawResourcePatch; + public static synthetic fun rawResourcePatch$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/RawResourcePatch; + public static final fun resourcePatch (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch; + public static synthetic fun resourcePatch$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch; +} + +public final class app/revanced/patcher/patch/PatchResult { + public final fun getException ()Lapp/revanced/patcher/patch/PatchException; + public final fun getPatch ()Lapp/revanced/patcher/patch/Patch; +} + +public final class app/revanced/patcher/patch/Patch_jvmKt { + public static final fun isPatch (Ljava/lang/Class;)Z + public static final fun loadPatches (Ljava/util/Set;)Lapp/revanced/patcher/patch/Patches; +} + +public final class app/revanced/patcher/patch/Patches : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { + public fun add (Lapp/revanced/patcher/patch/Patch;)Z + public synthetic fun add (Ljava/lang/Object;)Z + public fun addAll (Ljava/util/Collection;)Z + public fun clear ()V + public fun contains (Lapp/revanced/patcher/patch/Patch;)Z + public final fun contains (Ljava/lang/Object;)Z + public fun containsAll (Ljava/util/Collection;)Z + public final fun getPatchesByFile ()Ljava/util/Map; + public fun getSize ()I + public fun isEmpty ()Z + public fun iterator ()Ljava/util/Iterator; + public fun remove (Ljava/lang/Object;)Z + public fun removeAll (Ljava/util/Collection;)Z + public fun retainAll (Ljava/util/Collection;)Z + public final fun size ()I + public fun toArray ()[Ljava/lang/Object; + public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; +} + +public final class app/revanced/patcher/patch/RawResourcePatch : app/revanced/patcher/patch/Patch { + public fun toString ()Ljava/lang/String; +} + +public final class app/revanced/patcher/patch/RawResourcePatchBuilder : app/revanced/patcher/patch/PatchBuilder { + public synthetic fun build$core ()Lapp/revanced/patcher/patch/Patch; +} + +public final class app/revanced/patcher/patch/ResourcePatch : app/revanced/patcher/patch/Patch { + public fun toString ()Ljava/lang/String; +} + +public final class app/revanced/patcher/patch/ResourcePatchBuilder : app/revanced/patcher/patch/PatchBuilder { + public synthetic fun build$core ()Lapp/revanced/patcher/patch/Patch; +} + +public final class app/revanced/patcher/patch/ResourcePatchContext : app/revanced/patcher/patch/PatchContext { + public final fun delete (Ljava/lang/String;)Z + public final fun document (Ljava/io/InputStream;)Lapp/revanced/patcher/util/Document; + public final fun document (Ljava/lang/String;)Lapp/revanced/patcher/util/Document; + public fun get ()Lapp/revanced/patcher/PatcherResult$PatchedResources; + public synthetic fun get ()Ljava/lang/Object; + public final fun get (Ljava/lang/String;Z)Ljava/io/File; + public static synthetic fun get$default (Lapp/revanced/patcher/patch/ResourcePatchContext;Ljava/lang/String;ZILjava/lang/Object;)Ljava/io/File; +} + +public final class app/revanced/patcher/util/Document : java/io/Closeable, org/w3c/dom/Document { + public fun adoptNode (Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node; + public fun appendChild (Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node; + public fun cloneNode (Z)Lorg/w3c/dom/Node; + public fun close ()V + public fun compareDocumentPosition (Lorg/w3c/dom/Node;)S + public fun createAttribute (Ljava/lang/String;)Lorg/w3c/dom/Attr; + public fun createAttributeNS (Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/Attr; + public fun createCDATASection (Ljava/lang/String;)Lorg/w3c/dom/CDATASection; + public fun createComment (Ljava/lang/String;)Lorg/w3c/dom/Comment; + public fun createDocumentFragment ()Lorg/w3c/dom/DocumentFragment; + public fun createElement (Ljava/lang/String;)Lorg/w3c/dom/Element; + public fun createElementNS (Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/Element; + public fun createEntityReference (Ljava/lang/String;)Lorg/w3c/dom/EntityReference; + public fun createProcessingInstruction (Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/ProcessingInstruction; + public fun createTextNode (Ljava/lang/String;)Lorg/w3c/dom/Text; + public fun getAttributes ()Lorg/w3c/dom/NamedNodeMap; + public fun getBaseURI ()Ljava/lang/String; + public fun getChildNodes ()Lorg/w3c/dom/NodeList; + public fun getDoctype ()Lorg/w3c/dom/DocumentType; + public fun getDocumentElement ()Lorg/w3c/dom/Element; + public fun getDocumentURI ()Ljava/lang/String; + public fun getDomConfig ()Lorg/w3c/dom/DOMConfiguration; + public fun getElementById (Ljava/lang/String;)Lorg/w3c/dom/Element; + public fun getElementsByTagName (Ljava/lang/String;)Lorg/w3c/dom/NodeList; + public fun getElementsByTagNameNS (Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/NodeList; + public fun getFeature (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; + public fun getFirstChild ()Lorg/w3c/dom/Node; + public fun getImplementation ()Lorg/w3c/dom/DOMImplementation; + public fun getInputEncoding ()Ljava/lang/String; + public fun getLastChild ()Lorg/w3c/dom/Node; + public fun getLocalName ()Ljava/lang/String; + public fun getNamespaceURI ()Ljava/lang/String; + public fun getNextSibling ()Lorg/w3c/dom/Node; + public fun getNodeName ()Ljava/lang/String; + public fun getNodeType ()S + public fun getNodeValue ()Ljava/lang/String; + public fun getOwnerDocument ()Lorg/w3c/dom/Document; + public fun getParentNode ()Lorg/w3c/dom/Node; + public fun getPrefix ()Ljava/lang/String; + public fun getPreviousSibling ()Lorg/w3c/dom/Node; + public fun getStrictErrorChecking ()Z + public fun getTextContent ()Ljava/lang/String; + public fun getUserData (Ljava/lang/String;)Ljava/lang/Object; + public fun getXmlEncoding ()Ljava/lang/String; + public fun getXmlStandalone ()Z + public fun getXmlVersion ()Ljava/lang/String; + public fun hasAttributes ()Z + public fun hasChildNodes ()Z + public fun importNode (Lorg/w3c/dom/Node;Z)Lorg/w3c/dom/Node; + public fun insertBefore (Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node; + public fun isDefaultNamespace (Ljava/lang/String;)Z + public fun isEqualNode (Lorg/w3c/dom/Node;)Z + public fun isSameNode (Lorg/w3c/dom/Node;)Z + public fun isSupported (Ljava/lang/String;Ljava/lang/String;)Z + public fun lookupNamespaceURI (Ljava/lang/String;)Ljava/lang/String; + public fun lookupPrefix (Ljava/lang/String;)Ljava/lang/String; + public fun normalize ()V + public fun normalizeDocument ()V + public fun removeChild (Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node; + public fun renameNode (Lorg/w3c/dom/Node;Ljava/lang/String;Ljava/lang/String;)Lorg/w3c/dom/Node; + public fun replaceChild (Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node; + public fun setDocumentURI (Ljava/lang/String;)V + public fun setNodeValue (Ljava/lang/String;)V + public fun setPrefix (Ljava/lang/String;)V + public fun setStrictErrorChecking (Z)V + public fun setTextContent (Ljava/lang/String;)V + public fun setUserData (Ljava/lang/String;Ljava/lang/Object;Lorg/w3c/dom/UserDataHandler;)Ljava/lang/Object; + public fun setXmlStandalone (Z)V + public fun setXmlVersion (Ljava/lang/String;)V +} + +public final class app/revanced/patcher/util/MethodNavigator { + public final fun getValue (Lapp/revanced/patcher/patch/BytecodePatchContext;Lkotlin/reflect/KProperty;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun original (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/iface/Method; + public final fun stop (Lapp/revanced/patcher/patch/BytecodePatchContext;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; + public final fun to (Lapp/revanced/patcher/patch/BytecodePatchContext;ILkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/util/MethodNavigator; + public final fun to (Lapp/revanced/patcher/patch/BytecodePatchContext;[I)Lapp/revanced/patcher/util/MethodNavigator; + public static synthetic fun to$default (Lapp/revanced/patcher/util/MethodNavigator;Lapp/revanced/patcher/patch/BytecodePatchContext;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/util/MethodNavigator; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseAnnotationEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)V + public fun getElements ()Ljava/util/Set; + public fun getType ()Ljava/lang/String; + public final fun setType (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseArrayEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)V + public fun getValue ()Ljava/util/List; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseBooleanEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)V + public fun getValue ()Z + public final fun setValue (Z)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseByteEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)V + public fun getValue ()B + public final fun setValue (B)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseCharEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)V + public fun getValue ()C + public final fun setValue (C)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseDoubleEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)V + public fun getValue ()D + public final fun setValue (D)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue; +} + +public abstract interface class com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue : com/android/tools/smali/dexlib2/iface/value/EncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue$Companion; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseEnumEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference; + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFieldEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference; + public fun getValueType ()I + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFloatEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)V + public fun getValue ()F + public final fun setValue (F)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseIntEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)V + public fun getValue ()I + public final fun setValue (I)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseLongEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)V + public fun getValue ()J + public final fun setValue (J)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference; + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodHandleEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodHandleReference; + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodHandleReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodTypeEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)V + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodProtoReference; + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodProtoReference;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseNullEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue$Companion; + public fun ()V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseShortEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)V + public fun getValue ()S + public final fun setValue (S)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseStringEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/StringEncodedValue;)V + public fun getValue ()Ljava/lang/String; + public final fun setValue (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseTypeEncodedValue, com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue { + public static final field Companion Lcom/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)V + public fun getValue ()Ljava/lang/String; + public final fun setValue (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)Lcom/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableAnnotation : com/android/tools/smali/dexlib2/base/BaseAnnotation { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableAnnotation$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/Annotation;)V + public fun getElements ()Ljava/util/Set; + public fun getType ()Ljava/lang/String; + public fun getVisibility ()I +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableAnnotation$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Annotation;)Lcom/android/tools/smali/dexlib2/mutable/MutableAnnotation; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement : com/android/tools/smali/dexlib2/base/BaseAnnotationElement { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableAnnotationElement$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)V + public fun getName ()Ljava/lang/String; + public synthetic fun getValue ()Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue; + public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue; + public final fun setName (Ljava/lang/String;)V + public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue;)V +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)Lcom/android/tools/smali/dexlib2/mutable/MutableAnnotationElement; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableClassDef : com/android/tools/smali/dexlib2/base/reference/BaseTypeReference, com/android/tools/smali/dexlib2/iface/ClassDef { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)V + public final fun charAt (I)C + public fun get (I)C + public fun getAccessFlags ()I + public fun getAnnotations ()Ljava/util/Set; + public synthetic fun getDirectMethods ()Ljava/lang/Iterable; + public fun getDirectMethods ()Ljava/util/Set; + public synthetic fun getFields ()Ljava/lang/Iterable; + public fun getFields ()Ljava/util/Set; + public synthetic fun getInstanceFields ()Ljava/lang/Iterable; + public fun getInstanceFields ()Ljava/util/Set; + public fun getInterfaces ()Ljava/util/List; + public fun getLength ()I + public synthetic fun getMethods ()Ljava/lang/Iterable; + public fun getMethods ()Ljava/util/Set; + public fun getSourceFile ()Ljava/lang/String; + public synthetic fun getStaticFields ()Ljava/lang/Iterable; + public fun getStaticFields ()Ljava/util/Set; + public fun getSuperclass ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public synthetic fun getVirtualMethods ()Ljava/lang/Iterable; + public fun getVirtualMethods ()Ljava/util/Set; + public final fun length ()I + public final fun setAccessFlags (I)V + public final fun setSourceFile (Ljava/lang/String;)V + public final fun setSuperClass (Ljava/lang/String;)V + public final fun setType (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableClassDef$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lcom/android/tools/smali/dexlib2/mutable/MutableClassDef; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableField : com/android/tools/smali/dexlib2/base/reference/BaseFieldReference, com/android/tools/smali/dexlib2/iface/Field { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableField$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/Field;)V + public fun getAccessFlags ()I + public fun getAnnotations ()Ljava/util/Set; + public fun getDefiningClass ()Ljava/lang/String; + public fun getHiddenApiRestrictions ()Ljava/util/Set; + public synthetic fun getInitialValue ()Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue; + public fun getInitialValue ()Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue; + public fun getName ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public final fun setAccessFlags (I)V + public final fun setDefiningClass (Ljava/lang/String;)V + public final fun setInitialValue (Lcom/android/tools/smali/dexlib2/iface/value/MutableEncodedValue;)V + public final fun setName (Ljava/lang/String;)V + public final fun setType (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableField$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Field;)Lcom/android/tools/smali/dexlib2/mutable/MutableField; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableMethod : com/android/tools/smali/dexlib2/base/reference/BaseMethodReference, com/android/tools/smali/dexlib2/iface/Method { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableMethod$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/Method;)V + public fun getAccessFlags ()I + public fun getAnnotations ()Ljava/util/Set; + public fun getDefiningClass ()Ljava/lang/String; + public fun getHiddenApiRestrictions ()Ljava/util/Set; + public fun getImplementation ()Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation; + public synthetic fun getImplementation ()Lcom/android/tools/smali/dexlib2/iface/MethodImplementation; + public fun getName ()Ljava/lang/String; + public fun getParameterTypes ()Ljava/util/List; + public fun getParameters ()Ljava/util/List; + public fun getReturnType ()Ljava/lang/String; + public final fun setAccessFlags (I)V + public final fun setDefiningClass (Ljava/lang/String;)V + public final fun setName (Ljava/lang/String;)V + public final fun setReturnType (Ljava/lang/String;)V +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableMethod$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Method;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethod; +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableMethodParameter : com/android/tools/smali/dexlib2/base/BaseMethodParameter, com/android/tools/smali/dexlib2/iface/MethodParameter { + public static final field Companion Lcom/android/tools/smali/dexlib2/mutable/MutableMethodParameter$Companion; + public fun (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)V + public final fun charAt (I)C + public fun get (I)C + public fun getAnnotations ()Ljava/util/Set; + public fun getLength ()I + public fun getName ()Ljava/lang/String; + public fun getSignature ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public final fun length ()I +} + +public final class com/android/tools/smali/dexlib2/mutable/MutableMethodParameter$Companion { + public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)Lcom/android/tools/smali/dexlib2/mutable/MutableMethodParameter; +} + diff --git a/core/build.gradle.kts b/core/build.gradle.kts new file mode 100644 index 0000000..1186b90 --- /dev/null +++ b/core/build.gradle.kts @@ -0,0 +1,109 @@ +import com.android.build.api.dsl.androidLibrary +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation + +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.android.kotlin.multiplatform.library) + alias(libs.plugins.vanniktech.mavenPublish) +} + +group = "app.revanced" + +kotlin { + @OptIn(ExperimentalAbiValidation::class) + abiValidation { + enabled = true + } + + jvm() + androidLibrary { + namespace = "app.revanced.patcher" + compileSdk = libs.versions.android.compileSdk.get().toInt() + minSdk = libs.versions.android.minSdk.get().toInt() + + withHostTestBuilder {}.configure {} + withDeviceTestBuilder { + sourceSetTreeName = "test" + } + + compilations.configureEach { + compilerOptions.configure { + jvmTarget.set( + JvmTarget.JVM_11 + ) + } + } + } + sourceSets { + commonMain.dependencies { + implementation(libs.apktool.lib) + implementation(libs.kotlin.reflect) + implementation(libs.kotlinx.coroutines.core) + implementation(libs.multidexlib2) + implementation(libs.smali) + implementation(libs.xpp3) + } + + jvmTest.dependencies { + implementation(libs.mockk) + implementation(libs.kotlin.test) + } + } + compilerOptions { + freeCompilerArgs = listOf("-Xcontext-parameters") + } +} + +tasks { + named("jvmProcessResources") { + expand("projectVersion" to project.version) + } + + named("jvmTest") { + useJUnitPlatform() + } +} + +mavenPublishing { + publishing { + repositories { + maven { + name = "githubPackages" + url = uri("https://maven.pkg.github.com/revanced/revanced-patcher") + credentials(PasswordCredentials::class) + } + } + } + + signAllPublications() + extensions.getByType().useGpgCmd() + + coordinates(group.toString(), project.name, version.toString()) + + pom { + name = "ReVanced Patcher" + description = "Patcher used by ReVanced." + inceptionYear = "2022" + url = "https://revanced.app" + licenses { + license { + name = "GNU General Public License v3.0" + url = "https://www.gnu.org/licenses/gpl-3.0.en.html" + } + } + developers { + developer { + id = "ReVanced" + name = "ReVanced" + email = "contact@revanced.app" + } + } + scm { + connection = "scm:git:git://github.com/revanced/revanced-patcher.git" + developerConnection = "scm:git:git@github.com:revanced/revanced-patcher.git" + url = "https://github.com/revanced/revanced-patcher" + } + } +} + diff --git a/core/src/androidMain/kotlin/app/revanced/patcher/patch/Patch.android.kt b/core/src/androidMain/kotlin/app/revanced/patcher/patch/Patch.android.kt new file mode 100644 index 0000000..f3ee873 --- /dev/null +++ b/core/src/androidMain/kotlin/app/revanced/patcher/patch/Patch.android.kt @@ -0,0 +1,32 @@ +package app.revanced.patcher.patch + +import dalvik.system.DexClassLoader +import lanchon.multidexlib2.BasicDexFileNamer +import lanchon.multidexlib2.MultiDexIO +import java.io.File + +actual val Class<*>.isPatch get() = Patch::class.java.isAssignableFrom(this) + +/** + * Loads patches from DEX files declared as public static fields + * or returned by public static and non-parametrized methods. + * Patches with no name are not loaded. + * + * @param patchesFiles The DEX files to load the patches from. + * + * @return The loaded patches. + */ +actual fun loadPatches(patchesFiles: Set) = loadPatches( + patchesFiles, + { patchBundle -> + MultiDexIO.readDexFile(true, patchBundle, BasicDexFileNamer(), null, null).classes + .map { classDef -> + classDef.type.substring(1, classDef.length - 1) + } + }, + DexClassLoader( + patchesFiles.joinToString(File.pathSeparator) { it.absolutePath }, + null, + null, null + ) +) diff --git a/core/src/androidMain/kotlin/collections/MutableMap.android.kt b/core/src/androidMain/kotlin/collections/MutableMap.android.kt new file mode 100644 index 0000000..8ff5cb0 --- /dev/null +++ b/core/src/androidMain/kotlin/collections/MutableMap.android.kt @@ -0,0 +1,7 @@ +package collections + +actual fun MutableMap.kmpMerge( + key: K, + value: V, + remappingFunction: (oldValue: V, newValue: V) -> V +) = merge(key, value, remappingFunction) \ No newline at end of file diff --git a/core/src/androidMain/kotlin/java/io/File.android.kt b/core/src/androidMain/kotlin/java/io/File.android.kt new file mode 100644 index 0000000..9f4d938 --- /dev/null +++ b/core/src/androidMain/kotlin/java/io/File.android.kt @@ -0,0 +1,8 @@ +package java.io + +import java.nio.charset.Charset + +internal actual fun File.kmpResolve(child: String) = resolve(child) +internal actual fun File.kmpDeleteRecursively() = deleteRecursively() +internal actual fun File.kmpInputStream() = inputStream() +internal actual fun File.kmpBufferedWriter(charset: Charset) = bufferedWriter(charset) \ No newline at end of file diff --git a/core/src/commonMain/kotlin/app/revanced/patcher/Fingerprint.kt b/core/src/commonMain/kotlin/app/revanced/patcher/Fingerprint.kt new file mode 100644 index 0000000..ad46187 --- /dev/null +++ b/core/src/commonMain/kotlin/app/revanced/patcher/Fingerprint.kt @@ -0,0 +1,598 @@ +@file:Suppress("unused", "MemberVisibilityCanBePrivate") + +package app.revanced.patcher + +import app.revanced.patcher.extensions.instructionsOrNull +import app.revanced.patcher.patch.BytecodePatchContext +import app.revanced.patcher.patch.PatchException +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.StringReference +import com.android.tools.smali.dexlib2.util.MethodUtil + +/** + * A fingerprint for a method. A fingerprint is a partial description of a method. + * It is used to uniquely match a method by its characteristics. + * + * An example fingerprint for a public method that takes a single string parameter and returns void: + * ``` + * fingerprint { + * accessFlags(AccessFlags.PUBLIC) + * returns("V") + * parameters("Ljava/lang/String;") + * } + * ``` + * + * @param accessFlags The exact access flags using values of [AccessFlags]. + * @param returnType The return type. Compared using [String.startsWith]. + * @param parameters The parameters. Partial matches allowed and follow the same rules as [returnType]. + * @param opcodes A pattern of instruction opcodes. `null` can be used as a wildcard. + * @param strings A list of the strings. Compared using [String.contains]. + * @param custom A custom condition for this fingerprint. + * @param fuzzyPatternScanThreshold The threshold for fuzzy scanning the [opcodes] pattern. + */ +class Fingerprint internal constructor( + internal val accessFlags: Int?, + internal val returnType: String?, + internal val parameters: List?, + internal val opcodes: List?, + internal val strings: List?, + internal val custom: ((method: Method, classDef: ClassDef) -> Boolean)?, + private val fuzzyPatternScanThreshold: Int, +) { + @Suppress("ktlint:standard:backing-property-naming") + // Backing field needed for lazy initialization. + private var _matchOrNull: Match? = null + + /** + * The match for this [Fingerprint]. Null if unmatched. + */ + context(_: BytecodePatchContext) + private val matchOrNull: Match? + get() = matchOrNull() + + /** + * Match using [BytecodePatchContext.lookupMaps]. + * + * Generally faster than the other [matchOrNull] overloads when there are many methods to check for a match. + * + * Fingerprints can be optimized for performance: + * - Slowest: Specify [custom] or [opcodes] and nothing else. + * - Fast: Specify [accessFlags], [returnType]. + * - Faster: Specify [accessFlags], [returnType] and [parameters]. + * - Fastest: Specify [strings], with at least one string being an exact (non-partial) match. + * + * @return The [Match] if a match was found or if the fingerprint is already matched to a method, null otherwise. + */ + context(context: BytecodePatchContext) + internal fun matchOrNull(): Match? { + if (_matchOrNull != null) return _matchOrNull + + var match = strings?.mapNotNull { + context.classDefs.methodsByString[it] + }?.minByOrNull { it.size }?.let { methodClasses -> + methodClasses.forEach { method -> + val match = matchOrNull(method, context.classDefs[method.definingClass]!!) + if (match != null) return@let match + } + + null + } + if (match != null) return match + context.classDefs.forEach { classDef -> + match = matchOrNull(classDef) + if (match != null) return match + } + + return null + } + + /** + * Match using a [ClassDef]. + * + * @param classDef The class to match against. + * @return The [Match] if a match was found or if the fingerprint is already matched to a method, null otherwise. + */ + context(_: BytecodePatchContext) + fun matchOrNull( + classDef: ClassDef, + ): Match? { + if (_matchOrNull != null) return _matchOrNull + + for (method in classDef.methods) { + val match = matchOrNull(method, classDef) + if (match != null) return match + } + + return null + } + + /** + * Match using a [Method]. + * The class is retrieved from the method. + * + * @param method The method to match against. + * @return The [Match] if a match was found or if the fingerprint is already matched to a method, null otherwise. + */ + context(context: BytecodePatchContext) + fun matchOrNull( + method: Method, + ) = matchOrNull(method, context.classDefs[method.definingClass]!!) + + /** + * Match using a [Method]. + * + * @param method The method to match against. + * @param classDef The class the method is a member of. + * @return The [Match] if a match was found or if the fingerprint is already matched to a method, null otherwise. + */ + context(context: BytecodePatchContext) + fun matchOrNull( + method: Method, + classDef: ClassDef, + ): Match? { + if (_matchOrNull != null) return _matchOrNull + + if (returnType != null && !method.returnType.startsWith(returnType)) { + return null + } + + if (accessFlags != null && accessFlags != method.accessFlags) { + return null + } + + fun parametersEqual( + parameters1: Iterable, + parameters2: Iterable, + ): Boolean { + if (parameters1.count() != parameters2.count()) return false + val iterator1 = parameters1.iterator() + parameters2.forEach { + if (!it.startsWith(iterator1.next())) return false + } + return true + } + + // TODO: parseParameters() + if (parameters != null && !parametersEqual(parameters, method.parameterTypes)) { + return null + } + + if (custom != null && !custom.invoke(method, classDef)) { + return null + } + + val stringMatches: List? = + if (strings != null) { + buildList { + val instructions = method.instructionsOrNull ?: return null + + val stringsList = strings.toMutableList() + + instructions.forEachIndexed { instructionIndex, instruction -> + if ( + instruction.opcode != Opcode.CONST_STRING && + instruction.opcode != Opcode.CONST_STRING_JUMBO + ) { + return@forEachIndexed + } + + val string = ((instruction as ReferenceInstruction).reference as StringReference).string + val index = stringsList.indexOfFirst(string::contains) + if (index == -1) return@forEachIndexed + + add(Match.StringMatch(string, instructionIndex)) + stringsList.removeAt(index) + } + + if (stringsList.isNotEmpty()) return null + } + } else { + null + } + + val patternMatch = if (opcodes != null) { + val instructions = method.instructionsOrNull ?: return null + + fun patternScan(): Match.PatternMatch? { + val fingerprintFuzzyPatternScanThreshold = fuzzyPatternScanThreshold + + val instructionLength = instructions.count() + val patternLength = opcodes.size + + for (index in 0 until instructionLength) { + var patternIndex = 0 + var threshold = fingerprintFuzzyPatternScanThreshold + + while (index + patternIndex < instructionLength) { + val originalOpcode = instructions.elementAt(index + patternIndex).opcode + val patternOpcode = opcodes.elementAt(patternIndex) + + if (patternOpcode != null && patternOpcode.ordinal != originalOpcode.ordinal) { + // Reaching maximum threshold (0) means, + // the pattern does not match to the current instructions. + if (threshold-- == 0) break + } + + if (patternIndex < patternLength - 1) { + // If the entire pattern has not been scanned yet, continue the scan. + patternIndex++ + continue + } + + // The entire pattern has been scanned. + return Match.PatternMatch( + index, + index + patternIndex, + ) + } + } + + return null + } + + patternScan() ?: return null + } else { + null + } + + _matchOrNull = Match( + context, + classDef, + method, + patternMatch, + stringMatches, + ) + + return _matchOrNull + } + + private val exception get() = PatchException("Failed to match the fingerprint: $this") + + /** + * The match for this [Fingerprint]. + * + * @throws PatchException If the [Fingerprint] has not been matched. + */ + context(_: BytecodePatchContext) + private val match + get() = matchOrNull ?: throw exception + + /** + * Match using a [ClassDef]. + * + * @param classDef The class to match against. + * @return The [Match] if a match was found or if the fingerprint is already matched to a method, null otherwise. + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + fun match( + classDef: ClassDef, + ) = matchOrNull(classDef) ?: throw exception + + /** + * Match using a [Method]. + * The class is retrieved from the method. + * + * @param method The method to match against. + * @return The [Match] if a match was found or if the fingerprint is already matched to a method, null otherwise. + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + fun match( + method: Method, + ) = matchOrNull(method) ?: throw exception + + /** + * Match using a [Method]. + * + * @param method The method to match against. + * @param classDef The class the method is a member of. + * @return The [Match] if a match was found or if the fingerprint is already matched to a method, null otherwise. + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + fun match( + method: Method, + classDef: ClassDef, + ) = matchOrNull(method, classDef) ?: throw exception + + /** + * The class the matching method is a member of. + */ + context(_: BytecodePatchContext) + val originalClassDefOrNull + get() = matchOrNull?.originalClassDef + + /** + * The matching method. + */ + context(_: BytecodePatchContext) + val originalMethodOrNull + get() = matchOrNull?.originalMethod + + /** + * The mutable version of [originalClassDefOrNull]. + * + * Accessing this property allocates a [ClassProxy]. + * Use [originalClassDefOrNull] if mutable access is not required. + */ + context(_: BytecodePatchContext) + val classDefOrNull + get() = matchOrNull?.classDef + + /** + * The mutable version of [originalMethodOrNull]. + * + * Accessing this property allocates a [ClassProxy]. + * Use [originalMethodOrNull] if mutable access is not required. + */ + context(_: BytecodePatchContext) + val methodOrNull + get() = matchOrNull?.method + + /** + * The match for the opcode pattern. + */ + context(_: BytecodePatchContext) + val patternMatchOrNull + get() = matchOrNull?.patternMatch + + /** + * The matches for the strings. + */ + context(_: BytecodePatchContext) + val stringMatchesOrNull + get() = matchOrNull?.stringMatches + + /** + * The class the matching method is a member of. + * + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + val originalClassDef + get() = match.originalClassDef + + /** + * The matching method. + * + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + val originalMethod + get() = match.originalMethod + + /** + * The mutable version of [originalClassDef]. + * + * Accessing this property allocates a [ClassProxy]. + * Use [originalClassDef] if mutable access is not required. + * + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + val classDef + get() = match.classDef + + /** + * The mutable version of [originalMethod]. + * + * Accessing this property allocates a [ClassProxy]. + * Use [originalMethod] if mutable access is not required. + * + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + val method + get() = match.method + + /** + * The match for the opcode pattern. + * + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + val patternMatch + get() = match.patternMatch + + /** + * The matches for the strings. + * + * @throws PatchException If the fingerprint has not been matched. + */ + context(_: BytecodePatchContext) + val stringMatches + get() = match.stringMatches +} + +/** + * A match of a [Fingerprint]. + * + * @param originalClassDef The class the matching method is a member of. + * @param originalMethod The matching method. + * @param patternMatch The match for the opcode pattern. + * @param stringMatches The matches for the strings. + */ +class Match internal constructor( + val context: BytecodePatchContext, + val originalClassDef: ClassDef, + val originalMethod: Method, + val patternMatch: PatternMatch?, + val stringMatches: List?, +) { + /** + * The mutable version of [originalClassDef]. + * + * Accessing this property allocates a new mutable instance. + * Use [originalClassDef] if mutable access is not required. + */ + val classDef by lazy { context.firstClassDefMutable(originalClassDef.type) } + + /** + * The mutable version of [originalMethod]. + * + * Accessing this property allocates a new mutable instance. + * Use [originalMethod] if mutable access is not required. + */ + val method by lazy { classDef.methods.first { MethodUtil.methodSignaturesMatch(it, originalMethod) } } + + /** + * A match for an opcode pattern. + * @param startIndex The index of the first opcode of the pattern in the method. + * @param endIndex The index of the last opcode of the pattern in the method. + */ + class PatternMatch internal constructor( + val startIndex: Int, + val endIndex: Int, + ) + + /** + * A match for a string. + * + * @param string The string that matched. + * @param index The index of the instruction in the method. + */ + class StringMatch internal constructor(val string: String, val index: Int) +} + +/** + * A builder for [Fingerprint]. + * + * @property accessFlags The exact access flags using values of [AccessFlags]. + * @property returnType The return type compared using [String.startsWith]. + * @property parameters The parameters of the method. Partial matches allowed and follow the same rules as [returnType]. + * @property opcodes An opcode pattern of the instructions. Wildcard or unknown opcodes can be specified by `null`. + * @property strings A list of the strings compared each using [String.contains]. + * @property customBlock A custom condition for this fingerprint. + * @property fuzzyPatternScanThreshold The threshold for fuzzy pattern scanning. + * + * @constructor Create a new [FingerprintBuilder]. + */ +class FingerprintBuilder internal constructor( + private val fuzzyPatternScanThreshold: Int = 0, +) { + private var accessFlags: Int? = null + private var returnType: String? = null + private var parameters: List? = null + private var opcodes: List? = null + private var strings: List? = null + private var customBlock: ((method: Method, classDef: ClassDef) -> Boolean)? = null + + /** + * Set the access flags. + * + * @param accessFlags The exact access flags using values of [AccessFlags]. + */ + fun accessFlags(accessFlags: Int) { + this.accessFlags = accessFlags + } + + /** + * Set the access flags. + * + * @param accessFlags The exact access flags using values of [AccessFlags]. + */ + fun accessFlags(vararg accessFlags: AccessFlags) { + this.accessFlags = accessFlags.fold(0) { acc, it -> acc or it.value } + } + + /** + * Set the return type. + * + * @param returnType The return type compared using [String.startsWith]. + */ + fun returns(returnType: String) { + this.returnType = returnType + } + + /** + * Set the parameters. + * + * @param parameters The parameters of the method. Partial matches allowed and follow the same rules as [returnType]. + */ + fun parameters(vararg parameters: String) { + this.parameters = parameters.toList() + } + + /** + * Set the opcodes. + * + * @param opcodes An opcode pattern of instructions. + * Wildcard or unknown opcodes can be specified by `null`. + */ + fun opcodes(vararg opcodes: Opcode?) { + this.opcodes = opcodes.toList() + } + + /** + * Set the opcodes. + * + * @param instructions A list of instructions or opcode names in SMALI format. + * - Wildcard or unknown opcodes can be specified by `null`. + * - Empty lines are ignored. + * - Each instruction must be on a new line. + * - The opcode name is enough, no need to specify the operands. + * + * @throws Exception If an unknown opcode is used. + */ + fun opcodes(instructions: String) { + this.opcodes = instructions.trimIndent().split("\n").filter { + it.isNotBlank() + }.map { + // Remove any operands. + val name = it.split(" ", limit = 1).first().trim() + if (name == "null") return@map null + + opcodesByName[name] ?: throw Exception("Unknown opcode: $name") + } + } + + /** + * Set the strings. + * + * @param strings A list of strings compared each using [String.contains]. + */ + fun strings(vararg strings: String) { + this.strings = strings.toList() + } + + /** + * Set a custom condition for this fingerprint. + * + * @param customBlock A custom condition for this fingerprint. + */ + fun custom(customBlock: (method: Method, classDef: ClassDef) -> Boolean) { + this.customBlock = customBlock + } + + internal fun build() = Fingerprint( + accessFlags, + returnType, + parameters, + opcodes, + strings, + customBlock, + fuzzyPatternScanThreshold, + ) + + private companion object { + val opcodesByName = Opcode.entries.associateBy { it.name } + } +} + +/** + * Create a [Fingerprint]. + * + * @param fuzzyPatternScanThreshold The threshold for fuzzy pattern scanning. Default is 0. + * @param block The block to build the [Fingerprint]. + * + * @return The created [Fingerprint]. + */ +fun fingerprint( + fuzzyPatternScanThreshold: Int = 0, + block: FingerprintBuilder.() -> Unit, +) = FingerprintBuilder(fuzzyPatternScanThreshold).apply(block).build() diff --git a/src/main/kotlin/app/revanced/patcher/InternalApi.kt b/core/src/commonMain/kotlin/app/revanced/patcher/InternalApi.kt similarity index 100% rename from src/main/kotlin/app/revanced/patcher/InternalApi.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/InternalApi.kt diff --git a/core/src/commonMain/kotlin/app/revanced/patcher/Matching.kt b/core/src/commonMain/kotlin/app/revanced/patcher/Matching.kt new file mode 100644 index 0000000..69decf5 --- /dev/null +++ b/core/src/commonMain/kotlin/app/revanced/patcher/Matching.kt @@ -0,0 +1,814 @@ +@file:Suppress("unused", "MemberVisibilityCanBePrivate", "CONTEXT_RECEIVERS_DEPRECATED") + +package app.revanced.patcher + +import app.revanced.patcher.extensions.* +import app.revanced.patcher.patch.BytecodePatchContext +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.HiddenApiRestriction +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.* +import com.android.tools.smali.dexlib2.iface.Annotation +import com.android.tools.smali.dexlib2.iface.instruction.* +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22t +import com.android.tools.smali.dexlib2.util.MethodUtil +import com.sun.jdi.StringReference +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +fun Iterable.anyClassDef(predicate: ClassDef.() -> Boolean) = any(predicate) + +fun ClassDef.anyMethod(predicate: Method.() -> Boolean) = methods.any(predicate) + +fun ClassDef.anyDirectMethod(predicate: Method.() -> Boolean) = directMethods.any(predicate) + +fun ClassDef.anyVirtualMethod(predicate: Method.() -> Boolean) = virtualMethods.any(predicate) + +fun ClassDef.anyField(predicate: Field.() -> Boolean) = fields.any(predicate) + +fun ClassDef.anyInstanceField(predicate: Field.() -> Boolean) = instanceFields.any(predicate) + +fun ClassDef.anyStaticField(predicate: Field.() -> Boolean) = staticFields.any(predicate) + +fun ClassDef.anyInterface(predicate: String.() -> Boolean) = interfaces.any(predicate) + +fun ClassDef.anyAnnotation(predicate: Annotation.() -> Boolean) = annotations.any(predicate) + +fun Method.implementation(predicate: MethodImplementation.() -> Boolean) = implementation?.predicate() ?: false + +fun Method.anyParameter(predicate: MethodParameter.() -> Boolean) = parameters.any(predicate) + +fun Method.anyParameterType(predicate: CharSequence.() -> Boolean) = parameterTypes.any(predicate) + +fun Method.anyAnnotation(predicate: Annotation.() -> Boolean) = annotations.any(predicate) + +fun Method.anyHiddenApiRestriction(predicate: HiddenApiRestriction.() -> Boolean) = hiddenApiRestrictions.any(predicate) + +fun MethodImplementation.anyInstruction(predicate: Instruction.() -> Boolean) = instructions.any(predicate) + +fun MethodImplementation.anyTryBlock(predicate: TryBlock.() -> Boolean) = tryBlocks.any(predicate) + +fun MethodImplementation.anyDebugItem(predicate: Any.() -> Boolean) = debugItems.any(predicate) + +fun Iterable.anyInstruction(predicate: Instruction.() -> Boolean) = any(predicate) + +fun BytecodePatchContext.firstClassDefOrNull(predicate: context(PredicateContext) ClassDef.() -> Boolean) = + with(PredicateContext()) { classDefs.firstOrNull { it.predicate() } } + +fun BytecodePatchContext.firstClassDef(predicate: context(PredicateContext) ClassDef.() -> Boolean) = + requireNotNull(firstClassDefOrNull(predicate)) + +fun BytecodePatchContext.firstClassDefMutableOrNull(predicate: context(PredicateContext) ClassDef.() -> Boolean) = + firstClassDefOrNull(predicate)?.let { classDefs.getOrReplaceMutable(it) } + +fun BytecodePatchContext.firstClassDefMutable(predicate: context(PredicateContext) ClassDef.() -> Boolean) = + requireNotNull(firstClassDefMutableOrNull(predicate)) + +fun BytecodePatchContext.firstClassDefOrNull( + type: String, predicate: (context(PredicateContext) ClassDef.() -> Boolean)? = null +) = classDefs[type]?.takeIf { + predicate == null || with(PredicateContext()) { it.predicate() } +} + +fun BytecodePatchContext.firstClassDef( + type: String, + predicate: (context(PredicateContext) ClassDef.() -> Boolean)? = null +) = requireNotNull(firstClassDefOrNull(type, predicate)) + +fun BytecodePatchContext.firstClassDefMutableOrNull( + type: String, + predicate: (context(PredicateContext) ClassDef.() -> Boolean)? = null +) = firstClassDefOrNull(type, predicate)?.let { classDefs.getOrReplaceMutable(it) } + +fun BytecodePatchContext.firstClassDefMutable( + type: String, + predicate: (context(PredicateContext) ClassDef.() -> Boolean)? = null +) = requireNotNull(firstClassDefMutableOrNull(type, predicate)) + +fun BytecodePatchContext.firstMethodOrNull(predicate: context(PredicateContext) Method.() -> Boolean): Method? { + val methods = classDefs.asSequence().flatMap { it.methods.asSequence() } + with(PredicateContext()) { + return methods.firstOrNull { it.predicate() } + } +} + +fun BytecodePatchContext.firstMethod(predicate: context(PredicateContext) Method.() -> Boolean) = + requireNotNull(firstMethodOrNull(predicate)) + +fun BytecodePatchContext.firstMethodMutableOrNull(predicate: context(PredicateContext) Method.() -> Boolean) = + firstMethodOrNull(predicate)?.let { method -> + firstClassDefMutable(method.definingClass).methods.first { + MethodUtil.methodSignaturesMatch(method, it) + } + } + +fun BytecodePatchContext.firstMethodMutable(predicate: context(PredicateContext) Method.() -> Boolean) = + requireNotNull(firstMethodMutableOrNull(predicate)) + +fun BytecodePatchContext.firstMethodOrNull( + vararg strings: String, + predicate: context(PredicateContext) Method.() -> Boolean = { true }, +) = with(PredicateContext()) { + val methodsWithStrings = strings.mapNotNull { classDefs.methodsByString[it] } + if (methodsWithStrings.size != strings.size) return null + + methodsWithStrings.minBy { it.size }.firstOrNull { method -> + val containsAllOtherStrings = methodsWithStrings.all { method in it } + containsAllOtherStrings && method.predicate() + } +} + +fun BytecodePatchContext.firstMethod( + vararg strings: String, + predicate: context(PredicateContext) Method.() -> Boolean = { true }, +) = requireNotNull(firstMethodOrNull(*strings, predicate = predicate)) + +fun BytecodePatchContext.firstMethodMutableOrNull( + vararg strings: String, + predicate: context(PredicateContext) Method.() -> Boolean = { true }, +) = firstMethodOrNull(*strings, predicate = predicate)?.let { method -> + firstClassDefMutable(method.definingClass).methods.first { + MethodUtil.methodSignaturesMatch( + method, it + ) + } +} + +fun BytecodePatchContext.firstMethodMutable( + vararg strings: String, predicate: context(PredicateContext) Method.() -> Boolean = { true } +) = requireNotNull(firstMethodMutableOrNull(*strings, predicate = predicate)) + +class CachedReadOnlyProperty internal constructor( + private val block: BytecodePatchContext.(KProperty<*>) -> T +) : ReadOnlyProperty { + private var value: T? = null + private var cached = false + + override fun getValue(thisRef: BytecodePatchContext, property: KProperty<*>): T { + if (!cached) { + value = thisRef.block(property) + cached = true + } + + return value!! + } +} + +fun gettingFirstClassDefOrNull(predicate: context(PredicateContext) ClassDef.() -> Boolean) = + CachedReadOnlyProperty { firstClassDefOrNull(predicate) } + +fun gettingFirstClassDef(predicate: context(PredicateContext) ClassDef.() -> Boolean) = + CachedReadOnlyProperty { firstClassDef(predicate) } + +fun gettingFirstClassDefMutableOrNull(predicate: context(PredicateContext) ClassDef.() -> Boolean) = + CachedReadOnlyProperty { firstClassDefMutableOrNull(predicate) } + +fun gettingFirstClassDefMutable(predicate: context(PredicateContext) ClassDef.() -> Boolean) = + CachedReadOnlyProperty { firstClassDefMutable(predicate) } + +fun gettingFirstClassDefOrNull( + type: String, predicate: (context(PredicateContext) ClassDef.() -> Boolean)? = null +) = CachedReadOnlyProperty { firstClassDefOrNull(type, predicate) } + +fun gettingFirstClassDef( + type: String, predicate: (context(PredicateContext) ClassDef.() -> Boolean)? = null +) = CachedReadOnlyProperty { firstClassDef(type, predicate) } + +fun gettingFirstClassDefMutableOrNull( + type: String, predicate: (context(PredicateContext) ClassDef.() -> Boolean)? = null +) = CachedReadOnlyProperty { firstClassDefMutableOrNull(type, predicate) } + +fun gettingFirstClassDefMutable( + type: String, predicate: (context(PredicateContext) ClassDef.() -> Boolean)? = null +) = CachedReadOnlyProperty { firstClassDefMutable(type, predicate) } + +fun gettingFirstMethodOrNull(predicate: context(PredicateContext) Method.() -> Boolean) = + CachedReadOnlyProperty { firstMethodOrNull(predicate) } + +fun gettingFirstMethod(predicate: context(PredicateContext) Method.() -> Boolean) = + CachedReadOnlyProperty { firstMethod(predicate) } + +fun gettingFirstMethodMutableOrNull(predicate: context(PredicateContext) Method.() -> Boolean) = + CachedReadOnlyProperty { firstMethodMutableOrNull(predicate) } + +fun gettingFirstMethodMutable(predicate: context(PredicateContext) Method.() -> Boolean) = + CachedReadOnlyProperty { firstMethodMutable(predicate) } + +fun gettingFirstMethodOrNull( + vararg strings: String, + predicate: context(PredicateContext) Method.() -> Boolean = { true }, +) = CachedReadOnlyProperty { firstMethodOrNull(*strings, predicate = predicate) } + +fun gettingFirstMethod( + vararg strings: String, + predicate: context(PredicateContext) Method.() -> Boolean = { true }, +) = CachedReadOnlyProperty { firstMethod(*strings, predicate = predicate) } + +fun gettingFirstMethodMutableOrNull( + vararg strings: String, + predicate: context(PredicateContext) Method.() -> Boolean = { true }, +) = CachedReadOnlyProperty { firstMethodMutableOrNull(*strings, predicate = predicate) } + +fun gettingFirstMethodMutable( + vararg strings: String, + predicate: context(PredicateContext) Method.() -> Boolean = { true }, +) = CachedReadOnlyProperty { firstMethodMutable(*strings, predicate = predicate) } + +// region Matcher + +// region IndexedMatcher + +fun indexedMatcher() = IndexedMatcher() + +fun indexedMatcher(build: IndexedMatcher.() -> Unit) = + IndexedMatcher().apply(build) + +fun Iterable.matchIndexed(build: IndexedMatcher.() -> Unit) = + indexedMatcher(build)(this) + +context(_: PredicateContext) +fun Iterable.rememberedMatchIndexed(key: Any, build: IndexedMatcher.() -> Unit) = + indexedMatcher()(key, this, build) + +context(matcher: IndexedMatcher) +fun head( + predicate: T.(lastMatchedIndex: Int, currentIndex: Int) -> Boolean +): T.(Int, Int) -> Boolean = { lastMatchedIndex, currentIndex -> + currentIndex == 0 && predicate(lastMatchedIndex, currentIndex) +} + +context(matcher: IndexedMatcher) +fun head(predicate: T.() -> Boolean): T.(Int, Int) -> Boolean = + head { _, _ -> predicate() } + +context(matcher: IndexedMatcher) +fun after( + range: IntRange = 1..1, + predicate: T.(lastMatchedIndex: Int, currentIndex: Int) -> Boolean +): T.(Int, Int) -> Boolean = predicate@{ lastMatchedIndex, currentIndex -> + val distance = currentIndex - lastMatchedIndex + + matcher.nextIndex = when { + distance < range.first -> lastMatchedIndex + range.first + distance > range.last -> -1 + else -> return@predicate predicate(lastMatchedIndex, currentIndex) + } + + false +} + +context(matcher: IndexedMatcher) +fun after(range: IntRange = 1..1, predicate: T.() -> Boolean) = + after(range) { _, _ -> predicate() } + +context(matcher: IndexedMatcher) +operator fun (T.(Int, Int) -> Boolean).unaryPlus() = matcher.add(this) + +class IndexedMatcher : Matcher Boolean>() { + private val _indices: MutableList = mutableListOf() + val indices: List = _indices + + private var lastMatchedIndex = -1 + private var currentIndex = -1 + var nextIndex: Int? = null + + override fun invoke(haystack: Iterable): Boolean { + // Normalize to list + val hay = haystack as? List ?: haystack.toList() + + _indices.clear() + this@IndexedMatcher.lastMatchedIndex = -1 + currentIndex = -1 + + data class Frame( + val patternIndex: Int, + val lastMatchedIndex: Int, + val previousFrame: Frame?, + var nextHayIndex: Int, + val matchedIndex: Int + ) + + val stack = ArrayDeque() + stack.add( + Frame( + patternIndex = 0, + lastMatchedIndex = -1, + previousFrame = null, + nextHayIndex = 0, + matchedIndex = -1 + ) + ) + + while (stack.isNotEmpty()) { + val frame = stack.last() + + if (frame.nextHayIndex >= hay.size || nextIndex == -1) { + stack.removeLast() + nextIndex = null + continue + } + + val i = frame.nextHayIndex + currentIndex = i + lastMatchedIndex = frame.lastMatchedIndex + nextIndex = null + + if (this[frame.patternIndex](hay[i], lastMatchedIndex, currentIndex)) { + Frame( + patternIndex = frame.patternIndex + 1, + lastMatchedIndex = i, + previousFrame = frame, + nextHayIndex = i + 1, + matchedIndex = i + ).also { + if (it.patternIndex == size) { + _indices += buildList(size) { + var f: Frame? = it + while (f != null && f.matchedIndex != -1) { + add(f.matchedIndex) + f = f.previousFrame + } + }.asReversed() + + return true + } + }.let(stack::add) + } + + frame.nextHayIndex = when (val nextIndex = nextIndex) { + null -> frame.nextHayIndex + 1 + -1 -> 0 // Frame will be removed next loop. + else -> nextIndex + } + } + + return false + } +} + +// endregion + +context(_: PredicateContext) +inline operator fun > M.invoke(key: Any, iterable: Iterable, builder: M.() -> Unit) = + remembered(key) { apply(builder) }(iterable) + +context(_: PredicateContext) +inline operator fun > M.invoke( + iterable: Iterable, + builder: M.() -> Unit +) = invoke(this@invoke.hashCode(), iterable, builder) + +abstract class Matcher : MutableList by mutableListOf() { + var matchIndex = -1 + protected set + + abstract operator fun invoke(haystack: Iterable): Boolean +} + +// endregion Matcher + +class PredicateContext internal constructor() : MutableMap by mutableMapOf() + +context(context: PredicateContext) +inline fun remembered(key: Any, defaultValue: () -> V) = + context[key] as? V ?: defaultValue().also { context[key] = it } + + +fun T.declarativePredicate(build: DeclarativePredicateBuilder.() -> Unit) = + DeclarativePredicateBuilder().apply(build).all(this) + +context(_: PredicateContext) +fun T.rememberedDeclarativePredicate(key: Any, block: DeclarativePredicateBuilder.() -> Unit): Boolean = + remembered(key) { DeclarativePredicateBuilder().apply(block) }.all(this) + +context(_: PredicateContext) +private fun T.rememberedDeclarativePredicate(predicate: context(PredicateContext, T) DeclarativePredicateBuilder.() -> Unit) = + rememberedDeclarativePredicate("declarative predicate build") { predicate() } + +fun BytecodePatchContext.firstClassDefByDeclarativePredicateOrNull( + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = firstClassDefOrNull { rememberedDeclarativePredicate(predicate) } + +fun BytecodePatchContext.firstClassDefByDeclarativePredicate( + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = requireNotNull(firstClassDefByDeclarativePredicateOrNull(predicate)) + +fun BytecodePatchContext.firstClassDefMutableByDeclarativePredicateOrNull( + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = firstClassDefMutableOrNull { rememberedDeclarativePredicate(predicate) } + +fun BytecodePatchContext.firstClassDefMutableByDeclarativePredicate( + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = requireNotNull(firstClassDefMutableByDeclarativePredicateOrNull(predicate)) + +fun BytecodePatchContext.firstClassDefByDeclarativePredicateOrNull( + type: String, + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = firstClassDefOrNull(type) { rememberedDeclarativePredicate(predicate) } + +fun BytecodePatchContext.firstClassDefByDeclarativePredicate( + type: String, + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = requireNotNull(firstClassDefByDeclarativePredicateOrNull(type, predicate)) + +fun BytecodePatchContext.firstClassDefMutableByDeclarativePredicateOrNull( + type: String, + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = firstClassDefMutableOrNull(type) { rememberedDeclarativePredicate(predicate) } + +fun BytecodePatchContext.firstClassDefMutableByDeclarativePredicate( + type: String, + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = requireNotNull(firstClassDefMutableByDeclarativePredicateOrNull(type, predicate)) + +fun BytecodePatchContext.firstMethodByDeclarativePredicateOrNull( + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = firstMethodOrNull { rememberedDeclarativePredicate(predicate) } + +fun BytecodePatchContext.firstMethodByDeclarativePredicate( + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = requireNotNull(firstMethodByDeclarativePredicateOrNull(predicate)) + +fun BytecodePatchContext.firstMethodMutableByDeclarativePredicateOrNull( + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = firstMethodMutableOrNull { rememberedDeclarativePredicate(predicate) } + +fun BytecodePatchContext.firstMethodMutableByDeclarativePredicate( + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = requireNotNull(firstMethodMutableByDeclarativePredicateOrNull(predicate)) + +fun BytecodePatchContext.firstMethodByDeclarativePredicateOrNull( + vararg strings: String, + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = firstMethodOrNull(*strings) { rememberedDeclarativePredicate(predicate) } + +fun BytecodePatchContext.firstMethodByDeclarativePredicate( + vararg strings: String, + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = requireNotNull(firstMethodByDeclarativePredicateOrNull(*strings, predicate = predicate)) + +fun BytecodePatchContext.firstMethodMutableByDeclarativePredicateOrNull( + vararg strings: String, + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = firstMethodMutableOrNull(*strings) { rememberedDeclarativePredicate(predicate) } + +fun BytecodePatchContext.firstMethodMutableByDeclarativePredicate( + vararg strings: String, + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = requireNotNull(firstMethodMutableByDeclarativePredicateOrNull(*strings, predicate = predicate)) + +fun gettingFirstClassDefByDeclarativePredicateOrNull( + type: String, + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = gettingFirstClassDefOrNull(type) { rememberedDeclarativePredicate(predicate) } + +fun gettingFirstClassDefByDeclarativePredicate( + type: String, + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = CachedReadOnlyProperty { firstClassDefByDeclarativePredicate(type, predicate) } + +fun gettingFirstClassDefMutableByDeclarativePredicateOrNull( + type: String, + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = gettingFirstClassDefMutableOrNull(type) { rememberedDeclarativePredicate(predicate) } + +fun gettingFirstClassDefMutableByDeclarativePredicate( + type: String, + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = CachedReadOnlyProperty { firstClassDefMutableByDeclarativePredicate(type, predicate) } + +fun gettingFirstClassDefByDeclarativePredicateOrNull( + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = gettingFirstClassDefOrNull { rememberedDeclarativePredicate(predicate) } + +fun gettingFirstClassDefByDeclarativePredicate( + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = CachedReadOnlyProperty { firstClassDefByDeclarativePredicate(predicate) } + +fun gettingFirstClassDefMutableByDeclarativePredicateOrNull( + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = gettingFirstClassDefMutableOrNull { rememberedDeclarativePredicate(predicate) } + +fun gettingFirstClassDefMutableByDeclarativePredicate( + predicate: context(PredicateContext, ClassDef) DeclarativePredicateBuilder.() -> Unit +) = CachedReadOnlyProperty { firstClassDefMutableByDeclarativePredicate(predicate) } + +fun gettingFirstMethodByDeclarativePredicateOrNull( + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = gettingFirstMethodOrNull { rememberedDeclarativePredicate(predicate) } + +fun gettingFirstMethodByDeclarativePredicate( + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = CachedReadOnlyProperty { firstMethodByDeclarativePredicate(predicate = predicate) } + +fun gettingFirstMethodMutableByDeclarativePredicateOrNull( + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = gettingFirstMethodMutableOrNull { rememberedDeclarativePredicate(predicate) } + +fun gettingFirstMethodMutableByDeclarativePredicate( + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = CachedReadOnlyProperty { firstMethodMutableByDeclarativePredicate(predicate = predicate) } + +fun gettingFirstMethodByDeclarativePredicateOrNull( + vararg strings: String, + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = gettingFirstMethodOrNull(*strings) { rememberedDeclarativePredicate(predicate) } + +fun gettingFirstMethodByDeclarativePredicate( + vararg strings: String, + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = CachedReadOnlyProperty { firstMethodByDeclarativePredicate(*strings, predicate = predicate) } + +fun gettingFirstMethodMutableByDeclarativePredicateOrNull( + vararg strings: String, + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = gettingFirstMethodMutableOrNull(*strings) { rememberedDeclarativePredicate(predicate) } + +fun gettingFirstMethodMutableByDeclarativePredicate( + vararg strings: String, + predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) = CachedReadOnlyProperty { firstMethodMutableByDeclarativePredicate(*strings, predicate = predicate) } + + +class DeclarativePredicateBuilder internal constructor() { + private val children = mutableListOf Boolean>() + + fun anyOf(block: DeclarativePredicateBuilder.() -> Unit) { + val child = DeclarativePredicateBuilder().apply(block) + children += { child.children.any { it() } } + } + + fun predicate(block: T.() -> Boolean) { + children += block + } + + fun all(target: T): Boolean = children.all { target.it() } + fun any(target: T): Boolean = children.all { target.it() } +} + +fun firstMethodComposite( + vararg strings: String, + builder: + context(PredicateContext, Method, IndexedMatcher, MutableList) DeclarativePredicateBuilder.() -> Unit +) = with(indexedMatcher()) matcher@{ + with(mutableListOf()) strings@{ + addAll(strings) + + Composition( + indices = this@matcher.indices, + strings = this@strings + ) { builder() } + } +} + +val m = firstMethodComposite("lookup") { + instructions( + head { string == "str" }, + anyOf(), + anyOf(after(1..2, string("also lookup"))), + string("s", String::startsWith), + string(), + literal(), + after(1..4, anyOf()), + noneOf(`is`()), + instruction { opcode == Opcode.CONST_STRING }, + { _, _ -> opcode == Opcode.CONST_STRING }, + ) + instructions { + +head(literal()) + + if (true) + +after(1..2, string("lookup")) + else + +instruction { opcode == Opcode.CONST_STRING } + + add { currentIndex, lastMatchedIndex -> + currentIndex == 2 && opcode == Opcode.CONST_STRING + } + } + + instructions { + +anyOf(after(1..2, string("also lookup")), Opcode.IF_EQ()) + +head(anyOf(string("s"), "s"(), Opcode.IF_EQ())) + +head(allOf(Opcode.CONST_STRING_JUMBO(), "str"())) + add(instruction { this.opcode == Opcode.CONST_STRING || this.string == "lookup" }) + add(instruction { string == "lookup" }) + +after(1..2, anyOf(string("s"), Opcode.IF_EQ())) + +string("also lookup") + +"equals"() + +"prefix" { startsWith(it) } + +string { startsWith("prefix") } + +"suffix"(String::endsWith) + +literal(12) { it >= this } + +literal(1232) + +literal { this >= 1123 } + +literal() + +string() + +string { startsWith("s") } + +method() + +reference() + +field() + +`is`() + +`is`() + +allOf(`is`(), string("test")) + +`is` { reference !is StringReference } + +`is` { registerCount > 2 } + +registers(0, 1, 1, 2) + +noneOf(registers({ size > 3 }), reference { contains("SomeClass") }) + +type() + +Opcode.CONST_STRING() + +after(1..2, Opcode.RETURN_VOID()) + +reference { startsWith("some") } + +field("s") + +allOf() // Wildcard + +anyOf(noneOf(string(), literal(123)), allOf(Opcode.CONST_STRING(), string("tet"))) + +method("abc") { startsWith(it) } + +after(1..2, string("also lookup") { startsWith(it) }) + +after(1..2, anyOf(string("a", String::endsWith), Opcode.CONST_4())) + +reference { contains("some") } + +method("name") + +field("name") + +after(1..2, reference("com/example", String::contains)) + +after(1..2, reference("lookup()V", String::endsWith)) + +after(1..2, reference("Lcom/example;->method()V", String::startsWith)) + +after(1..2, reference("Lcom/example;->method()V")) + +after(1..2, reference("Lcom/example;->field:Ljava/lang/String;") { endsWith(it) }) + } +} + +inline fun `is`( + crossinline predicate: T.() -> Boolean = { true } +): Instruction.(Int, Int) -> Boolean = { _, _ -> (this as? T)?.predicate() == true } + +fun instruction(predicate: Instruction.() -> Boolean): Instruction.(Int, Int) -> Boolean = { _, _ -> predicate() } + +fun registers(predicate: IntArray.() -> Boolean = { true }): Instruction.(Int, Int) -> Boolean = { _, _ -> + when (this) { + is RegisterRangeInstruction -> + IntArray(registerCount) { startRegister + it }.predicate() + + is FiveRegisterInstruction -> + intArrayOf(registerC, registerD, registerE, registerF, registerG).predicate() + + is ThreeRegisterInstruction -> + intArrayOf(registerA, registerB, registerC).predicate() + + is TwoRegisterInstruction -> + intArrayOf(registerA, registerB).predicate() + + is OneRegisterInstruction -> + intArrayOf(registerA).predicate() + + else -> false + } +} + +fun registers( + vararg registers: Int, + compare: IntArray.(registers: IntArray) -> Boolean = { registers -> + this.size >= registers.size && registers.indices.all { this[it] == registers[it] } + } +) = registers({ compare(registers) }) + +fun literal(predicate: Long.() -> Boolean = { true }): Instruction.(Int, Int) -> Boolean = + { _, _ -> wideLiteral?.predicate() == true } + +fun literal(literal: Long, compare: Long.(Long) -> Boolean = Long::equals) = + literal { compare(literal) } + +fun reference(predicate: String.() -> Boolean = { true }): Instruction.(Int, Int) -> Boolean = + predicate@{ _, _ -> this.reference?.toString()?.predicate() == true } + +fun reference(reference: String, compare: String.(String) -> Boolean = String::equals) = + reference { compare(reference) } + +fun field(predicate: String.() -> Boolean = { true }): Instruction.(Int, Int) -> Boolean = { _, _ -> + fieldReference?.name?.predicate() == true +} + +fun field(name: String, compare: String.(String) -> Boolean = String::equals) = + field { compare(name) } + + +fun type(predicate: String.() -> Boolean = { true }): Instruction.(Int, Int) -> Boolean = + { _, _ -> type?.predicate() == true } + +fun type(type: String, compare: String.(String) -> Boolean = String::equals) = + type { compare(type) } + +fun method(predicate: String.() -> Boolean = { true }): Instruction.(Int, Int) -> Boolean = { _, _ -> + methodReference?.name?.predicate() == true +} + +fun method(name: String, compare: String.(String) -> Boolean = String::equals) = + method { compare(name) } + +fun string(compare: String.() -> Boolean = { true }): Instruction.(Int, Int) -> Boolean = predicate@{ _, _ -> + this@predicate.string?.compare() == true +} + +context(stringsList: MutableList, builder: DeclarativePredicateBuilder) +fun string( + string: String, + compare: String.(String) -> Boolean = String::equals +): Instruction.(Int, Int) -> Boolean { + if (compare == String::equals) stringsList += string + + return string { compare(string) } +} + +context(stringsList: MutableList) +operator fun String.invoke(compare: String.(String) -> Boolean = String::equals): Instruction.(Int, Int) -> Boolean { + if (compare == String::equals) stringsList += this + + return { _, _ -> string?.compare(this@invoke) == true } +} + +operator fun Opcode.invoke(): Instruction.(currentIndex: Int, lastMatchedIndex: Int) -> Boolean = + { _, _ -> opcode == this@invoke } + +fun anyOf( + vararg predicates: Instruction.(currentIndex: Int, lastMatchedIndex: Int) -> Boolean +): Instruction.(Int, Int) -> Boolean = { currentIndex, lastMatchedIndex -> + predicates.any { predicate -> predicate(currentIndex, lastMatchedIndex) } +} + +fun allOf( + vararg predicates: Instruction.(currentIndex: Int, lastMatchedIndex: Int) -> Boolean +): Instruction.(Int, Int) -> Boolean = { currentIndex, lastMatchedIndex -> + predicates.all { predicate -> predicate(currentIndex, lastMatchedIndex) } +} + +fun noneOf( + vararg predicates: Instruction.(currentIndex: Int, lastMatchedIndex: Int) -> Boolean +): Instruction.(Int, Int) -> Boolean = { currentIndex, lastMatchedIndex -> + predicates.none { predicate -> predicate(currentIndex, lastMatchedIndex) } +} + +fun DeclarativePredicateBuilder.accessFlags(vararg flags: AccessFlags) = + predicate { accessFlags(*flags) } + +fun DeclarativePredicateBuilder.returnType( + returnType: String, + compare: String.(String) -> Boolean = String::startsWith +) = predicate { this.returnType.compare(returnType) } + +fun DeclarativePredicateBuilder.name( + name: String, + compare: String.(String) -> Boolean = String::equals +) = + predicate { this.name.compare(name) } + +fun DeclarativePredicateBuilder.definingClass( + definingClass: String, + compare: String.(String) -> Boolean = String::equals +) = predicate { this.definingClass.compare(definingClass) } + +fun DeclarativePredicateBuilder.parameterTypes(vararg parameterTypePrefixes: String) = predicate { + parameterTypes.size == parameterTypePrefixes.size && parameterTypes.zip(parameterTypePrefixes) + .all { (a, b) -> a.startsWith(b) } +} + +context(matcher: IndexedMatcher) +fun DeclarativePredicateBuilder.instructions( + build: IndexedMatcher.() -> Unit +) { + matcher.apply(build) + predicate { implementation { matcher(instructions) } } +} + +context(matcher: IndexedMatcher) +fun DeclarativePredicateBuilder.instructions( + vararg predicates: Instruction.(currentIndex: Int, lastMatchedIndex: Int) -> Boolean +) = instructions { addAll(predicates) } + +fun DeclarativePredicateBuilder.custom(block: Method.() -> Boolean) { + predicate { block() } +} + +class Composition internal constructor( + val indices: List, + val strings: List, + private val predicate: context(PredicateContext, Method) DeclarativePredicateBuilder.() -> Unit +) { + private var _methodOrNull: com.android.tools.smali.dexlib2.mutable.MutableMethod? = null + + context(context: BytecodePatchContext) + val methodOrNull: com.android.tools.smali.dexlib2.mutable.MutableMethod? + get() { + if (_methodOrNull == null) { + _methodOrNull = if (strings.isEmpty()) + context.firstMethodMutableByDeclarativePredicateOrNull(predicate) + else + context.firstMethodMutableByDeclarativePredicateOrNull( + strings = strings.toTypedArray(), + predicate + ) + } + + return _methodOrNull + } + + context(_: BytecodePatchContext) + val method get() = requireNotNull(methodOrNull) +} diff --git a/src/main/kotlin/app/revanced/patcher/PackageMetadata.kt b/core/src/commonMain/kotlin/app/revanced/patcher/PackageMetadata.kt similarity index 100% rename from src/main/kotlin/app/revanced/patcher/PackageMetadata.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/PackageMetadata.kt diff --git a/src/main/kotlin/app/revanced/patcher/Patcher.kt b/core/src/commonMain/kotlin/app/revanced/patcher/Patcher.kt similarity index 95% rename from src/main/kotlin/app/revanced/patcher/Patcher.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/Patcher.kt index 1247cb9..d8cdec8 100644 --- a/src/main/kotlin/app/revanced/patcher/Patcher.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/Patcher.kt @@ -1,9 +1,11 @@ package app.revanced.patcher import app.revanced.patcher.patch.* +import com.google.common.annotations.VisibleForTesting import kotlinx.coroutines.flow.flow import java.io.Closeable import java.util.logging.Logger +import kotlin.reflect.jvm.jvmName /** * A Patcher. @@ -11,7 +13,7 @@ import java.util.logging.Logger * @param config The configuration to use for the patcher. */ class Patcher(private val config: PatcherConfig) : Closeable { - private val logger = Logger.getLogger(this::class.java.name) + private val logger = Logger.getLogger(this::class.jvmName) /** * The context containing the current state of the patcher. @@ -69,7 +71,7 @@ class Patcher(private val config: PatcherConfig) : Closeable { // Recursively execute all dependency patches. dependencies.forEach { dependency -> - dependency.execute(executedPatches).exception?.let{ + dependency.execute(executedPatches).exception?.let { return PatchResult( this, PatchException( @@ -96,10 +98,9 @@ class Patcher(private val config: PatcherConfig) : Closeable { context.resourceContext.decodeResources(config.resourceMode) } - logger.info("Initializing lookup maps") + logger.info("Initializing cache") - // Accessing the lazy lookup maps to initialize them. - context.bytecodeContext.lookupMaps + context.bytecodeContext.classDefs.initializeCache() logger.info("Executing patches") diff --git a/src/main/kotlin/app/revanced/patcher/PatcherConfig.kt b/core/src/commonMain/kotlin/app/revanced/patcher/PatcherConfig.kt similarity index 96% rename from src/main/kotlin/app/revanced/patcher/PatcherConfig.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/PatcherConfig.kt index 037f7d3..5ee117d 100644 --- a/src/main/kotlin/app/revanced/patcher/PatcherConfig.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/PatcherConfig.kt @@ -3,7 +3,10 @@ package app.revanced.patcher import app.revanced.patcher.patch.ResourcePatchContext import brut.androlib.Config import java.io.File +import java.io.deleteRecursively +import java.io.resolve import java.util.logging.Logger +import kotlin.reflect.jvm.jvmName /** * The configuration for the patcher. @@ -38,7 +41,7 @@ class PatcherConfig( frameworkFileDirectory: String? = null, ) : this(apkFile, temporaryFilesPath, aaptBinaryPath?.let { File(it) }, frameworkFileDirectory) - private val logger = Logger.getLogger(PatcherConfig::class.java.name) + private val logger = Logger.getLogger(PatcherConfig::class.jvmName) /** * The mode to use for resource decoding and compiling. diff --git a/src/main/kotlin/app/revanced/patcher/PatcherContext.kt b/core/src/commonMain/kotlin/app/revanced/patcher/PatcherContext.kt similarity index 100% rename from src/main/kotlin/app/revanced/patcher/PatcherContext.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/PatcherContext.kt diff --git a/src/main/kotlin/app/revanced/patcher/PatcherResult.kt b/core/src/commonMain/kotlin/app/revanced/patcher/PatcherResult.kt similarity index 100% rename from src/main/kotlin/app/revanced/patcher/PatcherResult.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/PatcherResult.kt diff --git a/src/main/kotlin/app/revanced/patcher/extensions/Instruction.kt b/core/src/commonMain/kotlin/app/revanced/patcher/extensions/Instruction.kt similarity index 60% rename from src/main/kotlin/app/revanced/patcher/extensions/Instruction.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/extensions/Instruction.kt index f16e030..01160d1 100644 --- a/src/main/kotlin/app/revanced/patcher/extensions/Instruction.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/extensions/Instruction.kt @@ -1,16 +1,12 @@ package app.revanced.patcher.extensions -import app.revanced.patcher.dex.mutable.MutableMethod import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcodes import com.android.tools.smali.dexlib2.builder.BuilderInstruction -import com.android.tools.smali.dexlib2.iface.instruction.DualReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.Instruction +import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.reference.* -import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.writer.builder.DexBuilder import com.android.tools.smali.smali.smaliFlexLexer import com.android.tools.smali.smali.smaliParser @@ -20,39 +16,6 @@ import org.antlr.runtime.TokenSource import org.antlr.runtime.tree.CommonTreeNodeStream import java.io.StringReader -inline fun Instruction.reference(predicate: T.() -> Boolean) = - ((this as? ReferenceInstruction)?.reference as? T)?.predicate() ?: false - -inline fun Instruction.reference2(predicate: T.() -> Boolean) = - ((this as? DualReferenceInstruction)?.reference2 as? T)?.predicate() ?: false - -fun Instruction.methodReference(predicate: MethodReference.() -> Boolean) = - reference(predicate) - -fun Instruction.methodReference(methodReference: MethodReference) = - methodReference { MethodUtil.methodSignaturesMatch(methodReference, this) } - -fun Instruction.fieldReference(predicate: FieldReference.() -> Boolean) = - reference(predicate) - -fun Instruction.fieldReference(fieldName: String) = - fieldReference { name == fieldName } - -fun Instruction.type(predicate: String.() -> Boolean) = - reference { type.predicate() } - -fun Instruction.type(type: String) = - type { this == type } - -fun Instruction.string(predicate: String.() -> Boolean) = - reference { string.predicate() } - -fun Instruction.string(string: String) = - string { this == string } - -fun Instruction.opcode(opcode: Opcode) = this.opcode == opcode - -fun Instruction.wideLiteral(wideLiteral: Long) = (this as? WideLiteralInstruction)?.wideLiteral == wideLiteral private inline fun Instruction.reference(): T? = (this as? ReferenceInstruction)?.reference as? T @@ -61,24 +24,45 @@ val Instruction.reference: Reference? get() = reference() val Instruction.methodReference - get() = - reference() + get() = reference() val Instruction.fieldReference - get() = - reference() + get() = reference() val Instruction.typeReference - get() = - reference() + get() = reference() val Instruction.stringReference - get() = - reference() + get() = reference() +/** TODO: This is technically missing for consistency: + +private inline fun Instruction.reference2(): T? = +(this as? DualReferenceInstruction)?.reference2 as? T + +val Instruction.reference2: Reference? +get() = reference2() + +val Instruction.methodReference2 +get() = reference2() + +val Instruction.fieldReference2 +get() = reference2() + +val Instruction.typeReference2 +get() = reference2() + +val Instruction.stringReference2 +get() = reference2() + **/ + +val Instruction.type + get() = typeReference?.type + +val Instruction.string + get() = stringReference?.string val Instruction.wideLiteral - get() = - (this as? WideLiteralInstruction)?.wideLiteral + get() = (this as? NarrowLiteralInstruction)?.wideLiteral private const val CLASS_HEADER = ".class LInlineCompiler;\n.super Ljava/lang/Object;\n" @@ -94,7 +78,7 @@ private val sb by lazy { StringBuilder(512) } * @param templateMethod The method to compile the instructions against. * @returns A list of instructions. */ -fun String.toInstructions(templateMethod: MutableMethod? = null): List { +fun String.toInstructions(templateMethod: com.android.tools.smali.dexlib2.mutable.MutableMethod? = null): List { val parameters = templateMethod?.parameterTypes?.joinToString("") { it } ?: "" val registers = templateMethod?.implementation?.registerCount ?: 1 // TODO: Should this be 0? val isStatic = templateMethod?.let { AccessFlags.STATIC.isSet(it.accessFlags) } ?: true diff --git a/src/main/kotlin/app/revanced/patcher/extensions/Method.kt b/core/src/commonMain/kotlin/app/revanced/patcher/extensions/Method.kt similarity index 96% rename from src/main/kotlin/app/revanced/patcher/extensions/Method.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/extensions/Method.kt index 3275d6b..55ff3a3 100644 --- a/src/main/kotlin/app/revanced/patcher/extensions/Method.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/extensions/Method.kt @@ -1,6 +1,6 @@ package app.revanced.patcher.extensions -import app.revanced.patcher.dex.mutable.MutableMethod +import com.android.tools.smali.dexlib2.mutable.MutableMethod import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.builder.BuilderInstruction import com.android.tools.smali.dexlib2.builder.BuilderOffsetInstruction @@ -64,7 +64,7 @@ fun MutableMethodImplementation.removeInstructions(count: Int) = removeInstructi fun MutableMethodImplementation.replaceInstructions( index: Int, instructions: List, -) = instructions.forEach { replaceInstruction(index, it) } +) = instructions.forEachIndexed { i, instruction -> replaceInstruction(index + i, instruction) } /** * Add an instruction to a method at the given index. @@ -100,7 +100,8 @@ fun MutableMethod.addInstruction( * * @param smaliInstructions The instruction to add. */ -fun MutableMethod.addInstruction(smaliInstructions: String) = implementation!!.addInstruction(smaliInstructions.toInstructions(this).first()) +fun MutableMethod.addInstruction(smaliInstructions: String) = + implementation!!.addInstruction(smaliInstructions.toInstructions(this).first()) /** * Add instructions to a method at the given index. @@ -118,7 +119,8 @@ fun MutableMethod.addInstructions( * * @param instructions The instructions to add. */ -fun MutableMethod.addInstructions(instructions: List) = implementation!!.addInstructions(instructions) +fun MutableMethod.addInstructions(instructions: List) = + implementation!!.addInstructions(instructions) /** * Add instructions to a method. @@ -135,7 +137,8 @@ fun MutableMethod.addInstructions( * * @param smaliInstructions The instructions to add. */ -fun MutableMethod.addInstructions(smaliInstructions: String) = implementation!!.addInstructions(smaliInstructions.toInstructions(this)) +fun MutableMethod.addInstructions(smaliInstructions: String) = + implementation!!.addInstructions(smaliInstructions.toInstructions(this)) /** * Add instructions to a method at the given index. @@ -193,6 +196,7 @@ fun MutableMethod.addInstructionsWithLabels( i.registerB, label, ) + is BuilderInstruction30t -> BuilderInstruction30t(i.opcode, label) is BuilderInstruction31t -> BuilderInstruction31t(i.opcode, i.registerA, label) else -> throw IllegalStateException( diff --git a/core/src/commonMain/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt b/core/src/commonMain/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt new file mode 100644 index 0000000..137179e --- /dev/null +++ b/core/src/commonMain/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt @@ -0,0 +1,287 @@ +package app.revanced.patcher.patch + +import app.revanced.patcher.InternalApi +import app.revanced.patcher.PatcherConfig +import app.revanced.patcher.PatcherResult +import com.android.tools.smali.dexlib2.mutable.MutableClassDef +import com.android.tools.smali.dexlib2.mutable.MutableClassDef.Companion.toMutable +import app.revanced.patcher.extensions.instructionsOrNull +import app.revanced.patcher.util.ClassMerger.merge +import app.revanced.patcher.util.MethodNavigator +import com.android.tools.smali.dexlib2.iface.ClassDef +import com.android.tools.smali.dexlib2.iface.DexFile +import com.android.tools.smali.dexlib2.iface.Method +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.StringReference +import lanchon.multidexlib2.BasicDexFileNamer +import lanchon.multidexlib2.DexIO +import lanchon.multidexlib2.MultiDexIO +import lanchon.multidexlib2.RawDexIO +import java.io.Closeable +import java.io.IOException +import java.io.deleteRecursively +import java.io.inputStream +import java.io.resolve +import java.util.logging.Logger +import kotlin.reflect.jvm.jvmName + +/** + * A context for patches containing the current state of the bytecode. + * + * @param config The [PatcherConfig] used to create this context. + */ +@Suppress("MemberVisibilityCanBePrivate") +class BytecodePatchContext internal constructor(internal val config: PatcherConfig) : + PatchContext>, + Closeable { + private val logger = Logger.getLogger(this::class.jvmName) + + inner class ClassDefs private constructor( + dexFile: DexFile, + private val classDefs: MutableSet = dexFile.classes.toMutableSet() + ) : + MutableSet by classDefs { + private val byType = mutableMapOf() + + operator fun get(name: String): ClassDef? = byType[name] + + // Better performance according to + // https://github.com/LisoUseInAIKyrios/revanced-patcher/commit/9b6d95d4f414a35ed68da37b0ecd8549df1ef63a + private val _methodsByStrings = + LinkedHashMap>(2 * size, 0.5f) + + val methodsByString: Map> = _methodsByStrings + + // Can have a use-case in the future: + // private val _methodsWithString = methodsByString.values.flatten().toMutableSet() + // val methodsWithString: Set = _methodsWithString + + constructor() : this( + MultiDexIO.readDexFile( + true, + config.apkFile, + BasicDexFileNamer(), + null, + null + ) + ) + + internal val opcodes = dexFile.opcodes + + override fun add(element: ClassDef): Boolean { + val added = classDefs.add(element) + if (added) addCache(element) + + return added + } + + override fun addAll(elements: Collection): Boolean { + var anyAdded = false + elements.forEach { element -> + val added = classDefs.add(element) + if (added) { + addCache(element) + anyAdded = true + } + } + + return anyAdded + } + + // TODO: There is one default method "removeIf" in MutableSet, which we cannot override in the common module. + // The method must be overloaded with a NotImplementedException to avoid cache desynchronization. + + override fun clear() { + classDefs.clear() + byType.clear() + _methodsByStrings.clear() + } + + override fun remove(element: ClassDef): Boolean { + val removed = classDefs.remove(element) + if (removed) removeCache(element) + + return removed + } + + override fun removeAll(elements: Collection): Boolean { + var anyRemoved = false + elements.forEach { element -> + val removed = classDefs.remove(element) + if (removed) { + removeCache(element) + anyRemoved = true + } + } + + return anyRemoved + } + + override fun retainAll(elements: Collection) = + removeAll(classDefs.asSequence().filter { it !in elements }) + + private fun addCache(classDef: ClassDef) { + byType[classDef.type] = classDef + + classDef.forEachString { method, string -> + _methodsByStrings.getOrPut(string) { + // Maybe adjusting load factor/ initial size can improve performance. + mutableSetOf() + } += method + } + } + + private fun removeCache(classDef: ClassDef) { + byType -= classDef.type + + classDef.forEachString { method, string -> + if (_methodsByStrings[string]?.also { it -= method }?.isEmpty() == true) + _methodsByStrings -= string + } + } + + + private fun ClassDef.forEachString(action: (Method, String) -> Unit) { + methods.asSequence().forEach { method -> + method.instructionsOrNull?.asSequence() + ?.filterIsInstance() + ?.map { it.reference } + ?.filterIsInstance() + ?.map { it.string } + ?.forEach { string -> + action(method, string) + } + } + } + + /** + * Get a mutable version of the given [classDef], replacing it in the set if necessary. + * + * @param classDef The [ClassDef] to get or replace. + * @return The mutable version of the [classDef]. + * @see MutableClassDef + * @see toMutable + */ + fun getOrReplaceMutable(classDef: ClassDef): MutableClassDef { + if (classDef !is MutableClassDef) { + val mutableClassDef = classDef.toMutable() + this -= classDef + this += mutableClassDef + + return mutableClassDef + } + + return classDef + } + + internal fun initializeCache() = classDefs.forEach(::addCache) + + internal fun clearCache() { + byType.clear() + _methodsByStrings.clear() + } + } + + /** + * The list of classes. + */ + val classDefs = ClassDefs() + + /** + * Merge the extension of [bytecodePatch] into the [BytecodePatchContext]. + * If no extension is present, the function will return early. + * + * @param bytecodePatch The [BytecodePatch] to merge the extension of. + */ + internal fun mergeExtension(bytecodePatch: BytecodePatch) { + val extensionStream = bytecodePatch.extensionInputStream?.get() + ?: return logger.fine("Extension not found") + + RawDexIO.readRawDexFile( + extensionStream, 0, null + ).classes.forEach { classDef -> + val existingClass = classDefs[classDef.type] ?: run { + logger.fine { "Adding class \"$classDef\"" } + + classDefs += classDef + + return@forEach + } + + logger.fine { "Class \"$classDef\" exists already. Adding missing methods and fields." } + + existingClass.merge(classDef, this@BytecodePatchContext).let { mergedClass -> + // If the class was merged, replace the original class with the merged class. + if (mergedClass === existingClass) { + return@let + } + + classDefs -= existingClass + classDefs += mergedClass + } + } + + extensionStream.close() + } + + /** + * Navigate a method. + * + * @param method The method to navigate. + * + * @return A [MethodNavigator] for the method. + */ + fun navigate(method: MethodReference) = MethodNavigator(method) + + /** + * Compile bytecode from the [BytecodePatchContext]. + * + * @return The compiled bytecode. + */ + @InternalApi + override fun get(): Set { + logger.info("Compiling patched dex files") + + classDefs.clearCache() + System.gc() + + val patchedDexFileResults = + config.patchedFiles.resolve("dex").also { + it.deleteRecursively() // Make sure the directory is empty. + it.mkdirs() + }.apply { + MultiDexIO.writeDexFile( + true, + -1, + this, + BasicDexFileNamer(), + object : DexFile { + override fun getClasses() = classDefs.let { + // More performant according to + // https://github.com/LisoUseInAIKyrios/revanced-patcher/ + // commit/8c26ad08457fb1565ea5794b7930da42a1c81cf1 + // #diff-be698366d9868784ecf7da3fd4ac9d2b335b0bb637f9f618fbe067dbd6830b8fR197 + // TODO: Benchmark, if actually faster. + HashSet(it.size * 3 / 2).apply { addAll(it) } + } + + override fun getOpcodes() = classDefs.opcodes + }, + DexIO.DEFAULT_MAX_DEX_POOL_SIZE, + ) { _, entryName, _ -> logger.info { "Compiled $entryName" } } + }.listFiles { it.isFile }!!.map { + PatcherResult.PatchedDexFile(it.name, it.inputStream()) + }.toSet() + + return patchedDexFileResults + } + + override fun close() { + try { + classDefs.clear() + } catch (e: IOException) { + logger.warning("Failed to clear BytecodePatchContext: ${e.message}") + } + } +} diff --git a/src/main/kotlin/app/revanced/patcher/patch/Option.kt b/core/src/commonMain/kotlin/app/revanced/patcher/patch/Option.kt similarity index 99% rename from src/main/kotlin/app/revanced/patcher/patch/Option.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/patch/Option.kt index c37a1e6..2999d2b 100644 --- a/src/main/kotlin/app/revanced/patcher/patch/Option.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/patch/Option.kt @@ -1,7 +1,10 @@ +@file:Suppress("unused") + package app.revanced.patcher.patch import kotlin.reflect.KProperty import kotlin.reflect.KType +import kotlin.reflect.jvm.jvmName import kotlin.reflect.typeOf /** @@ -162,8 +165,8 @@ class Options internal constructor( (option as Option).value = value } catch (e: ClassCastException) { throw OptionException.InvalidValueTypeException( - value?.let { it::class.java.name } ?: "null", - option.value?.let { it::class.java.name } ?: "null", + value?.let { it::class.jvmName } ?: "null", + option.value?.let { it::class.jvmName } ?: "null", ) } } diff --git a/src/main/kotlin/app/revanced/patcher/patch/Patch.kt b/core/src/commonMain/kotlin/app/revanced/patcher/patch/Patch.kt similarity index 75% rename from src/main/kotlin/app/revanced/patcher/patch/Patch.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/patch/Patch.kt index 1639ba8..a918721 100644 --- a/src/main/kotlin/app/revanced/patcher/patch/Patch.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/patch/Patch.kt @@ -4,17 +4,12 @@ package app.revanced.patcher.patch import app.revanced.patcher.Patcher import app.revanced.patcher.PatcherContext -import dalvik.system.DexClassLoader -import lanchon.multidexlib2.BasicDexFileNamer -import lanchon.multidexlib2.MultiDexIO import java.io.File import java.io.InputStream import java.lang.reflect.Member import java.lang.reflect.Method import java.lang.reflect.Modifier -import java.net.URLClassLoader import java.util.function.Supplier -import java.util.jar.JarFile import kotlin.properties.ReadOnlyProperty typealias PackageName = String @@ -33,7 +28,7 @@ sealed interface PatchContext : Supplier * * @param C The [PatchContext] to execute and finalize the patch with. * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @param dependencies Other patches this patch depends on. @@ -127,7 +122,7 @@ internal fun Iterable>.forEachRecursively( * A bytecode patch. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @param compatiblePackages The packages the patch is compatible with. @@ -149,7 +144,7 @@ class BytecodePatch internal constructor( compatiblePackages: Set?, dependencies: Set>, options: Set>, - val extensionInputStream: Supplier?, + internal val extensionInputStream: Supplier?, executeBlock: (BytecodePatchContext) -> Unit, finalizeBlock: ((BytecodePatchContext) -> Unit)?, ) : Patch( @@ -176,7 +171,7 @@ class BytecodePatch internal constructor( * A raw resource patch. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @param compatiblePackages The packages the patch is compatible with. @@ -219,7 +214,7 @@ class RawResourcePatch internal constructor( * A resource patch. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @param compatiblePackages The packages the patch is compatible with. @@ -263,7 +258,7 @@ class ResourcePatch internal constructor( * * @param C The [PatchContext] to execute and finalize the patch with. * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @property compatiblePackages The packages the patch is compatible with. @@ -380,7 +375,7 @@ private fun > B.buildPatch(block: B.() -> Unit = {}) = apply * A [BytecodePatchBuilder] builder. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @property extensionInputStream Getter for the extension input stream of the patch. @@ -393,23 +388,20 @@ class BytecodePatchBuilder internal constructor( description: String?, use: Boolean, ) : PatchBuilder(name, description, use) { - // Must be internal for the inlined function "extendWith". - @PublishedApi internal var extensionInputStream: Supplier? = null - // Inlining is necessary to get the class loader that loaded the patch - // to load the extension from the resources. /** * Set the extension of the patch. * * @param extension The name of the extension resource. */ - @Suppress("NOTHING_TO_INLINE") - inline fun extendWith(extension: String) = apply { - val classLoader = object {}.javaClass.classLoader + fun extendWith(extension: String) = apply { + // Should be the classloader which loaded the patch class. + val classLoader = Class.forName(Thread.currentThread().stackTrace[2].className).classLoader!! extensionInputStream = Supplier { - classLoader.getResourceAsStream(extension) ?: throw PatchException("Extension \"$extension\" not found") + classLoader.getResourceAsStream(extension) + ?: throw PatchException("Extension \"$extension\" not found") } } @@ -430,7 +422,7 @@ class BytecodePatchBuilder internal constructor( * Create a new [BytecodePatch]. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @param block The block to build the patch. @@ -463,7 +455,7 @@ fun gettingBytecodePatch( * A [RawResourcePatch] builder. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @@ -490,7 +482,7 @@ class RawResourcePatchBuilder internal constructor( * Create a new [RawResourcePatch]. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @param block The block to build the patch. @@ -522,7 +514,7 @@ fun gettingRawResourcePatch( * A [ResourcePatch] builder. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @@ -549,7 +541,7 @@ class ResourcePatchBuilder internal constructor( * Create a new [ResourcePatch]. * * @param name The name of the patch. - * If null, the patch is named "Patch" and will not be loaded by [PatchLoader]. + * If null, the patch is named "Patch" and will not be loaded by [loadPatches]. * @param description The description of the patch. * @param use Weather or not the patch should be used. * @param block The block to build the patch. @@ -598,142 +590,45 @@ class PatchException(errorMessage: String?, cause: Throwable?) : Exception(error class PatchResult internal constructor(val patch: Patch<*>, val exception: PatchException? = null) /** - * A loader for patches. + * A collection of patches loaded from patches files. * - * Loads unnamed patches from JAR or DEX files declared as public static fields - * or returned by public static and non-parametrized methods. - * - * @param byPatchesFile The patches associated by the patches file they were loaded from. + * @property patchesByFile The patches mapped by their patches file. */ -sealed class PatchLoader private constructor( - val byPatchesFile: Map>>, -) : Set> by byPatchesFile.values.flatten().toSet() { - /** - * @param patchesFiles A set of JAR or DEX files to load the patches from. - * @param getBinaryClassNames A function that returns the binary names of all classes accessible by the class loader. - * @param classLoader The [ClassLoader] to use for loading the classes. - */ - private constructor( - patchesFiles: Set, - getBinaryClassNames: (patchesFile: File) -> List, - classLoader: ClassLoader, - ) : this(classLoader.loadPatches(patchesFiles.associateWith { getBinaryClassNames(it).toSet() })) +class Patches internal constructor(val patchesByFile: Map>>) : Set> +by patchesByFile.values.flatten().toSet() - /** - * A [PatchLoader] for JAR files. - * - * @param patchesFiles The JAR files to load the patches from. - * - * @constructor Create a new [PatchLoader] for JAR files. - */ - class Jar(patchesFiles: Set) : - PatchLoader( - patchesFiles, - { file -> - JarFile(file).entries().toList().filter { it.name.endsWith(".class") } - .map { it.name.substringBeforeLast('.').replace('/', '.') } - }, - URLClassLoader(patchesFiles.map { it.toURI().toURL() }.toTypedArray()), - ) +internal fun loadPatches( + patchesFiles: Set, + getBinaryClassNames: (patchesFile: File) -> List, + classLoader: ClassLoader, +): Patches { + fun Member.isUsable(): Boolean { + if (this is Method && parameterCount != 0) return false - /** - * A [PatchLoader] for [Dex] files. - * - * @param patchesFiles The DEX files to load the patches from. - * @param optimizedDexDirectory The directory to store optimized DEX files in. - * This parameter is deprecated and has no effect since API level 26. - * - * @constructor Create a new [PatchLoader] for [Dex] files. - */ - class Dex(patchesFiles: Set, optimizedDexDirectory: File? = null) : - PatchLoader( - patchesFiles, - { patchBundle -> - MultiDexIO.readDexFile(true, patchBundle, BasicDexFileNamer(), null, null).classes - .map { classDef -> - classDef.type.substring(1, classDef.length - 1) - } - }, - DexClassLoader( - patchesFiles.joinToString(File.pathSeparator) { it.absolutePath }, - optimizedDexDirectory?.absolutePath, - null, - this::class.java.classLoader, - ), - ) - - // Companion object required for unit tests. - private companion object { - val Class<*>.isPatch get() = Patch::class.java.isAssignableFrom(this) - - /** - * Public static fields that are patches. - */ - private val Class<*>.patchFields - get() = fields.filter { field -> - field.type.isPatch && field.canAccess() - }.map { field -> - field.get(null) as Patch<*> - } - - /** - * Public static and non-parametrized methods that return patches. - */ - private val Class<*>.patchMethods - get() = methods.filter { method -> - method.returnType.isPatch && method.parameterCount == 0 && method.canAccess() - }.map { method -> - method.invoke(null) as Patch<*> - } - - /** - * Loads unnamed patches declared as public static fields - * or returned by public static and non-parametrized methods. - * - * @param binaryClassNamesByPatchesFile The binary class name of the classes to load the patches from - * associated by the patches file. - * - * @return The loaded patches associated by the patches file. - */ - private fun ClassLoader.loadPatches(binaryClassNamesByPatchesFile: Map>) = - binaryClassNamesByPatchesFile.mapValues { (_, binaryClassNames) -> - binaryClassNames.asSequence().map { - loadClass(it) - }.flatMap { - it.patchFields + it.patchMethods - }.filter { - it.name != null - }.toSet() - } - - private fun Member.canAccess(): Boolean { - if (this is Method && parameterCount != 0) return false - - return Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) - } + return Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) } + + fun Class<*>.getPatchFields() = fields.filter { field -> + field.type.isPatch && field.isUsable() + }.map { field -> + field.get(null) as Patch<*> + } + + fun Class<*>.getPatchMethods() = methods.filter { method -> + method.returnType.isPatch && method.parameterCount == 0 && method.isUsable() + }.map { method -> + method.invoke(null) as Patch<*> + } + + return Patches(patchesFiles.associateWith { file -> + getBinaryClassNames(file).map { + classLoader.loadClass(it) + }.flatMap { clazz -> + clazz.getPatchMethods() + clazz.getPatchFields() + }.filter { it.name != null }.toSet() + }) } -/** - * Loads patches from JAR files declared as public static fields - * or returned by public static and non-parametrized methods. - * Patches with no name are not loaded. - * - * @param patchesFiles The JAR files to load the patches from. - * - * @return The loaded patches. - */ -fun loadPatchesFromJar(patchesFiles: Set) = - PatchLoader.Jar(patchesFiles) +expect fun loadPatches(patchesFiles: Set): Patches -/** - * Loads patches from DEX files declared as public static fields - * or returned by public static and non-parametrized methods. - * Patches with no name are not loaded. - * - * @param patchesFiles The DEX files to load the patches from. - * - * @return The loaded patches. - */ -fun loadPatchesFromDex(patchesFiles: Set, optimizedDexDirectory: File? = null) = - PatchLoader.Dex(patchesFiles, optimizedDexDirectory) +internal expect val Class<*>.isPatch: Boolean diff --git a/src/main/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt b/core/src/commonMain/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt similarity index 99% rename from src/main/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt index a65481d..69fbc6e 100644 --- a/src/main/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/patch/ResourcePatchContext.kt @@ -16,8 +16,10 @@ import brut.androlib.res.xml.ResXmlUtils import brut.directory.ExtFile import java.io.InputStream import java.io.OutputStream +import java.io.resolve import java.nio.file.Files import java.util.logging.Logger +import kotlin.reflect.jvm.jvmName /** * A context for patches containing the current state of resources. @@ -29,7 +31,7 @@ class ResourcePatchContext internal constructor( private val packageMetadata: PackageMetadata, private val config: PatcherConfig, ) : PatchContext { - private val logger = Logger.getLogger(ResourcePatchContext::class.java.name) + private val logger = Logger.getLogger(ResourcePatchContext::class.jvmName) /** * Read a document from an [InputStream]. diff --git a/src/main/kotlin/app/revanced/patcher/util/ClassMerger.kt b/core/src/commonMain/kotlin/app/revanced/patcher/util/ClassMerger.kt similarity index 90% rename from src/main/kotlin/app/revanced/patcher/util/ClassMerger.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/util/ClassMerger.kt index 728bce9..b2fcb49 100644 --- a/src/main/kotlin/app/revanced/patcher/util/ClassMerger.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/util/ClassMerger.kt @@ -1,6 +1,12 @@ package app.revanced.patcher.util -import app.revanced.patcher.dex.mutable.MutableClassDef +import com.android.tools.smali.dexlib2.mutable.MutableClassDef +import com.android.tools.smali.dexlib2.mutable.MutableClassDef.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableField +import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableMethod +import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable +import app.revanced.patcher.firstClassDefOrNull import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.util.ClassMerger.Utils.asMutableClass import app.revanced.patcher.util.ClassMerger.Utils.filterAny @@ -8,23 +14,19 @@ import app.revanced.patcher.util.ClassMerger.Utils.filterNotAny import app.revanced.patcher.util.ClassMerger.Utils.isPublic import app.revanced.patcher.util.ClassMerger.Utils.toPublic import app.revanced.patcher.util.ClassMerger.Utils.traverseClassHierarchy -import app.revanced.patcher.dex.mutable.MutableClassDef.Companion.toMutable -import app.revanced.patcher.dex.mutable.MutableField -import app.revanced.patcher.dex.mutable.MutableField.Companion.toMutable -import app.revanced.patcher.dex.mutable.MutableMethod -import app.revanced.patcher.dex.mutable.MutableMethod.Companion.toMutable import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.iface.ClassDef import com.android.tools.smali.dexlib2.util.MethodUtil import java.util.logging.Logger import kotlin.reflect.KFunction2 +import kotlin.reflect.jvm.jvmName /** * Experimental class to merge a [ClassDef] with another. * Note: This will not consider method implementations or if the class is missing a superclass or interfaces. */ internal object ClassMerger { - private val logger = Logger.getLogger(ClassMerger::class.java.name) + private val logger = Logger.getLogger(ClassMerger::class.jvmName) /** * Merge a class with [otherClass]. @@ -181,12 +183,13 @@ internal object ClassMerger { callback(targetClass) targetClass.superclass ?: return - classDefs.find { targetClass.superclass == it.type }?.mutable()?.let { - traverseClassHierarchy(it, callback) + + firstClassDefOrNull { type == targetClass.superclass }?.let { classDef -> + traverseClassHierarchy(classDefs.getOrReplaceMutable(classDef), callback) } } - fun ClassDef.asMutableClass() = if (this is MutableClassDef) this else this.toMutable() + fun ClassDef.asMutableClass() = this as? MutableClassDef ?: this.toMutable() /** * Check if the [AccessFlags.PUBLIC] flag is set. diff --git a/src/main/kotlin/app/revanced/patcher/util/Document.kt b/core/src/commonMain/kotlin/app/revanced/patcher/util/Document.kt similarity index 80% rename from src/main/kotlin/app/revanced/patcher/util/Document.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/util/Document.kt index c768552..1d5ea7c 100644 --- a/src/main/kotlin/app/revanced/patcher/util/Document.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/util/Document.kt @@ -1,14 +1,19 @@ package app.revanced.patcher.util +import collections.merge +import com.google.common.base.Charsets import org.w3c.dom.Document import java.io.Closeable import java.io.File import java.io.InputStream +import java.io.bufferedWriter +import java.io.inputStream import javax.xml.parsers.DocumentBuilderFactory import javax.xml.transform.OutputKeys import javax.xml.transform.TransformerFactory import javax.xml.transform.dom.DOMSource import javax.xml.transform.stream.StreamResult +import kotlin.use class Document internal constructor( inputStream: InputStream, @@ -29,7 +34,7 @@ class Document internal constructor( if (readerCount[it]!! > 1) { throw IllegalStateException( "Two or more instances are currently reading $it." + - "To be able to close this instance, no other instances may be reading $it at the same time.", + "To be able to close this instance, no other instances may be reading $it at the same time.", ) } else { readerCount.remove(it) @@ -40,9 +45,9 @@ class Document internal constructor( if (isAndroid) { transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-16") transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes") - it.bufferedWriter(charset = Charsets.UTF_8).use { writer -> - transformer.transform(DOMSource(this), StreamResult(writer)) - } + val writer = it.bufferedWriter(charset = Charsets.UTF_8) + transformer.transform(DOMSource(this), StreamResult(writer)) + writer.close() } else { transformer.transform(DOMSource(this), StreamResult(it)) } diff --git a/src/main/kotlin/app/revanced/patcher/util/MethodNavigator.kt b/core/src/commonMain/kotlin/app/revanced/patcher/util/MethodNavigator.kt similarity index 86% rename from src/main/kotlin/app/revanced/patcher/util/MethodNavigator.kt rename to core/src/commonMain/kotlin/app/revanced/patcher/util/MethodNavigator.kt index ab4117d..d58f872 100644 --- a/src/main/kotlin/app/revanced/patcher/util/MethodNavigator.kt +++ b/core/src/commonMain/kotlin/app/revanced/patcher/util/MethodNavigator.kt @@ -2,8 +2,10 @@ package app.revanced.patcher.util -import app.revanced.patcher.dex.mutable.MutableMethod +import com.android.tools.smali.dexlib2.mutable.MutableMethod import app.revanced.patcher.extensions.instructionsOrNull +import app.revanced.patcher.firstClassDef +import app.revanced.patcher.firstClassDefMutable import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.iface.ClassDef import com.android.tools.smali.dexlib2.iface.Method @@ -82,10 +84,9 @@ class MethodNavigator internal constructor( * @return The last navigated method mutably. */ context(context: BytecodePatchContext) - fun stop() = with(context) { - classDefs.find(matchesCurrentMethodReferenceDefiningClass)!!.mutable().firstMethodBySignature - as MutableMethod - } + fun stop() = context.firstClassDefMutable(lastNavigatedMethodReference.definingClass) + .firstMethodBySignature as MutableMethod + /** * Get the last navigated method mutably. @@ -101,14 +102,7 @@ class MethodNavigator internal constructor( * @return The last navigated method immutably. */ context(context: BytecodePatchContext) - fun original(): Method = context.classDefs.first(matchesCurrentMethodReferenceDefiningClass).firstMethodBySignature - - /** - * Predicate to match the class defining the current method reference. - */ - private val matchesCurrentMethodReferenceDefiningClass = { classDef: ClassDef -> - classDef.type == lastNavigatedMethodReference.definingClass - } + fun original(): Method = context.firstClassDef(lastNavigatedMethodReference.definingClass).firstMethodBySignature /** * Find the first [lastNavigatedMethodReference] in the class. diff --git a/core/src/commonMain/kotlin/collections/MutableMap.kt b/core/src/commonMain/kotlin/collections/MutableMap.kt new file mode 100644 index 0000000..1a66170 --- /dev/null +++ b/core/src/commonMain/kotlin/collections/MutableMap.kt @@ -0,0 +1,13 @@ +package collections + +internal expect fun MutableMap.kmpMerge( + key: K, + value: V, + remappingFunction: (oldValue: V, newValue: V) -> V, +) + +internal fun MutableMap.merge( + key: K, + value: V, + remappingFunction: (oldValue: V, newValue: V) -> V, +) = kmpMerge(key, value, remappingFunction) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableAnnotationEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt similarity index 50% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableAnnotationEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt index 9eb4e79..99d1a64 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableAnnotationEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableAnnotationEncodedValue.kt @@ -1,9 +1,7 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value -import app.revanced.patcher.dex.mutable.MutableAnnotationElement.Companion.toMutable import com.android.tools.smali.dexlib2.base.value.BaseAnnotationEncodedValue -import com.android.tools.smali.dexlib2.iface.AnnotationElement -import com.android.tools.smali.dexlib2.iface.value.AnnotationEncodedValue +import com.android.tools.smali.dexlib2.mutable.MutableAnnotationElement.Companion.toMutable class MutableAnnotationEncodedValue(annotationEncodedValue: AnnotationEncodedValue) : BaseAnnotationEncodedValue(), @@ -14,15 +12,15 @@ class MutableAnnotationEncodedValue(annotationEncodedValue: AnnotationEncodedVal annotationEncodedValue.elements.map { annotationElement -> annotationElement.toMutable() }.toMutableSet() } - override fun getType(): String = this.type - fun setType(type: String) { this.type = type } - override fun getElements(): MutableSet = _elements + override fun getType() = this.type + + override fun getElements() = _elements companion object { - fun AnnotationEncodedValue.toMutable(): MutableAnnotationEncodedValue = MutableAnnotationEncodedValue(this) + fun AnnotationEncodedValue.toMutable() = MutableAnnotationEncodedValue(this) } } diff --git a/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt new file mode 100644 index 0000000..97363b1 --- /dev/null +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableArrayEncodedValue.kt @@ -0,0 +1,16 @@ +package com.android.tools.smali.dexlib2.iface.value + +import com.android.tools.smali.dexlib2.base.value.BaseArrayEncodedValue +import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable + +class MutableArrayEncodedValue(arrayEncodedValue: ArrayEncodedValue) : BaseArrayEncodedValue(), MutableEncodedValue { + private val _value by lazy { + arrayEncodedValue.value.map { encodedValue -> encodedValue.toMutable() }.toMutableList() + } + + override fun getValue() = _value + + companion object { + fun ArrayEncodedValue.toMutable(): MutableArrayEncodedValue = MutableArrayEncodedValue(this) + } +} diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableBooleanEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt similarity index 80% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableBooleanEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt index 9293cc4..ca24cb7 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableBooleanEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableBooleanEncodedValue.kt @@ -1,19 +1,18 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseBooleanEncodedValue -import com.android.tools.smali.dexlib2.iface.value.BooleanEncodedValue class MutableBooleanEncodedValue(booleanEncodedValue: BooleanEncodedValue) : BaseBooleanEncodedValue(), MutableEncodedValue { private var value = booleanEncodedValue.value - override fun getValue(): Boolean = this.value - fun setValue(value: Boolean) { this.value = value } + override fun getValue(): Boolean = this.value + companion object { fun BooleanEncodedValue.toMutable(): MutableBooleanEncodedValue = MutableBooleanEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt similarity index 70% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt index d9bdae4..82b04c0 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableByteEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableByteEncodedValue.kt @@ -1,19 +1,16 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseByteEncodedValue -import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue -class MutableByteEncodedValue(byteEncodedValue: ByteEncodedValue) : - BaseByteEncodedValue(), - MutableEncodedValue { +class MutableByteEncodedValue(byteEncodedValue: ByteEncodedValue) : BaseByteEncodedValue(), MutableEncodedValue { private var value = byteEncodedValue.value - override fun getValue(): Byte = this.value - fun setValue(value: Byte) { this.value = value } + override fun getValue(): Byte = this.value + companion object { fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableCharEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt similarity index 70% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableCharEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt index 4f6a6d1..eef4676 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableCharEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableCharEncodedValue.kt @@ -1,19 +1,16 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseCharEncodedValue -import com.android.tools.smali.dexlib2.iface.value.CharEncodedValue -class MutableCharEncodedValue(charEncodedValue: CharEncodedValue) : - BaseCharEncodedValue(), - MutableEncodedValue { +class MutableCharEncodedValue(charEncodedValue: CharEncodedValue) : BaseCharEncodedValue(), MutableEncodedValue { private var value = charEncodedValue.value - override fun getValue(): Char = this.value - fun setValue(value: Char) { this.value = value } + override fun getValue(): Char = this.value + companion object { fun CharEncodedValue.toMutable(): MutableCharEncodedValue = MutableCharEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableDoubleEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt similarity index 80% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableDoubleEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt index 1af6dba..6259ec2 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableDoubleEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableDoubleEncodedValue.kt @@ -1,19 +1,18 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseDoubleEncodedValue -import com.android.tools.smali.dexlib2.iface.value.DoubleEncodedValue class MutableDoubleEncodedValue(doubleEncodedValue: DoubleEncodedValue) : BaseDoubleEncodedValue(), MutableEncodedValue { private var value = doubleEncodedValue.value - override fun getValue(): Double = this.value - fun setValue(value: Double) { this.value = value } + override fun getValue(): Double = this.value + companion object { fun DoubleEncodedValue.toMutable(): MutableDoubleEncodedValue = MutableDoubleEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt similarity index 94% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt index 9cc2a13..bf3112b 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEncodedValue.kt @@ -1,7 +1,6 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.ValueType -import com.android.tools.smali.dexlib2.iface.value.* interface MutableEncodedValue : EncodedValue { companion object { diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableEnumEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt similarity index 74% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableEnumEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt index 07b2a17..5c41b7d 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableEnumEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableEnumEncodedValue.kt @@ -1,20 +1,17 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseEnumEncodedValue import com.android.tools.smali.dexlib2.iface.reference.FieldReference -import com.android.tools.smali.dexlib2.iface.value.EnumEncodedValue -class MutableEnumEncodedValue(enumEncodedValue: EnumEncodedValue) : - BaseEnumEncodedValue(), - MutableEncodedValue { +class MutableEnumEncodedValue(enumEncodedValue: EnumEncodedValue) : BaseEnumEncodedValue(), MutableEncodedValue { private var value = enumEncodedValue.value - override fun getValue(): FieldReference = this.value - fun setValue(value: FieldReference) { this.value = value } + override fun getValue(): FieldReference = this.value + companion object { fun EnumEncodedValue.toMutable(): MutableEnumEncodedValue = MutableEnumEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableFieldEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt similarity index 77% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableFieldEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt index e56451d..14d1144 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableFieldEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFieldEncodedValue.kt @@ -1,23 +1,20 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.ValueType import com.android.tools.smali.dexlib2.base.value.BaseFieldEncodedValue import com.android.tools.smali.dexlib2.iface.reference.FieldReference -import com.android.tools.smali.dexlib2.iface.value.FieldEncodedValue -class MutableFieldEncodedValue(fieldEncodedValue: FieldEncodedValue) : - BaseFieldEncodedValue(), - MutableEncodedValue { +class MutableFieldEncodedValue(fieldEncodedValue: FieldEncodedValue) : BaseFieldEncodedValue(), MutableEncodedValue { private var value = fieldEncodedValue.value - override fun getValueType(): Int = ValueType.FIELD - - override fun getValue(): FieldReference = this.value - fun setValue(value: FieldReference) { this.value = value } + override fun getValueType(): Int = ValueType.FIELD + + override fun getValue(): FieldReference = this.value + companion object { fun FieldEncodedValue.toMutable(): MutableFieldEncodedValue = MutableFieldEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableFloatEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt similarity index 70% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableFloatEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt index 5028ff1..9d23b6b 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableFloatEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableFloatEncodedValue.kt @@ -1,19 +1,16 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseFloatEncodedValue -import com.android.tools.smali.dexlib2.iface.value.FloatEncodedValue -class MutableFloatEncodedValue(floatEncodedValue: FloatEncodedValue) : - BaseFloatEncodedValue(), - MutableEncodedValue { +class MutableFloatEncodedValue(floatEncodedValue: FloatEncodedValue) : BaseFloatEncodedValue(), MutableEncodedValue { private var value = floatEncodedValue.value - override fun getValue(): Float = this.value - fun setValue(value: Float) { this.value = value } + override fun getValue(): Float = this.value + companion object { fun FloatEncodedValue.toMutable(): MutableFloatEncodedValue = MutableFloatEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableIntEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt similarity index 70% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableIntEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt index 67fad3f..e035b1f 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableIntEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableIntEncodedValue.kt @@ -1,19 +1,16 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseIntEncodedValue -import com.android.tools.smali.dexlib2.iface.value.IntEncodedValue -class MutableIntEncodedValue(intEncodedValue: IntEncodedValue) : - BaseIntEncodedValue(), - MutableEncodedValue { +class MutableIntEncodedValue(intEncodedValue: IntEncodedValue) : BaseIntEncodedValue(), MutableEncodedValue { private var value = intEncodedValue.value - override fun getValue(): Int = this.value - fun setValue(value: Int) { this.value = value } + override fun getValue(): Int = this.value + companion object { fun IntEncodedValue.toMutable(): MutableIntEncodedValue = MutableIntEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableLongEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt similarity index 70% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableLongEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt index 2db7a00..04953ff 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableLongEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableLongEncodedValue.kt @@ -1,19 +1,16 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseLongEncodedValue -import com.android.tools.smali.dexlib2.iface.value.LongEncodedValue -class MutableLongEncodedValue(longEncodedValue: LongEncodedValue) : - BaseLongEncodedValue(), - MutableEncodedValue { +class MutableLongEncodedValue(longEncodedValue: LongEncodedValue) : BaseLongEncodedValue(), MutableEncodedValue { private var value = longEncodedValue.value - override fun getValue(): Long = this.value - fun setValue(value: Long) { this.value = value } + override fun getValue(): Long = this.value + companion object { fun LongEncodedValue.toMutable(): MutableLongEncodedValue = MutableLongEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt similarity index 82% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt index 4addacf..b0aa267 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodEncodedValue.kt @@ -1,20 +1,19 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseMethodEncodedValue import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.iface.value.MethodEncodedValue class MutableMethodEncodedValue(methodEncodedValue: MethodEncodedValue) : BaseMethodEncodedValue(), MutableEncodedValue { private var value = methodEncodedValue.value - override fun getValue(): MethodReference = this.value - fun setValue(value: MethodReference) { this.value = value } + override fun getValue(): MethodReference = this.value + companion object { fun MethodEncodedValue.toMutable(): MutableMethodEncodedValue = MutableMethodEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodHandleEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt similarity index 83% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodHandleEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt index 7c06402..1899b3c 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodHandleEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodHandleEncodedValue.kt @@ -1,20 +1,19 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseMethodHandleEncodedValue import com.android.tools.smali.dexlib2.iface.reference.MethodHandleReference -import com.android.tools.smali.dexlib2.iface.value.MethodHandleEncodedValue class MutableMethodHandleEncodedValue(methodHandleEncodedValue: MethodHandleEncodedValue) : BaseMethodHandleEncodedValue(), MutableEncodedValue { private var value = methodHandleEncodedValue.value - override fun getValue(): MethodHandleReference = this.value - fun setValue(value: MethodHandleReference) { this.value = value } + override fun getValue(): MethodHandleReference = this.value + companion object { fun MethodHandleEncodedValue.toMutable(): MutableMethodHandleEncodedValue = MutableMethodHandleEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodTypeEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt similarity index 72% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodTypeEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt index 4ecec51..57e1124 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableMethodTypeEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableMethodTypeEncodedValue.kt @@ -1,20 +1,17 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseMethodTypeEncodedValue import com.android.tools.smali.dexlib2.iface.reference.MethodProtoReference -import com.android.tools.smali.dexlib2.iface.value.MethodTypeEncodedValue -class MutableMethodTypeEncodedValue(methodTypeEncodedValue: MethodTypeEncodedValue) : - BaseMethodTypeEncodedValue(), - MutableEncodedValue { +class MutableMethodTypeEncodedValue(methodTypeEncodedValue: MethodTypeEncodedValue) : BaseMethodTypeEncodedValue(), MutableEncodedValue { private var value = methodTypeEncodedValue.value - override fun getValue(): MethodProtoReference = this.value - fun setValue(value: MethodProtoReference) { this.value = value } + override fun getValue(): MethodProtoReference = this.value + companion object { fun MethodTypeEncodedValue.toMutable(): MutableMethodTypeEncodedValue = MutableMethodTypeEncodedValue(this) } diff --git a/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt new file mode 100644 index 0000000..e600c2a --- /dev/null +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableNullEncodedValue.kt @@ -0,0 +1,9 @@ +package com.android.tools.smali.dexlib2.iface.value + +import com.android.tools.smali.dexlib2.base.value.BaseNullEncodedValue + +class MutableNullEncodedValue : BaseNullEncodedValue(), MutableEncodedValue { + companion object { + fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this) + } +} diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableShortEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt similarity index 80% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableShortEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt index 3090778..740bcf7 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableShortEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableShortEncodedValue.kt @@ -1,19 +1,18 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseShortEncodedValue -import com.android.tools.smali.dexlib2.iface.value.ShortEncodedValue class MutableShortEncodedValue(shortEncodedValue: ShortEncodedValue) : BaseShortEncodedValue(), MutableEncodedValue { private var value = shortEncodedValue.value - override fun getValue(): Short = this.value - fun setValue(value: Short) { this.value = value } + override fun getValue(): Short = this.value + companion object { fun ShortEncodedValue.toMutable(): MutableShortEncodedValue = MutableShortEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableStringEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt similarity index 72% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableStringEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt index 001c60e..052e934 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableStringEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableStringEncodedValue.kt @@ -1,20 +1,18 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseStringEncodedValue -import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue -import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue class MutableStringEncodedValue(stringEncodedValue: StringEncodedValue) : BaseStringEncodedValue(), MutableEncodedValue { private var value = stringEncodedValue.value - override fun getValue(): String = this.value - fun setValue(value: String) { this.value = value } + override fun getValue(): String = this.value + companion object { fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableTypeEncodedValue.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt similarity index 62% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableTypeEncodedValue.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt index c058926..ddf1436 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableTypeEncodedValue.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/iface/value/MutableTypeEncodedValue.kt @@ -1,19 +1,16 @@ -package app.revanced.patcher.dex.mutable.encodedValue +package com.android.tools.smali.dexlib2.iface.value import com.android.tools.smali.dexlib2.base.value.BaseTypeEncodedValue -import com.android.tools.smali.dexlib2.iface.value.TypeEncodedValue -class MutableTypeEncodedValue(typeEncodedValue: TypeEncodedValue) : - BaseTypeEncodedValue(), - MutableEncodedValue { +class MutableTypeEncodedValue(typeEncodedValue: TypeEncodedValue) : BaseTypeEncodedValue(), MutableEncodedValue { private var value = typeEncodedValue.value - override fun getValue(): String = this.value - fun setValue(value: String) { this.value = value } + override fun getValue() = this.value + companion object { fun TypeEncodedValue.toMutable(): MutableTypeEncodedValue = MutableTypeEncodedValue(this) } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableAnnotation.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt similarity index 52% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/MutableAnnotation.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt index fc4228e..703d3cc 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableAnnotation.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotation.kt @@ -1,21 +1,21 @@ -package app.revanced.patcher.dex.mutable +package com.android.tools.smali.dexlib2.mutable -import app.revanced.patcher.dex.mutable.MutableAnnotationElement.Companion.toMutable import com.android.tools.smali.dexlib2.base.BaseAnnotation import com.android.tools.smali.dexlib2.iface.Annotation +import com.android.tools.smali.dexlib2.mutable.MutableAnnotationElement.Companion.toMutable class MutableAnnotation(annotation: Annotation) : BaseAnnotation() { private val visibility = annotation.visibility private val type = annotation.type private val _elements by lazy { annotation.elements.map { element -> element.toMutable() }.toMutableSet() } - override fun getType(): String = type + override fun getType() = type - override fun getElements(): MutableSet = _elements + override fun getElements() = _elements - override fun getVisibility(): Int = visibility + override fun getVisibility() = visibility companion object { - fun Annotation.toMutable(): MutableAnnotation = MutableAnnotation(this) + fun Annotation.toMutable() = MutableAnnotation(this) } } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableAnnotationElement.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt similarity index 52% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/MutableAnnotationElement.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt index 08cbb4b..59076a7 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableAnnotationElement.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableAnnotationElement.kt @@ -1,10 +1,9 @@ -package app.revanced.patcher.dex.mutable +package com.android.tools.smali.dexlib2.mutable -import app.revanced.patcher.dex.mutable.encodedValue.MutableEncodedValue -import app.revanced.patcher.dex.mutable.encodedValue.MutableEncodedValue.Companion.toMutable import com.android.tools.smali.dexlib2.base.BaseAnnotationElement import com.android.tools.smali.dexlib2.iface.AnnotationElement -import com.android.tools.smali.dexlib2.iface.value.EncodedValue +import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue +import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable class MutableAnnotationElement(annotationElement: AnnotationElement) : BaseAnnotationElement() { private var name = annotationElement.name @@ -18,11 +17,11 @@ class MutableAnnotationElement(annotationElement: AnnotationElement) : BaseAnnot this.value = value } - override fun getName(): String = name + override fun getName() = name - override fun getValue(): EncodedValue = value + override fun getValue() = value companion object { - fun AnnotationElement.toMutable(): MutableAnnotationElement = MutableAnnotationElement(this) + fun AnnotationElement.toMutable() = MutableAnnotationElement(this) } } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableClassDef.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt similarity index 52% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/MutableClassDef.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt index 8587e3c..77d5354 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableClassDef.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableClassDef.kt @@ -1,16 +1,14 @@ -package app.revanced.patcher.dex.mutable +package com.android.tools.smali.dexlib2.mutable -import app.revanced.patcher.dex.mutable.MutableAnnotation.Companion.toMutable -import app.revanced.patcher.dex.mutable.MutableField.Companion.toMutable -import app.revanced.patcher.dex.mutable.MutableMethod.Companion.toMutable import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference import com.android.tools.smali.dexlib2.iface.ClassDef +import com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import com.android.tools.smali.dexlib2.util.FieldUtil import com.android.tools.smali.dexlib2.util.MethodUtil -class MutableClassDef(classDef: ClassDef) : - BaseTypeReference(), - ClassDef { +class MutableClassDef(classDef: ClassDef) : BaseTypeReference(), ClassDef { // Class private var type = classDef.type private var sourceFile = classDef.sourceFile @@ -24,8 +22,8 @@ class MutableClassDef(classDef: ClassDef) : // Methods private val _methods by lazy { classDef.methods.map { method -> method.toMutable() }.toMutableSet() } - private val _directMethods by lazy { _methods.filter { method -> MethodUtil.isDirect(method) }.toMutableSet() } - private val _virtualMethods by lazy { _methods.filter { method -> !MethodUtil.isDirect(method) }.toMutableSet() } + private val _directMethods by lazy { methods.filter { method -> MethodUtil.isDirect(method) }.toMutableSet() } + private val _virtualMethods by lazy { methods.filter { method -> !MethodUtil.isDirect(method) }.toMutableSet() } // Fields private val _fields by lazy { classDef.fields.map { field -> field.toMutable() }.toMutableSet() } @@ -48,29 +46,29 @@ class MutableClassDef(classDef: ClassDef) : this.superclass = superclass } - override fun getType(): String = type + override fun getType() = type - override fun getAccessFlags(): Int = accessFlags + override fun getAccessFlags() = accessFlags - override fun getSourceFile(): String? = sourceFile + override fun getSourceFile() = sourceFile - override fun getSuperclass(): String? = superclass + override fun getSuperclass() = superclass - override fun getInterfaces(): MutableList = _interfaces + override fun getInterfaces() = _interfaces - override fun getAnnotations(): MutableSet = _annotations + override fun getAnnotations() = _annotations - override fun getStaticFields(): MutableSet = _staticFields + override fun getStaticFields() = _staticFields - override fun getInstanceFields(): MutableSet = _instanceFields + override fun getInstanceFields() = _instanceFields - override fun getFields(): MutableSet = _fields + override fun getFields() = _fields - override fun getDirectMethods(): MutableSet = _directMethods + override fun getDirectMethods() = _directMethods - override fun getVirtualMethods(): MutableSet = _virtualMethods + override fun getVirtualMethods() = _virtualMethods - override fun getMethods(): MutableSet = _methods + override fun getMethods() = _methods companion object { fun ClassDef.toMutable(): MutableClassDef = MutableClassDef(this) diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableField.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableField.kt similarity index 51% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/MutableField.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableField.kt index 22d9014..6354912 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableField.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableField.kt @@ -1,15 +1,12 @@ -package app.revanced.patcher.dex.mutable +package com.android.tools.smali.dexlib2.mutable -import app.revanced.patcher.dex.mutable.MutableAnnotation.Companion.toMutable -import app.revanced.patcher.dex.mutable.encodedValue.MutableEncodedValue -import app.revanced.patcher.dex.mutable.encodedValue.MutableEncodedValue.Companion.toMutable -import com.android.tools.smali.dexlib2.HiddenApiRestriction import com.android.tools.smali.dexlib2.base.reference.BaseFieldReference import com.android.tools.smali.dexlib2.iface.Field +import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue +import com.android.tools.smali.dexlib2.iface.value.MutableEncodedValue.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable -class MutableField(field: Field) : - BaseFieldReference(), - Field { +class MutableField(field: Field) : BaseFieldReference(), Field { private var definingClass = field.definingClass private var name = field.name private var type = field.type @@ -39,21 +36,21 @@ class MutableField(field: Field) : this.initialValue = initialValue } - override fun getDefiningClass(): String = this.definingClass + override fun getDefiningClass() = this.definingClass - override fun getName(): String = this.name + override fun getName() = this.name - override fun getType(): String = this.type + override fun getType() = this.type - override fun getAnnotations(): MutableSet = this._annotations + override fun getAnnotations() = this._annotations - override fun getAccessFlags(): Int = this.accessFlags + override fun getAccessFlags() = this.accessFlags - override fun getHiddenApiRestrictions(): MutableSet = this._hiddenApiRestrictions + override fun getHiddenApiRestrictions() = this._hiddenApiRestrictions - override fun getInitialValue(): MutableEncodedValue? = this.initialValue + override fun getInitialValue() = this.initialValue companion object { - fun Field.toMutable(): MutableField = MutableField(this) + fun Field.toMutable() = MutableField(this) } } diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableMethod.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt similarity index 52% rename from src/main/kotlin/app/revanced/patcher/dex/mutable/MutableMethod.kt rename to core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt index 00fdeb5..f6dd23b 100644 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableMethod.kt +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethod.kt @@ -1,21 +1,18 @@ -package app.revanced.patcher.dex.mutable +package com.android.tools.smali.dexlib2.mutable -import app.revanced.patcher.dex.mutable.MutableAnnotation.Companion.toMutable -import app.revanced.patcher.dex.mutable.MutableMethodParameter.Companion.toMutable -import com.android.tools.smali.dexlib2.HiddenApiRestriction import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableMethodParameter.Companion.toMutable -class MutableMethod(method: Method) : - BaseMethodReference(), - Method { +class MutableMethod(method: Method) : BaseMethodReference(), Method { private var definingClass = method.definingClass private var name = method.name private var accessFlags = method.accessFlags private var returnType = method.returnType - // Create own mutable MethodImplementation (due to not being able to change members like register count) + // TODO: Create own mutable MethodImplementation (due to not being able to change members like register count) private val _implementation by lazy { method.implementation?.let { MutableMethodImplementation(it) } } private val _annotations by lazy { method.annotations.map { annotation -> annotation.toMutable() }.toMutableSet() } private val _parameters by lazy { method.parameters.map { parameter -> parameter.toMutable() }.toMutableList() } @@ -38,25 +35,25 @@ class MutableMethod(method: Method) : this.returnType = returnType } - override fun getDefiningClass(): String = definingClass + override fun getDefiningClass() = definingClass - override fun getName(): String = name + override fun getName() = name - override fun getParameterTypes(): MutableList = _parameterTypes + override fun getParameterTypes() = _parameterTypes - override fun getReturnType(): String = returnType + override fun getReturnType() = returnType - override fun getAnnotations(): MutableSet = _annotations + override fun getAnnotations() = _annotations - override fun getAccessFlags(): Int = accessFlags + override fun getAccessFlags() = accessFlags - override fun getHiddenApiRestrictions(): MutableSet = _hiddenApiRestrictions + override fun getHiddenApiRestrictions() = _hiddenApiRestrictions - override fun getParameters(): MutableList = _parameters + override fun getParameters() = _parameters - override fun getImplementation(): MutableMethodImplementation? = _implementation + override fun getImplementation() = _implementation companion object { - fun Method.toMutable(): MutableMethod = MutableMethod(this) + fun Method.toMutable() = MutableMethod(this) } } diff --git a/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt new file mode 100644 index 0000000..4540b1c --- /dev/null +++ b/core/src/commonMain/kotlin/com/android/tools/smali/dexlib2/mutable/MutableMethodParameter.kt @@ -0,0 +1,26 @@ +package com.android.tools.smali.dexlib2.mutable + +import com.android.tools.smali.dexlib2.base.BaseMethodParameter +import com.android.tools.smali.dexlib2.iface.MethodParameter +import com.android.tools.smali.dexlib2.mutable.MutableAnnotation.Companion.toMutable + +class MutableMethodParameter(parameter: MethodParameter) : BaseMethodParameter(), MethodParameter { + private var type = parameter.type + private var name = parameter.name + private var signature = parameter.signature + private val _annotations by lazy { + parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet() + } + + override fun getType() = type + + override fun getName() = name + + override fun getSignature() = signature + + override fun getAnnotations() = _annotations + + companion object { + fun MethodParameter.toMutable() = MutableMethodParameter(this) + } +} diff --git a/core/src/commonMain/kotlin/java/io/File.kt b/core/src/commonMain/kotlin/java/io/File.kt new file mode 100644 index 0000000..8669495 --- /dev/null +++ b/core/src/commonMain/kotlin/java/io/File.kt @@ -0,0 +1,17 @@ +package java.io + +internal expect fun File.kmpResolve(child: String): File + +internal fun File.resolve(child: String) = kmpResolve(child) + +internal expect fun File.kmpDeleteRecursively(): Boolean + +internal fun File.deleteRecursively() = kmpDeleteRecursively() + +internal expect fun File.kmpInputStream(): InputStream + +internal fun File.inputStream() = kmpInputStream() + +internal expect fun File.kmpBufferedWriter(charset: java.nio.charset.Charset): BufferedWriter + +internal fun File.bufferedWriter(charset: java.nio.charset.Charset) = kmpBufferedWriter(charset) \ No newline at end of file diff --git a/core/src/jvmMain/kotlin/app/revanced/patcher/patch/Patch.jvm.kt b/core/src/jvmMain/kotlin/app/revanced/patcher/patch/Patch.jvm.kt new file mode 100644 index 0000000..0c7ffe8 --- /dev/null +++ b/core/src/jvmMain/kotlin/app/revanced/patcher/patch/Patch.jvm.kt @@ -0,0 +1,26 @@ +package app.revanced.patcher.patch + +import java.io.File +import java.net.URLClassLoader +import java.util.function.Predicate +import java.util.jar.JarFile + +actual val Class<*>.isPatch get() = Patch::class.java.isAssignableFrom(this) + +/** + * Loads patches from JAR files declared as public static fields + * or returned by public static and non-parametrized methods. + * Patches with no name are not loaded. + * + * @param patchesFiles The JAR files to load the patches from. + * + * @return The loaded patches. + */ +actual fun loadPatches(patchesFiles: Set) = loadPatches( + patchesFiles, + { file -> + JarFile(file).entries().toList().filter { it.name.endsWith(".class") } + .map { it.name.substringBeforeLast('.').replace('/', '.') } + }, + URLClassLoader(patchesFiles.map { it.toURI().toURL() }.toTypedArray()), +) diff --git a/core/src/jvmMain/kotlin/collections/MutableMap.jvm.kt b/core/src/jvmMain/kotlin/collections/MutableMap.jvm.kt new file mode 100644 index 0000000..4068c22 --- /dev/null +++ b/core/src/jvmMain/kotlin/collections/MutableMap.jvm.kt @@ -0,0 +1,7 @@ +package collections + +internal actual fun MutableMap.kmpMerge( + key: K, + value: V, + remappingFunction: (oldValue: V, newValue: V) -> V +) = merge(key, value, remappingFunction) \ No newline at end of file diff --git a/core/src/jvmMain/kotlin/java/io/File.jvm.kt b/core/src/jvmMain/kotlin/java/io/File.jvm.kt new file mode 100644 index 0000000..2772efc --- /dev/null +++ b/core/src/jvmMain/kotlin/java/io/File.jvm.kt @@ -0,0 +1,9 @@ +package java.io + +import java.nio.charset.Charset + + +internal actual fun File.kmpResolve(child: String) = resolve(child) +internal actual fun File.kmpDeleteRecursively() = deleteRecursively() +internal actual fun File.kmpInputStream() = inputStream() +internal actual fun File.kmpBufferedWriter(charset: Charset) = bufferedWriter(charset) \ No newline at end of file diff --git a/src/test/kotlin/app/revanced/patcher/ExtensionsTest.kt b/core/src/jvmTest/kotlin/app/revanced/patcher/ExtensionsTest.kt similarity index 98% rename from src/test/kotlin/app/revanced/patcher/ExtensionsTest.kt rename to core/src/jvmTest/kotlin/app/revanced/patcher/ExtensionsTest.kt index d665f1c..57e0ba9 100644 --- a/src/test/kotlin/app/revanced/patcher/ExtensionsTest.kt +++ b/core/src/jvmTest/kotlin/app/revanced/patcher/ExtensionsTest.kt @@ -1,7 +1,7 @@ package app.revanced.patcher -import app.revanced.patcher.dex.mutable.MutableMethod -import app.revanced.patcher.dex.mutable.MutableMethod.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableMethod +import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import app.revanced.patcher.extensions.* import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode diff --git a/src/test/kotlin/app/revanced/patcher/PatcherTest.kt b/core/src/jvmTest/kotlin/app/revanced/patcher/PatcherTest.kt similarity index 67% rename from src/test/kotlin/app/revanced/patcher/PatcherTest.kt rename to core/src/jvmTest/kotlin/app/revanced/patcher/PatcherTest.kt index e2db339..c64d761 100644 --- a/src/test/kotlin/app/revanced/patcher/PatcherTest.kt +++ b/core/src/jvmTest/kotlin/app/revanced/patcher/PatcherTest.kt @@ -3,17 +3,23 @@ package app.revanced.patcher import app.revanced.patcher.extensions.toInstructions import app.revanced.patcher.patch.* import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.ClassDef +import com.android.tools.smali.dexlib2.Opcodes +import com.android.tools.smali.dexlib2.iface.DexFile +import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.immutable.ImmutableClassDef import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation import io.mockk.every import io.mockk.just import io.mockk.mockk +import io.mockk.mockkStatic import io.mockk.runs +import io.mockk.spyk import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking -import org.junit.jupiter.api.BeforeEach +import lanchon.multidexlib2.MultiDexIO +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.assertAll import org.junit.jupiter.api.assertThrows import java.util.logging.Logger @@ -21,11 +27,14 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertNotNull +import kotlin.test.assertNull internal object PatcherTest { private lateinit var patcher: Patcher + private lateinit var patcherContext: PatcherContext - @BeforeEach + @JvmStatic + @BeforeAll fun setUp() { patcher = mockk { // Can't mock private fields, until https://github.com/mockk/mockk/issues/1244 is resolved. @@ -40,9 +49,73 @@ internal object PatcherTest { Logger.getAnonymousLogger(), ) - every { context.bytecodeContext.classDefs } returns mockk(relaxed = true) every { this@mockk() } answers { callOriginal() } } + + val classDefs = mutableSetOf( + ImmutableClassDef( + "class", + 0, + null, + null, + null, + null, + null, + listOf( + ImmutableMethod( + "class", + "method", + emptyList(), + "V", + 0, + null, + null, + ImmutableMethodImplementation( + 2, + """ + const-string v0, "Hello, World!" + iput-object v0, p0, Ljava/lang/System;->out:Ljava/io/PrintStream; + iget-object v0, p0, Ljava/lang/System;->out:Ljava/io/PrintStream; + return-void + const-string v0, "This is a test." + return-object v0 + invoke-virtual { p0, v0 }, Ljava/io/PrintStream;->println(Ljava/lang/String;)V + invoke-static { p0 }, Ljava/lang/System;->currentTimeMillis()J + check-cast p0, Ljava/io/PrintStream; + """.toInstructions(), + null, + null + ), + ), + ), + ) + ) + + patcherContext = mockk { + every { bytecodeContext } returns mockk context@{ + every { config } returns mockk { + every { apkFile } returns mockk() + } + + mockkStatic(MultiDexIO::readDexFile) + every { + MultiDexIO.readDexFile( + any(), + any(), + any(), + any(), + any() + ) + } returns mockk { + every { classes } returns classDefs + every { opcodes } returns Opcodes.getDefault() + } + every { this@context.classDefs } returns ClassDefs().apply { initializeCache() } + every { mergeExtension(any()) } just runs + } + } + + every { patcher.context } returns patcherContext } @Test @@ -156,11 +229,13 @@ internal object PatcherTest { } @Test - fun `throws if unmatched fingerprint match is delegated`() { + fun `throws if unmatched fingerprint match is used`() { val patch = bytecodePatch { execute { // Fingerprint can never match. - val fingerprint = fingerprint { } + val fingerprint = fingerprint { + strings("doesnt exist") + } // Throws, because the fingerprint can't be matched. fingerprint.patternMatch @@ -175,14 +250,16 @@ internal object PatcherTest { val iterable = (1..10).toList() val matcher = indexedMatcher() - matcher.apply { head { this > 5 } } + matcher.apply { + +head { this > 5 } + } assertFalse( matcher(iterable), "Should not match at any other index than first" ) matcher.clear() - matcher.apply { head { this == 1 } }(iterable) + matcher.apply { +head { this == 1 } }(iterable) assertEquals( listOf(0), matcher.indices, @@ -190,11 +267,11 @@ internal object PatcherTest { ) matcher.clear() - matcher.apply { add { this > 0 } }(iterable) + matcher.apply { add { _, _ -> this > 0 } }(iterable) assertEquals(1, matcher.indices.size, "Should only match once.") matcher.clear() - matcher.apply { add { this == 2 } }(iterable) + matcher.apply { add { _, _ -> this == 2 } }(iterable) assertEquals( listOf(1), matcher.indices, @@ -203,9 +280,9 @@ internal object PatcherTest { matcher.clear() matcher.apply { - head { this == 1 } - add { this == 2 } - add { this == 4 } + +head { this == 1 } + add { _, _ -> this == 2 } + add { _, _ -> this == 4 } }(iterable) assertEquals( listOf(0, 1, 3), @@ -215,7 +292,7 @@ internal object PatcherTest { matcher.clear() matcher.apply { - after { this == 1 } + +after { this == 1 } }(iterable) assertEquals( listOf(0), @@ -225,7 +302,7 @@ internal object PatcherTest { matcher.clear() matcher.apply { - after(2..Int.MAX_VALUE) { this == 1 } + +after(2..Int.MAX_VALUE) { this == 1 } } assertFalse( matcher(iterable), @@ -234,7 +311,7 @@ internal object PatcherTest { matcher.clear() matcher.apply { - after(1..1) { this == 2 } + +after(1..1) { this == 2 } } assertFalse( matcher(iterable), @@ -243,10 +320,10 @@ internal object PatcherTest { matcher.clear() matcher.apply { - head { this == 1 } - after(2..5) { this == 4 } - add { this == 8 } - add { this == 9 } + +head { this == 1 } + +after(2..5) { this == 4 } + add { _, _ -> this == 8 } + add { _, _ -> this == 9 } }(iterable) assertEquals( listOf(0, 3, 7, 8), @@ -256,93 +333,55 @@ internal object PatcherTest { } @Test - fun `matches fingerprint`() { - every { patcher.context.bytecodeContext.classDefs } returns mutableSetOf( - ImmutableClassDef( - "class", - 0, - null, - null, - null, - null, - null, - listOf( - ImmutableMethod( - "class", - "method", - emptyList(), - "V", - 0, - null, - null, - ImmutableMethodImplementation( - 2, - """ - const-string v0, "Hello, World!" - iput-object v0, p0, Ljava/lang/System;->out:Ljava/io/PrintStream; - iget-object v0, p0, Ljava/lang/System;->out:Ljava/io/PrintStream; - return-void - const-string v0, "This is a test." - return-object v0 - invoke-virtual { p0, v0 }, Ljava/io/PrintStream;->println(Ljava/lang/String;)V - invoke-static { p0 }, Ljava/lang/System;->currentTimeMillis()J - check-cast p0, Ljava/io/PrintStream; - """.toInstructions(), - null, - null - ), - ), - ), - ), - ) - every { - with(patcher.context.bytecodeContext) { - any(ClassDef::class).mutable() + fun `matches via composite`() { + fun composite(fail: Boolean = false) = firstMethodComposite { + name("method") + definingClass("class") + + if (fail) returnType("doesnt exist") + + instructions( + head(Opcode.CONST_STRING()), + `is`(), + noneOf(registers()), + string("test", String::contains), + after(1..3, allOf(Opcode.INVOKE_VIRTUAL(), registers(1, 0))), + allOf(), + type("PrintStream;", String::endsWith) + ) + } + + with(patcher.context.bytecodeContext) { + assertNotNull(composite().methodOrNull) { + "Expected to find a method matching the composite fingerprint." } - } answers { callOriginal() } - - val a = gettingFirstMethodOrNull { true } + assertNull(composite(fail = true).methodOrNull) { + "Expected to not find a method matching the composite fingerprint." + } + } + } + @Test + fun `matches fingerprint`() { val fingerprint = fingerprint { returns("V") } val fingerprint2 = fingerprint { returns("V") } val fingerprint3 = fingerprint { returns("V") } - val composite = firstMethodComposite { - instructions { - head { opcode == Opcode.CONST_STRING } - add { opcode == Opcode.IPUT_OBJECT } - } - } - - val patches = setOf( - bytecodePatch { - execute { - fingerprint.match(classDefs.first().methods.first()) - fingerprint2.match(classDefs.first()) - fingerprint3.originalClassDef - composite.method - } - }, - ) - - patches() - - with(patcher.context.bytecodeContext) - { + with(patcher.context.bytecodeContext) { assertAll( "Expected fingerprints to match.", - { assertNotNull(fingerprint.originalClassDefOrNull) }, - { assertNotNull(fingerprint2.originalClassDefOrNull) }, + { assertNotNull(fingerprint.matchOrNull(this.classDefs.first().methods.first())) }, + { assertNotNull(fingerprint2.matchOrNull(this.classDefs.first())) }, { assertNotNull(fingerprint3.originalClassDefOrNull) }, - { assertEquals("method", composite.method.name) }, ) } } private operator fun Set>.invoke(): List { - every { patcher.context.executablePatches } returns toMutableSet() - every { patcher.context.bytecodeContext.lookupMaps } returns with(patcher.context.bytecodeContext) { LookupMaps() } - every { with(patcher.context.bytecodeContext) { mergeExtension(any()) } } just runs + // TODO: Ideally most of this mocking could be moved to setUp, + // but by doing so the mocking breaks and it is not clear why. + + every { patcherContext.executablePatches } returns toMutableSet() return runBlocking { patcher().toList().also { results -> diff --git a/src/test/kotlin/app/revanced/patcher/patch/PatchLoaderTest.kt b/core/src/jvmTest/kotlin/app/revanced/patcher/patch/PatchLoaderTest.kt similarity index 52% rename from src/test/kotlin/app/revanced/patcher/patch/PatchLoaderTest.kt rename to core/src/jvmTest/kotlin/app/revanced/patcher/patch/PatchLoaderTest.kt index 8f90fef..fd79b00 100644 --- a/src/test/kotlin/app/revanced/patcher/patch/PatchLoaderTest.kt +++ b/core/src/jvmTest/kotlin/app/revanced/patcher/patch/PatchLoaderTest.kt @@ -2,6 +2,7 @@ package app.revanced.patcher.patch +import io.mockk.mockk import org.junit.jupiter.api.Test import java.io.File import kotlin.reflect.KFunction @@ -47,44 +48,23 @@ private fun privateNamedPatchFunction() = privatePatch // endregion internal object PatchLoaderTest { - private const val LOAD_PATCHES_FUNCTION_NAME = "loadPatches" private val TEST_PATCHES_CLASS = ::publicPatch.javaField!!.declaringClass.name private val TEST_PATCHES_CLASS_LOADER = ::publicPatch.javaClass.classLoader @Test fun `loads patches correctly`() { - // Get instance of private PatchLoader.Companion class. - val patchLoaderCompanionObject = getPrivateFieldByType( - PatchLoader::class.java, - PatchLoader::class.companionObject!!.javaObjectType, + val patches = loadPatches( + setOf(mockk()), + { listOf(TEST_PATCHES_CLASS) }, + TEST_PATCHES_CLASS_LOADER ) - // Get private PatchLoader.Companion.loadPatches function from PatchLoader.Companion. - @Suppress("UNCHECKED_CAST") - val loadPatchesFunction = getPrivateFunctionByName( - patchLoaderCompanionObject, - LOAD_PATCHES_FUNCTION_NAME, - ) as KFunction>>> - - // Call private PatchLoader.Companion.loadPatches function. - val patches = loadPatchesFunction.call( - patchLoaderCompanionObject, - TEST_PATCHES_CLASS_LOADER, - mapOf(File("patchesFile") to setOf(TEST_PATCHES_CLASS)), - ).values.first() - assertEquals( 2, patches.size, "Expected 2 patches to be loaded, " + - "because there's only two named patches declared as public static fields " + - "or returned by public static and non-parametrized methods.", + "because there's only two named patches declared as public static fields " + + "or returned by public static and non-parametrized methods.", ) } - - private fun getPrivateFieldByType(cls: Class<*>, fieldType: Class<*>) = - cls.declaredFields.first { it.type == fieldType }.apply { isAccessible = true }.get(null) - - private fun getPrivateFunctionByName(obj: Any, @Suppress("SameParameterValue") methodName: String) = - obj::class.declaredFunctions.first { it.name == methodName }.apply { isAccessible = true } } diff --git a/src/test/kotlin/app/revanced/patcher/patch/PatchTest.kt b/core/src/jvmTest/kotlin/app/revanced/patcher/patch/PatchTest.kt similarity index 100% rename from src/test/kotlin/app/revanced/patcher/patch/PatchTest.kt rename to core/src/jvmTest/kotlin/app/revanced/patcher/patch/PatchTest.kt diff --git a/src/test/kotlin/app/revanced/patcher/patch/options/OptionsTest.kt b/core/src/jvmTest/kotlin/app/revanced/patcher/patch/options/OptionsTest.kt similarity index 100% rename from src/test/kotlin/app/revanced/patcher/patch/options/OptionsTest.kt rename to core/src/jvmTest/kotlin/app/revanced/patcher/patch/options/OptionsTest.kt diff --git a/src/test/kotlin/app/revanced/patcher/util/SmaliTest.kt b/core/src/jvmTest/kotlin/app/revanced/patcher/util/SmaliTest.kt similarity index 97% rename from src/test/kotlin/app/revanced/patcher/util/SmaliTest.kt rename to core/src/jvmTest/kotlin/app/revanced/patcher/util/SmaliTest.kt index acd88f0..41dfd5d 100644 --- a/src/test/kotlin/app/revanced/patcher/util/SmaliTest.kt +++ b/core/src/jvmTest/kotlin/app/revanced/patcher/util/SmaliTest.kt @@ -1,6 +1,6 @@ package app.revanced.patcher.util -import app.revanced.patcher.dex.mutable.MutableMethod.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import app.revanced.patcher.extensions.* import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode diff --git a/gradle.properties b/gradle.properties index 4ef4a41..3732b5a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,11 @@ -org.gradle.parallel = true -org.gradle.caching = true -version = 22.0.0 +version = 22.0.0-local +#Kotlin +kotlin.code.style=official +kotlin.daemon.jvmargs=-Xmx3072M +#Gradle +org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M" +org.gradle.caching=true +org.gradle.configuration-cache=true +#Android +android.nonTransitiveRClass=true +android.useAndroidX=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 93e58e4..4f6dfaf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,8 +1,10 @@ + [versions] -android = "4.1.1.4" -apktool-lib = "2.10.1.1" -binary-compatibility-validator = "0.18.1" +agp = "8.12.3" +android-compileSdk = "36" +android-minSdk = "26" kotlin = "2.2.21" +apktool-lib = "2.10.1.1" kotlinx-coroutines-core = "1.10.2" mockk = "1.14.6" multidexlib2 = "3.0.3.r3" @@ -10,9 +12,9 @@ multidexlib2 = "3.0.3.r3" #noinspection GradleDependency smali = "3.0.9" xpp3 = "1.1.4c" +vanniktechMavenPublish = "0.35.0" [libraries] -android = { module = "com.google.android:android", version.ref = "android" } apktool-lib = { module = "app.revanced:apktool-lib", version.ref = "apktool-lib" } kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" } @@ -23,5 +25,6 @@ smali = { module = "com.android.tools.smali:smali", version.ref = "smali" } xpp3 = { module = "xpp3:xpp3", version.ref = "xpp3" } [plugins] -binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" } -kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" } +kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +vanniktech-mavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "vanniktechMavenPublish" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7c4586c843d1d3e9090525f1898cde..f8e1ee3125fe0768e9a76ee977ac089eb657005e 100644 GIT binary patch delta 37546 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 ViWOqhpbE9Pgm@VkPRs$7QUEQ2q;UWM diff --git a/gradlew b/gradlew index f5feea6..adff685 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a21..c4bdd3a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle.kts b/settings.gradle.kts index b4d1a12..9fe0d61 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1 +1,24 @@ rootProject.name = "revanced-patcher" +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + +pluginManagement { + repositories { + mavenCentral() + google() + } +} + +dependencyResolutionManagement { + repositories { + mavenCentral() + google() + maven { + name = "githubPackages" + // A repository must be specified for some reason. "registry" is a dummy. + url = uri("https://maven.pkg.github.com/revanced/registry") + credentials(PasswordCredentials::class) + } + } +} + +include(":core") diff --git a/src/main/kotlin/app/revanced/patcher/Fingerprint.kt b/src/main/kotlin/app/revanced/patcher/Fingerprint.kt deleted file mode 100644 index dae502c..0000000 --- a/src/main/kotlin/app/revanced/patcher/Fingerprint.kt +++ /dev/null @@ -1,784 +0,0 @@ -@file:Suppress("unused", "MemberVisibilityCanBePrivate") - -package app.revanced.patcher - -import app.revanced.patcher.InstructionLocation.* -import app.revanced.patcher.Match.PatternMatch -import app.revanced.patcher.Matcher.MatchContext -import app.revanced.patcher.extensions.getInstruction -import app.revanced.patcher.extensions.instructionsOrNull -import app.revanced.patcher.extensions.opcode -import app.revanced.patcher.extensions.string -import app.revanced.patcher.extensions.stringReference -import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.patch.PatchException -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.ClassDef -import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.iface.instruction.Instruction -import com.android.tools.smali.dexlib2.util.MethodUtil - -/** - * A fingerprint for a method. A fingerprint is a partial description of a method. - * It is used to uniquely match a method by its characteristics. - * - * An example fingerprint for a public method that takes a single string parameter and returns void: - * ``` - * fingerprint { - * accessFlags(AccessFlags.PUBLIC) - * returns("V") - * parameters("Ljava/lang/String;") - * } - * ``` - * - * @param accessFlags The exact access flags using values of [AccessFlags]. - * @param returnType The return type. Compared using [String.startsWith]. - * @param parameters The parameters. Partial matches allowed and follow the same rules as [returnType]. - * @param filters A list of filters to match, declared in the same order the instructions appear in the method. - * @param strings A list of the strings that appear anywhere in the method. Compared using [String.contains]. - * @param custom A custom condition for this fingerprint. - */ -class Fingerprint internal constructor( - internal val accessFlags: Int?, - internal val returnType: String?, - internal val parameters: List?, - internal val filters: List?, - @Deprecated("Instead use instruction filters") - internal val strings: List?, - internal val custom: ((method: Method, classDef: ClassDef) -> Boolean)?, -) { - // Backing field needed for lazy initialization. - private var _matchOrNull: Match? = null - - /** - * Clears the current match, forcing this fingerprint to resolve again. - * This method should only be used if this fingerprint is re-used after it's modified, - * and the prior match indexes are no longer correct. - */ - fun clearMatch() { - _matchOrNull = null - } - - /** - * The match for this [Fingerprint], or `null` if no matches exist. - */ - context(context: BytecodePatchContext) - fun matchOrNull(): Match? { - if (_matchOrNull != null) return _matchOrNull - - var stringMatches: List? = null - - val matchIndices = indexedMatcher() - - // This line is needed, because the method must be passed by reference to "matchIndices". - // Referencing the method directly would "hardcode" it in the cached pattern by value. - // By using this variable, the reference can be updated for each method. - lateinit var currentMethod: Method - - context(_: MatchContext) - fun Method.match(): Boolean { - if (this@Fingerprint.accessFlags != null && this@Fingerprint.accessFlags != accessFlags) - return false - - if (this@Fingerprint.returnType != null && !returnType.startsWith(this@Fingerprint.returnType)) - return false - - if (this@Fingerprint.parameters != null && !parametersStartsWith( - parameterTypes, - this@Fingerprint.parameters - ) - ) - return false - - if (custom != null && !custom(this, context.lookupMaps.classDefsByType[definingClass]!!)) - return false - - stringMatches = if (strings != null) { - val instructions = instructionsOrNull ?: return false - var stringsList: MutableList? = null - - buildList { - instructions.forEachIndexed { instructionIndex, instruction -> - if (stringsList == null) stringsList = strings.toMutableList() - - val string = instruction.stringReference?.string ?: return@forEachIndexed - val index = stringsList.indexOfFirst(string::contains) - if (index < 0) return@forEachIndexed - - add(Match.StringMatch(string, instructionIndex)) - stringsList.removeAt(index) - } - - if (stringsList == null || stringsList.isNotEmpty()) return false - } - - } else null - - currentMethod = this - return filters == null || matchIndices(instructionsOrNull ?: return false) { - filters.forEach { filter -> - val filterMatches: Instruction.() -> Boolean = { filter.matches(currentMethod, this) } - - when (val location = filter.location) { - is MatchAfterImmediately -> after { filterMatches() } - is MatchAfterWithin -> after(1..location.matchDistance) { filterMatches() } - is MatchAfterAnywhere -> add { filterMatches() } - is MatchAfterAtLeast -> after(location.minimumDistanceFromLastInstruction..Int.MAX_VALUE) { filterMatches() } - is MatchAfterRange -> after(location.minimumDistanceFromLastInstruction..location.maximumDistanceFromLastInstruction) { filterMatches() } - is MatchFirst -> head { filterMatches() } - } - } - } - } - - val allStrings = buildList { - if (filters != null) addAll( - (filters.filterIsInstance() + filters.filterIsInstance().flatMap { - it.filters.filterIsInstance() - }) - ) - }.map { it.stringValue } + (strings ?: emptyList()) - - val method = if (allStrings.isNotEmpty()) { - context.firstMethodOrNull(strings = allStrings.toTypedArray()) { match() } - ?: context(MatchContext()) { context.lookupMaps.methodsWithString.firstOrNull { it.match() } } - } else { - context.firstMethodOrNull { match() } - } ?: return null - - val instructionMatches = filters?.withIndex()?.map { (i, filter) -> - val matchIndex = matchIndices.indices[i] - - Match.InstructionMatch(filter, matchIndex, method.getInstruction(matchIndex)) - } - - _matchOrNull = Match( - context, - context.lookupMaps.classDefsByType[method.definingClass]!!, - method, - instructionMatches, - stringMatches, - ) - - return _matchOrNull - } - - /** - * Match using a [ClassDef]. - * - * @param classDef The class to match against. - * @return The [Match] if a match was found or if the - * fingerprint is already matched to a method, null otherwise. - */ - context(_: BytecodePatchContext) - fun matchOrNull( - classDef: ClassDef, - ): Match? { - if (_matchOrNull != null) return _matchOrNull - - for (method in classDef.methods) { - val match = matchOrNull(classDef, method) - if (match != null) { - _matchOrNull = match - return match - } - } - - return null - } - - /** - * Match using a [Method]. - * The class is retrieved from the method. - * - * @param method The method to match against. - * @return The [Match] if a match was found or if the fingerprint is previously matched to a method, - * otherwise `null`. - */ - context(context: BytecodePatchContext) - fun matchOrNull( - method: Method, - ): Match? { - if (_matchOrNull != null) return _matchOrNull - - return matchOrNull(context.lookupMaps.classDefsByType[method.definingClass]!!, method) - } - - /** - * Match using a [Method]. - * - * @param method The method to match against. - * @param classDef The class the method is a member of. - * @return The [Match] if a match was found or if the fingerprint is previously matched to a method, - * otherwise `null`. - */ - context(context: BytecodePatchContext) - fun matchOrNull( - classDef: ClassDef, - method: Method, - ): Match? { - if (_matchOrNull != null) return _matchOrNull - - var stringMatches: List? = null - - val matchIndices = indexedMatcher() - - context(_: MatchContext) - fun Method.match(): Boolean { - if (this@Fingerprint.accessFlags != null && this@Fingerprint.accessFlags != accessFlags) - return false - - if (this@Fingerprint.returnType != null && !returnType.startsWith(this@Fingerprint.returnType)) - return false - - if (this@Fingerprint.parameters != null && !parametersStartsWith( - parameterTypes, - this@Fingerprint.parameters - ) - ) - return false - - if (custom != null && !custom(this, classDef)) - return false - - stringMatches = if (strings != null) { - val instructions = instructionsOrNull ?: return false - var stringsList: MutableList? = null - - buildList { - instructions.forEachIndexed { instructionIndex, instruction -> - if (stringsList == null) stringsList = strings.toMutableList() - - val string = instruction.stringReference?.string ?: return@forEachIndexed - val index = stringsList.indexOfFirst(string::contains) - if (index < 0) return@forEachIndexed - - add(Match.StringMatch(string, instructionIndex)) - stringsList.removeAt(index) - } - - if (stringsList == null || stringsList.isNotEmpty()) return false - } - - } else null - - return filters == null || matchIndices(instructionsOrNull ?: return false) { - filters.forEach { filter -> - val filterMatches: Instruction.() -> Boolean = { filter.matches(method, this) } - - when (val location = filter.location) { - is MatchAfterImmediately -> after { filterMatches() } - is MatchAfterWithin -> after(1..location.matchDistance) { filterMatches() } - is MatchAfterAnywhere -> add { filterMatches() } - is MatchAfterAtLeast -> after(location.minimumDistanceFromLastInstruction..Int.MAX_VALUE) { filterMatches() } - is MatchAfterRange -> after(location.minimumDistanceFromLastInstruction..location.maximumDistanceFromLastInstruction) { filterMatches() } - is MatchFirst -> head { filterMatches() } - } - } - } - } - - if (!context(MatchContext()) { method.match() }) return null - val instructionMatches = filters?.withIndex()?.map { (i, filter) -> - val matchIndex = matchIndices.indices[i] - Match.InstructionMatch(filter, matchIndex, method.getInstruction(matchIndex)) - } - - _matchOrNull = Match( - context, - context.lookupMaps.classDefsByType[method.definingClass]!!, - method, - instructionMatches, - stringMatches, - ) - - return _matchOrNull - } - - fun patchException() = PatchException("Failed to match the fingerprint: $this") - - /** - * The match for this [Fingerprint]. - * - * @return The [Match] of this fingerprint. - * @throws PatchException If the [Fingerprint] failed to match. - */ - context(_: BytecodePatchContext) - fun match() = matchOrNull() ?: throw patchException() - - /** - * Match using a [ClassDef]. - * - * @param classDef The class to match against. - * @return The [Match] of this fingerprint. - * @throws PatchException If the fingerprint failed to match. - */ - context(_: BytecodePatchContext) - fun match( - classDef: ClassDef, - ) = matchOrNull(classDef) ?: throw patchException() - - /** - * Match using a [Method]. - * The class is retrieved from the method. - * - * @param method The method to match against. - * @return The [Match] of this fingerprint. - * @throws PatchException If the fingerprint failed to match. - */ - context(_: BytecodePatchContext) - fun match( - method: Method, - ) = matchOrNull(method) ?: throw patchException() - - /** - * Match using a [Method]. - * - * @param method The method to match against. - * @param classDef The class the method is a member of. - * @return The [Match] of this fingerprint. - * @throws PatchException If the fingerprint failed to match. - */ - context(_: BytecodePatchContext) - fun match( - method: Method, - classDef: ClassDef, - ) = matchOrNull(classDef, method) ?: throw patchException() - - /** - * The class the matching method is a member of, or null if this fingerprint did not match. - */ - context(_: BytecodePatchContext) - val originalClassDefOrNull - get() = matchOrNull()?.originalClassDef - - /** - * The matching method, or null of this fingerprint did not match. - */ - context(_: BytecodePatchContext) - val originalMethodOrNull - get() = matchOrNull()?.originalMethod - - /** - * The mutable version of [originalClassDefOrNull]. - * - * Accessing this property allocates a new mutable instance. - * Use [originalClassDefOrNull] if mutable access is not required. - */ - context(_: BytecodePatchContext) - val classDefOrNull - get() = matchOrNull()?.classDef - - /** - * The mutable version of [originalMethodOrNull]. - * - * Accessing this property allocates a new mutable instance. - * Use [originalMethodOrNull] if mutable access is not required. - */ - context(_: BytecodePatchContext) - val methodOrNull - get() = matchOrNull()?.method - - /** - * The match for the opcode pattern, or null if this fingerprint did not match. - */ - context(_: BytecodePatchContext) - @Deprecated("instead use instructionMatchesOrNull") - val patternMatchOrNull: PatternMatch? - get() { - val match = this.matchOrNull() - if (match == null || match.instructionMatchesOrNull == null) { - return null - } - return match.patternMatch - } - - /** - * The match for the instruction filters, or null if this fingerprint did not match. - */ - context(_: BytecodePatchContext) - val instructionMatchesOrNull - get() = matchOrNull()?.instructionMatchesOrNull - - /** - * The matches for the strings, or null if this fingerprint did not match. - * - * This does not give matches for strings declared using [string] instruction filters. - */ - context(_: BytecodePatchContext) - @Deprecated("Instead use string instructions and `instructionMatchesOrNull()`") - val stringMatchesOrNull - get() = matchOrNull()?.stringMatchesOrNull - - /** - * The class the matching method is a member of. - * - * @throws PatchException If the fingerprint has not been matched. - */ - context(_: BytecodePatchContext) - val originalClassDef - get() = match().originalClassDef - - /** - * The matching method. - * - * @throws PatchException If the fingerprint has not been matched. - */ - context(_: BytecodePatchContext) - val originalMethod - get() = match().originalMethod - - /** - * The mutable version of [originalClassDef]. - * - * Accessing this property allocates a new mutable instance. - * Use [originalClassDef] if mutable access is not required. - * - * @throws PatchException If the fingerprint has not been matched. - */ - context(_: BytecodePatchContext) - val classDef - get() = match().classDef - - /** - * The mutable version of [originalMethod]. - * - * Accessing this property allocates a new mutable instance. - * Use [originalMethod] if mutable access is not required. - * - * @throws PatchException If the fingerprint has not been matched. - */ - context(_: BytecodePatchContext) - val method - get() = match().method - - /** - * The match for the opcode pattern. - * - * @throws PatchException If the fingerprint has not been matched. - */ - context(_: BytecodePatchContext) - @Deprecated("Instead use instructionMatch") - val patternMatch - get() = match().patternMatch - - /** - * Instruction filter matches. - * - * @throws PatchException If the fingerprint has not been matched. - */ - context(_: BytecodePatchContext) - val instructionMatches - get() = match().instructionMatches - - /** - * The matches for the strings declared using `strings()`. - * This does not give matches for strings declared using [string] instruction filters. - * - * @throws PatchException If the fingerprint has not been matched. - */ - context(_: BytecodePatchContext) - @Deprecated("Instead use string instructions and `instructionMatches()`") - val stringMatches - get() = match().stringMatches -} - -/** - * A match of a [Fingerprint]. - * - * @param originalClassDef The class the matching method is a member of. - * @param originalMethod The matching method. - * @param _instructionMatches The match for the instruction filters. - * @param _stringMatches The matches for the strings declared using `strings()`. - */ -class Match internal constructor( - val context: BytecodePatchContext, - val originalClassDef: ClassDef, - val originalMethod: Method, - private val _instructionMatches: List?, - private val _stringMatches: List?, -) { - /** - * The mutable version of [originalClassDef]. - * - * Accessing this property allocates a new mutable instance. - * Use [originalClassDef] if mutable access is not required. - */ - val classDef by lazy { with(context) { originalClassDef.mutable() } } - - /** - * The mutable version of [originalMethod]. - * - * Accessing this property allocates a new mutable instance. - * Use [originalMethod] if mutable access is not required. - */ - val method by lazy { classDef.methods.first { MethodUtil.methodSignaturesMatch(it, originalMethod) } } - - @Deprecated("Instead use instructionMatches", ReplaceWith("instructionMatches")) - val patternMatch by lazy { - if (_instructionMatches == null) throw PatchException("Did not match $this") - @SuppressWarnings("deprecation") - PatternMatch(_instructionMatches.first().index, _instructionMatches.last().index) - } - - val instructionMatches - get() = _instructionMatches ?: throw PatchException("Fingerprint declared no instruction filters") - val instructionMatchesOrNull = _instructionMatches - - @Deprecated("Instead use string instructions and `instructionMatches()`") - val stringMatches - get() = _stringMatches ?: throw PatchException("Fingerprint declared no strings") - - @Deprecated("Instead use string instructions and `instructionMatchesOrNull()`") - val stringMatchesOrNull = _stringMatches - - /** - * A match for an opcode pattern. - * @param startIndex The index of the first opcode of the pattern in the method. - * @param endIndex The index of the last opcode of the pattern in the method. - */ - @Deprecated("Instead use InstructionMatch") - class PatternMatch internal constructor( - val startIndex: Int, - val endIndex: Int, - ) - - /** - * A match for a string. - * - * @param string The string that matched. - * @param index The index of the instruction in the method. - */ - @Deprecated("Instead use string instructions and `InstructionMatch`") - class StringMatch internal constructor(val string: String, val index: Int) - - /** - * A match for a [InstructionFilter]. - * @param filter The filter that matched - * @param index The instruction index it matched with. - * @param instruction The instruction that matched. - */ - class InstructionMatch internal constructor( - val filter: InstructionFilter, - val index: Int, - val instruction: Instruction - ) { - @Suppress("UNCHECKED_CAST") - fun getInstruction(): T = instruction as T - } -} - -/** - * A builder for [Fingerprint]. - * - * @property accessFlags The exact access flags using values of [AccessFlags]. - * @property returnType The return type compared using [String.startsWith]. - * @property parameters The parameters of the method. Partial matches allowed and follow the same rules as [returnType]. - * @property instructionFilters Filters to match the method instructions. - * @property strings A list of the strings compared each using [String.contains]. - * @property customBlock A custom condition for this fingerprint. - * - * @constructor Create a new [FingerprintBuilder]. - */ -class FingerprintBuilder() { - private var accessFlags: Int? = null - private var returnType: String? = null - private var parameters: List? = null - private var instructionFilters: List? = null - private var strings: List? = null - private var customBlock: ((method: Method, classDef: ClassDef) -> Boolean)? = null - - /** - * Set the access flags. - * - * @param accessFlags The exact access flags using values of [AccessFlags]. - */ - fun accessFlags(accessFlags: Int) { - this.accessFlags = accessFlags - } - - /** - * Set the access flags. - * - * @param accessFlags The exact access flags using values of [AccessFlags]. - */ - fun accessFlags(vararg accessFlags: AccessFlags) { - this.accessFlags = accessFlags.fold(0) { acc, it -> acc or it.value } - } - - /** - * Set the return type. - * - * If [accessFlags] includes [AccessFlags.CONSTRUCTOR], then there is no need to - * set a return type set since constructors are always void return type. - * - * @param returnType The return type compared using [String.startsWith]. - */ - fun returns(returnType: String) { - this.returnType = returnType - } - - /** - * Set the parameters. - * - * @param parameters The parameters of the method. - * Partial matches allowed and follow the same rules as [returnType]. - */ - fun parameters(vararg parameters: String) { - this.parameters = parameters.toList() - } - - private fun verifyNoFiltersSet() { - if (this.instructionFilters != null) { - throw PatchException("Instruction filters already set") - } - } - - /** - * A pattern of opcodes, where each opcode must appear immediately after the previous. - * - * To use opcodes with other [InstructionFilter] objects, - * instead use [instructions] with individual opcodes declared using [opcode]. - * - * This method is identical to declaring individual opcode filters - * with [InstructionFilter.location] set to [InstructionLocation.MatchAfterImmediately] - * for all but the first opcode. - * - * Unless absolutely necessary, it is recommended to instead use [instructions] - * with more fine grained filters. - * - * ``` - * opcodes( - * Opcode.INVOKE_VIRTUAL, // First opcode matches anywhere in the method. - * Opcode.MOVE_RESULT_OBJECT, // Must match exactly after INVOKE_VIRTUAL. - * Opcode.IPUT_OBJECT // Must match exactly after MOVE_RESULT_OBJECT. - * ) - * ``` - * is identical to: - * ``` - * instructions( - * opcode(Opcode.INVOKE_VIRTUAL), // First opcode matches anywhere in the method. - * opcode(Opcode.MOVE_RESULT_OBJECT, maxAfter = 0), // Must match exactly after INVOKE_VIRTUAL. - * opcode(Opcode.IPUT_OBJECT, maxAfter = 0) // Must match exactly after MOVE_RESULT_OBJECT. - * ) - * ``` - * - * @param opcodes An opcode pattern of instructions. - * Wildcard or unknown opcodes can be specified by `null`. - */ - fun opcodes(vararg opcodes: Opcode?) { - verifyNoFiltersSet() - if (opcodes.isEmpty()) throw IllegalArgumentException("One or more opcodes is required") - - this.instructionFilters = OpcodesFilter.listOfOpcodes(opcodes.toList()) - } - - /** - * A pattern of opcodes from SMALI formatted text, - * where each opcode must appear immediately after the previous opcode. - * - * Unless absolutely necessary, it is recommended to instead use [instructions]. - * - * @param instructions A list of instructions or opcode names in SMALI format. - * - Wildcard or unknown opcodes can be specified by `null`. - * - Empty lines are ignored. - * - Each instruction must be on a new line. - * - The opcode name is enough, no need to specify the operands. - * - * @throws Exception If an unknown opcode is used. - */ - fun opcodes(instructions: String) { - verifyNoFiltersSet() - if (instructions.isBlank()) throw IllegalArgumentException("No instructions declared (empty string)") - - this.instructionFilters = OpcodesFilter.listOfOpcodes( - instructions.trimIndent().split("\n").filter { - it.isNotBlank() - }.map { - // Remove any operands. - val name = it.split(" ", limit = 1).first().trim() - if (name == "null") return@map null - - opcodesByName[name] ?: throw IllegalArgumentException("Unknown opcode: $name") - } - ) - } - - /** - * A list of instruction filters to match. - */ - fun instructions(vararg instructionFilters: InstructionFilter) { - verifyNoFiltersSet() - if (instructionFilters.isEmpty()) throw IllegalArgumentException("One or more instructions is required") - - this.instructionFilters = instructionFilters.toList() - } - - /** - * Set the strings. - * - * @param strings A list of strings compared each using [String.contains]. - */ - @Deprecated("Instead use `instruction()` filters and `string()` instruction declarations") - fun strings(vararg strings: String) { - this.strings = strings.toList() - } - - /** - * Set a custom condition for this fingerprint. - * - * @param customBlock A custom condition for this fingerprint. - */ - fun custom(customBlock: (method: Method, classDef: ClassDef) -> Boolean) { - this.customBlock = customBlock - } - - fun build(): Fingerprint { - // If access flags include constructor then - // skip the return type check since it's always void. - if (returnType?.equals("V") == true && accessFlags != null - && AccessFlags.CONSTRUCTOR.isSet(accessFlags!!) - ) { - returnType = null - } - - return Fingerprint( - accessFlags, - returnType, - parameters, - instructionFilters, - strings, - customBlock, - ) - } - - - private companion object { - val opcodesByName = Opcode.entries.associateBy { it.name } - } -} - -fun fingerprint( - block: FingerprintBuilder.() -> Unit, -) = FingerprintBuilder().apply(block).build() - -/** - * Matches two lists of parameters, where the first parameter list - * starts with the values of the second list. - */ -internal fun parametersStartsWith( - targetMethodParameters: Iterable, - fingerprintParameters: Iterable, -): Boolean { - if (fingerprintParameters.count() != targetMethodParameters.count()) return false - val fingerprintIterator = fingerprintParameters.iterator() - - targetMethodParameters.forEach { - if (!it.startsWith(fingerprintIterator.next())) return false - } - - return true -} - - diff --git a/src/main/kotlin/app/revanced/patcher/InstructionFilter.kt b/src/main/kotlin/app/revanced/patcher/InstructionFilter.kt deleted file mode 100644 index e54bd12..0000000 --- a/src/main/kotlin/app/revanced/patcher/InstructionFilter.kt +++ /dev/null @@ -1,1075 +0,0 @@ -package app.revanced.patcher - -import app.revanced.patcher.FieldAccessFilter.Companion.parseJvmFieldAccess -import app.revanced.patcher.MethodCallFilter.Companion.parseJvmMethodCall -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.Method -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.instruction.WideLiteralInstruction -import com.android.tools.smali.dexlib2.iface.reference.FieldReference -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 java.util.* - -/** - * Simple interface to control how much space is allowed between a previous - * [InstructionFilter] match and the current [InstructionFilter]. - */ -fun interface InstructionLocation { - /** - * @param previouslyMatchedIndex The previously matched index, or -1 if this is the first filter. - * @param currentIndex The current method index that is about to be checked. - */ - fun indexIsValidForMatching(previouslyMatchedIndex: Int, currentIndex: Int) : Boolean - - /** - * Matching can occur anywhere after the previous instruction filter match index. - * Is the default behavior for all filters. - */ - class MatchAfterAnywhere : InstructionLocation { - override fun indexIsValidForMatching(previouslyMatchedIndex: Int, currentIndex: Int) = true - } - - /** - * Matches the first instruction of a method. - * - * This can only be used for the first filter, and using with any other filter will throw an exception. - */ - class MatchFirst() : InstructionLocation { - override fun indexIsValidForMatching(previouslyMatchedIndex: Int, currentIndex: Int) : Boolean { - require(previouslyMatchedIndex < 0) { - "MatchFirst can only be used for the first instruction filter" - } - return true - } - } - - /** - * Instruction index immediately after the previous filter. - * - * Useful for opcodes that must always appear immediately after the last filter such as: - * - [Opcode.MOVE_RESULT] - * - [Opcode.MOVE_RESULT_WIDE] - * - [Opcode.MOVE_RESULT_OBJECT] - * - * This cannot be used for the first filter and will throw an exception. - */ - class MatchAfterImmediately() : InstructionLocation { - override fun indexIsValidForMatching(previouslyMatchedIndex: Int, currentIndex: Int) : Boolean { - require(previouslyMatchedIndex >= 0) { - "MatchAfterImmediately cannot be used for the first instruction filter" - } - return currentIndex - 1 == previouslyMatchedIndex - } - } - - /** - * Instruction index can occur within a range of the previous instruction filter match index. - * used to constrain instruction matching to a region after the previous instruction filter. - * - * This cannot be used for the first filter and will throw an exception. - * - * @param matchDistance The number of unmatched instructions that can exist between the - * current instruction filter and the previously matched instruction filter. - * A value of 0 means the current filter can only match immediately after - * the previously matched instruction (making this functionally identical to - * [MatchAfterImmediately]). A value of 10 means between 0 and 10 unmatched - * instructions can exist between the previously matched instruction and - * the current instruction filter. - */ - class MatchAfterWithin(val matchDistance: Int) : InstructionLocation { - init { - require(matchDistance >= 0) { - "matchDistance must be non-negative" - } - } - - override fun indexIsValidForMatching(previouslyMatchedIndex: Int, currentIndex: Int) : Boolean { - require(previouslyMatchedIndex >= 0) { - "MatchAfterImmediately cannot be used for the first instruction filter" - } - return currentIndex - previouslyMatchedIndex - 1 <= matchDistance - } - } - - /** - * Instruction index can occur only after a minimum number of unmatched instructions from the - * previous instruction match. Or if this is used with the first filter of a fingerprint then - * this can only match starting from a given instruction index. - * - * @param minimumDistanceFromLastInstruction The minimum number of unmatched instructions that - * must exist between this instruction and the last matched instruction. A value of 0 is - * functionally identical to [MatchAfterImmediately]. - */ - class MatchAfterAtLeast(var minimumDistanceFromLastInstruction: Int) : InstructionLocation { - init { - require(minimumDistanceFromLastInstruction >= 0) { - "minimumDistanceFromLastInstruction must >= 0" - } - } - - override fun indexIsValidForMatching(previouslyMatchedIndex: Int, currentIndex: Int) : Boolean { - return currentIndex - previouslyMatchedIndex - 1 >= minimumDistanceFromLastInstruction - } - } - - /** - * Functionally combines both [MatchAfterAtLeast] and [MatchAfterWithin] to give a bounded range - * where the next instruction must match relative to the previous matched instruction. - * - * Unlike [MatchAfterImmediately] or [MatchAfterWithin], this can be used for the first filter - * to constrain matching to a specific range starting from index 0. - * - * @param minimumDistanceFromLastInstruction The minimum number of unmatched instructions that - * must exist between this instruction and the last - * matched instruction. - * @param maximumDistanceFromLastInstruction The maximum number of unmatched instructions - * that can exist between this instruction and the - * last matched instruction. - */ - class MatchAfterRange( - val minimumDistanceFromLastInstruction: Int, - val maximumDistanceFromLastInstruction: Int - ) : InstructionLocation { - - private val minMatcher = MatchAfterAtLeast(minimumDistanceFromLastInstruction) - private val maxMatcher = MatchAfterWithin(maximumDistanceFromLastInstruction) - - init { - require(minimumDistanceFromLastInstruction <= maximumDistanceFromLastInstruction) { - "minimumDistanceFromLastInstruction must be <= maximumDistanceFromLastInstruction" - } - } - - override fun indexIsValidForMatching(previouslyMatchedIndex: Int, currentIndex: Int): Boolean { - // For the first filter, previouslyMatchedIndex will be -1, and both delegates - // will correctly enforce their own semantics starting from index 0. - return minMatcher.indexIsValidForMatching(previouslyMatchedIndex, currentIndex) && - maxMatcher.indexIsValidForMatching(previouslyMatchedIndex, currentIndex) - } - } -} - - - -/** - * String comparison type. - */ -enum class StringComparisonType { - EQUALS, - CONTAINS, - STARTS_WITH, - ENDS_WITH; - - /** - * @param targetString The target string to search - * @param searchString To search for in the target string (or to compare entirely for equality). - */ - fun compare(targetString: String, searchString: String): Boolean { - return when (this) { - EQUALS -> targetString == searchString - CONTAINS -> targetString.contains(searchString) - STARTS_WITH -> targetString.startsWith(searchString) - ENDS_WITH -> targetString.endsWith(searchString) - } - } - - /** - * Throws [IllegalArgumentException] if the class type search string is invalid and can never match. - */ - internal fun validateSearchStringForClassType(classTypeSearchString: String) { - when (this) { - EQUALS -> { - STARTS_WITH.validateSearchStringForClassType(classTypeSearchString) - ENDS_WITH.validateSearchStringForClassType(classTypeSearchString) - } - CONTAINS -> Unit // Nothing to validate, anything goes. - STARTS_WITH -> require(classTypeSearchString.startsWith('L')) { - "Class type does not start with L: $classTypeSearchString" - } - ENDS_WITH -> require(classTypeSearchString.endsWith(';')) { - "Class type does not end with a semicolon: $classTypeSearchString" - } - } - } -} - - - -/** - * Matches method [Instruction] objects, similar to how [Fingerprint] matches entire methods. - * - * The most basic filters match only opcodes and nothing more, - * and more precise filters can match: - * - Field references (get/put opcodes) by name/type. - * - Method calls (invoke_* opcodes) by name/parameter/return type. - * - Object instantiation for specific class types. - * - Literal const values. - * - * If creating a custom filter for unusual or app specific purposes, consider extending - * [OpcodeFilter] or [OpcodesFilter] to reduce boilerplate opcode checking logic. - */ -fun interface InstructionFilter { - - /** - * The [InstructionLocation] associated with this filter. - */ - val location: InstructionLocation - get() = InstructionLocation.MatchAfterAnywhere() - - /** - * If this filter matches the method instruction. - * - * @param enclosingMethod The method of that contains [instruction]. - * @param instruction The instruction to check for a match. - */ - fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean -} - - - -class AnyInstruction internal constructor( - internal val filters: List, - override val location: InstructionLocation -) : InstructionFilter { - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ) : Boolean { - return filters.any { filter -> - filter.matches(enclosingMethod, instruction) - } - } -} - -/** - * Logical OR operator where the first filter that matches satisfies this filter. - * - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun anyInstruction( - vararg filters: InstructionFilter, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = AnyInstruction(filters.asList(), location) - - - -/** - * Single opcode match. - * - * Patches can extend this as desired to do unusual or app specific instruction filtering. - * Or Alternatively can implement [InstructionFilter] directly. - * - * @param opcode Opcode to match. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -open class OpcodeFilter( - val opcode: Opcode, - override val location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) : InstructionFilter { - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean { - return instruction.opcode == opcode - } -} - -/** - * Single opcode match. - * - * @param opcode Opcode to match. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun opcode( - opcode: Opcode, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = OpcodeFilter(opcode, location) - - - -/** - * Matches a single instruction from many kinds of opcodes. - * - * Patches can extend this as desired to do unusual or app specific instruction filtering. - * Or Alternatively can implement [InstructionFilter] directly. - * - * @param opcodes Set of opcodes to match to. Value of `null` will match any opcode. - * If matching only a single opcode then instead use [OpcodeFilter]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -open class OpcodesFilter protected constructor( - val opcodes: EnumSet?, - override val location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) : InstructionFilter { - - protected constructor( - opcodes: List?, - location: InstructionLocation - ) : this(if (opcodes == null) null else EnumSet.copyOf(opcodes), location) - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean { - if (opcodes == null) { - return true // Match anything. - } - return opcodes.contains(instruction.opcode) - } - - internal companion object { - /** - * First opcode can match anywhere in a method, but all - * subsequent opcodes must match after the previous opcode. - * - * A value of `null` indicates to match any opcode. - */ - internal fun listOfOpcodes(opcodes: Collection): List { - val list = ArrayList(opcodes.size) - var location: InstructionLocation? = null - - opcodes.forEach { opcode -> - // First opcode can match anywhere. - val opcodeLocation = location ?: InstructionLocation.MatchAfterAnywhere() - - list += if (opcode == null) { - // Null opcode matches anything. - OpcodesFilter( - null as List?, - opcodeLocation - ) - } else { - OpcodeFilter(opcode, opcodeLocation) - } - - if (location == null) { - location = InstructionLocation.MatchAfterImmediately() - } - } - - return list - } - } -} - - - -class LiteralFilter internal constructor( - val literal: () -> Long, - opcodes: List? = null, - location: InstructionLocation -) : OpcodesFilter(opcodes, location) { - - /** - * Store the lambda value instead of calling it more than once. - */ - internal val literalValue: Long by lazy(literal) - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean { - if (!super.matches(enclosingMethod, instruction)) { - return false - } - - if (instruction !is WideLiteralInstruction) return false - - return instruction.wideLiteral == literalValue - } -} - -/** - * Long literal. Automatically converts literal to opcode hex. - * - * @param literal Literal number. - * @param opcodes Opcodes to match. By default this matches any literal number opcode such as: - * [Opcode.CONST_4], [Opcode.CONST_16], [Opcode.CONST], [Opcode.CONST_WIDE]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun literal( - literal: Long, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = LiteralFilter({ literal }, opcodes, location) - -/** - * Integer literal. Automatically converts literal to opcode hex. - * - * @param literal Literal number. - * @param opcodes Opcodes to match. By default this matches any literal number opcode such as: - * [Opcode.CONST_4], [Opcode.CONST_16], [Opcode.CONST], [Opcode.CONST_WIDE]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun literal( - literal: Int, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = LiteralFilter({ literal.toLong() }, opcodes, location) - -/** - * Double point literal. Automatically converts literal to opcode hex. - * - * @param literal Literal number. - * @param opcodes Opcodes to match. By default this matches any literal number opcode such as: - * [Opcode.CONST_4], [Opcode.CONST_16], [Opcode.CONST], [Opcode.CONST_WIDE]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun literal( - literal: Double, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = LiteralFilter({ literal.toRawBits() }, opcodes, location) - -/** - * Floating point literal. Automatically converts literal to opcode hex. - * - * @param literal Floating point literal. - * @param opcodes Opcodes to match. By default this matches any literal number opcode such as: - * [Opcode.CONST_4], [Opcode.CONST_16], [Opcode.CONST], [Opcode.CONST_WIDE]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun literal( - literal: Float, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = LiteralFilter({ literal.toRawBits().toLong() }, opcodes, location) - -/** - * Literal number value. Automatically converts the provided number to opcode hex. - * - * @param literal Literal number. - * @param opcodes Opcodes to match. By default this matches any literal number opcode such as: - * [Opcode.CONST_4], [Opcode.CONST_16], [Opcode.CONST], [Opcode.CONST_WIDE]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun literal( - literal: () -> Long, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = LiteralFilter(literal, opcodes, location) - - - -class MethodCallFilter internal constructor( - val definingClass: String? = null, - val name: String? = null, - val parameters: List? = null, - val returnType: String? = null, - opcodes: List? = null, - location: InstructionLocation -) : OpcodesFilter(opcodes, location) { - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean { - if (!super.matches(enclosingMethod, instruction)) { - return false - } - - val reference = (instruction as? ReferenceInstruction)?.reference as? MethodReference - ?: return false - - if (definingClass != null) { - val referenceClass = reference.definingClass - - if (!StringComparisonType.ENDS_WITH.compare(referenceClass, definingClass)) { - // Check if 'this' defining class is used. - // Would be nice if this also checked all super classes, - // but doing so requires iteratively checking all superclasses - // up to the root class since class defs are mere Strings. - if (!(definingClass == "this" && referenceClass == enclosingMethod.definingClass)) { - return false - } // else, the method call is for 'this' class. - } - } - - if (name != null && reference.name != name) { - return false - } - - if (returnType != null && - !StringComparisonType.STARTS_WITH.compare(reference.returnType, returnType)) { - return false - } - - if (parameters != null && - !parametersStartsWith(reference.parameterTypes, parameters)) { - return false - } - - return true - } - - internal companion object { - private val regex = Regex("""^(L[^;]+;)->([^(\s]+)\(([^)]*)\)(\[?L[^;]+;|\[?[BCSIJFDZV])${'$'}""") - - internal fun parseJvmMethodCall( - methodSignature: String, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() - ): MethodCallFilter { - val matchResult = regex.matchEntire(methodSignature) - ?: throw IllegalArgumentException("Invalid method signature: $methodSignature") - - val classDescriptor = matchResult.groupValues[1] - val methodName = matchResult.groupValues[2] - val paramDescriptorString = matchResult.groupValues[3] - val returnDescriptor = matchResult.groupValues[4] - - val paramDescriptors = parseParameterDescriptors(paramDescriptorString) - - return MethodCallFilter( - classDescriptor, - methodName, - paramDescriptors, - returnDescriptor, - opcodes, - location - ) - } - - /** - * Parses a single JVM type descriptor or an array descriptor at the current position. - * For example: Lcom/example/SomeClass; or I or [I or [Lcom/example/SomeClass; - */ - private fun parseSingleType(params: String, startIndex: Int): Pair { - var i = startIndex - - // Skip past array declaration, including multi-dimensional arrays. - val paramsLength = params.length - while (i < paramsLength && params[i] == '[') { - i++ - } - - return if (i < paramsLength && params[i] == 'L') { - // It's an object type starting with 'L', read until ';' - val semicolonPos = params.indexOf(';', i) - if (semicolonPos < 0) { - throw IllegalArgumentException("Malformed object descriptor (missing semicolon): $params") - } - // Substring from startIndex up to and including the semicolon. - val typeDescriptor = params.substring(startIndex, semicolonPos + 1) - typeDescriptor to (semicolonPos + 1) - } else { - // It's either a primitive or we've already consumed the array part - // So just take one character (e.g. 'I', 'Z', 'B', etc.) - val typeDescriptor = params.substring(startIndex, i + 1) - typeDescriptor to (i + 1) - } - } - - /** - * Parses the parameters into a list of JVM type descriptors. - */ - private fun parseParameterDescriptors(paramString: String): List { - val result = mutableListOf() - var currentIndex = 0 - val stringLength = paramString.length - - while (currentIndex < stringLength) { - val (type, nextIndex) = parseSingleType(paramString, currentIndex) - result.add(type) - currentIndex = nextIndex - } - - return result - } - } -} - -/** - * Matches a method call, such as: - * `invoke-virtual {v3, v4}, La;->b(I)V` - * - * @param definingClass Defining class of the field call. Compares using [StringComparisonType.ENDS_WITH]. - * For calls to a method in the same class, use 'this' as the defining class. - * Note: 'this' does not work for fields found in superclasses. - * @param name Full name of the method. Compares using [StringComparisonType.EQUALS]. - * @param parameters Parameters of the method call. Each parameter matches using[StringComparisonType.STARTS_WITH] - * and semantics are the same as [Fingerprint] parameters. - * @param returnType Return type. Matches using [StringComparisonType.STARTS_WITH]. - * @param opcodes Opcode types to match. By default this matches any method call opcode: `Opcode.INVOKE_*`. - * If this filter must match specific types of method call, then specify the desired opcodes -such as [Opcode.INVOKE_STATIC], [Opcode.INVOKE_STATIC_RANGE] to match only static calls. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun methodCall( - definingClass: String? = null, - name: String? = null, - parameters: List? = null, - returnType: String? = null, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = MethodCallFilter( - definingClass, - name, - parameters, - returnType, - opcodes, - location -) - -/** - * Matches a method call, such as: - * `invoke-virtual {v3, v4}, La;->b(I)V` - * - * @param definingClass Defining class of the field call. Compares using [StringComparisonType.ENDS_WITH]. - * For calls to a method in the same class, use 'this' as the defining class. - * Note: 'this' does not work for fields found in superclasses. - * @param name Full name of the method. Compares using [StringComparisonType.EQUALS]. - * @param parameters Parameters of the method call. Each parameter matches using[StringComparisonType.STARTS_WITH] - * and semantics are the same as [Fingerprint] parameters. - * @param returnType Return type. Matches using [StringComparisonType.STARTS_WITH]. - * @param opcode Single opcode type to match. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun methodCall( - definingClass: String? = null, - name: String? = null, - parameters: List? = null, - returnType: String? = null, - opcode: Opcode, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = MethodCallFilter( - definingClass, - name, - parameters, - returnType, - listOf(opcode), - location -) - -/** - * Method call for a copy pasted SMALI style method signature. e.g.: - * `Landroid/view/View;->inflate(Landroid/content/Context;ILandroid/view/ViewGroup;)Landroid/view/View;` - * - * Should never be used with obfuscated method names or parameter/return types. - * - * @param smali Smali method call reference, such as - * `Landroid/view/View;->inflate(Landroid/content/Context;ILandroid/view/ViewGroup;)Landroid/view/View;`. - * @param opcodes List of all possible opcodes to match. Defaults to matching all method calls types: `Opcode.INVOKE_*`. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun methodCall( - smali: String, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = parseJvmMethodCall(smali, opcodes, location) - -/** - * Method call for a copy pasted SMALI style method signature. e.g.: - * `Landroid/view/View;->inflate(Landroid/content/Context;ILandroid/view/ViewGroup;)Landroid/view/View;` - * - * Should never be used with obfuscated method names or parameter/return types. - * - * @param smali Smali method call reference, such as - * `Landroid/view/View;->inflate(Landroid/content/Context;ILandroid/view/ViewGroup;)Landroid/view/View;`. - * @param opcode Single opcode type to match. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun methodCall( - smali: String, - opcode: Opcode, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = parseJvmMethodCall(smali, listOf(opcode), location) - - - -class FieldAccessFilter internal constructor( - val definingClass: String? = null, - val name: String? = null, - val type: String? = null, - opcodes: List? = null, - location: InstructionLocation -) : OpcodesFilter(opcodes, location) { - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean { - if (!super.matches(enclosingMethod, instruction)) { - return false - } - - val reference = (instruction as? ReferenceInstruction)?.reference as? FieldReference - ?: return false - - if (definingClass != null) { - val referenceClass = reference.definingClass - - if (!referenceClass.endsWith(definingClass)) { - if (!(definingClass == "this" && referenceClass == enclosingMethod.definingClass)) { - return false - } // else, the method call is for 'this' class. - } - } - - if (name != null && reference.name != name) { - return false - } - - if (type != null && !reference.type.startsWith(type)) { - return false - } - - return true - } - - internal companion object { - private val regex = Regex("""^(L[^;]+;)->([^:]+):(\[?L[^;]+;|\[?[BCSIJFDZV])${'$'}""") - - internal fun parseJvmFieldAccess( - fieldSignature: String, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() - ): FieldAccessFilter { - val matchResult = regex.matchEntire(fieldSignature) - ?: throw IllegalArgumentException("Invalid field access smali: $fieldSignature") - - return fieldAccess( - definingClass = matchResult.groupValues[1], - name = matchResult.groupValues[2], - type = matchResult.groupValues[3], - opcodes = opcodes, - location = location - ) - } - } -} - - -/** - * Matches a field call, such as: - * `iget-object v0, p0, Lahhh;->g:Landroid/view/View;` - * - * @param definingClass Defining class of the field call. Compares using [StringComparisonType.ENDS_WITH]. - * For calls to a method in the same class, use 'this' as the defining class. - * Note: 'this' does not work for fields found in superclasses. - * @param name Full name of the field. Compares using [StringComparisonType.EQUALS]. - * @param type Class type of field. Compares using [StringComparisonType.STARTS_WITH]. - * @param opcode Single opcode type to match. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun fieldAccess( - definingClass: String? = null, - name: String? = null, - type: String? = null, - opcode: Opcode, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = fieldAccess( - definingClass, - name, - type, - listOf(opcode), - location -) - -/** - * Matches a field call, such as: - * `iget-object v0, p0, Lahhh;->g:Landroid/view/View;` - * - * @param definingClass Defining class of the field call. Compares using [StringComparisonType.ENDS_WITH]. - * For calls to a method in the same class, use 'this' as the defining class. - * Note: 'this' does not work for fields found in superclasses. - * @param name Full name of the field. Compares using [StringComparisonType.EQUALS]. - * @param type Class type of field. Compares using [StringComparisonType.STARTS_WITH]. - * @param opcodes List of all possible opcodes to match. Defaults to matching all get/put opcodes. - * (`Opcode.IGET`, `Opcode.SGET`, `Opcode.IPUT`, `Opcode.SPUT`, etc). - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun fieldAccess( - definingClass: String? = null, - name: String? = null, - type: String? = null, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = FieldAccessFilter( - definingClass, - name, - type, - opcodes, - location -) - -/** - * Field access for a copy pasted SMALI style field access call. e.g.: - * `Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;` - * - * Should never be used with obfuscated field names or obfuscated field types. - * @param smali Smali field access statement, such as `Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;`. - * @param opcodes List of all possible opcodes to match. Defaults to matching all get/put opcodes. - * (`Opcode.IGET`, `Opcode.SGET`, `Opcode.IPUT`, `Opcode.SPUT`, etc). - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun fieldAccess( - smali: String, - opcodes: List? = null, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = parseJvmFieldAccess(smali, opcodes, location) - -/** - * Field access for a copy pasted SMALI style field access call. e.g.: - * `Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;` - * - * Should never be used with obfuscated field names or obfuscated field types. - * - * @param smali Smali field access statement, such as `Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;`. - * @param opcode Single opcode type to match. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun fieldAccess( - smali: String, - opcode: Opcode, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = parseJvmFieldAccess(smali, listOf(opcode), location) - - - -class StringFilter internal constructor( - val string: () -> String, - val comparison: StringComparisonType, - location: InstructionLocation -) : OpcodesFilter(listOf(Opcode.CONST_STRING, Opcode.CONST_STRING_JUMBO), location) { - - /** - * Store the lambda value instead of calling it more than once. - */ - internal val stringValue: String by lazy (string) - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean { - if (!super.matches(enclosingMethod, instruction)) { - return false - } - - val stringReference = (instruction as ReferenceInstruction).reference as StringReference - return comparison.compare(stringReference.string, stringValue) - } -} - -/** - * Literal String instruction. - * - * @param string string literal, using exact matching of [StringComparisonType.EQUALS]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun string( - string: String, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = StringFilter({ string }, StringComparisonType.EQUALS, location) - -/** - * Literal String instruction. - * - * @param string string literal, using exact matching of [StringComparisonType.EQUALS]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun string( - string: () -> String, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = StringFilter(string, StringComparisonType.EQUALS, location) - -/** - * Literal String instruction. - * - * @param string string literal. - * @param comparison How to compare the string literal. For more precise matching of strings, - * consider using [anyInstruction] with multiple exact string declarations. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun string( - string: String, - /** - * How to match a given string opcode literal. Default is exact string equality. For more - * precise matching of multiple strings, consider using [anyInstruction] with multiple - * exact string declarations. - */ - comparison: StringComparisonType = StringComparisonType.EQUALS, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = StringFilter({ string }, comparison, location) - -/** - * Literal String instruction. - * - * @param string string literal. - * @param comparison How to compare the string literal. For more precise matching of strings, - * consider using [anyInstruction] with multiple exact string declarations. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun string( - string: () -> String, - comparison: StringComparisonType, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = StringFilter(string, comparison, location) - - - -class NewInstanceFilter internal constructor ( - val type: () -> String, - val comparison: StringComparisonType, - location: InstructionLocation -) : OpcodesFilter(listOf(Opcode.NEW_INSTANCE, Opcode.NEW_ARRAY), location) { - - /** - * Store the lambda value instead of calling it more than once. - */ - private val typeValue: String by lazy { - val typeValue = type() - comparison.validateSearchStringForClassType(typeValue) - typeValue - } - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean { - if (!super.matches(enclosingMethod, instruction)) { - return false - } - - val reference = (instruction as ReferenceInstruction).reference as TypeReference - return comparison.compare(reference.type, typeValue) - } -} - -/** - * Opcode type [Opcode.NEW_INSTANCE] or [Opcode.NEW_ARRAY] with a non obfuscated class type. - * - * @param type Class type, compared using [StringComparisonType.ENDS_WITH]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun newInstance( - type: String, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = NewInstanceFilter({ type }, StringComparisonType.ENDS_WITH, location) - -/** - * Opcode type [Opcode.NEW_INSTANCE] or [Opcode.NEW_ARRAY] with a non obfuscated class type. - * - * @param type Class type, compared using [StringComparisonType.ENDS_WITH]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun newInstance( - type: () -> String, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere(), -) = NewInstanceFilter(type, StringComparisonType.ENDS_WITH, location) - -/** - * Opcode type [Opcode.NEW_INSTANCE] or [Opcode.NEW_ARRAY] with a non obfuscated class type. - * - * @param type Class type. - * @param comparison How to compare the opcode class type. For more precise matching of types, - * consider using [anyInstruction] with multiple exact type declarations. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun newInstance( - type: String, - comparison: StringComparisonType, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = NewInstanceFilter({ type }, comparison, location) - -/** - * Opcode type [Opcode.NEW_INSTANCE] or [Opcode.NEW_ARRAY] with a non obfuscated class type. - * - * @param type Class type. - * @param comparison How to compare the opcode class type. For more precise matching of types, - * consider using [anyInstruction] with multiple exact type declarations. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun newInstance( - type: () -> String, - comparison: StringComparisonType, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = NewInstanceFilter(type, comparison, location) - - - -class CheckCastFilter internal constructor( - val type: () -> String, - val comparison: StringComparisonType, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) : OpcodeFilter(Opcode.CHECK_CAST, location) { - - /** - * Store the lambda value instead of calling it more than once. - */ - internal val typeValue: String by lazy { - val typeValue = type() - comparison.validateSearchStringForClassType(typeValue) - typeValue - } - - override fun matches( - enclosingMethod: Method, - instruction: Instruction - ): Boolean { - if (!super.matches(enclosingMethod, instruction)) { - return false - } - - val reference = (instruction as ReferenceInstruction).reference as TypeReference - return comparison.compare(reference.type, typeValue) - } -} - -/** - * Opcode type [Opcode.CHECK_CAST] with a non obfuscated class type. - * - * @param type Class type, compared using [StringComparisonType.ENDS_WITH]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun checkCast( - type: String, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = CheckCastFilter({ type }, StringComparisonType.ENDS_WITH, location) - -/** - * Opcode type [Opcode.CHECK_CAST] with a non obfuscated class type. - * - * @param type Class type, compared using [StringComparisonType.ENDS_WITH]. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun checkCast( - type: () -> String, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = CheckCastFilter(type, StringComparisonType.ENDS_WITH, location) - -/** - * Opcode type [Opcode.CHECK_CAST] with a non obfuscated class type using the provided string comparison type. - * - * @param type Class type. - * @param comparison How to compare the opcode class type. For more precise matching of types, - * consider using [anyInstruction] with multiple exact type declarations. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun checkCast( - type: String, - comparison: StringComparisonType, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = CheckCastFilter({ type }, comparison, location) - -/** - * Opcode type [Opcode.CHECK_CAST] with a non obfuscated class type using the provided string comparison type. - * - * @param type Class type. - * @param comparison How to compare the opcode class type. For more precise matching of types, - * consider using [anyInstruction] with multiple exact type declarations. - * @param location Where this filter is allowed to match. Default is anywhere after the previous instruction. - */ -fun checkCast( - type: () -> String, - comparison: StringComparisonType, - location: InstructionLocation = InstructionLocation.MatchAfterAnywhere() -) = CheckCastFilter(type, comparison, location) diff --git a/src/main/kotlin/app/revanced/patcher/Matching.kt b/src/main/kotlin/app/revanced/patcher/Matching.kt deleted file mode 100644 index dc84f74..0000000 --- a/src/main/kotlin/app/revanced/patcher/Matching.kt +++ /dev/null @@ -1,582 +0,0 @@ -@file:Suppress("unused", "MemberVisibilityCanBePrivate", "CONTEXT_RECEIVERS_DEPRECATED") - -package app.revanced.patcher - -import app.revanced.patcher.Matcher.MatchContext -import app.revanced.patcher.dex.mutable.MutableMethod -import app.revanced.patcher.extensions.accessFlags -import app.revanced.patcher.patch.BytecodePatchContext -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.HiddenApiRestriction -import com.android.tools.smali.dexlib2.iface.* -import com.android.tools.smali.dexlib2.iface.Annotation -import com.android.tools.smali.dexlib2.iface.instruction.Instruction -import com.android.tools.smali.dexlib2.util.MethodUtil -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty - -fun Iterable.anyClassDef(predicate: ClassDef.() -> Boolean) = any(predicate) - -fun ClassDef.anyMethod(predicate: Method.() -> Boolean) = methods.any(predicate) - -fun ClassDef.anyDirectMethod(predicate: Method.() -> Boolean) = directMethods.any(predicate) - -fun ClassDef.anyVirtualMethod(predicate: Method.() -> Boolean) = virtualMethods.any(predicate) - -fun ClassDef.anyField(predicate: Field.() -> Boolean) = fields.any(predicate) - -fun ClassDef.anyInstanceField(predicate: Field.() -> Boolean) = instanceFields.any(predicate) - -fun ClassDef.anyStaticField(predicate: Field.() -> Boolean) = staticFields.any(predicate) - -fun ClassDef.anyInterface(predicate: String.() -> Boolean) = interfaces.any(predicate) - -fun ClassDef.anyAnnotation(predicate: Annotation.() -> Boolean) = annotations.any(predicate) - -fun Method.implementation(predicate: MethodImplementation.() -> Boolean) = implementation?.predicate() ?: false - -fun Method.anyParameter(predicate: MethodParameter.() -> Boolean) = parameters.any(predicate) - -fun Method.anyParameterType(predicate: CharSequence.() -> Boolean) = parameterTypes.any(predicate) - -fun Method.anyAnnotation(predicate: Annotation.() -> Boolean) = annotations.any(predicate) - -fun Method.anyHiddenApiRestriction(predicate: HiddenApiRestriction.() -> Boolean) = hiddenApiRestrictions.any(predicate) - -fun MethodImplementation.anyInstruction(predicate: Instruction.() -> Boolean) = instructions.any(predicate) - -fun MethodImplementation.anyTryBlock(predicate: TryBlock.() -> Boolean) = tryBlocks.any(predicate) - -fun MethodImplementation.anyDebugItem(predicate: Any.() -> Boolean) = debugItems.any(predicate) - -fun Iterable.anyInstruction(predicate: Instruction.() -> Boolean) = any(predicate) - -fun BytecodePatchContext.firstClassDefOrNull(predicate: context(MatchContext) ClassDef.() -> Boolean) = - with(MatchContext()) { classDefs.firstOrNull { it.predicate() } } - -fun BytecodePatchContext.firstClassDef(predicate: context(MatchContext) ClassDef.() -> Boolean) = - requireNotNull(firstClassDefOrNull(predicate)) - -fun BytecodePatchContext.firstClassDefMutableOrNull(predicate: context(MatchContext) ClassDef.() -> Boolean) = - firstClassDefOrNull(predicate)?.mutable() - -fun BytecodePatchContext.firstClassDefMutable(predicate: context(MatchContext) ClassDef.() -> Boolean) = - requireNotNull(firstClassDefMutableOrNull(predicate)) - -fun BytecodePatchContext.firstClassDefOrNull( - type: String, predicate: (context(MatchContext) ClassDef.() -> Boolean)? = null -) = lookupMaps.classDefsByType[type]?.takeIf { - predicate == null || with(MatchContext()) { it.predicate() } -} - -fun BytecodePatchContext.firstClassDef( - type: String, predicate: (context(MatchContext) ClassDef.() -> Boolean)? = null -) = requireNotNull(firstClassDefOrNull(type, predicate)) - -fun BytecodePatchContext.firstClassDefMutableOrNull( - type: String, predicate: (context(MatchContext) ClassDef.() -> Boolean)? = null -) = firstClassDefOrNull(type, predicate)?.mutable() - -fun BytecodePatchContext.firstClassDefMutable( - type: String, predicate: (context(MatchContext) ClassDef.() -> Boolean)? = null -) = requireNotNull(firstClassDefMutableOrNull(type, predicate)) - -fun Iterable.firstMethodOrNull(predicate: context(MatchContext) Method.() -> Boolean) = - with(MatchContext()) { - this@firstMethodOrNull.asSequence().flatMap { it.methods.asSequence() }.firstOrNull { it.predicate() } - } - -fun Iterable.firstMethod(predicate: context(MatchContext) Method.() -> Boolean) = - requireNotNull(firstMethodOrNull(predicate)) - -/** Can't compile due to JVM platform declaration clash -fun Iterable.firstMethodOrNull(predicate: context(MatchContext) Method.() -> Boolean) = -with(MatchContext()) { firstOrNull { it.predicate() } } - -fun Iterable.firstMethod(predicate: context(MatchContext) Method.() -> Boolean) = -with(MatchContext()) { requireNotNull(firstMethodOrNull(predicate)) } - **/ -fun BytecodePatchContext.firstMethodOrNull(predicate: context(MatchContext) Method.() -> Boolean) = - classDefs.firstMethodOrNull(predicate) - -fun BytecodePatchContext.firstMethod(predicate: context(MatchContext) Method.() -> Boolean) = - requireNotNull(firstMethodOrNull(predicate)) - -fun BytecodePatchContext.firstMethodMutableOrNull(predicate: context(MatchContext) Method.() -> Boolean) = - classDefs.firstMethodOrNull(predicate)?.let { method -> - lookupMaps.classDefsByType[method.definingClass]!!.mutable().methods.first { - MethodUtil.methodSignaturesMatch(method, it) - } - } - -fun BytecodePatchContext.firstMethodMutable(predicate: context(MatchContext) Method.() -> Boolean) = - requireNotNull(firstMethodMutableOrNull(predicate)) - -fun BytecodePatchContext.firstMethodOrNull( - vararg strings: String, - predicate: context(MatchContext) Method.() -> Boolean = { true }, -) = with(MatchContext()) { - strings.mapNotNull { lookupMaps.methodsByStrings[it] }.minByOrNull { it.size }?.firstOrNull { it.predicate() } -} - -fun BytecodePatchContext.firstMethod( - vararg strings: String, - predicate: context(MatchContext) Method.() -> Boolean = { true }, -) = requireNotNull(firstMethodOrNull(*strings, predicate = predicate)) - -fun BytecodePatchContext.firstMethodMutableOrNull( - vararg strings: String, - predicate: context(MatchContext) Method.() -> Boolean = { true }, -) = with(MatchContext()) { - strings.mapNotNull { lookupMaps.methodsByStrings[it] }.minByOrNull { it.size }?.let { methods -> - methods.firstOrNull { it.predicate() }?.let { method -> - firstClassDefMutable(method.definingClass).methods.first { - MethodUtil.methodSignaturesMatch( - method, it - ) - } - } - } -} - -fun BytecodePatchContext.firstMethodMutable( - vararg strings: String, predicate: context(MatchContext) Method.() -> Boolean = { true } -) = requireNotNull(firstMethodMutableOrNull(*strings, predicate = predicate)) - -class CachedReadOnlyProperty internal constructor( - private val block: BytecodePatchContext.(KProperty<*>) -> T -) : ReadOnlyProperty { - private var value: T? = null - private var cached = false - - override fun getValue(thisRef: BytecodePatchContext, property: KProperty<*>): T { - if (!cached) { - value = thisRef.block(property) - cached = true - } - - return value!! - } -} - -fun gettingFirstClassDefOrNull(predicate: context(MatchContext) ClassDef.() -> Boolean) = - CachedReadOnlyProperty { firstClassDefOrNull(predicate) } - -fun gettingFirstClassDef(predicate: context(MatchContext) ClassDef.() -> Boolean) = - CachedReadOnlyProperty { firstClassDef(predicate) } - -fun gettingFirstClassDefMutableOrNull(predicate: context(MatchContext) ClassDef.() -> Boolean) = - CachedReadOnlyProperty { firstClassDefMutableOrNull(predicate) } - -fun gettingFirstClassDefMutable(predicate: context(MatchContext) ClassDef.() -> Boolean) = - CachedReadOnlyProperty { firstClassDefMutable(predicate) } - -fun gettingFirstClassDefOrNull( - type: String, predicate: (context(MatchContext) ClassDef.() -> Boolean)? = null -) = CachedReadOnlyProperty { firstClassDefOrNull(type, predicate) } - -fun gettingFirstClassDef( - type: String, predicate: (context(MatchContext) ClassDef.() -> Boolean)? = null -) = CachedReadOnlyProperty { firstClassDef(type, predicate) } - -fun gettingFirstClassDefMutableOrNull( - type: String, predicate: (context(MatchContext) ClassDef.() -> Boolean)? = null -) = CachedReadOnlyProperty { firstClassDefMutableOrNull(type, predicate) } - -fun gettingFirstClassDefMutable( - type: String, predicate: (context(MatchContext) ClassDef.() -> Boolean)? = null -) = CachedReadOnlyProperty { firstClassDefMutable(type, predicate) } - -fun gettingFirstMethodOrNull(predicate: context(MatchContext) Method.() -> Boolean) = - CachedReadOnlyProperty { firstMethodOrNull(predicate) } - -fun gettingFirstMethod(predicate: context(MatchContext) Method.() -> Boolean) = - CachedReadOnlyProperty { firstMethod(predicate) } - -fun gettingFirstMethodMutableOrNull(predicate: context(MatchContext) Method.() -> Boolean) = - CachedReadOnlyProperty { firstMethodMutableOrNull(predicate) } - -fun gettingFirstMethodMutable(predicate: context(MatchContext) Method.() -> Boolean) = - CachedReadOnlyProperty { firstMethodMutable(predicate) } - -fun gettingFirstMethodOrNull( - vararg strings: String, - predicate: context(MatchContext) Method.() -> Boolean = { true }, -) = CachedReadOnlyProperty { firstMethodOrNull(*strings, predicate = predicate) } - -fun gettingFirstMethod( - vararg strings: String, - predicate: context(MatchContext) Method.() -> Boolean = { true }, -) = CachedReadOnlyProperty { firstMethod(*strings, predicate = predicate) } - -fun gettingFirstMethodMutableOrNull( - vararg strings: String, - predicate: context(MatchContext) Method.() -> Boolean = { true }, -) = CachedReadOnlyProperty { firstMethodMutableOrNull(*strings, predicate = predicate) } - -fun gettingFirstMethodMutable( - vararg strings: String, - predicate: context(MatchContext) Method.() -> Boolean = { true }, -) = CachedReadOnlyProperty { firstMethodMutable(*strings, predicate = predicate) } - -fun indexedMatcher() = IndexedMatcher() - -fun indexedMatcher(build: IndexedMatcher.() -> Unit) = - IndexedMatcher().apply(build) - -fun Iterable.matchIndexed(build: IndexedMatcher.() -> Unit) = - indexedMatcher(build)(this) - -context(_: MatchContext) -fun Iterable.matchIndexed(key: Any, build: IndexedMatcher.() -> Unit) = - indexedMatcher()(key, this, build) - -context(_: MatchContext) -operator fun IndexedMatcher.invoke(key: Any, iterable: Iterable, builder: IndexedMatcher.() -> Unit) = - remember(key) { apply(builder) }(iterable) - -context(_: MatchContext) -operator fun IndexedMatcher.invoke(iterable: Iterable, builder: IndexedMatcher.() -> Unit) = - invoke(this@invoke.hashCode(), iterable, builder) - -abstract class Matcher : MutableList by mutableListOf() { - var matchIndex = -1 - protected set - - abstract operator fun invoke(haystack: Iterable): Boolean - - class MatchContext internal constructor() : MutableMap by mutableMapOf() -} - -context(context: MatchContext) -inline fun remember(key: Any, defaultValue: () -> V) = - context[key] as? V ?: defaultValue().also { context[key] = it } - -class IndexedMatcher() : Matcher Boolean>() { - private val _indices: MutableList = mutableListOf() - val indices: List = _indices - - private var lastMatchedIndex = -1 - private var currentIndex = -1 - - private var nextIndex: Int? = null - - override fun invoke(haystack: Iterable): Boolean { - // Normalize to list - val hay = haystack as? List ?: haystack.toList() - - _indices.clear() - this@IndexedMatcher.lastMatchedIndex = -1 - currentIndex = -1 - - data class Frame( - val patternIndex: Int, - val lastMatchedIndex: Int, - val previousFrame: Frame?, - var nextHayIndex: Int, - val matchedIndex: Int - ) - - val stack = ArrayDeque() - stack.add( - Frame( - patternIndex = 0, - lastMatchedIndex = -1, - previousFrame = null, - nextHayIndex = 0, - matchedIndex = -1 - ) - ) - - while (stack.isNotEmpty()) { - val frame = stack.last() - - if (frame.nextHayIndex >= hay.size || nextIndex == -1) { - stack.removeLast() - nextIndex = null - continue - } - - val i = frame.nextHayIndex - currentIndex = i - lastMatchedIndex = frame.lastMatchedIndex - nextIndex = null - - if (this[frame.patternIndex](hay[i], lastMatchedIndex, currentIndex)) { - Frame( - patternIndex = frame.patternIndex + 1, - lastMatchedIndex = i, - previousFrame = frame, - nextHayIndex = i + 1, - matchedIndex = i - ).also { - if (it.patternIndex == size) { - _indices += buildList(size) { - var f: Frame? = it - while (f != null && f.matchedIndex != -1) { - add(f.matchedIndex) - f = f.previousFrame - } - }.asReversed() - - return true - } - }.let(stack::add) - } - - frame.nextHayIndex = when (val nextIndex = nextIndex) { - null -> frame.nextHayIndex + 1 - -1 -> 0 // Frame will be removed next loop. - else -> nextIndex - } - } - - return false - } - - fun head(predicate: T.(lastMatchedIndex: Int, currentIndex: Int) -> Boolean) = - add { lastMatchedIndex, currentIndex -> - currentIndex == 0 && predicate(lastMatchedIndex, currentIndex) - } - - fun head(predicate: T.() -> Boolean) = - head { _, _ -> predicate() } - - fun after(range: IntRange = 1..1, predicate: T.(lastMatchedIndex: Int, currentIndex: Int) -> Boolean) = - add { lastMatchedIndex, currentIndex -> - val distance = currentIndex - lastMatchedIndex - - nextIndex = when { - distance < range.first -> lastMatchedIndex + range.first - distance > range.last -> -1 - else -> return@add predicate(lastMatchedIndex, currentIndex) - } - - false - } - - fun after(range: IntRange = 1..1, predicate: T.() -> Boolean) = - after(range) { _, _ -> predicate() } - - fun add(predicate: T.() -> Boolean) = add { _, _ -> predicate() } -} - -fun T.declarativePredicate(build: DeclarativePredicateBuilder.() -> Unit) = - DeclarativePredicateBuilder().apply(build).all(this) - -context(_: MatchContext) -fun T.rememberDeclarativePredicate(key: Any, block: DeclarativePredicateBuilder.() -> Unit): Boolean = - remember(key) { DeclarativePredicateBuilder().apply(block) }.all(this) - -context(_: MatchContext) -private fun T.rememberDeclarativePredicate(predicate: context(MatchContext, T) DeclarativePredicateBuilder.() -> Unit) = - rememberDeclarativePredicate("declarative predicate build") { predicate() } - -fun BytecodePatchContext.firstClassDefByDeclarativePredicateOrNull( - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = firstClassDefOrNull { rememberDeclarativePredicate(predicate) } - -fun BytecodePatchContext.firstClassDefByDeclarativePredicate( - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = requireNotNull(firstClassDefByDeclarativePredicateOrNull(predicate)) - -fun BytecodePatchContext.firstClassDefMutableByDeclarativePredicateOrNull( - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = firstClassDefMutableOrNull { rememberDeclarativePredicate(predicate) } - -fun BytecodePatchContext.firstClassDefMutableByDeclarativePredicate( - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = requireNotNull(firstClassDefMutableByDeclarativePredicateOrNull(predicate)) - -fun BytecodePatchContext.firstClassDefByDeclarativePredicateOrNull( - type: String, - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = firstClassDefOrNull(type) { rememberDeclarativePredicate(predicate) } - -fun BytecodePatchContext.firstClassDefByDeclarativePredicate( - type: String, - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = requireNotNull(firstClassDefByDeclarativePredicateOrNull(type, predicate)) - -fun BytecodePatchContext.firstClassDefMutableByDeclarativePredicateOrNull( - type: String, - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = firstClassDefMutableOrNull(type) { rememberDeclarativePredicate(predicate) } - -fun BytecodePatchContext.firstClassDefMutableByDeclarativePredicate( - type: String, - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = requireNotNull(firstClassDefMutableByDeclarativePredicateOrNull(type, predicate)) - -fun BytecodePatchContext.firstMethodByDeclarativePredicateOrNull( - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = firstMethodOrNull { rememberDeclarativePredicate(predicate) } - -fun BytecodePatchContext.firstMethodByDeclarativePredicate( - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = requireNotNull(firstMethodByDeclarativePredicateOrNull(predicate)) - -fun BytecodePatchContext.firstMethodMutableByDeclarativePredicateOrNull( - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = firstMethodMutableOrNull { rememberDeclarativePredicate(predicate) } - -fun BytecodePatchContext.firstMethodMutableByDeclarativePredicate( - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = requireNotNull(firstMethodMutableByDeclarativePredicateOrNull(predicate)) - -fun BytecodePatchContext.firstMethodByDeclarativePredicateOrNull( - vararg strings: String, - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = firstMethodOrNull(*strings) { rememberDeclarativePredicate(predicate) } - -fun BytecodePatchContext.firstMethodByDeclarativePredicate( - vararg strings: String, - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = requireNotNull(firstMethodByDeclarativePredicateOrNull(*strings, predicate = predicate)) - -fun BytecodePatchContext.firstMethodMutableByDeclarativePredicateOrNull( - vararg strings: String, - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = firstMethodMutableOrNull(*strings) { rememberDeclarativePredicate(predicate) } - -fun BytecodePatchContext.firstMethodMutableByDeclarativePredicate( - vararg strings: String, - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = requireNotNull(firstMethodMutableByDeclarativePredicateOrNull(*strings, predicate = predicate)) - -fun gettingFirstClassDefByDeclarativePredicateOrNull( - type: String, - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = gettingFirstClassDefOrNull(type) { rememberDeclarativePredicate(predicate) } - -fun gettingFirstClassDefByDeclarativePredicate( - type: String, - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = CachedReadOnlyProperty { firstClassDefByDeclarativePredicate(type, predicate) } - -fun gettingFirstClassDefMutableByDeclarativePredicateOrNull( - type: String, - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = gettingFirstClassDefMutableOrNull(type) { rememberDeclarativePredicate(predicate) } - -fun gettingFirstClassDefMutableByDeclarativePredicate( - type: String, - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = CachedReadOnlyProperty { firstClassDefMutableByDeclarativePredicate(type, predicate) } - -fun gettingFirstClassDefByDeclarativePredicateOrNull( - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = gettingFirstClassDefOrNull { rememberDeclarativePredicate(predicate) } - -fun gettingFirstClassDefByDeclarativePredicate( - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = CachedReadOnlyProperty { firstClassDefByDeclarativePredicate(predicate) } - -fun gettingFirstClassDefMutableByDeclarativePredicateOrNull( - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = gettingFirstClassDefMutableOrNull { rememberDeclarativePredicate(predicate) } - -fun gettingFirstClassDefMutableByDeclarativePredicate( - predicate: context(MatchContext, ClassDef) DeclarativePredicateBuilder.() -> Unit -) = CachedReadOnlyProperty { firstClassDefMutableByDeclarativePredicate(predicate) } - -fun gettingFirstMethodByDeclarativePredicateOrNull( - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = gettingFirstMethodOrNull { rememberDeclarativePredicate(predicate) } - -fun gettingFirstMethodByDeclarativePredicate( - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = CachedReadOnlyProperty { firstMethodByDeclarativePredicate(predicate = predicate) } - -fun gettingFirstMethodMutableByDeclarativePredicateOrNull( - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = gettingFirstMethodMutableOrNull { rememberDeclarativePredicate(predicate) } - -fun gettingFirstMethodMutableByDeclarativePredicate( - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = CachedReadOnlyProperty { firstMethodMutableByDeclarativePredicate(predicate = predicate) } - -fun gettingFirstMethodByDeclarativePredicateOrNull( - vararg strings: String, - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = gettingFirstMethodOrNull(*strings) { rememberDeclarativePredicate(predicate) } - -fun gettingFirstMethodByDeclarativePredicate( - vararg strings: String, - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = CachedReadOnlyProperty { firstMethodByDeclarativePredicate(*strings, predicate = predicate) } - -fun gettingFirstMethodMutableByDeclarativePredicateOrNull( - vararg strings: String, - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = gettingFirstMethodMutableOrNull(*strings) { rememberDeclarativePredicate(predicate) } - -fun gettingFirstMethodMutableByDeclarativePredicate( - vararg strings: String, - predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) = CachedReadOnlyProperty { firstMethodMutableByDeclarativePredicate(*strings, predicate = predicate) } - - -class DeclarativePredicateBuilder internal constructor() { - private val children = mutableListOf Boolean>() - - fun anyOf(block: DeclarativePredicateBuilder.() -> Unit) { - val child = DeclarativePredicateBuilder().apply(block) - children += { child.children.any { it() } } - } - - fun predicate(block: T.() -> Boolean) { - children += block - } - - fun all(target: T): Boolean = children.all { target.it() } - fun any(target: T): Boolean = children.all { target.it() } -} - -fun firstMethodComposite( - predicate: - context(MatchContext, Method, IndexedMatcher) DeclarativePredicateBuilder.() -> Unit -) = with(indexedMatcher()) { Composition(indices = this.indices) { predicate() } } - -fun DeclarativePredicateBuilder.accessFlags(vararg flags: AccessFlags) { - predicate { accessFlags(*flags) } -} - -fun DeclarativePredicateBuilder.returns(returnType: String) { - predicate { this.returnType.startsWith(returnType) } -} - -fun DeclarativePredicateBuilder.parameterTypes(vararg parameterTypes: String) = predicate { - this.parameterTypes.size == parameterTypes.size && this.parameterTypes.zip(parameterTypes) - .all { (a, b) -> a.startsWith(b) } -} - -context(_: MatchContext, indexedMatcher: IndexedMatcher) -fun DeclarativePredicateBuilder.instructions( - build: context(MatchContext, Method) IndexedMatcher.() -> Unit -) = predicate { implementation { indexedMatcher(indexedMatcher.hashCode(), instructions) { build() } } } - -context(_: MatchContext) -fun DeclarativePredicateBuilder.custom(block: context(MatchContext) Method.() -> Boolean) { - predicate { block() } -} - -class Composition internal constructor( - val indices: List, - private val predicate: context(MatchContext, Method) DeclarativePredicateBuilder.() -> Unit -) { - private var _methodOrNull: MutableMethod? = null - - context(context: BytecodePatchContext) - val methodOrNull: MutableMethod? - get() { - if (_methodOrNull == null) { - _methodOrNull = context.firstMethodMutableByDeclarativePredicateOrNull(predicate) - } - - return _methodOrNull - } - - context(_: BytecodePatchContext) - val method get() = requireNotNull(methodOrNull) -} diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableMethodParameter.kt b/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableMethodParameter.kt deleted file mode 100644 index 57097fe..0000000 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/MutableMethodParameter.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patcher.dex.mutable - -import app.revanced.patcher.dex.mutable.MutableAnnotation.Companion.toMutable -import com.android.tools.smali.dexlib2.base.BaseMethodParameter -import com.android.tools.smali.dexlib2.iface.MethodParameter - -// TODO: finish overriding all members if necessary -class MutableMethodParameter(parameter: MethodParameter) : - BaseMethodParameter(), - MethodParameter { - private var type = parameter.type - private var name = parameter.name - private var signature = parameter.signature - private val _annotations by lazy { - parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet() - } - - override fun getType(): String = type - - override fun getName(): String? = name - - override fun getSignature(): String? = signature - - override fun getAnnotations(): MutableSet = _annotations - - companion object { - fun MethodParameter.toMutable(): MutableMethodParameter = MutableMethodParameter(this) - } -} diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableArrayEncodedValue.kt b/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableArrayEncodedValue.kt deleted file mode 100644 index 69b0664..0000000 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableArrayEncodedValue.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patcher.dex.mutable.encodedValue - -import app.revanced.patcher.dex.mutable.encodedValue.MutableEncodedValue.Companion.toMutable -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 - -class MutableArrayEncodedValue(arrayEncodedValue: ArrayEncodedValue) : - BaseArrayEncodedValue(), - MutableEncodedValue { - private val _value by lazy { - arrayEncodedValue.value.map { encodedValue -> encodedValue.toMutable() }.toMutableList() - } - - override fun getValue(): MutableList = _value - - companion object { - fun ArrayEncodedValue.toMutable(): MutableArrayEncodedValue = MutableArrayEncodedValue(this) - } -} diff --git a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableNullEncodedValue.kt b/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableNullEncodedValue.kt deleted file mode 100644 index 25ca990..0000000 --- a/src/main/kotlin/app/revanced/patcher/dex/mutable/encodedValue/MutableNullEncodedValue.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.patcher.dex.mutable.encodedValue - -import com.android.tools.smali.dexlib2.base.value.BaseNullEncodedValue -import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue - -class MutableNullEncodedValue : - BaseNullEncodedValue(), - MutableEncodedValue { - companion object { - fun ByteEncodedValue.toMutable(): MutableByteEncodedValue = MutableByteEncodedValue(this) - } -} diff --git a/src/main/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt b/src/main/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt deleted file mode 100644 index b1727de..0000000 --- a/src/main/kotlin/app/revanced/patcher/patch/BytecodePatchContext.kt +++ /dev/null @@ -1,228 +0,0 @@ -package app.revanced.patcher.patch - -import app.revanced.patcher.InternalApi -import app.revanced.patcher.PatcherConfig -import app.revanced.patcher.PatcherResult -import app.revanced.patcher.dex.mutable.MutableClassDef -import app.revanced.patcher.dex.mutable.MutableClassDef.Companion.toMutable -import app.revanced.patcher.extensions.instructionsOrNull -import app.revanced.patcher.util.ClassMerger.merge -import app.revanced.patcher.util.MethodNavigator -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.dexlib2.iface.Method -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.StringReference -import lanchon.multidexlib2.BasicDexFileNamer -import lanchon.multidexlib2.DexIO -import lanchon.multidexlib2.MultiDexIO -import lanchon.multidexlib2.RawDexIO -import java.io.Closeable -import java.io.IOException -import java.util.LinkedHashMap -import java.util.logging.Logger - - -/** - * A context for patches containing the current state of the bytecode. - * - * @param config The [PatcherConfig] used to create this context. - */ -@Suppress("MemberVisibilityCanBePrivate") -class BytecodePatchContext internal constructor(private val config: PatcherConfig) : - PatchContext>, - Closeable { - private val logger = Logger.getLogger(this::class.java.name) - - /** - * [Opcodes] of the supplied [PatcherConfig.apkFile]. - */ - internal val opcodes: Opcodes - - /** - * The list of classes. - */ - val classDefs = MultiDexIO.readDexFile( - true, - config.apkFile, - BasicDexFileNamer(), - null, - null, - ).also { opcodes = it.opcodes }.classes.toMutableSet() - - /** - * The lookup maps for methods and the class they are a member of from the [classDefs]. - */ - internal val lookupMaps by lazy { _lookupMaps ?: LookupMaps().also { _lookupMaps = it } } - private var _lookupMaps: LookupMaps? = null // For freeing up memory when compiling. - - /** - * Merge the extension of [bytecodePatch] into the [BytecodePatchContext]. - * If no extension is present, the function will return early. - * - * @param bytecodePatch The [BytecodePatch] to merge the extension of. - */ - internal fun mergeExtension(bytecodePatch: BytecodePatch) { - bytecodePatch.extensionInputStream?.get()?.use { extensionStream -> - RawDexIO.readRawDexFile(extensionStream, 0, null).classes.forEach { classDef -> - val existingClass = lookupMaps.classDefsByType[classDef.type] ?: run { - logger.fine { "Adding class \"$classDef\"" } - - classDefs += classDef - lookupMaps += classDef - - return@forEach - } - - logger.fine { "Class \"$classDef\" exists already. Adding missing methods and fields." } - - existingClass.merge(classDef, this@BytecodePatchContext).let { mergedClass -> - // If the class was merged, replace the original class with the merged class. - if (mergedClass === existingClass) { - return@let - } - - classDefs -= existingClass - lookupMaps -= existingClass - - classDefs += mergedClass - lookupMaps += mergedClass - } - } - } ?: logger.fine("No extension to merge") - } - - /** - * Convert a [ClassDef] to a [MutableClassDef]. - * If the [ClassDef] is already a [MutableClassDef], it is returned as is. - * - * @return The mutable version of the [ClassDef]. - */ - fun ClassDef.mutable(): MutableClassDef = this as? MutableClassDef ?: also { - classDefs -= this - lookupMaps -= this - }.toMutable().also { - classDefs += it - lookupMaps += it - } - - /** - * Navigate a method. - * - * @param method The method to navigate. - * - * @return A [MethodNavigator] for the method. - */ - fun navigate(method: MethodReference) = MethodNavigator(method) - - /** - * Compile bytecode from the [BytecodePatchContext]. - * - * @return The compiled bytecode. - */ - @InternalApi - override fun get(): Set { - logger.info("Compiling patched dex files") - - // Free up memory before compiling the dex files. - close() - System.gc() - - val patchedDexFileResults = - config.patchedFiles.resolve("dex").also { - it.deleteRecursively() // Make sure the directory is empty. - it.mkdirs() - }.apply { - MultiDexIO.writeDexFile( - true, - -1, - this, - BasicDexFileNamer(), - object : DexFile { - override fun getClasses() = this@BytecodePatchContext.classDefs.let { - // More performant according to - // https://github.com/LisoUseInAIKyrios/revanced-patcher/commit/8c26ad08457fb1565ea5794b7930da42a1c81cf1#diff-be698366d9868784ecf7da3fd4ac9d2b335b0bb637f9f618fbe067dbd6830b8fR197 - // TODO: Benchmark, if actually faster. - HashSet(it.size * 3 / 2).apply { addAll(it) } - } - - override fun getOpcodes() = this@BytecodePatchContext.opcodes - }, - DexIO.DEFAULT_MAX_DEX_POOL_SIZE, - ) { _, entryName, _ -> logger.info { "Compiled $entryName" } } - }.listFiles { it.isFile }!!.map { - PatcherResult.PatchedDexFile(it.name, it.inputStream()) - }.toSet() - - // Free up more memory, although it is unclear if this is actually helpful. - classDefs.clear() - System.gc() - - return patchedDexFileResults - } - - override fun close() { - try { - _lookupMaps = null - } catch (e: IOException) { - logger.warning("Failed to clear BytecodePatchContext: ${e.message}") - } - } - - internal inner class LookupMaps { - // No custom HashMap needed here, according to - // https://github.com/LisoUseInAIKyrios/revanced-patcher/commit/9b6d95d4f414a35ed68da37b0ecd8549df1ef63a - // TODO: Benchmark, if actually faster. - private val _classDefsByType = mutableMapOf() - val classDefsByType: Map = _classDefsByType - - // Better performance according to - // https://github.com/LisoUseInAIKyrios/revanced-patcher/commit/9b6d95d4f414a35ed68da37b0ecd8549df1ef63a - private val _methodsByStrings = - LinkedHashMap>(2 * classDefs.size, 0.5f) - - val methodsByStrings: Map> = _methodsByStrings - - private val _methodsWithString = methodsByStrings.values.flatten().toMutableSet() - val methodsWithString: Set = _methodsWithString - - init { - classDefs.forEach(::plusAssign) - } - - private fun ClassDef.forEachString(action: (Method, String) -> Unit) = methods.asSequence().forEach { method -> - method.instructionsOrNull?.asSequence() - ?.filterIsInstance() - ?.map { it.reference } - ?.filterIsInstance() - ?.map { it.string } - ?.forEach { string -> - action(method, string) - } - } - - operator fun plusAssign(classDef: ClassDef) { - _classDefsByType[classDef.type] = classDef - - classDef.forEachString { method, string -> - _methodsWithString += method - _methodsByStrings.getOrPut(string) { - mutableListOf() - } += method - } - } - - operator fun minusAssign(classDef: ClassDef) { - _classDefsByType -= classDef.type - - classDef.forEachString { method, string -> - _methodsWithString.remove(method) - - if (_methodsByStrings[string]?.also { it -= method }?.isEmpty() == true) - _methodsByStrings -= string - } - } - } -} diff --git a/src/main/resources/app/revanced/patcher/version.properties b/src/main/resources/app/revanced/patcher/version.properties deleted file mode 100644 index 308c9f8..0000000 --- a/src/main/resources/app/revanced/patcher/version.properties +++ /dev/null @@ -1 +0,0 @@ -version=${projectVersion} \ No newline at end of file