mirror of
https://github.com/ReVanced/revanced-patcher.git
synced 2026-01-12 06:16:18 +00:00
Compare commits
66 Commits
v14.2.0-de
...
v15.0.3-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b37906fa35 | ||
|
|
356f1f1553 | ||
|
|
e882af74ee | ||
|
|
46875fb28e | ||
|
|
417c3e4234 | ||
|
|
6d2c28807b | ||
|
|
4d6e08a650 | ||
|
|
5cebc1fd30 | ||
|
|
ac61731dc6 | ||
|
|
9e4ffabd5c | ||
|
|
3f410bd39f | ||
|
|
d51bc32e37 | ||
|
|
b7f6aa94cc | ||
|
|
ff965e6953 | ||
|
|
468d5d7421 | ||
|
|
fc95b28c49 | ||
|
|
69184187d9 | ||
|
|
a802d0df46 | ||
|
|
8de30633ae | ||
|
|
a1fbb7990f | ||
|
|
aa71146b1b | ||
|
|
9fdb8f087f | ||
|
|
670f0153de | ||
|
|
1d7aeca696 | ||
|
|
4e7811ea07 | ||
|
|
e11283744a | ||
|
|
91cdfd53ef | ||
|
|
bc7d6b9941 | ||
|
|
6b1e0a1656 | ||
|
|
72c9eb2129 | ||
|
|
4bc4b0dc01 | ||
|
|
637d48746f | ||
|
|
9a109c129b | ||
|
|
d49e4ee5ea | ||
|
|
30f0ea29a3 | ||
|
|
49930f6565 | ||
|
|
909d89fa8d | ||
|
|
81d1d7f544 | ||
|
|
67b7dff67a | ||
|
|
4b76d19596 | ||
|
|
080fbe9feb | ||
|
|
d3721229bf | ||
|
|
86c1c9c772 | ||
|
|
c299817193 | ||
|
|
fcc1de45ed | ||
|
|
a29931f2ec | ||
|
|
3fc6a139ee | ||
|
|
4dd04975d9 | ||
|
|
3b4db3ddb7 | ||
|
|
c4a7117ee8 | ||
|
|
b4e900fde8 | ||
|
|
9818d730e4 | ||
|
|
11a3378659 | ||
|
|
1bb05f22d3 | ||
|
|
26b70554c4 | ||
|
|
93b29d2e83 | ||
|
|
072986374a | ||
|
|
2c590d212a | ||
|
|
6cc863efb3 | ||
|
|
b832812767 | ||
|
|
c44558cacd | ||
|
|
6d83a720cd | ||
|
|
8d0dd9c448 | ||
|
|
64020eec49 | ||
|
|
4dedfb85cb | ||
|
|
55d694579a |
6
.github/workflows/pull_request.yml
vendored
6
.github/workflows/pull_request.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: PR to main
|
||||
name: Open a PR to main
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
MESSAGE: merge branch `${{ github.head_ref || github.ref_name }}` to `main`
|
||||
MESSAGE: Merge branch `${{ github.head_ref || github.ref_name }}` to `main`
|
||||
|
||||
jobs:
|
||||
pull-request:
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Open pull request
|
||||
uses: repo-sync/pull-request@v2
|
||||
with:
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Make sure the release step uses its own credentials:
|
||||
# https://github.com/cycjimmy/semantic-release-action#private-packages
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
- name: Build with Gradle
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./gradlew clean --no-daemon
|
||||
run: ./gradlew build clean --no-daemon
|
||||
- name: Setup semantic-release
|
||||
run: npm install
|
||||
- name: Release
|
||||
|
||||
193
CHANGELOG.md
193
CHANGELOG.md
@@ -1,3 +1,196 @@
|
||||
## [15.0.3-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.2...v15.0.3-dev.1) (2023-09-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix SMALI compilation on devices with RTL language ([#242](https://github.com/ReVanced/revanced-patcher/issues/242)) ([356f1f1](https://github.com/ReVanced/revanced-patcher/commit/356f1f155348347a8f318a2e024716ebf4fec99b))
|
||||
|
||||
## [15.0.2](https://github.com/ReVanced/revanced-patcher/compare/v15.0.1...v15.0.2) (2023-09-27)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Do not unnecessary resolve fingeprints twice ([#241](https://github.com/ReVanced/revanced-patcher/issues/241)) ([4d6e08a](https://github.com/ReVanced/revanced-patcher/commit/4d6e08a650dde6ec2e18611c5db1ab92b9a61dd1))
|
||||
|
||||
## [15.0.2-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.1...v15.0.2-dev.1) (2023-09-26)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Do not unnecessary resolve fingeprints twice ([#241](https://github.com/ReVanced/revanced-patcher/issues/241)) ([4d6e08a](https://github.com/ReVanced/revanced-patcher/commit/4d6e08a650dde6ec2e18611c5db1ab92b9a61dd1))
|
||||
|
||||
## [15.0.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0...v15.0.1) (2023-09-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Remove log management ([d51bc32](https://github.com/ReVanced/revanced-patcher/commit/d51bc32e37a865194c3825471085b3ccf8c78421))
|
||||
|
||||
## [15.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0...v15.0.1-dev.1) (2023-09-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Remove log management ([d51bc32](https://github.com/ReVanced/revanced-patcher/commit/d51bc32e37a865194c3825471085b3ccf8c78421))
|
||||
|
||||
# [15.0.0](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0) (2023-09-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Account for source patch dependency for tests ([6918418](https://github.com/ReVanced/revanced-patcher/commit/69184187d90f126478d2f49415c1e3381217557f))
|
||||
* Always make the generated patch depend on the source patch ([8de3063](https://github.com/ReVanced/revanced-patcher/commit/8de30633ae6eb7acf7f0a351e26d4a6c2fdbdfec))
|
||||
* Catch correct exception ([637d487](https://github.com/ReVanced/revanced-patcher/commit/637d48746ff8694e01c5aead1c75a9a1efeb5ac8))
|
||||
* Delegate `PatchBundleLoader` by mutable set of patches ([9a109c1](https://github.com/ReVanced/revanced-patcher/commit/9a109c129b135a634be1aad4130a06d9e8e96ecd))
|
||||
* Do not resolve the proxied patch to the proxy in the dependency list ([e112837](https://github.com/ReVanced/revanced-patcher/commit/e11283744a21fe2d09435e99d6924462b6aac3b8))
|
||||
* Do not set `CompatiblePackage.versions` if `@CompatiblePackage.versions` is empty ([6b1e0a1](https://github.com/ReVanced/revanced-patcher/commit/6b1e0a16568124e9f82fb5740353360fa8ec614a))
|
||||
* Filter for patches correctly ([4bc4b0d](https://github.com/ReVanced/revanced-patcher/commit/4bc4b0dc0104073b62528d02a88383cecd7a50e7))
|
||||
* Find dependency in `context.allPatches` ([670f015](https://github.com/ReVanced/revanced-patcher/commit/670f0153de10c6f0db25b08df1c01a2905037f84))
|
||||
* Log the correct patch names ([9fdb8f0](https://github.com/ReVanced/revanced-patcher/commit/9fdb8f087f62babf6081879db65c80db639aa0a7))
|
||||
* Make `CompatiblePackage.versions` a property ([67b7dff](https://github.com/ReVanced/revanced-patcher/commit/67b7dff67a212b4fc30eb4f0cbe58f0ba09fb09a))
|
||||
* Print patch name instead of class name ([4e7811e](https://github.com/ReVanced/revanced-patcher/commit/4e7811ea07762667a1f22526dc176022038f60eb))
|
||||
* Print stack trace of exception ([aa71146](https://github.com/ReVanced/revanced-patcher/commit/aa71146b1bf4ffebcc81a1663e15abae89e97ff0))
|
||||
* Run code-block if `executablePatches` does not yet contain `patch` ([1d7aeca](https://github.com/ReVanced/revanced-patcher/commit/1d7aeca696be873dfaf88eaa6d312949a3b8572b))
|
||||
* Suppress logger when loading patches in `PatchBundleLoader` ([72c9eb2](https://github.com/ReVanced/revanced-patcher/commit/72c9eb212985f99f3390cf1faa10ab547d2dbe7e))
|
||||
* Use correct module name ([080fbe9](https://github.com/ReVanced/revanced-patcher/commit/080fbe9feb9d4ea9ec4e599ecef296eacd803b05))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* Internalize processor constructor ([a802d0d](https://github.com/ReVanced/revanced-patcher/commit/a802d0df463695976e85d8391762942eb977920b))
|
||||
|
||||
|
||||
* feat Use `Set` as super type for `PatchBundleLoader` ([4b76d19](https://github.com/ReVanced/revanced-patcher/commit/4b76d1959691babf8c99d3d5235df4a4388956f0))
|
||||
* feat!: Add patch annotation processor ([3fc6a13](https://github.com/ReVanced/revanced-patcher/commit/3fc6a139eef67237c116fb4e3e29bf9542d3a981))
|
||||
* feat!: Remove patch annotations ([3b4db3d](https://github.com/ReVanced/revanced-patcher/commit/3b4db3ddb72cdcee8af2f787eadf58eeb37543de))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add patch annotation processor ([#231](https://github.com/ReVanced/revanced-patcher/issues/231)) ([a29931f](https://github.com/ReVanced/revanced-patcher/commit/a29931f2ec0a666dba209b54855425d9dc2f4462))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This gets rid of the public constructor.
|
||||
* `PatchBundleLoader` is not a map anymore
|
||||
* This renames packages and the Maven package.
|
||||
* The manifest for patches has been removed, and the properties have been added to patches. Patches are now `OptionsContainer`. The `@Patch` annotation has been removed in favour of the `@Patch` annotation from the annotation processor.
|
||||
* Patch annotations have been removed. PatcherException is now thrown in various places. PatchBundleLoader is now a map of patches associated by their name. Patches are now instances.
|
||||
|
||||
# [15.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.3...v15.0.0-dev.4) (2023-09-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Account for source patch dependency for tests ([6918418](https://github.com/ReVanced/revanced-patcher/commit/69184187d90f126478d2f49415c1e3381217557f))
|
||||
* Always make the generated patch depend on the source patch ([8de3063](https://github.com/ReVanced/revanced-patcher/commit/8de30633ae6eb7acf7f0a351e26d4a6c2fdbdfec))
|
||||
* Catch correct exception ([637d487](https://github.com/ReVanced/revanced-patcher/commit/637d48746ff8694e01c5aead1c75a9a1efeb5ac8))
|
||||
* Delegate `PatchBundleLoader` by mutable set of patches ([9a109c1](https://github.com/ReVanced/revanced-patcher/commit/9a109c129b135a634be1aad4130a06d9e8e96ecd))
|
||||
* Do not resolve the proxied patch to the proxy in the dependency list ([e112837](https://github.com/ReVanced/revanced-patcher/commit/e11283744a21fe2d09435e99d6924462b6aac3b8))
|
||||
* Do not set `CompatiblePackage.versions` if `@CompatiblePackage.versions` is empty ([6b1e0a1](https://github.com/ReVanced/revanced-patcher/commit/6b1e0a16568124e9f82fb5740353360fa8ec614a))
|
||||
* Filter for patches correctly ([4bc4b0d](https://github.com/ReVanced/revanced-patcher/commit/4bc4b0dc0104073b62528d02a88383cecd7a50e7))
|
||||
* Find dependency in `context.allPatches` ([670f015](https://github.com/ReVanced/revanced-patcher/commit/670f0153de10c6f0db25b08df1c01a2905037f84))
|
||||
* Log the correct patch names ([9fdb8f0](https://github.com/ReVanced/revanced-patcher/commit/9fdb8f087f62babf6081879db65c80db639aa0a7))
|
||||
* Print patch name instead of class name ([4e7811e](https://github.com/ReVanced/revanced-patcher/commit/4e7811ea07762667a1f22526dc176022038f60eb))
|
||||
* Print stack trace of exception ([aa71146](https://github.com/ReVanced/revanced-patcher/commit/aa71146b1bf4ffebcc81a1663e15abae89e97ff0))
|
||||
* Run code-block if `executablePatches` does not yet contain `patch` ([1d7aeca](https://github.com/ReVanced/revanced-patcher/commit/1d7aeca696be873dfaf88eaa6d312949a3b8572b))
|
||||
* Suppress logger when loading patches in `PatchBundleLoader` ([72c9eb2](https://github.com/ReVanced/revanced-patcher/commit/72c9eb212985f99f3390cf1faa10ab547d2dbe7e))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* Internalize processor constructor ([a802d0d](https://github.com/ReVanced/revanced-patcher/commit/a802d0df463695976e85d8391762942eb977920b))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This gets rid of the public constructor.
|
||||
|
||||
# [15.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.2...v15.0.0-dev.3) (2023-09-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Make `CompatiblePackage.versions` a property ([67b7dff](https://github.com/ReVanced/revanced-patcher/commit/67b7dff67a212b4fc30eb4f0cbe58f0ba09fb09a))
|
||||
* Use correct module name ([080fbe9](https://github.com/ReVanced/revanced-patcher/commit/080fbe9feb9d4ea9ec4e599ecef296eacd803b05))
|
||||
|
||||
|
||||
* feat Use `Set` as super type for `PatchBundleLoader` ([4b76d19](https://github.com/ReVanced/revanced-patcher/commit/4b76d1959691babf8c99d3d5235df4a4388956f0))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* `PatchBundleLoader` is not a map anymore
|
||||
* This renames packages and the Maven package.
|
||||
|
||||
# [15.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.1...v15.0.0-dev.2) (2023-09-06)
|
||||
|
||||
# [15.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0-dev.1) (2023-09-04)
|
||||
|
||||
|
||||
* feat!: Add patch annotation processor ([3fc6a13](https://github.com/ReVanced/revanced-patcher/commit/3fc6a139eef67237c116fb4e3e29bf9542d3a981))
|
||||
* feat!: Remove patch annotations ([3b4db3d](https://github.com/ReVanced/revanced-patcher/commit/3b4db3ddb72cdcee8af2f787eadf58eeb37543de))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add patch annotation processor ([#231](https://github.com/ReVanced/revanced-patcher/issues/231)) ([a29931f](https://github.com/ReVanced/revanced-patcher/commit/a29931f2ec0a666dba209b54855425d9dc2f4462))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* The manifest for patches has been removed, and the properties have been added to patches. Patches are now `OptionsContainer`. The `@Patch` annotation has been removed in favour of the `@Patch` annotation from the annotation processor.
|
||||
* Patch annotations have been removed. PatcherException is now thrown in various places. PatchBundleLoader is now a map of patches associated by their name. Patches are now instances.
|
||||
|
||||
## [14.2.2](https://github.com/ReVanced/revanced-patcher/compare/v14.2.1...v14.2.2) (2023-08-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow setting `DexClassLoader.optimizedDirectory` ([11a3378](https://github.com/ReVanced/revanced-patcher/commit/11a337865947a6ac74a63ebb3f3f9bc2610f7771))
|
||||
|
||||
## [14.2.2-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.1...v14.2.2-dev.1) (2023-08-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow setting `DexClassLoader.optimizedDirectory` ([11a3378](https://github.com/ReVanced/revanced-patcher/commit/11a337865947a6ac74a63ebb3f3f9bc2610f7771))
|
||||
|
||||
## [14.2.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.0...v14.2.1) (2023-08-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not flag resource table as sparse when main package is not loaded ([b832812](https://github.com/ReVanced/revanced-patcher/commit/b832812767a06ec6ec232291e6d14c8c2f14118c))
|
||||
|
||||
## [14.2.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.0...v14.2.1-dev.1) (2023-08-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not flag resource table as sparse when main package is not loaded ([b832812](https://github.com/ReVanced/revanced-patcher/commit/b832812767a06ec6ec232291e6d14c8c2f14118c))
|
||||
|
||||
# [14.2.0](https://github.com/ReVanced/revanced-patcher/compare/v14.1.0...v14.2.0) (2023-08-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* load patches in lexicographical order ([e8f2087](https://github.com/ReVanced/revanced-patcher/commit/e8f2087a6ffa6077fb3a6a69e29f3aec72e2fc1b))
|
||||
* log when merging integrations ([983563e](https://github.com/ReVanced/revanced-patcher/commit/983563efb6d7c8d289464b8bf71a016b8a735630))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* compare types of classes ([55d6945](https://github.com/ReVanced/revanced-patcher/commit/55d694579ac2718b9e2c61ca5f38419c3775ef87))
|
||||
|
||||
# [14.2.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v14.2.0-dev.2...v14.2.0-dev.3) (2023-08-26)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* compare types of classes ([55d6945](https://github.com/ReVanced/revanced-patcher/commit/55d694579ac2718b9e2c61ca5f38419c3775ef87))
|
||||
|
||||
# [14.2.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v14.2.0-dev.1...v14.2.0-dev.2) (2023-08-26)
|
||||
|
||||
|
||||
|
||||
@@ -1,57 +1,10 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.8.20"
|
||||
`maven-publish`
|
||||
kotlin("jvm") version "1.9.0" apply false
|
||||
alias(libs.plugins.binary.compatibility.validator)
|
||||
}
|
||||
|
||||
group = "app.revanced"
|
||||
allprojects {
|
||||
apply(plugin = "maven-publish")
|
||||
|
||||
dependencies {
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.xpp3)
|
||||
implementation(libs.smali)
|
||||
implementation(libs.multidexlib2)
|
||||
implementation(libs.apktool.lib)
|
||||
implementation(libs.kotlin.reflect)
|
||||
|
||||
compileOnly(libs.android)
|
||||
|
||||
testImplementation(libs.kotlin.test)
|
||||
}
|
||||
|
||||
tasks {
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events("PASSED", "SKIPPED", "FAILED")
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
expand("projectVersion" to project.version)
|
||||
}
|
||||
}
|
||||
|
||||
kotlin { jvmToolchain(11) }
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
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<MavenPublication>("gpr") {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
group = "app.revanced"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 14.2.0-dev.2
|
||||
version = 15.0.3-dev.1
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
[versions]
|
||||
android = "4.1.1.4"
|
||||
kotlin-reflect = "1.9.0"
|
||||
apktool-lib = "2.8.2-5"
|
||||
apktool-lib = "2.8.2-6"
|
||||
kotlin-test = "1.8.20-RC"
|
||||
kotlinx-coroutines-core = "1.7.1"
|
||||
multidexlib2 = "3.0.3.r2"
|
||||
shadow = "8.1.1"
|
||||
smali = "3.0.3"
|
||||
symbol-processing-api = "1.9.0-1.0.11"
|
||||
xpp3 = "1.1.4c"
|
||||
|
||||
binary-compatibility-validator = "0.13.2"
|
||||
kotlin-compile-testing-ksp = "1.5.0"
|
||||
kotlinpoet-ksp = "1.14.2"
|
||||
ksp = "1.9.0-1.0.11"
|
||||
|
||||
[libraries]
|
||||
android = { module = "com.google.android:android", version.ref = "android" }
|
||||
@@ -18,4 +21,11 @@ kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotl
|
||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" }
|
||||
multidexlib2 = { module = "app.revanced:multidexlib2", version.ref = "multidexlib2" }
|
||||
smali = { module = "com.android.tools.smali:smali", version.ref = "smali" }
|
||||
symbol-processing-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "symbol-processing-api" }
|
||||
xpp3 = { module = "xpp3:xpp3", version.ref = "xpp3" }
|
||||
kotlin-compile-testing = { module = "com.github.tschuchortdev:kotlin-compile-testing-ksp", version.ref = "kotlin-compile-testing-ksp" }
|
||||
kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlinpoet-ksp" }
|
||||
|
||||
[plugins]
|
||||
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
|
||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
@@ -0,0 +1,24 @@
|
||||
public abstract interface annotation class app/revanced/patcher/patch/annotation/CompatiblePackage : java/lang/annotation/Annotation {
|
||||
public abstract fun name ()Ljava/lang/String;
|
||||
public abstract fun versions ()[Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract interface annotation class app/revanced/patcher/patch/annotation/Patch : java/lang/annotation/Annotation {
|
||||
public abstract fun compatiblePackages ()[Lapp/revanced/patcher/patch/annotation/CompatiblePackage;
|
||||
public abstract fun dependencies ()[Ljava/lang/Class;
|
||||
public abstract fun description ()Ljava/lang/String;
|
||||
public abstract fun name ()Ljava/lang/String;
|
||||
public abstract fun requiresIntegrations ()Z
|
||||
public abstract fun use ()Z
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/annotation/processor/PatchProcessor : com/google/devtools/ksp/processing/SymbolProcessor {
|
||||
public fun process (Lcom/google/devtools/ksp/processing/Resolver;)Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/annotation/processor/PatchProcessorProvider : com/google/devtools/ksp/processing/SymbolProcessorProvider {
|
||||
public fun <init> ()V
|
||||
public fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lapp/revanced/patcher/patch/annotation/processor/PatchProcessor;
|
||||
public synthetic fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lcom/google/devtools/ksp/processing/SymbolProcessor;
|
||||
}
|
||||
|
||||
74
revanced-patch-annotation-processor/build.gradle.kts
Normal file
74
revanced-patch-annotation-processor/build.gradle.kts
Normal file
@@ -0,0 +1,74 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.9.0"
|
||||
alias(libs.plugins.ksp)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.symbol.processing.api)
|
||||
implementation(libs.kotlinpoet.ksp)
|
||||
implementation(project(":revanced-patcher"))
|
||||
|
||||
testImplementation(libs.kotlin.test)
|
||||
testImplementation(libs.kotlin.compile.testing)
|
||||
}
|
||||
|
||||
tasks {
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events("PASSED", "SKIPPED", "FAILED")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kotlin { jvmToolchain(11) }
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
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<MavenPublication>("gpr") {
|
||||
from(components["java"])
|
||||
|
||||
version = project.version.toString()
|
||||
|
||||
pom {
|
||||
name = "ReVanced patch annotation processor"
|
||||
description = "Annotation processor for patches."
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
revanced-patch-annotation-processor/settings.gradle.kts
Normal file
2
revanced-patch-annotation-processor/settings.gradle.kts
Normal file
@@ -0,0 +1,2 @@
|
||||
rootProject.name = "revanced-patch-annotation-processor"
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package app.revanced.patcher.patch.annotation
|
||||
|
||||
import java.lang.annotation.Inherited
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Annotation for [app.revanced.patcher.patch.Patch] classes.
|
||||
*
|
||||
* @param name The name of the patch. If empty, the patch will be unnamed.
|
||||
* @param description The description of the patch. If empty, no description will be used.
|
||||
* @param dependencies The patches this patch depends on.
|
||||
* @param compatiblePackages The packages this patch is compatible with.
|
||||
* @param use Whether this patch should be used.
|
||||
* @param requiresIntegrations Whether this patch requires integrations.
|
||||
*/
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Inherited
|
||||
annotation class Patch(
|
||||
val name: String = "",
|
||||
val description: String = "",
|
||||
val dependencies: Array<KClass<out app.revanced.patcher.patch.Patch<*>>> = [],
|
||||
val compatiblePackages: Array<CompatiblePackage> = [],
|
||||
val use: Boolean = true,
|
||||
// TODO: Remove this property, once integrations are coupled with patches.
|
||||
val requiresIntegrations: Boolean = false,
|
||||
)
|
||||
|
||||
/**
|
||||
* A package that a [app.revanced.patcher.patch.Patch] is compatible with.
|
||||
*
|
||||
* @param name The name of the package.
|
||||
* @param versions The versions of the package.
|
||||
*/
|
||||
annotation class CompatiblePackage(
|
||||
val name: String,
|
||||
val versions: Array<String> = [],
|
||||
)
|
||||
@@ -0,0 +1,207 @@
|
||||
package app.revanced.patcher.patch.annotation.processor
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import com.google.devtools.ksp.processing.CodeGenerator
|
||||
import com.google.devtools.ksp.processing.Dependencies
|
||||
import com.google.devtools.ksp.processing.Resolver
|
||||
import com.google.devtools.ksp.processing.SymbolProcessor
|
||||
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||
import com.google.devtools.ksp.symbol.KSAnnotation
|
||||
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||
import com.google.devtools.ksp.symbol.KSType
|
||||
import com.google.devtools.ksp.validate
|
||||
import com.squareup.kotlinpoet.*
|
||||
import com.squareup.kotlinpoet.ksp.toClassName
|
||||
import com.squareup.kotlinpoet.ksp.writeTo
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class PatchProcessor internal constructor(
|
||||
private val codeGenerator: CodeGenerator,
|
||||
) : SymbolProcessor {
|
||||
|
||||
private fun KSAnnotated.isSubclassOf(cls: KClass<*>): Boolean {
|
||||
if (this !is KSClassDeclaration) return false
|
||||
|
||||
if (qualifiedName?.asString() == cls.qualifiedName) return true
|
||||
|
||||
return superTypes.any { it.resolve().declaration.isSubclassOf(cls) }
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun process(resolver: Resolver): List<KSAnnotated> {
|
||||
val patches = buildMap {
|
||||
resolver.getSymbolsWithAnnotation(Patch::class.qualifiedName!!).filter {
|
||||
// Do not check here if Patch is super of the class, because it is expensive.
|
||||
// Check it later when processing.
|
||||
it.validate() && it.isSubclassOf(app.revanced.patcher.patch.Patch::class)
|
||||
}.map {
|
||||
it as KSClassDeclaration
|
||||
}.forEach { patchDeclaration ->
|
||||
patchDeclaration.annotations.find {
|
||||
it.annotationType.resolve().declaration.qualifiedName!!.asString() == Patch::class.qualifiedName!!
|
||||
}?.let { annotation ->
|
||||
fun KSAnnotation.property(name: String) =
|
||||
arguments.find { it.name!!.asString() == name }?.value!!
|
||||
|
||||
val name =
|
||||
annotation.property("name").toString().ifEmpty { null }
|
||||
|
||||
val description =
|
||||
annotation.property("description").toString().ifEmpty { null }
|
||||
|
||||
val dependencies =
|
||||
(annotation.property("dependencies") as List<KSType>).ifEmpty { null }
|
||||
|
||||
val compatiblePackages =
|
||||
(annotation.property("compatiblePackages") as List<KSAnnotation>).ifEmpty { null }
|
||||
|
||||
val use =
|
||||
annotation.property("use") as Boolean
|
||||
|
||||
val requiresIntegrations =
|
||||
annotation.property("requiresIntegrations") as Boolean
|
||||
|
||||
// Data class for KotlinPoet
|
||||
data class PatchData(
|
||||
val name: String?,
|
||||
val description: String?,
|
||||
val dependencies: List<ClassName>?,
|
||||
val compatiblePackages: List<CodeBlock>?,
|
||||
val use: Boolean,
|
||||
val requiresIntegrations: Boolean
|
||||
)
|
||||
|
||||
this[patchDeclaration] = PatchData(
|
||||
name,
|
||||
description,
|
||||
dependencies?.map { dependency -> dependency.toClassName() },
|
||||
compatiblePackages?.map {
|
||||
val packageName = it.property("name")
|
||||
val packageVersions = (it.property("versions") as List<String>).ifEmpty { null }
|
||||
?.joinToString(", ") { version -> "\"$version\"" }
|
||||
|
||||
CodeBlock.of(
|
||||
"%T(%S, %L)",
|
||||
app.revanced.patcher.patch.Patch.CompatiblePackage::class,
|
||||
packageName,
|
||||
packageVersions?.let { "setOf($packageVersions)" },
|
||||
)
|
||||
},
|
||||
use,
|
||||
requiresIntegrations
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If a patch depends on another, that is annotated, the dependency should be replaced with the generated patch,
|
||||
// because the generated patch has all the necessary properties to invoke the super constructor with,
|
||||
// unlike the annotated patch.
|
||||
val dependencyResolutionMap = buildMap {
|
||||
patches.values.filter { it.dependencies != null }.flatMap {
|
||||
it.dependencies!!
|
||||
}.distinct().forEach { dependency ->
|
||||
patches.keys.find { it.qualifiedName?.asString() == dependency.toString() }
|
||||
?.let { patch ->
|
||||
this[dependency] = ClassName(
|
||||
patch.packageName.asString(),
|
||||
patch.simpleName.asString() + "Generated"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
patches.forEach { (patchDeclaration, patchAnnotation) ->
|
||||
val isBytecodePatch = patchDeclaration.isSubclassOf(BytecodePatch::class)
|
||||
|
||||
val superClass = if (isBytecodePatch) {
|
||||
BytecodePatch::class
|
||||
} else {
|
||||
ResourcePatch::class
|
||||
}
|
||||
|
||||
val contextClass = if (isBytecodePatch) {
|
||||
BytecodeContext::class
|
||||
} else {
|
||||
ResourceContext::class
|
||||
}
|
||||
|
||||
val generatedPatchClassName = ClassName(
|
||||
patchDeclaration.packageName.asString(),
|
||||
patchDeclaration.simpleName.asString() + "Generated"
|
||||
)
|
||||
|
||||
FileSpec.builder(generatedPatchClassName)
|
||||
.addType(
|
||||
TypeSpec.objectBuilder(generatedPatchClassName)
|
||||
.superclass(superClass).apply {
|
||||
patchAnnotation.name?.let { name ->
|
||||
addSuperclassConstructorParameter("name = %S", name)
|
||||
}
|
||||
|
||||
patchAnnotation.description?.let { description ->
|
||||
addSuperclassConstructorParameter("description = %S", description)
|
||||
}
|
||||
|
||||
patchAnnotation.compatiblePackages?.let { compatiblePackages ->
|
||||
addSuperclassConstructorParameter(
|
||||
"compatiblePackages = setOf(%L)",
|
||||
compatiblePackages.joinToString(", ")
|
||||
)
|
||||
}
|
||||
|
||||
// The generated patch always depends on the source patch.
|
||||
addSuperclassConstructorParameter(
|
||||
"dependencies = setOf(%L)",
|
||||
buildList {
|
||||
patchAnnotation.dependencies?.forEach { dependency ->
|
||||
add("${(dependencyResolutionMap[dependency] ?: dependency)}::class")
|
||||
}
|
||||
|
||||
add("${patchDeclaration.toClassName()}::class")
|
||||
}.joinToString(", "),
|
||||
)
|
||||
|
||||
addSuperclassConstructorParameter(
|
||||
"use = %L", patchAnnotation.use
|
||||
)
|
||||
|
||||
addSuperclassConstructorParameter(
|
||||
"requiresIntegrations = %L",
|
||||
patchAnnotation.requiresIntegrations
|
||||
)
|
||||
}
|
||||
.addFunction(
|
||||
FunSpec.builder("execute")
|
||||
.addModifiers(KModifier.OVERRIDE)
|
||||
.addParameter("context", contextClass)
|
||||
.build()
|
||||
)
|
||||
.addInitializerBlock(
|
||||
CodeBlock.builder()
|
||||
.add(
|
||||
"%T.options.forEach { (_, option) ->",
|
||||
patchDeclaration.toClassName()
|
||||
)
|
||||
.addStatement(
|
||||
"options.register(option)"
|
||||
)
|
||||
.add(
|
||||
"}"
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
).build().writeTo(
|
||||
codeGenerator,
|
||||
Dependencies(false, patchDeclaration.containingFile!!)
|
||||
)
|
||||
}
|
||||
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patcher.patch.annotation.processor
|
||||
|
||||
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
|
||||
import com.google.devtools.ksp.processing.SymbolProcessorProvider
|
||||
|
||||
class PatchProcessorProvider : SymbolProcessorProvider {
|
||||
override fun create(environment: SymbolProcessorEnvironment) =
|
||||
PatchProcessor(environment.codeGenerator)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
app.revanced.patcher.patch.annotation.processor.PatchProcessorProvider
|
||||
@@ -0,0 +1,147 @@
|
||||
package app.revanced.patcher.patch.annotation.processor
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import com.tschuchort.compiletesting.KotlinCompilation
|
||||
import com.tschuchort.compiletesting.SourceFile
|
||||
import com.tschuchort.compiletesting.kspWithCompilation
|
||||
import com.tschuchort.compiletesting.symbolProcessorProviders
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNull
|
||||
|
||||
class TestPatchAnnotationProcessor {
|
||||
// region Processing
|
||||
|
||||
@Test
|
||||
fun testProcessing() = assertEquals(
|
||||
"Processable patch", compile(
|
||||
getSourceFile(
|
||||
"processing", "ProcessablePatch"
|
||||
)
|
||||
).loadPatch("$SAMPLE_PACKAGE.processing.ProcessablePatchGenerated").name
|
||||
)
|
||||
|
||||
@Test
|
||||
fun generateNullProperties() = compile(
|
||||
getSourceFile(
|
||||
"null", "NullPropertiesPatch"
|
||||
)
|
||||
).loadPatch("$SAMPLE_PACKAGE.null.NullPropertiesPatchGenerated").let {
|
||||
assertNull(it.description) // Because no description was provided.
|
||||
assertNull(it.compatiblePackages!!.first().versions) // Because no versions were provided.
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Dependencies
|
||||
|
||||
@Test
|
||||
fun testDependencies() {
|
||||
compile(
|
||||
getSourceFile(
|
||||
"dependencies", "DependentPatch"
|
||||
), getSourceFile(
|
||||
"dependencies", "DependencyPatch"
|
||||
)
|
||||
).let { result ->
|
||||
result.loadPatch("$SAMPLE_PACKAGE.dependencies.DependentPatchGenerated").let {
|
||||
// Dependency as well as the source class of the generated class.
|
||||
assertEquals(
|
||||
2,
|
||||
it.dependencies!!.size
|
||||
)
|
||||
|
||||
// The last dependency is always the source class of the generated class to respect
|
||||
// order of dependencies.
|
||||
assertEquals(
|
||||
result.loadPatch("$SAMPLE_PACKAGE.dependencies.DependentPatch")::class,
|
||||
it.dependencies!!.last()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Options
|
||||
|
||||
@Test
|
||||
fun testOptions() {
|
||||
val patch = compile(
|
||||
getSourceFile(
|
||||
"options", "OptionsPatch"
|
||||
)
|
||||
).loadPatch("$SAMPLE_PACKAGE.options.OptionsPatchGenerated")
|
||||
|
||||
assert(patch.options.isNotEmpty())
|
||||
assertEquals(patch.options["print"].title, "Print message")
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Limitations
|
||||
|
||||
@Test
|
||||
fun failingManualDependency() = assertEquals(
|
||||
1, // Generated patch is always dependent on source class.
|
||||
compile(
|
||||
getSourceFile(
|
||||
"limitations/manualdependency", "DependentPatch"
|
||||
), getSourceFile(
|
||||
"limitations/manualdependency", "DependencyPatch"
|
||||
)
|
||||
).loadPatch("$SAMPLE_PACKAGE.limitations.manualdependency.DependentPatchGenerated").dependencies!!.size
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
private companion object Utils {
|
||||
const val SAMPLE_PACKAGE = "app.revanced.patcher.patch.annotation.processor.samples"
|
||||
|
||||
/**
|
||||
* Get a source file from the given sample and class name.
|
||||
*
|
||||
* @param sample The sample to get the source file from.
|
||||
* @param className The name of the class to get the source file from.
|
||||
* @return The source file.
|
||||
*/
|
||||
fun getSourceFile(sample: String, className: String): SourceFile {
|
||||
val resourceName = "app/revanced/patcher/patch/annotation/processor/samples/$sample/$className.kt"
|
||||
return SourceFile.kotlin(
|
||||
"$className.kt",
|
||||
TestPatchAnnotationProcessor::class.java.classLoader.getResourceAsStream(resourceName)
|
||||
?.readAllBytes()
|
||||
?.toString(Charsets.UTF_8)
|
||||
?: error("Could not find resource $resourceName")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the given source files and return the result.
|
||||
*
|
||||
* @param sourceFiles The source files to compile.
|
||||
* @return The result of the compilation.
|
||||
*/
|
||||
fun compile(vararg sourceFiles: SourceFile) = KotlinCompilation().apply {
|
||||
sources = sourceFiles.asList()
|
||||
|
||||
symbolProcessorProviders = listOf(PatchProcessorProvider())
|
||||
|
||||
// Required until https://github.com/tschuchortdev/kotlin-compile-testing/issues/312 closed.
|
||||
kspWithCompilation = true
|
||||
|
||||
inheritClassPath = true
|
||||
messageOutputStream = System.out
|
||||
}.compile().also { result ->
|
||||
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode)
|
||||
}
|
||||
|
||||
// region Class loading
|
||||
|
||||
fun KotlinCompilation.Result.loadPatch(name: String) = classLoader.loadClass(name).loadPatch()
|
||||
|
||||
fun Class<*>.loadPatch() = this.getField("INSTANCE").get(null) as Patch<*>
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.dependencies
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(name = "Dependency patch")
|
||||
object DependencyPatch : ResourcePatch() {
|
||||
override fun execute(context: ResourceContext) {}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.dependencies
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(
|
||||
name = "Dependent patch",
|
||||
dependencies = [DependencyPatch::class],
|
||||
)
|
||||
object DependentPatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext) {}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.limitations.manualdependency
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(name = "Dependency patch")
|
||||
object DependencyPatch : ResourcePatch() {
|
||||
override fun execute(context: ResourceContext) { }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.limitations.manualdependency
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(name = "Dependent patch")
|
||||
object DependentPatch : BytecodePatch(
|
||||
// Dependency will not be executed correctly if it is manually specified.
|
||||
// The reason for this is that the dependency patch is annotated too,
|
||||
// so the processor will generate a new patch class for it embedding the annotated information.
|
||||
// Because the dependency is manually specified,
|
||||
// the processor will not be able to change this dependency to the generated class,
|
||||
// which means that the dependency will lose the annotated information.
|
||||
dependencies = setOf(DependencyPatch::class)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.`null`
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch(
|
||||
"Patch with null properties",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.youtube")],
|
||||
)
|
||||
object NullPropertiesPatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext) {}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.options
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
|
||||
|
||||
@Patch(name = "Options patch")
|
||||
object OptionsPatch : ResourcePatch() {
|
||||
override fun execute(context: ResourceContext) {}
|
||||
|
||||
@Suppress("unused")
|
||||
private val printOption by stringPatchOption(
|
||||
"print",
|
||||
null,
|
||||
"Print message",
|
||||
"The message to print."
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patcher.patch.annotation.processor.samples.processing
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
|
||||
@Patch("Processable patch")
|
||||
object ProcessablePatch : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext) {}
|
||||
}
|
||||
904
revanced-patcher/api/revanced-patcher.api
Normal file
904
revanced-patcher/api/revanced-patcher.api
Normal file
@@ -0,0 +1,904 @@
|
||||
public abstract interface class app/revanced/patcher/IntegrationsConsumer {
|
||||
public abstract fun acceptIntegrations (Ljava/util/List;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/PackageMetadata {
|
||||
public final fun getPackageName ()Ljava/lang/String;
|
||||
public final fun getPackageVersion ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patcher/PatchBundleLoader : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public synthetic fun <init> (Ljava/lang/ClassLoader;[Ljava/io/File;Lkotlin/jvm/functions/Function1;Ljava/util/Set;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
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 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/PatchBundleLoader$Dex : app/revanced/patcher/PatchBundleLoader {
|
||||
public fun <init> ([Ljava/io/File;)V
|
||||
public fun <init> ([Ljava/io/File;Ljava/io/File;)V
|
||||
public synthetic fun <init> ([Ljava/io/File;Ljava/io/File;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/PatchBundleLoader$Jar : app/revanced/patcher/PatchBundleLoader {
|
||||
public fun <init> ([Ljava/io/File;)V
|
||||
}
|
||||
|
||||
public abstract interface class app/revanced/patcher/PatchExecutorFunction : java/util/function/Function {
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/Patcher : app/revanced/patcher/IntegrationsConsumer, app/revanced/patcher/PatchExecutorFunction, app/revanced/patcher/PatchesConsumer, java/io/Closeable, java/util/function/Supplier {
|
||||
public fun <init> (Lapp/revanced/patcher/PatcherOptions;)V
|
||||
public fun acceptIntegrations (Ljava/util/List;)V
|
||||
public fun acceptPatches (Ljava/util/List;)V
|
||||
public synthetic fun apply (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun apply (Z)Lkotlinx/coroutines/flow/Flow;
|
||||
public fun close ()V
|
||||
public fun get ()Lapp/revanced/patcher/PatcherResult;
|
||||
public synthetic fun get ()Ljava/lang/Object;
|
||||
public final fun getContext ()Lapp/revanced/patcher/PatcherContext;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/PatcherContext {
|
||||
public final fun getPackageMetadata ()Lapp/revanced/patcher/PackageMetadata;
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patcher/PatcherException : java/lang/Exception {
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Throwable;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/PatcherException$CircularDependencyException : app/revanced/patcher/PatcherException {
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/PatcherOptions {
|
||||
public fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;)V
|
||||
public synthetic fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun copy (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;)Lapp/revanced/patcher/PatcherOptions;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/PatcherOptions;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;ILjava/lang/Object;)Lapp/revanced/patcher/PatcherOptions;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun hashCode ()I
|
||||
public final fun recreateResourceCacheDirectory ()Ljava/io/File;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/PatcherResult {
|
||||
public fun <init> (Ljava/util/List;Ljava/io/File;Ljava/util/List;)V
|
||||
public synthetic fun <init> (Ljava/util/List;Ljava/io/File;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()Ljava/util/List;
|
||||
public final fun component2 ()Ljava/io/File;
|
||||
public final fun component3 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/util/List;Ljava/io/File;Ljava/util/List;)Lapp/revanced/patcher/PatcherResult;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/PatcherResult;Ljava/util/List;Ljava/io/File;Ljava/util/List;ILjava/lang/Object;)Lapp/revanced/patcher/PatcherResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getDexFiles ()Ljava/util/List;
|
||||
public final fun getDoNotCompress ()Ljava/util/List;
|
||||
public final fun getResourceFile ()Ljava/io/File;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/PatcherResult$PatchedDexFile {
|
||||
public fun <init> (Ljava/lang/String;Ljava/io/InputStream;)V
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun getStream ()Ljava/io/InputStream;
|
||||
}
|
||||
|
||||
public abstract interface class app/revanced/patcher/PatchesConsumer {
|
||||
public abstract fun acceptPatches (Ljava/util/List;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/data/BytecodeContext : app/revanced/patcher/data/Context {
|
||||
public final fun findClass (Ljava/lang/String;)Lapp/revanced/patcher/util/proxy/ClassProxy;
|
||||
public final fun findClass (Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/util/proxy/ClassProxy;
|
||||
public synthetic fun get ()Ljava/lang/Object;
|
||||
public fun get ()Ljava/util/List;
|
||||
public final fun getClasses ()Lapp/revanced/patcher/util/ProxyClassList;
|
||||
public final fun proxy (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/util/proxy/ClassProxy;
|
||||
public final fun toMethodWalker (Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/method/MethodWalker;
|
||||
}
|
||||
|
||||
public abstract interface class app/revanced/patcher/data/Context : java/util/function/Supplier {
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/data/ResourceContext : app/revanced/patcher/data/Context, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public fun get ()Ljava/io/File;
|
||||
public synthetic fun get ()Ljava/lang/Object;
|
||||
public final fun get (Ljava/lang/String;)Ljava/io/File;
|
||||
public final fun getXmlEditor ()Lapp/revanced/patcher/data/ResourceContext$XmlFileHolder;
|
||||
public fun iterator ()Ljava/util/Iterator;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/data/ResourceContext$XmlFileHolder {
|
||||
public fun <init> (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||
public final fun get (Ljava/io/InputStream;)Lapp/revanced/patcher/util/DomFileEditor;
|
||||
public final fun get (Ljava/lang/String;)Lapp/revanced/patcher/util/DomFileEditor;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/extensions/ExtensionsKt {
|
||||
public static final fun newLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/Label;
|
||||
public static final fun or (ILcom/android/tools/smali/dexlib2/AccessFlags;)I
|
||||
public static final fun or (Lcom/android/tools/smali/dexlib2/AccessFlags;I)I
|
||||
public static final fun or (Lcom/android/tools/smali/dexlib2/AccessFlags;Lcom/android/tools/smali/dexlib2/AccessFlags;)I
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/extensions/InstructionExtensions {
|
||||
public static final field INSTANCE Lapp/revanced/patcher/extensions/InstructionExtensions;
|
||||
public final fun addInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V
|
||||
public final fun addInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
|
||||
public final fun addInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V
|
||||
public final fun addInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
|
||||
public final fun addInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
|
||||
public final fun addInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/util/List;)V
|
||||
public final fun addInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
|
||||
public final fun addInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/util/List;)V
|
||||
public final fun addInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;ILjava/util/List;)V
|
||||
public final fun addInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;Ljava/util/List;)V
|
||||
public final fun addInstructionsWithLabels (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;[Lapp/revanced/patcher/util/smali/ExternalLabel;)V
|
||||
public final fun getInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;
|
||||
public final fun getInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)Ljava/lang/Object;
|
||||
public final fun getInstruction (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;
|
||||
public final fun getInstruction (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)Ljava/lang/Object;
|
||||
public final fun getInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;)Ljava/util/List;
|
||||
public final fun removeInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
|
||||
public final fun removeInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
|
||||
public final fun removeInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;II)V
|
||||
public final fun removeInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)V
|
||||
public final fun removeInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;II)V
|
||||
public final fun replaceInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V
|
||||
public final fun replaceInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
|
||||
public final fun replaceInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
|
||||
public final fun replaceInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/util/List;)V
|
||||
public final fun replaceInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;ILjava/util/List;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/extensions/MethodFingerprintExtensions {
|
||||
public static final field INSTANCE Lapp/revanced/patcher/extensions/MethodFingerprintExtensions;
|
||||
public final fun getFuzzyPatternScanMethod (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/method/annotation/FuzzyPatternScanMethod;
|
||||
}
|
||||
|
||||
public abstract interface class app/revanced/patcher/fingerprint/Fingerprint {
|
||||
}
|
||||
|
||||
public abstract interface annotation class app/revanced/patcher/fingerprint/method/annotation/FuzzyPatternScanMethod : java/lang/annotation/Annotation {
|
||||
public abstract fun threshold ()I
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patcher/fingerprint/method/impl/MethodFingerprint : app/revanced/patcher/fingerprint/Fingerprint {
|
||||
public static final field Companion Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprint$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getResult ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;
|
||||
public final fun setResult (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprint$Companion {
|
||||
public final fun resolve (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprint;Lapp/revanced/patcher/data/BytecodeContext;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z
|
||||
public final fun resolve (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprint;Lapp/revanced/patcher/data/BytecodeContext;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z
|
||||
public final fun resolve (Ljava/lang/Iterable;Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/Iterable;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult {
|
||||
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public final fun component1 ()Lcom/android/tools/smali/dexlib2/iface/Method;
|
||||
public final fun component2 ()Lcom/android/tools/smali/dexlib2/iface/ClassDef;
|
||||
public final fun component3 ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;
|
||||
public final fun copy (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;Lapp/revanced/patcher/data/BytecodeContext;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;Lapp/revanced/patcher/data/BytecodeContext;ILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getClassDef ()Lcom/android/tools/smali/dexlib2/iface/ClassDef;
|
||||
public final fun getMethod ()Lcom/android/tools/smali/dexlib2/iface/Method;
|
||||
public final fun getMutableClass ()Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;
|
||||
public final fun getMutableMethod ()Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;
|
||||
public final fun getScanResult ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult {
|
||||
public fun <init> (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;)V
|
||||
public final fun component1 ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;
|
||||
public final fun component2 ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;
|
||||
public final fun copy (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;ILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getPatternScanResult ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;
|
||||
public final fun getStringsScanResult ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult {
|
||||
public fun <init> (IILjava/util/List;)V
|
||||
public synthetic fun <init> (IILjava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun component1 ()I
|
||||
public final fun component2 ()I
|
||||
public final fun component3 ()Ljava/util/List;
|
||||
public final fun copy (IILjava/util/List;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;IILjava/util/List;ILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getEndIndex ()I
|
||||
public final fun getStartIndex ()I
|
||||
public final fun getWarnings ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public final fun setWarnings (Ljava/util/List;)V
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult$Warning {
|
||||
public fun <init> (Lcom/android/tools/smali/dexlib2/Opcode;Lcom/android/tools/smali/dexlib2/Opcode;II)V
|
||||
public final fun component1 ()Lcom/android/tools/smali/dexlib2/Opcode;
|
||||
public final fun component2 ()Lcom/android/tools/smali/dexlib2/Opcode;
|
||||
public final fun component3 ()I
|
||||
public final fun component4 ()I
|
||||
public final fun copy (Lcom/android/tools/smali/dexlib2/Opcode;Lcom/android/tools/smali/dexlib2/Opcode;II)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult$Warning;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult$Warning;Lcom/android/tools/smali/dexlib2/Opcode;Lcom/android/tools/smali/dexlib2/Opcode;IIILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult$Warning;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getCorrectOpcode ()Lcom/android/tools/smali/dexlib2/Opcode;
|
||||
public final fun getInstructionIndex ()I
|
||||
public final fun getPatternIndex ()I
|
||||
public final fun getWrongOpcode ()Lcom/android/tools/smali/dexlib2/Opcode;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult {
|
||||
public fun <init> (Ljava/util/List;)V
|
||||
public final fun component1 ()Ljava/util/List;
|
||||
public final fun copy (Ljava/util/List;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;Ljava/util/List;ILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getMatches ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult$StringMatch {
|
||||
public fun <init> (Ljava/lang/String;I)V
|
||||
public final fun component1 ()Ljava/lang/String;
|
||||
public final fun component2 ()I
|
||||
public final fun copy (Ljava/lang/String;I)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult$StringMatch;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult$StringMatch;Ljava/lang/String;IILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult$StringMatch;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getIndex ()I
|
||||
public final fun getString ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public abstract interface class app/revanced/patcher/logging/Logger {
|
||||
public abstract fun error (Ljava/lang/String;)V
|
||||
public abstract fun info (Ljava/lang/String;)V
|
||||
public abstract fun trace (Ljava/lang/String;)V
|
||||
public abstract fun warn (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/logging/Logger$DefaultImpls {
|
||||
public static fun error (Lapp/revanced/patcher/logging/Logger;Ljava/lang/String;)V
|
||||
public static fun info (Lapp/revanced/patcher/logging/Logger;Ljava/lang/String;)V
|
||||
public static fun trace (Lapp/revanced/patcher/logging/Logger;Ljava/lang/String;)V
|
||||
public static fun warn (Lapp/revanced/patcher/logging/Logger;Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/logging/impl/NopLogger : app/revanced/patcher/logging/Logger {
|
||||
public static final field INSTANCE Lapp/revanced/patcher/logging/impl/NopLogger;
|
||||
public fun error (Ljava/lang/String;)V
|
||||
public fun info (Ljava/lang/String;)V
|
||||
public fun trace (Ljava/lang/String;)V
|
||||
public fun warn (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patcher/patch/BytecodePatch : app/revanced/patcher/patch/Patch {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZ)V
|
||||
public synthetic fun <init> (Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patcher/patch/Patch {
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public abstract fun execute (Lapp/revanced/patcher/data/Context;)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/PatchOptions;
|
||||
public final fun getRequiresIntegrations ()Z
|
||||
public final fun getUse ()Z
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/Patch$CompatiblePackage {
|
||||
public fun <init> (Ljava/lang/String;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun getVersions ()Ljava/util/Set;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/PatchException : java/lang/Exception {
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
|
||||
public fun <init> (Ljava/lang/Throwable;)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 abstract class app/revanced/patcher/patch/ResourcePatch : app/revanced/patcher/patch/Patch {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZ)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patcher/patch/options/PatchOption {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)V
|
||||
public final fun getDescription ()Ljava/lang/String;
|
||||
public final fun getKey ()Ljava/lang/String;
|
||||
public final fun getRequired ()Z
|
||||
public final fun getTitle ()Ljava/lang/String;
|
||||
public final fun getValidate ()Lkotlin/jvm/functions/Function1;
|
||||
public final fun getValue ()Ljava/lang/Object;
|
||||
public final fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object;
|
||||
public final fun setValue (Ljava/lang/Object;)V
|
||||
public final fun setValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patcher/patch/options/PatchOptionException : java/lang/Exception {
|
||||
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$InvalidValueTypeException : app/revanced/patcher/patch/options/PatchOptionException {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$PatchOptionNotFoundException : java/lang/Exception {
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$ValueRequiredException : java/lang/Exception {
|
||||
public fun <init> (Lapp/revanced/patcher/patch/options/PatchOption;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/PatchOptionException$ValueValidationException : java/lang/Exception {
|
||||
public fun <init> (Ljava/lang/Object;Lapp/revanced/patcher/patch/options/PatchOption;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/PatchOptions : java/util/Map, kotlin/jvm/internal/markers/KMutableMap {
|
||||
public fun <init> ()V
|
||||
public fun clear ()V
|
||||
public final fun containsKey (Ljava/lang/Object;)Z
|
||||
public fun containsKey (Ljava/lang/String;)Z
|
||||
public fun containsValue (Lapp/revanced/patcher/patch/options/PatchOption;)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/options/PatchOption;
|
||||
public final synthetic fun get (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun get (Ljava/lang/String;)Lapp/revanced/patcher/patch/options/PatchOption;
|
||||
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;Lapp/revanced/patcher/patch/options/PatchOption;)Lapp/revanced/patcher/patch/options/PatchOption;
|
||||
public fun putAll (Ljava/util/Map;)V
|
||||
public final fun register (Lapp/revanced/patcher/patch/options/PatchOption;)V
|
||||
public final fun remove (Ljava/lang/Object;)Lapp/revanced/patcher/patch/options/PatchOption;
|
||||
public final synthetic fun remove (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun remove (Ljava/lang/String;)Lapp/revanced/patcher/patch/options/PatchOption;
|
||||
public final fun set (Ljava/lang/String;Ljava/lang/Object;)V
|
||||
public final fun size ()I
|
||||
public final fun values ()Ljava/util/Collection;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/BooleanPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/BooleanPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/BooleanPatchOption$Companion {
|
||||
public final fun booleanPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/BooleanPatchOption;
|
||||
public static synthetic fun booleanPatchOption$default (Lapp/revanced/patcher/patch/options/types/BooleanPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/BooleanPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/FloatPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/FloatPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/FloatPatchOption$Companion {
|
||||
public final fun floatPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/FloatPatchOption;
|
||||
public static synthetic fun floatPatchOption$default (Lapp/revanced/patcher/patch/options/types/FloatPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/FloatPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/IntPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/IntPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/IntPatchOption$Companion {
|
||||
public final fun intPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/IntPatchOption;
|
||||
public static synthetic fun intPatchOption$default (Lapp/revanced/patcher/patch/options/types/IntPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/IntPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/LongPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/LongPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/LongPatchOption$Companion {
|
||||
public final fun longPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/LongPatchOption;
|
||||
public static synthetic fun longPatchOption$default (Lapp/revanced/patcher/patch/options/types/LongPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/LongPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/StringPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/StringPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/StringPatchOption$Companion {
|
||||
public final fun stringPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/StringPatchOption;
|
||||
public static synthetic fun stringPatchOption$default (Lapp/revanced/patcher/patch/options/types/StringPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/StringPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption$Companion {
|
||||
public final fun booleanArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption;
|
||||
public static synthetic fun booleanArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/FloatArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/FloatArrayPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/FloatArrayPatchOption$Companion {
|
||||
public final fun floatArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/FloatArrayPatchOption;
|
||||
public static synthetic fun floatArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/FloatArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/FloatArrayPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/IntArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/IntArrayPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/IntArrayPatchOption$Companion {
|
||||
public final fun intArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/IntArrayPatchOption;
|
||||
public static synthetic fun intArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/IntArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/IntArrayPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/LongArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/LongArrayPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/LongArrayPatchOption$Companion {
|
||||
public final fun longArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/LongArrayPatchOption;
|
||||
public static synthetic fun longArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/LongArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/LongArrayPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/StringArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
|
||||
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/StringArrayPatchOption$Companion;
|
||||
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/patch/options/types/array/StringArrayPatchOption$Companion {
|
||||
public final fun stringArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/StringArrayPatchOption;
|
||||
public static synthetic fun stringArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/StringArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/StringArrayPatchOption;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/DomFileEditor : java/io/Closeable {
|
||||
public fun <init> (Ljava/io/File;)V
|
||||
public fun close ()V
|
||||
public final fun getFile ()Lorg/w3c/dom/Document;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/ProxyClassList : java/util/Set, kotlin/jvm/internal/markers/KMutableSet {
|
||||
public final fun add (Lapp/revanced/patcher/util/proxy/ClassProxy;)Z
|
||||
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 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 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/util/method/MethodWalker {
|
||||
public final fun getMethod ()Lcom/android/tools/smali/dexlib2/iface/Method;
|
||||
public final fun nextMethod (IZ)Lapp/revanced/patcher/util/method/MethodWalker;
|
||||
public static synthetic fun nextMethod$default (Lapp/revanced/patcher/util/method/MethodWalker;IZILjava/lang/Object;)Lapp/revanced/patcher/util/method/MethodWalker;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/ClassProxy {
|
||||
public final fun getImmutableClass ()Lcom/android/tools/smali/dexlib2/iface/ClassDef;
|
||||
public final fun getMutableClass ()Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableAnnotation : com/android/tools/smali/dexlib2/base/BaseAnnotation {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableAnnotation$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/MutableAnnotation$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Annotation;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableAnnotation;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableAnnotationElement : com/android/tools/smali/dexlib2/base/BaseAnnotationElement {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableAnnotationElement$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableEncodedValue;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableAnnotationElement$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableAnnotationElement;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableClass : com/android/tools/smali/dexlib2/base/reference/BaseTypeReference, com/android/tools/smali/dexlib2/iface/ClassDef {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/MutableClass$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableField : com/android/tools/smali/dexlib2/base/reference/BaseFieldReference, com/android/tools/smali/dexlib2/iface/Field {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableField$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/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/util/proxy/mutableTypes/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/util/proxy/mutableTypes/MutableField$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Field;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableField;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableMethod : com/android/tools/smali/dexlib2/base/reference/BaseMethodReference, com/android/tools/smali/dexlib2/iface/Method {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/MutableMethod$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableMethodParameter : com/android/tools/smali/dexlib2/base/BaseMethodParameter, com/android/tools/smali/dexlib2/iface/MethodParameter {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethodParameter$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/MutableMethodParameter$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethodParameter;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableAnnotationEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseAnnotationEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableAnnotationEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableAnnotationEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableAnnotationEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableArrayEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseArrayEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableArrayEncodedValue$Companion;
|
||||
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)V
|
||||
public fun getValue ()Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableArrayEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableArrayEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableBooleanEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseBooleanEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableBooleanEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableBooleanEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableBooleanEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseByteEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableCharEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseCharEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableCharEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableCharEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableCharEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableDoubleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseDoubleEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableDoubleEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableDoubleEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableDoubleEncodedValue;
|
||||
}
|
||||
|
||||
public abstract interface class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue : com/android/tools/smali/dexlib2/iface/value/EncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue$Companion;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEnumEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseEnumEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEnumEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableEnumEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEnumEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFieldEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFieldEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFieldEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableFieldEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFieldEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFloatEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFloatEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFloatEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableFloatEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFloatEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableIntEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseIntEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableIntEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableIntEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableIntEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableLongEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseLongEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableLongEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableLongEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableLongEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableMethodEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodHandleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodHandleEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodHandleEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableMethodHandleEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodHandleEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodTypeEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodTypeEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableMethodTypeEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodTypeEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableNullEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseNullEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableNullEncodedValue$Companion;
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableNullEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableShortEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseShortEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableShortEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableShortEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableShortEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableStringEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseStringEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableStringEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableStringEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseTypeEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
|
||||
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableTypeEncodedValue$Companion;
|
||||
public fun <init> (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/util/proxy/mutableTypes/encodedValue/MutableTypeEncodedValue$Companion {
|
||||
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableTypeEncodedValue;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/smali/ExternalLabel {
|
||||
public fun <init> (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/util/smali/ExternalLabel;
|
||||
public static synthetic fun copy$default (Lapp/revanced/patcher/util/smali/ExternalLabel;Ljava/lang/String;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;ILjava/lang/Object;)Lapp/revanced/patcher/util/smali/ExternalLabel;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/smali/InlineSmaliCompiler {
|
||||
public static final field Companion Lapp/revanced/patcher/util/smali/InlineSmaliCompiler$Companion;
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/smali/InlineSmaliCompiler$Companion {
|
||||
public final fun compile (Ljava/lang/String;Ljava/lang/String;IZ)Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class app/revanced/patcher/util/smali/InlineSmaliCompilerKt {
|
||||
public static final fun toInstruction (Ljava/lang/String;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;
|
||||
public static synthetic fun toInstruction$default (Ljava/lang/String;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;
|
||||
public static final fun toInstructions (Ljava/lang/String;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;)Ljava/util/List;
|
||||
public static synthetic fun toInstructions$default (Ljava/lang/String;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/Object;)Ljava/util/List;
|
||||
}
|
||||
|
||||
82
revanced-patcher/build.gradle.kts
Normal file
82
revanced-patcher/build.gradle.kts
Normal file
@@ -0,0 +1,82 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.9.0"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.xpp3)
|
||||
implementation(libs.smali)
|
||||
implementation(libs.multidexlib2)
|
||||
implementation(libs.apktool.lib)
|
||||
implementation(libs.kotlin.reflect)
|
||||
|
||||
compileOnly(libs.android)
|
||||
|
||||
testImplementation(project(":revanced-patch-annotation-processor"))
|
||||
testImplementation(libs.kotlin.test)
|
||||
}
|
||||
|
||||
tasks {
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events("PASSED", "SKIPPED", "FAILED")
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
expand("projectVersion" to project.version)
|
||||
}
|
||||
}
|
||||
|
||||
kotlin { jvmToolchain(11) }
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
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<MavenPublication>("gpr") {
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
revanced-patcher/settings.gradle.kts
Normal file
1
revanced-patcher/settings.gradle.kts
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = "revanced-patcher"
|
||||
@@ -0,0 +1,127 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package app.revanced.patcher
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import dalvik.system.DexClassLoader
|
||||
import lanchon.multidexlib2.BasicDexFileNamer
|
||||
import lanchon.multidexlib2.MultiDexIO
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
import java.util.jar.JarFile
|
||||
import java.util.logging.Logger
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* A set of [Patch]es.
|
||||
*/
|
||||
typealias PatchSet = Set<Patch<*>>
|
||||
|
||||
/**
|
||||
* A [Patch] class.
|
||||
*/
|
||||
typealias PatchClass = KClass<out Patch<*>>
|
||||
|
||||
/**
|
||||
* A loader of [Patch]es from patch bundles.
|
||||
* This will load all [Patch]es from the given patch bundles that have a name.
|
||||
*
|
||||
* @param getBinaryClassNames A function that returns the binary names of all classes in a patch bundle.
|
||||
* @param classLoader The [ClassLoader] to use for loading the classes.
|
||||
* @param patchBundles A set of patches to initialize this instance with.
|
||||
*/
|
||||
sealed class PatchBundleLoader private constructor(
|
||||
classLoader: ClassLoader,
|
||||
patchBundles: Array<out File>,
|
||||
getBinaryClassNames: (patchBundle: File) -> List<String>,
|
||||
// This constructor parameter is unfortunately necessary,
|
||||
// so that a reference to the mutable set is present in the constructor to be able to add patches to it.
|
||||
// because the instance itself is a PatchSet, which is immutable, that is delegated by the parameter.
|
||||
private val patchSet: MutableSet<Patch<*>> = mutableSetOf()
|
||||
) : PatchSet by patchSet {
|
||||
private val logger = Logger.getLogger(PatchBundleLoader::class.java.name)
|
||||
|
||||
init {
|
||||
patchBundles.flatMap(getBinaryClassNames).asSequence().map {
|
||||
classLoader.loadClass(it)
|
||||
}.filter {
|
||||
Patch::class.java.isAssignableFrom(it)
|
||||
}.mapNotNull { patchClass ->
|
||||
patchClass.getInstance(logger, silent = true)
|
||||
}.filter {
|
||||
it.name != null
|
||||
}.let { patches ->
|
||||
patchSet.addAll(patches)
|
||||
}
|
||||
}
|
||||
|
||||
internal companion object Utils {
|
||||
/**
|
||||
* Instantiates a [Patch]. If the class is a singleton, the INSTANCE field will be used.
|
||||
*
|
||||
* @param logger The [Logger] to use for logging.
|
||||
* @param silent Whether to suppress logging.
|
||||
* @return The instantiated [Patch] or `null` if the [Patch] could not be instantiated.
|
||||
*/
|
||||
internal fun Class<*>.getInstance(logger: Logger, silent: Boolean = false): Patch<*>? {
|
||||
return try {
|
||||
getField("INSTANCE").get(null)
|
||||
} catch (exception: NoSuchFieldException) {
|
||||
if (!silent) logger.fine(
|
||||
"Patch class '${name}' has no INSTANCE field, therefor not a singleton. " +
|
||||
"Will try to instantiate it."
|
||||
)
|
||||
|
||||
try {
|
||||
getDeclaredConstructor().newInstance()
|
||||
} catch (exception: Exception) {
|
||||
if (!silent) logger.severe(
|
||||
"Patch class '${name}' is not singleton and has no suitable constructor, " +
|
||||
"therefor cannot be instantiated and will be ignored."
|
||||
)
|
||||
|
||||
return null
|
||||
}
|
||||
} as Patch<*>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A [PatchBundleLoader] for JAR files.
|
||||
*
|
||||
* @param patchBundles The path to patch bundles of JAR format.
|
||||
*/
|
||||
class Jar(vararg patchBundles: File) : PatchBundleLoader(
|
||||
URLClassLoader(patchBundles.map { it.toURI().toURL() }.toTypedArray()),
|
||||
patchBundles,
|
||||
{ patchBundle ->
|
||||
JarFile(patchBundle).entries().toList().filter { it.name.endsWith(".class") }
|
||||
.map { it.name.replace('/', '.').replace(".class", "") }
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* A [PatchBundleLoader] for [Dex] files.
|
||||
*
|
||||
* @param patchBundles The path to patch bundles of DEX format.
|
||||
* @param optimizedDexDirectory The directory to store optimized DEX files in.
|
||||
* This parameter is deprecated and has no effect since API level 26.
|
||||
*/
|
||||
class Dex(vararg patchBundles: File, optimizedDexDirectory: File? = null) : PatchBundleLoader(
|
||||
DexClassLoader(
|
||||
patchBundles.joinToString(File.pathSeparator) { it.absolutePath }, optimizedDexDirectory?.absolutePath,
|
||||
null,
|
||||
PatchBundleLoader::class.java.classLoader
|
||||
),
|
||||
patchBundles,
|
||||
{ patchBundle ->
|
||||
MultiDexIO.readDexFile(true, patchBundle, BasicDexFileNamer(), null, null).classes
|
||||
.map { classDef ->
|
||||
classDef.type.substring(1, classDef.length - 1)
|
||||
}
|
||||
}
|
||||
) {
|
||||
@Deprecated("This constructor is deprecated. Use the constructor with the second parameter instead.")
|
||||
constructor(vararg patchBundles: File) : this(*patchBundles, optimizedDexDirectory = null)
|
||||
}
|
||||
}
|
||||
265
revanced-patcher/src/main/kotlin/app/revanced/patcher/Patcher.kt
Normal file
265
revanced-patcher/src/main/kotlin/app/revanced/patcher/Patcher.kt
Normal file
@@ -0,0 +1,265 @@
|
||||
package app.revanced.patcher
|
||||
|
||||
import app.revanced.patcher.PatchBundleLoader.Utils.getInstance
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolveUsingLookupMap
|
||||
import app.revanced.patcher.patch.*
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
import java.util.function.Supplier
|
||||
import java.util.logging.Logger
|
||||
|
||||
/**
|
||||
* ReVanced Patcher.
|
||||
*
|
||||
* @param options The options for the patcher.
|
||||
*/
|
||||
class Patcher(
|
||||
private val options: PatcherOptions
|
||||
) : PatchExecutorFunction, PatchesConsumer, IntegrationsConsumer, Supplier<PatcherResult>, Closeable {
|
||||
private val logger = Logger.getLogger(Patcher::class.java.name)
|
||||
|
||||
/**
|
||||
* The context of ReVanced [Patcher].
|
||||
* This holds the current state of the patcher.
|
||||
*/
|
||||
val context = PatcherContext(options)
|
||||
|
||||
init {
|
||||
context.resourceContext.decodeResources(ResourceContext.ResourceDecodingMode.MANIFEST_ONLY)
|
||||
}
|
||||
|
||||
// TODO: Fix circular dependency detection.
|
||||
// /**
|
||||
// * Add [Patch]es to ReVanced [Patcher].
|
||||
// * It is not guaranteed that all supplied [Patch]es will be accepted, if an exception is thrown.
|
||||
// *
|
||||
// * @param patches The [Patch]es to add.
|
||||
// * @throws PatcherException.CircularDependencyException If a circular dependency is detected.
|
||||
// */
|
||||
/**
|
||||
* Add [Patch]es to ReVanced [Patcher].
|
||||
*
|
||||
* @param patches The [Patch]es to add.
|
||||
*/
|
||||
@Suppress("NAME_SHADOWING")
|
||||
override fun acceptPatches(patches: List<Patch<*>>) {
|
||||
/**
|
||||
* Add dependencies of a [Patch] recursively to [PatcherContext.allPatches].
|
||||
* If a [Patch] is already in [PatcherContext.allPatches], it will not be added again.
|
||||
*/
|
||||
fun PatchClass.putDependenciesRecursively() {
|
||||
if (context.allPatches.contains(this)) return
|
||||
|
||||
val dependency = this.java.getInstance(logger)!!
|
||||
context.allPatches[this] = dependency
|
||||
|
||||
dependency.dependencies?.forEach { it.putDependenciesRecursively() }
|
||||
}
|
||||
|
||||
// Add all patches and their dependencies to the context.
|
||||
for (patch in patches) context.executablePatches.putIfAbsent(patch::class, patch) ?: run {
|
||||
context.allPatches[patch::class] = patch
|
||||
|
||||
patch.dependencies?.forEach { it.putDependenciesRecursively() }
|
||||
}
|
||||
|
||||
/* TODO: Fix circular dependency detection.
|
||||
val graph = mutableMapOf<PatchClass, MutableList<PatchClass>>()
|
||||
fun PatchClass.visit() {
|
||||
if (this in graph) return
|
||||
|
||||
val group = graph.getOrPut(this) { mutableListOf(this) }
|
||||
|
||||
val dependencies = context.allPatches[this]!!.manifest.dependencies ?: return
|
||||
dependencies.forEach { dependency ->
|
||||
if (group == graph[dependency])
|
||||
throw PatcherException.CircularDependencyException(context.allPatches[this]!!.manifest.name)
|
||||
|
||||
graph[dependency] = group.apply { add(dependency) }
|
||||
dependency.visit()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns true if at least one patch or its dependencies matches the given predicate.
|
||||
*
|
||||
* @param predicate The predicate to match.
|
||||
*/
|
||||
fun Patch<*>.anyRecursively(predicate: (Patch<*>) -> Boolean): Boolean =
|
||||
predicate(this) || dependencies?.any { dependency ->
|
||||
context.allPatches[dependency]!!.anyRecursively(predicate)
|
||||
} ?: false
|
||||
|
||||
context.allPatches.values.let { patches ->
|
||||
// Determine, if resource patching is required.
|
||||
for (patch in patches)
|
||||
if (patch.anyRecursively { patch is ResourcePatch }) {
|
||||
options.resourceDecodingMode = ResourceContext.ResourceDecodingMode.FULL
|
||||
break
|
||||
}
|
||||
|
||||
// Determine, if merging integrations is required.
|
||||
for (patch in patches)
|
||||
if (!patch.anyRecursively { it.requiresIntegrations }) {
|
||||
context.bytecodeContext.integrations.merge = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add integrations to the [Patcher].
|
||||
*
|
||||
* @param integrations The integrations to add. Must be a DEX file or container of DEX files.
|
||||
*/
|
||||
override fun acceptIntegrations(integrations: List<File>) {
|
||||
context.bytecodeContext.integrations.addAll(integrations)
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute [Patch]es that were added to ReVanced [Patcher].
|
||||
*
|
||||
* @param returnOnError If true, ReVanced [Patcher] will return immediately if a [Patch] fails.
|
||||
* @return A pair of the name of the [Patch] and its [PatchResult].
|
||||
*/
|
||||
override fun apply(returnOnError: Boolean) = flow {
|
||||
|
||||
/**
|
||||
* Execute a [Patch] and its dependencies recursively.
|
||||
*
|
||||
* @param patch The [Patch] to execute.
|
||||
* @param executedPatches A map to prevent [Patch]es from being executed twice due to dependencies.
|
||||
* @return The result of executing the [Patch].
|
||||
*/
|
||||
fun executePatch(
|
||||
patch: Patch<*>,
|
||||
executedPatches: LinkedHashMap<Patch<*>, PatchResult>
|
||||
): PatchResult {
|
||||
val patchName = patch.name ?: patch.toString()
|
||||
|
||||
executedPatches[patch]?.let { patchResult ->
|
||||
patchResult.exception ?: return patchResult
|
||||
|
||||
// Return a new result with an exception indicating that the patch was not executed previously,
|
||||
// because it is a dependency of another patch that failed.
|
||||
return PatchResult(patch, PatchException("'$patchName' did not succeed previously"))
|
||||
}
|
||||
|
||||
// Recursively execute all dependency patches.
|
||||
patch.dependencies?.forEach { dependencyClass ->
|
||||
val dependency = context.allPatches[dependencyClass]!!
|
||||
val result = executePatch(dependency, executedPatches)
|
||||
|
||||
result.exception?.let {
|
||||
return PatchResult(
|
||||
patch,
|
||||
PatchException(
|
||||
"'$patchName' depends on '${dependency.name ?: dependency}' " +
|
||||
"that raised an exception:\n${it.stackTraceToString()}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return try {
|
||||
// TODO: Implement this in a more polymorphic way.
|
||||
when (patch) {
|
||||
is BytecodePatch -> {
|
||||
patch.fingerprints.resolveUsingLookupMap(context.bytecodeContext)
|
||||
patch.execute(context.bytecodeContext)
|
||||
}
|
||||
is ResourcePatch -> {
|
||||
patch.execute(context.resourceContext)
|
||||
}
|
||||
}
|
||||
|
||||
PatchResult(patch)
|
||||
} catch (exception: PatchException) {
|
||||
PatchResult(patch, exception)
|
||||
} catch (exception: Exception) {
|
||||
PatchResult(patch, PatchException(exception))
|
||||
}.also { executedPatches[patch] = it }
|
||||
}
|
||||
|
||||
if (context.bytecodeContext.integrations.merge) context.bytecodeContext.integrations.flush()
|
||||
|
||||
MethodFingerprint.initializeFingerprintResolutionLookupMaps(context.bytecodeContext)
|
||||
|
||||
// Prevent from decoding the app manifest twice if it is not needed.
|
||||
if (options.resourceDecodingMode == ResourceContext.ResourceDecodingMode.FULL)
|
||||
context.resourceContext.decodeResources(ResourceContext.ResourceDecodingMode.FULL)
|
||||
|
||||
logger.info("Executing patches")
|
||||
|
||||
val executedPatches = LinkedHashMap<Patch<*>, PatchResult>() // Key is name.
|
||||
|
||||
context.executablePatches.values.sortedBy { it.name }.forEach { patch ->
|
||||
val patchResult = executePatch(patch, executedPatches)
|
||||
|
||||
// If the patch failed, emit the result, even if it is closeable.
|
||||
// Results of executed patches that are closeable will be emitted later.
|
||||
patchResult.exception?.let {
|
||||
// Propagate exception to caller instead of wrapping it in a new exception.
|
||||
emit(patchResult)
|
||||
|
||||
if (returnOnError) return@flow
|
||||
} ?: run {
|
||||
if (patch is Closeable) return@run
|
||||
|
||||
emit(patchResult)
|
||||
}
|
||||
}
|
||||
|
||||
executedPatches.values
|
||||
.filter { it.exception == null }
|
||||
.filter { it.patch is Closeable }.asReversed().forEach { executedPatch ->
|
||||
val patch = executedPatch.patch
|
||||
|
||||
val result = try {
|
||||
(patch as Closeable).close()
|
||||
|
||||
executedPatch
|
||||
} catch (exception: PatchException) {
|
||||
PatchResult(patch, exception)
|
||||
} catch (exception: Exception) {
|
||||
PatchResult(patch, PatchException(exception))
|
||||
}
|
||||
|
||||
result.exception?.let {
|
||||
emit(
|
||||
PatchResult(
|
||||
patch,
|
||||
PatchException(
|
||||
"'${patch.name}' raised an exception while being closed: ${it.stackTraceToString()}",
|
||||
result.exception
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if (returnOnError) return@flow
|
||||
} ?: run {
|
||||
patch.name ?: return@run
|
||||
|
||||
emit(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() = MethodFingerprint.clearFingerprintResolutionLookupMaps()
|
||||
|
||||
/**
|
||||
* Compile and save the patched APK file.
|
||||
*
|
||||
* @return The [PatcherResult] containing the patched input files.
|
||||
*/
|
||||
override fun get() = PatcherResult(
|
||||
context.bytecodeContext.get(),
|
||||
context.resourceContext.get(),
|
||||
context.packageMetadata.apkInfo.doNotCompress?.toList()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package app.revanced.patcher
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.PatchClass
|
||||
import brut.androlib.apk.ApkInfo
|
||||
import brut.directory.ExtFile
|
||||
|
||||
@@ -19,9 +18,14 @@ class PatcherContext internal constructor(options: PatcherOptions) {
|
||||
val packageMetadata = PackageMetadata(ApkInfo(ExtFile(options.inputFile)))
|
||||
|
||||
/**
|
||||
* The list of [Patch]es to execute.
|
||||
* The map of [Patch]es associated by their [PatchClass].
|
||||
*/
|
||||
internal val patches = mutableListOf<PatchClass>()
|
||||
internal val executablePatches = mutableMapOf<PatchClass, Patch<*>>()
|
||||
|
||||
/**
|
||||
* The map of all [Patch]es and their dependencies associated by their [PatchClass].
|
||||
*/
|
||||
internal val allPatches = mutableMapOf<PatchClass, Patch<*>>()
|
||||
|
||||
/**
|
||||
* The [ResourceContext] of this [PatcherContext].
|
||||
@@ -33,5 +37,4 @@ class PatcherContext internal constructor(options: PatcherOptions) {
|
||||
* The [BytecodeContext] of this [PatcherContext].
|
||||
* This holds the current state of the bytecode.
|
||||
*/
|
||||
internal val bytecodeContext = BytecodeContext(options)
|
||||
}
|
||||
internal val bytecodeContext = BytecodeContext(options) }
|
||||
@@ -0,0 +1,16 @@
|
||||
package app.revanced.patcher
|
||||
|
||||
/**
|
||||
* An exception thrown by ReVanced [Patcher].
|
||||
*
|
||||
* @param errorMessage The exception message.
|
||||
* @param cause The corresponding [Throwable].
|
||||
*/
|
||||
sealed class PatcherException(errorMessage: String?, cause: Throwable?) : Exception(errorMessage, cause) {
|
||||
constructor(errorMessage: String) : this(errorMessage, null)
|
||||
|
||||
|
||||
class CircularDependencyException internal constructor(dependant: String) : PatcherException(
|
||||
"Patch '$dependant' causes a circular dependency"
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package app.revanced.patcher
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
|
||||
@FunctionalInterface
|
||||
interface PatchesConsumer {
|
||||
fun acceptPatches(patches: List<Patch<*>>)
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import app.revanced.patcher.PatcherContext
|
||||
import app.revanced.patcher.PatcherOptions
|
||||
import app.revanced.patcher.PatcherResult
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.annotations.RequiresIntegrations
|
||||
import app.revanced.patcher.util.ClassMerger.merge
|
||||
import app.revanced.patcher.util.ProxyClassList
|
||||
import app.revanced.patcher.util.method.MethodWalker
|
||||
@@ -97,7 +96,7 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
|
||||
internal inner class Integrations : MutableList<File> by mutableListOf(), Flushable {
|
||||
/**
|
||||
* Whether to merge integrations.
|
||||
* True when any supplied [Patch] is annotated with [RequiresIntegrations].
|
||||
* Set to true, if the field requiresIntegrations of any supplied [Patch] is true.
|
||||
*/
|
||||
var merge = false
|
||||
|
||||
@@ -109,6 +108,7 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
|
||||
|
||||
logger.info("Merging integrations")
|
||||
|
||||
// TODO: Multi-thread this.
|
||||
this@Integrations.forEach { integrations ->
|
||||
MultiDexIO.readDexFile(
|
||||
true,
|
||||
@@ -116,7 +116,7 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
|
||||
null,
|
||||
null
|
||||
).classes.forEach classDef@{ classDef ->
|
||||
val existingClass = classes.find { it == classDef } ?: run {
|
||||
val existingClass = classes.find { it.type == classDef.type } ?: run {
|
||||
logger.fine("Merging $classDef")
|
||||
classes.add(classDef)
|
||||
return@classDef
|
||||
@@ -83,6 +83,16 @@ class ResourceContext internal constructor(
|
||||
versionInfo.let {
|
||||
metadata.packageVersion = it.versionName ?: it.versionCode
|
||||
}
|
||||
|
||||
/*
|
||||
The ResTable if flagged as sparse if the main package is not loaded, which is the case here,
|
||||
because ResourcesDecoder.decodeResources loads the main package
|
||||
and not XmlPullStreamDecoder.decodeManifest.
|
||||
See ARSCDecoder.readTableType for more info.
|
||||
|
||||
Set this to false again to prevent the ResTable from being flagged as sparse falsely.
|
||||
*/
|
||||
metadata.apkInfo.sparseResources = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,7 @@ import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object MethodFingerprintExtensions {
|
||||
|
||||
/**
|
||||
* The name of a [MethodFingerprint].
|
||||
*/
|
||||
val MethodFingerprint.name: String
|
||||
get() = this.javaClass.simpleName
|
||||
|
||||
// TODO: Make this a property.
|
||||
/**
|
||||
* The [FuzzyPatternScanMethod] annotation of a [MethodFingerprint].
|
||||
*/
|
||||
@@ -159,10 +159,10 @@ abstract class MethodFingerprint(
|
||||
* - Faster: Specify [accessFlags], [returnType] and [parameters].
|
||||
* - Fastest: Specify [strings], with at least one string being an exact (non-partial) match.
|
||||
*/
|
||||
internal fun Iterable<MethodFingerprint>.resolveUsingLookupMap(context: BytecodeContext) {
|
||||
internal fun Set<MethodFingerprint>.resolveUsingLookupMap(context: BytecodeContext) {
|
||||
if (methods.isEmpty()) throw PatchException("lookup map not initialized")
|
||||
|
||||
for (fingerprint in this) {
|
||||
forEach { fingerprint ->
|
||||
fingerprint.resolveUsingLookupMap(context)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package app.revanced.patcher.patch
|
||||
|
||||
import app.revanced.patcher.PatchClass
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
/**
|
||||
* A ReVanced [Patch] that works on [BytecodeContext].
|
||||
*
|
||||
* @param fingerprints A list of [MethodFingerprint]s which will be resolved before the patch is executed.
|
||||
* @param name The name of the patch.
|
||||
* @param description The description of the patch.
|
||||
* @param compatiblePackages The packages the patch is compatible with.
|
||||
* @param dependencies The names of patches this patch depends on.
|
||||
* @param use Weather or not the patch should be used.
|
||||
* @param requiresIntegrations Weather or not the patch requires integrations.
|
||||
*/
|
||||
abstract class BytecodePatch(
|
||||
internal val fingerprints: Set<MethodFingerprint> = emptySet(),
|
||||
name: String? = null,
|
||||
description: String? = null,
|
||||
compatiblePackages: Set<CompatiblePackage>? = null,
|
||||
dependencies: Set<PatchClass>? = null,
|
||||
use: Boolean = true,
|
||||
// TODO: Remove this property, once integrations are coupled with patches.
|
||||
requiresIntegrations: Boolean = false,
|
||||
) : Patch<BytecodeContext>(name, description, compatiblePackages, dependencies, use, requiresIntegrations)
|
||||
@@ -0,0 +1,71 @@
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package app.revanced.patcher.patch
|
||||
|
||||
import app.revanced.patcher.PatchClass
|
||||
import app.revanced.patcher.Patcher
|
||||
import app.revanced.patcher.data.Context
|
||||
import app.revanced.patcher.patch.options.PatchOptions
|
||||
import java.io.Closeable
|
||||
|
||||
/**
|
||||
* A ReVanced patch.
|
||||
*
|
||||
* If an implementation of [Patch] also implements [Closeable]
|
||||
* it will be closed in reverse execution order of patches executed by ReVanced [Patcher].
|
||||
*
|
||||
* @param name The name of the patch.
|
||||
* @param description The description of the patch.
|
||||
* @param compatiblePackages The packages the patch is compatible with.
|
||||
* @param dependencies The names of patches this patch depends on.
|
||||
* @param use Weather or not the patch should be used.
|
||||
* @param requiresIntegrations Weather or not the patch requires integrations.
|
||||
* @param T The [Context] type this patch will work on.
|
||||
*/
|
||||
sealed class Patch<out T : Context<*>>(
|
||||
val name: String? = null,
|
||||
val description: String? = null,
|
||||
val compatiblePackages: Set<CompatiblePackage>? = null,
|
||||
val dependencies: Set<PatchClass>? = null,
|
||||
val use: Boolean = true,
|
||||
// TODO: Remove this property, once integrations are coupled with patches.
|
||||
val requiresIntegrations: Boolean = false,
|
||||
) {
|
||||
/**
|
||||
* The options of the patch associated by the options key.
|
||||
*/
|
||||
val options = PatchOptions()
|
||||
|
||||
/**
|
||||
* The execution function of the patch.
|
||||
*
|
||||
* @param context The [Context] the patch will work on.
|
||||
* @return The result of executing the patch.
|
||||
*/
|
||||
abstract fun execute(context: @UnsafeVariance T)
|
||||
|
||||
override fun hashCode() = name.hashCode()
|
||||
|
||||
override fun toString() = name ?: this::class.simpleName ?: "Unnamed patch"
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as Patch<*>
|
||||
|
||||
return name == other.name
|
||||
}
|
||||
|
||||
/**
|
||||
* A package a [Patch] is compatible with.
|
||||
*
|
||||
* @param name The name of the package.
|
||||
* @param versions The versions of the package.
|
||||
*/
|
||||
class CompatiblePackage(
|
||||
val name: String,
|
||||
val versions: Set<String>? = null,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patcher.patch
|
||||
|
||||
/**
|
||||
* A result of executing a [Patch].
|
||||
*
|
||||
* @param patch The [Patch] that was executed.
|
||||
* @param exception The [PatchException] thrown, if any.
|
||||
*/
|
||||
class PatchResult internal constructor(val patch: Patch<*>, val exception: PatchException? = null)
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.patcher.patch
|
||||
|
||||
import app.revanced.patcher.PatchClass
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
|
||||
/**
|
||||
* A ReVanced [Patch] that works on [ResourceContext].
|
||||
*
|
||||
* @param name The name of the patch.
|
||||
* @param description The description of the patch.
|
||||
* @param compatiblePackages The packages the patch is compatible with.
|
||||
* @param dependencies The names of patches this patch depends on.
|
||||
* @param use Weather or not the patch should be used.
|
||||
* @param requiresIntegrations Weather or not the patch requires integrations.
|
||||
*/
|
||||
abstract class ResourcePatch(
|
||||
name: String? = null,
|
||||
description: String? = null,
|
||||
compatiblePackages: Set<CompatiblePackage>? = null,
|
||||
dependencies: Set<PatchClass>? = null,
|
||||
use: Boolean = true,
|
||||
// TODO: Remove this property, once integrations are coupled with patches.
|
||||
requiresIntegrations: Boolean = false,
|
||||
) : Patch<ResourceContext>(name, description, compatiblePackages, dependencies, use, requiresIntegrations)
|
||||
@@ -0,0 +1,40 @@
|
||||
package app.revanced.patcher.patch.options
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* A [Patch] option.
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @param validate The function to validate values of the option.
|
||||
* @param T The value type of the option.
|
||||
*/
|
||||
abstract class PatchOption<T>(
|
||||
val key: String,
|
||||
default: T?,
|
||||
val title: String?,
|
||||
val description: String?,
|
||||
val required: Boolean,
|
||||
val validate: (T?) -> Boolean
|
||||
) {
|
||||
/**
|
||||
* The value of the [PatchOption].
|
||||
*/
|
||||
var value: T? = default
|
||||
set(value) {
|
||||
if (required && value == null) throw PatchOptionException.ValueRequiredException(this)
|
||||
if (!validate(value)) throw PatchOptionException.ValueValidationException(value, this)
|
||||
|
||||
field = value
|
||||
}
|
||||
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>) = value
|
||||
|
||||
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package app.revanced.patcher.patch.options
|
||||
|
||||
/**
|
||||
* An exception thrown when using [PatchOption]s.
|
||||
*
|
||||
* @param errorMessage The exception message.
|
||||
*/
|
||||
sealed class PatchOptionException(errorMessage: String) : Exception(errorMessage, null) {
|
||||
/**
|
||||
* An exception thrown when a [PatchOption] is set to an invalid value.
|
||||
*
|
||||
* @param invalidType The type of the value that was passed.
|
||||
* @param expectedType The type of the value that was expected.
|
||||
*/
|
||||
class InvalidValueTypeException(invalidType: String, expectedType: String) :
|
||||
PatchOptionException("Type $expectedType was expected but received type $invalidType")
|
||||
|
||||
/**
|
||||
* An exception thrown when a value did not satisfy the value conditions specified by the [PatchOption].
|
||||
*
|
||||
* @param value The value that failed validation.
|
||||
*/
|
||||
class ValueValidationException(value: Any?, option: PatchOption<*>) :
|
||||
Exception("The option value \"$value\" failed validation for ${option.key}")
|
||||
|
||||
/**
|
||||
* An exception thrown when a value is required but null was passed.
|
||||
*
|
||||
* @param option The [PatchOption] that requires a value.
|
||||
*/
|
||||
class ValueRequiredException(option: PatchOption<*>) :
|
||||
Exception("The option ${option.key} requires a value, but null was passed")
|
||||
|
||||
/**
|
||||
* An exception thrown when a [PatchOption] is not found.
|
||||
*
|
||||
* @param key The key of the [PatchOption].
|
||||
*/
|
||||
class PatchOptionNotFoundException(key: String)
|
||||
: Exception("No option with key $key")
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package app.revanced.patcher.patch.options
|
||||
|
||||
|
||||
/**
|
||||
* A map of [PatchOption]s associated by their keys.
|
||||
*
|
||||
* @param options The [PatchOption]s to initialize with.
|
||||
*/
|
||||
class PatchOptions internal constructor(
|
||||
private val options: MutableMap<String, PatchOption<*>> = mutableMapOf()
|
||||
) : MutableMap<String, PatchOption<*>> by options {
|
||||
/**
|
||||
* Register a [PatchOption]. Acts like [MutableMap.put].
|
||||
* @param value The [PatchOption] to register.
|
||||
*/
|
||||
fun register(value: PatchOption<*>) {
|
||||
options[value.key] = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an option's value.
|
||||
* @param key The identifier.
|
||||
* @param value The value.
|
||||
* @throws PatchOptionException.PatchOptionNotFoundException If the option does not exist.
|
||||
*/
|
||||
operator fun <T : Any> set(key: String, value: T?) {
|
||||
val option = this[key]
|
||||
|
||||
try {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(option as PatchOption<T>).value = value
|
||||
} catch (e: ClassCastException) {
|
||||
throw PatchOptionException.InvalidValueTypeException(
|
||||
value?.let { it::class.java.name } ?: "null",
|
||||
option.value?.let { it::class.java.name } ?: "null",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an option.
|
||||
*/
|
||||
override operator fun get(key: String) =
|
||||
options[key] ?: throw PatchOptionException.PatchOptionNotFoundException(key)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [Boolean].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class BooleanPatchOption private constructor(
|
||||
key: String,
|
||||
default: Boolean?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Boolean?) -> Boolean
|
||||
) : PatchOption<Boolean>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [BooleanPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [BooleanPatchOption].
|
||||
*
|
||||
* @see BooleanPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.booleanPatchOption(
|
||||
key: String,
|
||||
default: Boolean? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Boolean?) -> Boolean = { true }
|
||||
) = BooleanPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [Float].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class FloatPatchOption private constructor(
|
||||
key: String,
|
||||
default: Float?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Float?) -> Boolean
|
||||
) : PatchOption<Float>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [FloatPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [FloatPatchOption].
|
||||
*
|
||||
* @see FloatPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.floatPatchOption(
|
||||
key: String,
|
||||
default: Float? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Float?) -> Boolean = { true }
|
||||
) = FloatPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing an [Integer].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class IntPatchOption private constructor(
|
||||
key: String,
|
||||
default: Int?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Int?) -> Boolean
|
||||
) : PatchOption<Int>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [IntPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [IntPatchOption].
|
||||
*
|
||||
* @see IntPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.intPatchOption(
|
||||
key: String,
|
||||
default: Int? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Int?) -> Boolean = { true }
|
||||
) = IntPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [Long].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class LongPatchOption private constructor(
|
||||
key: String,
|
||||
default: Long?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Long?) -> Boolean
|
||||
) : PatchOption<Long>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [LongPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [LongPatchOption].
|
||||
*
|
||||
* @see LongPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.longPatchOption(
|
||||
key: String,
|
||||
default: Long? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Long?) -> Boolean = { true }
|
||||
) = LongPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [String].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class StringPatchOption private constructor(
|
||||
key: String,
|
||||
default: String?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (String?) -> Boolean
|
||||
) : PatchOption<String>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [StringPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [StringPatchOption].
|
||||
*
|
||||
* @see StringPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.stringPatchOption(
|
||||
key: String,
|
||||
default: String? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (String?) -> Boolean = { true }
|
||||
) = StringPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types.array
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [Boolean] array.
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class BooleanArrayPatchOption private constructor(
|
||||
key: String,
|
||||
default: Array<Boolean>?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Array<Boolean>?) -> Boolean
|
||||
) : PatchOption<Array<Boolean>>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [BooleanArrayPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [BooleanArrayPatchOption].
|
||||
*
|
||||
* @see BooleanArrayPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.booleanArrayPatchOption(
|
||||
key: String,
|
||||
default: Array<Boolean>? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Array<Boolean>?) -> Boolean = { true }
|
||||
) = BooleanArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types.array
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [Float] array.
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class FloatArrayPatchOption private constructor(
|
||||
key: String,
|
||||
default: Array<Float>?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Array<Float>?) -> Boolean
|
||||
) : PatchOption<Array<Float>>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [FloatArrayPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [FloatArrayPatchOption].
|
||||
*
|
||||
* @see FloatArrayPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.floatArrayPatchOption(
|
||||
key: String,
|
||||
default: Array<Float>? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Array<Float>?) -> Boolean = { true }
|
||||
) = FloatArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types.array
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing an [Integer] array.
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class IntArrayPatchOption private constructor(
|
||||
key: String,
|
||||
default: Array<Int>?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Array<Int>?) -> Boolean
|
||||
) : PatchOption<Array<Int>>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [IntArrayPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [IntArrayPatchOption].
|
||||
*
|
||||
* @see IntArrayPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.intArrayPatchOption(
|
||||
key: String,
|
||||
default: Array<Int>? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Array<Int>?) -> Boolean = { true }
|
||||
) = IntArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types.array
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [Long] array.
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class LongArrayPatchOption private constructor(
|
||||
key: String,
|
||||
default: Array<Long>?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Array<Long>?) -> Boolean
|
||||
) : PatchOption<Array<Long>>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [LongArrayPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [LongArrayPatchOption].
|
||||
*
|
||||
* @see LongArrayPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.longArrayPatchOption(
|
||||
key: String,
|
||||
default: Array<Long>? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Array<Long>?) -> Boolean = { true }
|
||||
) = LongArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package app.revanced.patcher.patch.options.types.array
|
||||
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [String] array.
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
*
|
||||
* @see PatchOption
|
||||
*/
|
||||
class StringArrayPatchOption private constructor(
|
||||
key: String,
|
||||
default: Array<String>?,
|
||||
title: String?,
|
||||
description: String?,
|
||||
required: Boolean,
|
||||
validator: (Array<String>?) -> Boolean
|
||||
) : PatchOption<Array<String>>(key, default, title, description, required, validator) {
|
||||
companion object {
|
||||
/**
|
||||
* Create a new [StringArrayPatchOption] and add it to the current [Patch].
|
||||
*
|
||||
* @param key The identifier.
|
||||
* @param default The default value.
|
||||
* @param title The title.
|
||||
* @param description A description.
|
||||
* @param required Whether the option is required.
|
||||
* @return The created [StringArrayPatchOption].
|
||||
*
|
||||
* @see StringArrayPatchOption
|
||||
* @see PatchOption
|
||||
*/
|
||||
fun <T : Patch<*>> T.stringArrayPatchOption(
|
||||
key: String,
|
||||
default: Array<String>? = null,
|
||||
title: String? = null,
|
||||
description: String? = null,
|
||||
required: Boolean = false,
|
||||
validator: (Array<String>?) -> Boolean = { true }
|
||||
) = StringArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import com.android.tools.smali.smali.smaliFlexLexer
|
||||
import com.android.tools.smali.smali.smaliParser
|
||||
import com.android.tools.smali.smali.smaliTreeWalker
|
||||
import java.io.InputStreamReader
|
||||
import java.util.Locale
|
||||
|
||||
private const val METHOD_TEMPLATE = """
|
||||
.class LInlineCompiler;
|
||||
@@ -33,7 +34,7 @@ class InlineSmaliCompiler {
|
||||
fun compile(
|
||||
instructions: String, parameters: String, registers: Int, forStaticMethod: Boolean
|
||||
): List<BuilderInstruction> {
|
||||
val input = METHOD_TEMPLATE.format(
|
||||
val input = METHOD_TEMPLATE.format(Locale.ENGLISH,
|
||||
if (forStaticMethod) {
|
||||
"static"
|
||||
} else {
|
||||
@@ -19,7 +19,7 @@ import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21s
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
private object InstructionExtensionsTest {
|
||||
@@ -0,0 +1,59 @@
|
||||
package app.revanced.patcher.patch.options
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.options.types.BooleanPatchOption.Companion.booleanPatchOption
|
||||
import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
|
||||
import app.revanced.patcher.patch.options.types.array.StringArrayPatchOption.Companion.stringArrayPatchOption
|
||||
import org.junit.jupiter.api.assertDoesNotThrow
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import kotlin.test.Test
|
||||
|
||||
internal class PatchOptionsTest {
|
||||
@Test
|
||||
fun `should not fail because default value is unvalidated`() {
|
||||
assertDoesNotThrow {
|
||||
OptionsTestPatch.options["required"].value
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should throw due to incorrect type`() {
|
||||
assertThrows<PatchOptionException.InvalidValueTypeException> {
|
||||
OptionsTestPatch.options["bool"] = 0
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should be nullable`() {
|
||||
OptionsTestPatch.options["bool"] = null
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `option should not be found`() {
|
||||
assertThrows<PatchOptionException.PatchOptionNotFoundException> {
|
||||
OptionsTestPatch.options["this option does not exist"] = 1
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should be able to add options manually`() {
|
||||
assertThrows<PatchOptionException.InvalidValueTypeException> {
|
||||
OptionsTestPatch.options["array"] = OptionsTestPatch.stringArrayOption
|
||||
}
|
||||
assertDoesNotThrow {
|
||||
OptionsTestPatch.options.register(OptionsTestPatch.stringArrayOption)
|
||||
}
|
||||
}
|
||||
|
||||
private object OptionsTestPatch : BytecodePatch() {
|
||||
private var stringOption by stringPatchOption("string", "default")
|
||||
private var booleanOption by booleanPatchOption("bool", true)
|
||||
private var requiredStringOption by stringPatchOption("required", "default", required = true)
|
||||
private var nullDefaultRequiredOption by stringPatchOption("null", null, required = true)
|
||||
|
||||
val stringArrayOption = stringArrayPatchOption("array", arrayOf("1", "2"))
|
||||
|
||||
override fun execute(context: BytecodeContext) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package app.revanced.patcher.patch.usage
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Format
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction11x
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableField
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableFieldReference
|
||||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference
|
||||
import com.android.tools.smali.dexlib2.immutable.value.ImmutableFieldEncodedValue
|
||||
import com.android.tools.smali.dexlib2.util.Preconditions
|
||||
import com.google.common.collect.ImmutableList
|
||||
|
||||
@Suppress("unused")
|
||||
@Patch(
|
||||
name = "Example bytecode patch",
|
||||
description = "Example demonstration of a bytecode patch.",
|
||||
dependencies = [ExampleResourcePatch::class],
|
||||
compatiblePackages = [CompatiblePackage("com.example.examplePackage", arrayOf("0.0.1", "0.0.2"))]
|
||||
)
|
||||
object ExampleBytecodePatch : BytecodePatch(setOf(ExampleFingerprint)) {
|
||||
// Entry point of a patch. Supplied fingerprints are resolved at this point.
|
||||
override fun execute(context: BytecodeContext) {
|
||||
ExampleFingerprint.result?.let { result ->
|
||||
// Let's modify it, so it prints "Hello, ReVanced! Editing bytecode."
|
||||
// Get the start index of our opcode pattern.
|
||||
// This will be the index of the instruction with the opcode CONST_STRING.
|
||||
val startIndex = result.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
result.mutableMethod.apply {
|
||||
replaceStringAt(startIndex, "Hello, ReVanced! Editing bytecode.")
|
||||
|
||||
// Store the fields initial value into the first virtual register.
|
||||
replaceInstruction(0, "sget-object v0, LTestClass;->dummyField:Ljava/io/PrintStream;")
|
||||
|
||||
// Now let's create a new call to our method and print the return value!
|
||||
// You can also use the smali compiler to create instructions.
|
||||
// For this sake of example I reuse the TestClass field dummyField inside the virtual register 0.
|
||||
//
|
||||
// Control flow instructions are not supported as of now.
|
||||
addInstructionsWithLabels(
|
||||
startIndex + 2,
|
||||
"""
|
||||
invoke-static { }, LTestClass;->returnHello()Ljava/lang/String;
|
||||
move-result-object v1
|
||||
invoke-virtual { v0, v1 }, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// Find the class in which the method matching our fingerprint is defined in.
|
||||
context.findClass(result.classDef.type)!!.mutableClass.apply {
|
||||
// Add a new method that returns a string.
|
||||
methods.add(
|
||||
ImmutableMethod(
|
||||
result.classDef.type,
|
||||
"returnHello",
|
||||
null,
|
||||
"Ljava/lang/String;",
|
||||
AccessFlags.PRIVATE or AccessFlags.STATIC,
|
||||
null,
|
||||
null,
|
||||
ImmutableMethodImplementation(
|
||||
1,
|
||||
ImmutableList.of(
|
||||
BuilderInstruction21c(
|
||||
Opcode.CONST_STRING,
|
||||
0,
|
||||
ImmutableStringReference("Hello, ReVanced! Adding bytecode.")
|
||||
),
|
||||
BuilderInstruction11x(Opcode.RETURN_OBJECT, 0)
|
||||
),
|
||||
null,
|
||||
null
|
||||
)
|
||||
).toMutable()
|
||||
)
|
||||
|
||||
// Add a field in the main class.
|
||||
// We will use this field in our method below to call println on.
|
||||
// The field holds the Ljava/io/PrintStream->out; field.
|
||||
fields.add(
|
||||
ImmutableField(
|
||||
type,
|
||||
"dummyField",
|
||||
"Ljava/io/PrintStream;",
|
||||
AccessFlags.PRIVATE or AccessFlags.STATIC,
|
||||
ImmutableFieldEncodedValue(
|
||||
ImmutableFieldReference(
|
||||
"Ljava/lang/System;",
|
||||
"out",
|
||||
"Ljava/io/PrintStream;"
|
||||
)
|
||||
),
|
||||
null,
|
||||
null
|
||||
).toMutable()
|
||||
)
|
||||
}
|
||||
} ?: throw PatchException("Fingerprint failed to resolve.")
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace an existing instruction with a new one containing a reference to a new string.
|
||||
* @param index The index of the instruction to replace.
|
||||
* @param string The replacement string.
|
||||
*/
|
||||
private fun MutableMethod.replaceStringAt(index: Int, string: String) {
|
||||
val instruction = getInstruction(index)
|
||||
|
||||
// Utility method of dexlib2.
|
||||
Preconditions.checkFormat(instruction.opcode, Format.Format21c)
|
||||
|
||||
// Cast this to an instruction of the format 21c.
|
||||
// The instruction format can be found in the docs at
|
||||
// https://source.android.com/devices/tech/dalvik/dalvik-bytecode
|
||||
val strInstruction = instruction as Instruction21c
|
||||
|
||||
// In our case we want an instruction with the opcode CONST_STRING
|
||||
// The format is 21c, so we create a new BuilderInstruction21c
|
||||
// This instruction will hold the string reference constant in the virtual register of the original instruction
|
||||
// For that a reference to the string is needed. It can be created with an ImmutableStringReference.
|
||||
// At last, use the method replaceInstruction to replace it at the given index startIndex.
|
||||
replaceInstruction(
|
||||
index,
|
||||
"const-string ${strInstruction.registerA}, ${ImmutableStringReference(string)}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user