1
mirror of https://github.com/revanced/revanced-patcher synced 2025-09-06 16:38:50 +02:00

Compare commits

..

45 Commits

Author SHA1 Message Date
semantic-release-bot
a2875d1d64 chore: Release v20.0.1-dev.4 [skip ci]
## [20.0.1-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v20.0.1-dev.3...v20.0.1-dev.4) (2024-10-07)

### Bug Fixes

* Make it work on Android by not using APIs from JVM unavailable to Android. ([2be6e97](2be6e97817))
2024-10-07 16:27:20 +00:00
oSumAtrIX
2be6e97817 fix: Make it work on Android by not using APIs from JVM unavailable to Android. 2024-10-07 18:25:43 +02:00
semantic-release-bot
348d0070e7 chore: Release v20.0.1-dev.3 [skip ci]
## [20.0.1-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v20.0.1-dev.2...v20.0.1-dev.3) (2024-10-03)

### Performance Improvements

* Free memory earlier and remove negligible lookup maps ([d53aacd](d53aacdad4))
2024-10-03 14:08:34 +00:00
oSumAtrIX
d53aacdad4 perf: Free memory earlier and remove negligible lookup maps
Negligible lookup maps used for matching fingerprints have been removed to reduce the likelihood of OOM when the maps are instantiated, commonly observed with 400M RAM. Additionally, lookup maps previously kept for the duration of the patcher instance are now cleared before the classes are compiled. This reduces the likelihood of OOM when compiling classes.
On a related note, a linear increase in memory usage is observed with every compiled class until all classes are compiled implying compiled classes not being freed by GC because they are still referenced. After compiling a class, the class is technically free-able though. The classes are assumed to be referenced in the `multidexlib2` library that takes the list of all classes to compile multiple DEX with and seems to hold the reference to all these classes in memory until all DEX are compiled. A clever fix would involve splitting the list of classes into chunks and getting rid of the list of all classes so that after every DEX compilation, the corresponding split of classes can be freed.
2024-10-03 16:06:42 +02:00
semantic-release-bot
f1615b7ab5 chore: Release v20.0.1-dev.2 [skip ci]
## [20.0.1-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v20.0.1-dev.1...v20.0.1-dev.2) (2024-10-01)
2024-10-01 15:31:49 +00:00
oSumAtrIX
ffb1d880d7 ci: Use permissions and regular GitHub token instead of PAT 2024-10-01 17:25:49 +02:00
oSumAtrIX
e95f13ae3e build(Needs bump): Update dependencies 2024-09-30 23:21:44 +02:00
oSumAtrIX
e1b984d601 ci: Adjust release commit message 2024-09-30 22:34:23 +02:00
semantic-release-bot
c2dc29e061 chore(release): 20.0.1-dev.1 [skip ci]
## [20.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0...v20.0.1-dev.1) (2024-09-18)

### Bug Fixes

* Check for class type exactly instead of with contains ([#310](https://github.com/ReVanced/revanced-patcher/issues/310)) ([69f2f20](69f2f20fd9))
2024-09-18 12:38:03 +00:00
oSumAtrIX
69f2f20fd9 fix: Check for class type exactly instead of with contains (#310) 2024-09-18 14:36:15 +02:00
Pg
525beda18e docs: Fix code example (#306) 2024-08-29 08:59:33 +02:00
oSumAtrIX
73d3cbf4ff build: Bump Gradle Wrapper to 8.9 2024-08-06 17:46:39 +02:00
semantic-release-bot
70278dd79d chore(release): 20.0.0 [skip ci]
# [20.0.0](https://github.com/ReVanced/revanced-patcher/compare/v19.3.1...v20.0.0) (2024-08-06)

### Bug Fixes

* Downgrade smali to fix dex compilation issue ([5227e98](5227e98abf))
* Improve exception message wording ([5481d0c](5481d0c54c))
* Make constructor internal as supposed ([7f44174](7f44174d91))
* Merge all extensions before initializing lookup maps ([8c4dd5b](8c4dd5b3a3))
* Use null for compatible package version when adding packages only ([736b3ee](736b3eebbf))

### Features

* Add ability to create options outside of a patch ([d310246](d310246852))
* Convert APIs to Kotlin DSL ([#298](https://github.com/ReVanced/revanced-patcher/issues/298)) ([11a911d](11a911dc67))

### BREAKING CHANGES

* Various old APIs are removed, and DSL APIs are added instead.
2024-08-06 14:56:20 +00:00
oSumAtrIX
5e98e9e30a chore: Merge branch dev to main (#279) 2024-08-06 16:54:38 +02:00
semantic-release-bot
ac1aff5a1a chore(release): 20.0.0-dev.4 [skip ci]
# [20.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.3...v20.0.0-dev.4) (2024-08-06)

### Bug Fixes

* Improve exception message wording ([bd434ce](bd434ceb33))
2024-08-06 16:53:42 +02:00
oSumAtrIX
5481d0c54c fix: Improve exception message wording 2024-08-06 16:53:42 +02:00
semantic-release-bot
4604742d0f chore(release): 20.0.0-dev.3 [skip ci]
# [20.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.2...v20.0.0-dev.3) (2024-08-01)

### Bug Fixes

* Make constructor internal as supposed ([e95fcd1](e95fcd1c0b))

### Features

* Add ability to create options outside of a patch ([b8d763a](b8d763a66e))
2024-08-06 16:53:42 +02:00
oSumAtrIX
4beb907a61 refactor: Sort dependencies 2024-08-06 16:53:42 +02:00
oSumAtrIX
7f44174d91 fix: Make constructor internal as supposed 2024-08-06 16:53:42 +02:00
oSumAtrIX
d310246852 feat: Add ability to create options outside of a patch 2024-08-06 16:53:42 +02:00
semantic-release-bot
dcc989243c chore(release): 20.0.0-dev.2 [skip ci]
# [20.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.1...v20.0.0-dev.2) (2024-07-31)

### Bug Fixes

* Downgrade smali to fix dex compilation issue ([714447d](714447de70))
* Merge all extensions before initializing lookup maps ([328aa87](328aa876d8))
* Use null for compatible package version when adding packages only ([a8e8fa4](a8e8fa4093))
2024-08-06 16:53:42 +02:00
oSumAtrIX
5227e98abf fix: Downgrade smali to fix dex compilation issue 2024-08-06 16:53:42 +02:00
oSumAtrIX
8c4dd5b3a3 fix: Merge all extensions before initializing lookup maps 2024-08-06 16:53:42 +02:00
oSumAtrIX
736b3eebbf fix: Use null for compatible package version when adding packages only 2024-08-06 16:53:42 +02:00
oSumAtrIX
b41a542952 refactor: Convert method bodies to single expression functions 2024-08-06 16:53:42 +02:00
oSumAtrIX
d21128fe2e build(Needs bump): Bump dependencies 2024-08-06 16:53:42 +02:00
oSumAtrIX
cf4374b8cf docs: Fix syntax issues and improve wording 2024-08-06 16:53:42 +02:00
semantic-release-bot
8a30b0fa10 chore(release): 20.0.0-dev.1 [skip ci]
# [20.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v19.3.1...v20.0.0-dev.1) (2024-07-22)

### Features

* Convert APIs to Kotlin DSL ([#298](https://github.com/ReVanced/revanced-patcher/issues/298)) ([3f9cbd2](3f9cbd2408))

### BREAKING CHANGES

* Various old APIs are removed, and DSL APIs are added instead.
2024-08-06 16:53:42 +02:00
oSumAtrIX
11a911dc67 feat: Convert APIs to Kotlin DSL (#298)
This commit converts various APIs to Kotlin DSL.

BREAKING CHANGE: Various old APIs are removed, and DSL APIs are added instead.
2024-08-06 16:53:42 +02:00
oSumAtrIX
6e3ba7419b ci: Correct usage of repository variable 2024-08-06 16:53:42 +02:00
oSumAtrIX
50a66ccfed docs: Improve issue templates 2024-08-06 16:53:42 +02:00
oSumAtrIX
0be79840b1 chore: Fix spelling mistake 2024-08-06 16:53:42 +02:00
Vologhat
d8b4c60321 refactor: Simplify mapping classes to their names (#290)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-08-06 16:53:42 +02:00
oSumAtrIX
f77e99e817 build: Publish sources 2024-08-06 16:53:42 +02:00
oSumAtrIX
ea26c486c0 build: Set target bytecode level to JVM 11 2024-08-06 16:53:42 +02:00
oSumAtrIX
bebb734608 ci: Update action 2024-08-06 16:53:42 +02:00
oSumAtrIX
d842f82d07 chore: Lint code 2024-08-06 16:53:42 +02:00
oSumAtrIX
82bab58ac2 build: Bump dependencies 2024-08-06 16:53:42 +02:00
oSumAtrIX
90b7631d9e refactor: Properly abstract Patch#execute function 2024-08-06 16:53:42 +02:00
oSumAtrIX
26d449e6d9 docs: Fix broken links 2024-08-06 16:53:42 +02:00
oSumAtrIX
49466060e3 docs: Fix docs link [skip ci] 2024-08-06 16:53:42 +02:00
oSumAtrIX
620ea5b852 docs: Un-indent markdown to fix rendering 2024-08-06 16:53:42 +02:00
oSumAtrIX
3e2168a2b2 chore: Revert using a relative image path
For some reason GitHub does not render them correctly
2024-08-06 16:53:42 +02:00
oSumAtrIX
13c77967b1 build: Bump dependencies 2024-08-06 16:53:42 +02:00
oSumAtrIX
f57e571a14 chore: Merge branch dev to main (#276) 2024-02-25 03:33:57 +01:00
49 changed files with 2664 additions and 1585 deletions

View File

@@ -10,6 +10,9 @@ on:
jobs:
release:
name: Release
permissions:
contents: write
packages: write
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -46,5 +49,5 @@ jobs:
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm exec semantic-release

View File

@@ -23,7 +23,8 @@
"assets": [
"CHANGELOG.md",
"gradle.properties"
]
],
"message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
[

View File

@@ -1,3 +1,76 @@
## [20.0.1-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v20.0.1-dev.3...v20.0.1-dev.4) (2024-10-07)
### Bug Fixes
* Make it work on Android by not using APIs from JVM unavailable to Android. ([2be6e97](https://github.com/ReVanced/revanced-patcher/commit/2be6e97817437f40e17893dfff3bea2cd4c3ff9e))
## [20.0.1-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v20.0.1-dev.2...v20.0.1-dev.3) (2024-10-03)
### Performance Improvements
* Free memory earlier and remove negligible lookup maps ([d53aacd](https://github.com/ReVanced/revanced-patcher/commit/d53aacdad4ed3750ddae526fb307577ea36e6171))
## [20.0.1-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v20.0.1-dev.1...v20.0.1-dev.2) (2024-10-01)
## [20.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0...v20.0.1-dev.1) (2024-09-18)
### Bug Fixes
* Check for class type exactly instead of with contains ([#310](https://github.com/ReVanced/revanced-patcher/issues/310)) ([69f2f20](https://github.com/ReVanced/revanced-patcher/commit/69f2f20fd99162f91cd9c531dfe47d00d3152ead))
# [20.0.0](https://github.com/ReVanced/revanced-patcher/compare/v19.3.1...v20.0.0) (2024-08-06)
### Bug Fixes
* Downgrade smali to fix dex compilation issue ([5227e98](https://github.com/ReVanced/revanced-patcher/commit/5227e98abfaa2ff1204eb20a0f2671f58c489930))
* Improve exception message wording ([5481d0c](https://github.com/ReVanced/revanced-patcher/commit/5481d0c54ccecc91cd8d15af1ba2d3285a33e5ab))
* Make constructor internal as supposed ([7f44174](https://github.com/ReVanced/revanced-patcher/commit/7f44174d91f0af0d50a83d80a7103c779241e094))
* Merge all extensions before initializing lookup maps ([8c4dd5b](https://github.com/ReVanced/revanced-patcher/commit/8c4dd5b3a309077fa9a3827b4931fc28b0517809))
* Use null for compatible package version when adding packages only ([736b3ee](https://github.com/ReVanced/revanced-patcher/commit/736b3eebbfdd7279b8d5fcfc5c46c9e3aadbee12))
### Features
* Add ability to create options outside of a patch ([d310246](https://github.com/ReVanced/revanced-patcher/commit/d310246852504b08a15f6376bbf25ac7c6fae76f))
* Convert APIs to Kotlin DSL ([#298](https://github.com/ReVanced/revanced-patcher/issues/298)) ([11a911d](https://github.com/ReVanced/revanced-patcher/commit/11a911dc674eb0801649949dd3f28dfeb00efe97))
### BREAKING CHANGES
* Various old APIs are removed, and DSL APIs are added instead.
# [20.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.3...v20.0.0-dev.4) (2024-08-06)
### Bug Fixes
* Improve exception message wording ([bd434ce](https://github.com/ReVanced/revanced-patcher/commit/bd434ceb3394d1d5292e8b94e5bfd6da0e4e9c72))
# [20.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.2...v20.0.0-dev.3) (2024-08-01)
### Bug Fixes
* Make constructor internal as supposed ([e95fcd1](https://github.com/ReVanced/revanced-patcher/commit/e95fcd1c0b641164bbf0840ec7e562aeb3bacc3e))
### Features
* Add ability to create options outside of a patch ([b8d763a](https://github.com/ReVanced/revanced-patcher/commit/b8d763a66e0601627dd71c8c24247726aa300146))
# [20.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v20.0.0-dev.1...v20.0.0-dev.2) (2024-07-31)
### Bug Fixes
* Downgrade smali to fix dex compilation issue ([714447d](https://github.com/ReVanced/revanced-patcher/commit/714447de70096bf736e8e1d31c14bb5f24195070))
* Merge all extensions before initializing lookup maps ([328aa87](https://github.com/ReVanced/revanced-patcher/commit/328aa876d8ed7826be3713754b6404195e9fe84b))
* Use null for compatible package version when adding packages only ([a8e8fa4](https://github.com/ReVanced/revanced-patcher/commit/a8e8fa4093deb8cffbd7a582409f41867f6b568b))
# [20.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v19.3.1...v20.0.0-dev.1) (2024-07-22)

View File

@@ -67,7 +67,8 @@ public final class app/revanced/patcher/PatcherConfig {
public synthetic fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/PatcherContext {
public final class app/revanced/patcher/PatcherContext : java/io/Closeable {
public fun close ()V
public final fun getPackageMetadata ()Lapp/revanced/patcher/PackageMetadata;
}
@@ -148,13 +149,13 @@ public final class app/revanced/patcher/patch/BytecodePatchBuilder : app/revance
}
public final class app/revanced/patcher/patch/BytecodePatchBuilder$InvokedFingerprint {
public fun <init> (Lapp/revanced/patcher/Fingerprint;)V
public final fun getValue (Ljava/lang/Void;Lkotlin/reflect/KProperty;)Lapp/revanced/patcher/Match;
}
public final class app/revanced/patcher/patch/BytecodePatchContext : app/revanced/patcher/patch/PatchContext {
public final class app/revanced/patcher/patch/BytecodePatchContext : app/revanced/patcher/patch/PatchContext, java/io/Closeable {
public final fun classBy (Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/util/proxy/ClassProxy;
public final fun classByType (Ljava/lang/String;)Lapp/revanced/patcher/util/proxy/ClassProxy;
public fun close ()V
public synthetic fun get ()Ljava/lang/Object;
public fun get ()Ljava/util/Set;
public final fun getClasses ()Lapp/revanced/patcher/util/ProxyClassList;
@@ -203,25 +204,43 @@ public final class app/revanced/patcher/patch/OptionException$ValueValidationExc
public final class app/revanced/patcher/patch/OptionKt {
public static final fun booleanOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun booleanOption (Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun booleanOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun booleanOption$default (Ljava/lang/String;Ljava/lang/Boolean;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun booleansOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun booleansOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun booleansOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun booleansOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun floatOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun floatOption (Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun floatOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun floatOption$default (Ljava/lang/String;Ljava/lang/Float;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun floatsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun floatsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun intOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun intOption (Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun intOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun intOption$default (Ljava/lang/String;Ljava/lang/Integer;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun intsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun intsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun intsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun intsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun longOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun longOption (Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun longOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun longOption$default (Ljava/lang/String;Ljava/lang/Long;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun longsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun longsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun longsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun longsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun stringOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun stringOption (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun stringOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun stringOption$default (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static final fun stringsOption (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static final fun stringsOption (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun stringsOption$default (Lapp/revanced/patcher/patch/PatchBuilder;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
public static synthetic fun stringsOption$default (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lapp/revanced/patcher/patch/Option;
}
public final class app/revanced/patcher/patch/Options : java/util/Map, kotlin/jvm/internal/markers/KMappedMarker {

View File

@@ -36,20 +36,21 @@ repositories {
}
dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.xpp3)
implementation(libs.smali)
implementation(libs.multidexlib2)
implementation(libs.apktool.lib)
implementation(libs.kotlin.reflect)
// TODO: Convert project to KMP.
compileOnly(libs.android) {
// Exclude, otherwise the org.w3c.dom API breaks.
exclude(group = "xerces", module = "xmlParserAPIs")
}
testImplementation(libs.kotlin.test)
implementation(libs.apktool.lib)
implementation(libs.kotlin.reflect)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.multidexlib2)
implementation(libs.smali)
implementation(libs.xpp3)
testImplementation(libs.mockk)
testImplementation(libs.kotlin.test)
}
kotlin {

View File

@@ -115,9 +115,9 @@ val disableAdsPatch = bytecodePatch(
Patches can have options to get and set before a patch is executed.
Options are useful for making patches configurable.
After loading the patches using `PatchLoader`, options can be set for a patch.
Multiple types are already inbuilt in ReVanced Patcher and are supported by any application that uses ReVanced Patcher.
Multiple types are already built into ReVanced Patcher and are supported by any application that uses ReVanced Patcher.
To define an option, use available `option` functions:
To define an option, use the available `option` functions:
```kt
val patch = bytecodePatch(name = "Patch") {
@@ -149,9 +149,21 @@ The type of an option can be obtained from the `type` property of the option:
option.type // The KType of the option.
```
Options can be declared outside of a patch and added to a patch manually:
```kt
val option = stringOption(key = "option")
bytecodePatch(name = "Patch") {
val value by option()
}
```
This is useful when the same option is referenced in multiple patches.
### 🧩 Extensions
An extension is a precompiled DEX file that is merged into the patched app before a patch is executed.
An extension is a precompiled DEX file merged into the patched app before a patch is executed.
While patches are compile-time constructs, extensions are runtime constructs
that extend the patched app with additional classes.
@@ -232,13 +244,13 @@ The same order is followed for multiple patches depending on the patch.
## 💡 Additional tips
- When using ´PatchLoader` to load patches, only patches with a name are loaded.
- When using `PatchLoader` to load patches, only patches with a name are loaded.
Refer to the inline documentation of `PatchLoader` for detailed information.
- Patches can depend on others. Dependencies are executed first.
The dependent patch will not be executed if a dependency raises an exception while executing.
- A patch can declare compatibility with specific packages and versions,
but patches can still be executed on any package or version.
It is recommended to declare compatibility to present known compatible packages and versions.
It is recommended that compatibility is specified to present known compatible packages and versions.
- If `compatibleWith` is not used, the patch is treated as compatible with any package
- If a package is specified with no versions, the patch is compatible with any version of the package
- If an empty array of versions is specified, the patch is not compatible with any version of the package.

View File

@@ -108,7 +108,7 @@ val rawResourcePatch = rawResourcePatch {
}
@Surpress("unused")
val resourcePatch = rawResourcePatch {
val resourcePatch = resourcePatch {
execute {
// TODO
}

View File

@@ -1,3 +1,3 @@
org.gradle.parallel = true
org.gradle.caching = true
version = 20.0.0-dev.1
version = 20.0.1-dev.4

View File

@@ -1,20 +1,22 @@
[versions]
android = "4.1.1.4"
apktool-lib = "2.9.3"
kotlin = "1.9.22"
kotlinx-coroutines-core = "1.7.3"
binary-compatibility-validator = "0.15.1"
kotlin = "2.0.0"
kotlinx-coroutines-core = "1.8.1"
mockk = "1.13.10"
multidexlib2 = "3.0.3.r3"
# Tracking https://github.com/google/smali/issues/64.
#noinspection GradleDependency
smali = "3.0.5"
binary-compatibility-validator = "0.14.0"
xpp3 = "1.1.4c"
[libraries]
android = { module = "com.google.android:android", version.ref = "android" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
apktool-lib = { module = "app.revanced:apktool-lib", version.ref = "apktool-lib" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
multidexlib2 = { module = "app.revanced:multidexlib2", version.ref = "multidexlib2" }
smali = { module = "com.android.tools.smali:smali", version.ref = "smali" }

Binary file not shown.

View File

@@ -1,6 +1,8 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dist
zipStorePath=wrapper/dists

22
gradlew vendored
View File

@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -83,7 +85,9 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -144,7 +148,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -152,7 +156,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -201,11 +205,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \

22
gradlew.bat vendored
View File

@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail

2972
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"@saithodev/semantic-release-backmerge": "^4.0.1",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.9.1",
"semantic-release": "^23.0.2"
"gradle-semantic-release-plugin": "^1.10.1",
"semantic-release": "^24.1.2"
}
}

View File

@@ -3,8 +3,7 @@
package app.revanced.patcher
import app.revanced.patcher.extensions.InstructionExtensions.instructionsOrNull
import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.BytecodePatchContext.LookupMaps.Companion.appendParameters
import app.revanced.patcher.patch.MethodClassPairs
import app.revanced.patcher.util.proxy.ClassProxy
@@ -67,36 +66,15 @@ class Fingerprint internal constructor(
}
// TODO: If only one string is necessary, why not use a single string for every fingerprint?
fun Fingerprint.lookupByStrings() = strings?.firstNotNullOfOrNull { lookupMaps.methodsByStrings[it] }
if (lookupByStrings()?.let(::match) == true) {
if (strings?.firstNotNullOfOrNull { lookupMaps.methodsByStrings[it] }?.let(::match) == true) {
return true
}
// No strings declared or none matched (partial matches are allowed).
// Use signature matching.
fun Fingerprint.lookupBySignature(): MethodClassPairs {
if (accessFlags == null) return lookupMaps.allMethods
var returnTypeValue = returnType
if (returnTypeValue == null) {
if (AccessFlags.CONSTRUCTOR.isSet(accessFlags)) {
// Constructors always have void return type.
returnTypeValue = "V"
} else {
return lookupMaps.allMethods
}
}
val signature =
buildString {
append(accessFlags)
append(returnTypeValue.first())
appendParameters(parameters ?: return@buildString)
}
return lookupMaps.methodsBySignature[signature] ?: return MethodClassPairs()
context.classes.forEach { classDef ->
if (match(context, classDef)) return true
}
return match(lookupBySignature())
return false
}
/**
@@ -129,7 +107,7 @@ class Fingerprint internal constructor(
fun match(
context: BytecodePatchContext,
method: Method,
) = match(context, method, context.classByType(method.definingClass)!!.immutableClass)
) = match(context, method, context.classBy { method.definingClass == it.type }!!.immutableClass)
/**
* Match using a [Method].

View File

@@ -39,9 +39,6 @@ class Patcher(private val config: PatcherConfig) : Closeable {
patch.addRecursively()
}
fun Patch<*>.anyRecursively(predicate: (Patch<*>) -> Boolean): Boolean =
predicate(this) || dependencies.any { dependency -> dependency.anyRecursively(predicate) }
context.allPatches.let { allPatches ->
// Check, if what kind of resource mode is required.
config.resourceMode = if (allPatches.any { patch -> patch.anyRecursively { it is ResourcePatch } }) {
@@ -99,6 +96,15 @@ class Patcher(private val config: PatcherConfig) : Closeable {
context.resourceContext.decodeResources(config.resourceMode)
}
logger.info("Merging extensions")
with(context.bytecodeContext) {
context.executablePatches.mergeExtensions()
// Initialize lookup maps.
lookupMaps
}
logger.info("Executing patches")
val executedPatches = LinkedHashMap<Patch<*>, PatchResult>()
@@ -146,7 +152,7 @@ class Patcher(private val config: PatcherConfig) : Closeable {
}
}
override fun close() = context.bytecodeContext.lookupMaps.close()
override fun close() = context.close()
/**
* Compile and save patched APK files.

View File

@@ -20,6 +20,7 @@ class PatcherConfig(
private val temporaryFilesPath: File = File("revanced-temporary-files"),
aaptBinaryPath: String? = null,
frameworkFileDirectory: String? = null,
@Deprecated("This is going to be removed in the future because it is not needed anymore.")
internal val multithreadingDexFileWriter: Boolean = false,
) {
private val logger = Logger.getLogger(PatcherConfig::class.java.name)

View File

@@ -5,6 +5,7 @@ import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.ResourcePatchContext
import brut.androlib.apk.ApkInfo
import brut.directory.ExtFile
import java.io.Closeable
/**
* A context for the patcher containing the current state of the patcher.
@@ -12,7 +13,7 @@ import brut.directory.ExtFile
* @param config The configuration for the patcher.
*/
@Suppress("MemberVisibilityCanBePrivate")
class PatcherContext internal constructor(config: PatcherConfig) {
class PatcherContext internal constructor(config: PatcherConfig): Closeable {
/**
* [PackageMetadata] of the supplied [PatcherConfig.apkFile].
*/
@@ -37,4 +38,6 @@ class PatcherContext internal constructor(config: PatcherConfig) {
* The context for patches containing the current state of the bytecode.
*/
internal val bytecodeContext = BytecodePatchContext(config)
override fun close() = bytecodeContext.close()
}

View File

@@ -21,7 +21,6 @@ import lanchon.multidexlib2.MultiDexIO
import lanchon.multidexlib2.RawDexIO
import java.io.Closeable
import java.io.FileFilter
import java.io.InputStream
import java.util.*
import java.util.logging.Logger
@@ -31,7 +30,9 @@ import java.util.logging.Logger
* @param config The [PatcherConfig] used to create this context.
*/
@Suppress("MemberVisibilityCanBePrivate")
class BytecodePatchContext internal constructor(private val config: PatcherConfig) : PatchContext<Set<PatcherResult.PatchedDexFile>> {
class BytecodePatchContext internal constructor(private val config: PatcherConfig) :
PatchContext<Set<PatcherResult.PatchedDexFile>>,
Closeable {
private val logger = Logger.getLogger(BytecodePatchContext::class.java.name)
/**
@@ -58,33 +59,41 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
internal val lookupMaps by lazy { LookupMaps(classes) }
/**
* Merge an extension to [classes].
*
* @param extensionInputStream The input stream of the extension to merge.
* Merge the extensions for this set of patches.
*/
internal fun merge(extensionInputStream: InputStream) {
val extension = extensionInputStream.readAllBytes()
internal fun Set<Patch<*>>.mergeExtensions() {
// Lookup map for fast checking if a class exists by its type.
val classesByType = mutableMapOf<String, ClassDef>().apply {
classes.forEach { classDef -> put(classDef.type, classDef) }
}
RawDexIO.readRawDexFile(extension, 0, null).classes.forEach { classDef ->
val existingClass = lookupMaps.classesByType[classDef.type] ?: run {
logger.fine("Adding class \"$classDef\"")
forEachRecursively { patch ->
if (patch is BytecodePatch && patch.extension != null) {
lookupMaps.classesByType[classDef.type] = classDef
classes += classDef
val extension = patch.extension.readAllBytes()
return@forEach
}
RawDexIO.readRawDexFile(extension, 0, null).classes.forEach { classDef ->
val existingClass = classesByType[classDef.type] ?: run {
logger.fine("Adding class \"$classDef\"")
logger.fine("Class \"$classDef\" exists already. Adding missing methods and fields.")
classes += classDef
classesByType[classDef.type] = classDef
existingClass.merge(classDef, this@BytecodePatchContext).let { mergedClass ->
// If the class was merged, replace the original class with the merged class.
if (mergedClass === existingClass) {
return@let
return@forEach
}
logger.fine("Class \"$classDef\" exists already. Adding missing methods and fields.")
existingClass.merge(classDef, this@BytecodePatchContext).let { mergedClass ->
// If the class was merged, replace the original class with the merged class.
if (mergedClass === existingClass) {
return@let
}
classes -= existingClass
classes += mergedClass
}
}
classes -= existingClass
classes += mergedClass
}
}
}
@@ -95,6 +104,7 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
* @param type The type of the class.
* @return A proxy for the first class that matches the type.
*/
@Deprecated("Use classBy { type in it.type } instead.", ReplaceWith("classBy { type in it.type }"))
fun classByType(type: String) = classBy { type in it.type }
/**
@@ -135,6 +145,9 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
override fun get(): Set<PatcherResult.PatchedDexFile> {
logger.info("Compiling patched dex files")
// Free up memory before compiling the dex files.
lookupMaps.close()
val patchedDexFileResults =
config.patchedFiles.resolve("dex").also {
it.deleteRecursively() // Make sure the directory is empty.
@@ -168,21 +181,6 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
* @param classes The list of classes to create the lookup maps from.
*/
internal class LookupMaps internal constructor(classes: List<ClassDef>) : Closeable {
/**
* Classes associated by their type.
*/
internal val classesByType = classes.associateBy { it.type }.toMutableMap()
/**
* All methods and the class they are a member of.
*/
internal val allMethods = MethodClassPairs()
/**
* Methods associated by its access flags, return type and parameter.
*/
internal val methodsBySignature = MethodClassPairsLookupMap()
/**
* Methods associated by strings referenced in it.
*/
@@ -193,22 +191,6 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
classDef.methods.forEach { method ->
val methodClassPair: MethodClassPair = method to classDef
// For fingerprints with no access or return type specified.
allMethods += methodClassPair
val accessFlagsReturnKey = method.accessFlags.toString() + method.returnType.first()
// Add <access><returnType> as the key.
methodsBySignature[accessFlagsReturnKey] = methodClassPair
// Add <access><returnType>[parameters] as the key.
methodsBySignature[
buildString {
append(accessFlagsReturnKey)
appendParameters(method.parameterTypes)
},
] = methodClassPair
// Add strings contained in the method as the key.
method.instructionsOrNull?.forEach instructions@{ instruction ->
if (instruction.opcode != Opcode.CONST_STRING && instruction.opcode != Opcode.CONST_STRING_JUMBO) {
@@ -249,11 +231,14 @@ class BytecodePatchContext internal constructor(private val config: PatcherConfi
}
override fun close() {
allMethods.clear()
methodsBySignature.clear()
methodsByStrings.clear()
}
}
override fun close() {
lookupMaps.close()
classes.clear()
}
}
/**

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,9 @@ import lanchon.multidexlib2.BasicDexFileNamer
import lanchon.multidexlib2.MultiDexIO
import java.io.File
import java.io.InputStream
import java.lang.reflect.Member
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.net.URLClassLoader
import java.util.jar.JarFile
import kotlin.reflect.KProperty
@@ -48,6 +51,9 @@ sealed class Patch<C : PatchContext<*>>(
// if a patch has a finalizing block in order to not emit it twice.
internal var finalizeBlock: (Patch<C>.(C) -> Unit)?,
) {
/**
* The options of the patch.
*/
val options = Options(options)
/**
@@ -85,6 +91,31 @@ sealed class Patch<C : PatchContext<*>>(
override fun toString() = name ?: "Patch"
}
internal fun Patch<*>.anyRecursively(
visited: MutableSet<Patch<*>> = mutableSetOf(),
predicate: (Patch<*>) -> Boolean,
): Boolean {
if (this in visited) return false
if (predicate(this)) return true
visited += this
return dependencies.any { it.anyRecursively(visited, predicate) }
}
internal fun Iterable<Patch<*>>.forEachRecursively(
visited: MutableSet<Patch<*>> = mutableSetOf(),
action: (Patch<*>) -> Unit,
): Unit = forEach {
if (it in visited) return@forEach
visited += it
action(it)
it.dependencies.forEachRecursively(visited, action)
}
/**
* A bytecode patch.
*
@@ -127,7 +158,6 @@ class BytecodePatch internal constructor(
finalizeBlock,
) {
override fun execute(context: PatcherContext) = with(context.bytecodeContext) {
extension?.let(::merge)
fingerprints.forEach { it.match(this) }
execute(this)
@@ -268,7 +298,14 @@ sealed class PatchBuilder<C : PatchContext<*>>(
*
* @param versions The versions of the package.
*/
operator fun String.invoke(vararg versions: String) = this to versions.toSet()
operator fun String.invoke(vararg versions: String) = invoke(versions.toSet())
/**
* Create a package a patch is compatible with.
*
* @param versions The versions of the package.
*/
private operator fun String.invoke(versions: Set<String>? = null) = this to versions
/**
* Add packages the patch is compatible with.
@@ -325,6 +362,16 @@ sealed class PatchBuilder<C : PatchContext<*>>(
internal abstract fun build(): Patch<C>
}
/**
* Builds a [Patch].
*
* @param B The [PatchBuilder] to build the patch with.
* @param block The block to build the patch.
*
* @return The built [Patch].
*/
private fun <B : PatchBuilder<*>> B.buildPatch(block: B.() -> Unit = {}) = apply(block).build()
/**
* A [BytecodePatchBuilder] builder.
*
@@ -352,13 +399,13 @@ class BytecodePatchBuilder internal constructor(
*/
operator fun Fingerprint.invoke() = InvokedFingerprint(also { fingerprints.add(it) })
class InvokedFingerprint(private val fingerprint: Fingerprint) {
class InvokedFingerprint internal constructor(private val fingerprint: Fingerprint) {
// The reason getValue isn't extending the Fingerprint class is
// because delegating makes only sense if the fingerprint was previously added to the patch by invoking it.
// It may be likely to forget invoking it. By wrapping the fingerprint into this class,
// the compiler will throw an error if the fingerprint was not invoked if attempting to delegate the match.
operator fun getValue(nothing: Nothing?, property: KProperty<*>) = fingerprint.match
?: throw PatchException("No fingerprint match to delegate to ${property.name}.")
?: throw PatchException("No fingerprint match to delegate to \"${property.name}\".")
}
// Must be internal for the inlined function "extendWith".
@@ -372,9 +419,10 @@ class BytecodePatchBuilder internal constructor(
*
* @param extension The name of the extension resource.
*/
@Suppress("NOTHING_TO_INLINE")
inline fun extendWith(extension: String) = apply {
this.extension = object {}.javaClass.classLoader.getResourceAsStream(extension)
?: throw PatchException("Extension resource \"$extension\" not found")
?: throw PatchException("Extension \"$extension\" not found")
}
override fun build() = BytecodePatch(
@@ -391,6 +439,24 @@ class BytecodePatchBuilder internal constructor(
)
}
/**
* Create a new [BytecodePatch].
*
* @param name The name of the patch.
* If null, the patch is named "Patch" and will not be loaded by [PatchLoader].
* @param description The description of the patch.
* @param use Weather or not the patch should be used.
* @param block The block to build the patch.
*
* @return The created [BytecodePatch].
*/
fun bytecodePatch(
name: String? = null,
description: String? = null,
use: Boolean = true,
block: BytecodePatchBuilder.() -> Unit = {},
) = BytecodePatchBuilder(name, description, use).buildPatch(block) as BytecodePatch
/**
* A [RawResourcePatch] builder.
*
@@ -418,6 +484,23 @@ class RawResourcePatchBuilder internal constructor(
)
}
/**
* Create a new [RawResourcePatch].
*
* @param name The name of the patch.
* If null, the patch is named "Patch" and will not be loaded by [PatchLoader].
* @param description The description of the patch.
* @param use Weather or not the patch should be used.
* @param block The block to build the patch.
* @return The created [RawResourcePatch].
*/
fun rawResourcePatch(
name: String? = null,
description: String? = null,
use: Boolean = true,
block: RawResourcePatchBuilder.() -> Unit = {},
) = RawResourcePatchBuilder(name, description, use).buildPatch(block) as RawResourcePatch
/**
* A [ResourcePatch] builder.
*
@@ -445,51 +528,6 @@ class ResourcePatchBuilder internal constructor(
)
}
/**
* Builds a [Patch].
*
* @param B The [PatchBuilder] to build the patch with.
* @param block The block to build the patch.
*
* @return The built [Patch].
*/
private fun <B : PatchBuilder<*>> B.buildPatch(block: B.() -> Unit = {}) = apply(block).build()
/**
* Create a new [BytecodePatch].
*
* @param name The name of the patch.
* If null, the patch is named "Patch" and will not be loaded by [PatchLoader].
* @param description The description of the patch.
* @param use Weather or not the patch should be used.
* @param block The block to build the patch.
*
* @return The created [BytecodePatch].
*/
fun bytecodePatch(
name: String? = null,
description: String? = null,
use: Boolean = true,
block: BytecodePatchBuilder.() -> Unit = {},
) = BytecodePatchBuilder(name, description, use).buildPatch(block) as BytecodePatch
/**
* Create a new [RawResourcePatch].
*
* @param name The name of the patch.
* If null, the patch is named "Patch" and will not be loaded by [PatchLoader].
* @param description The description of the patch.
* @param use Weather or not the patch should be used.
* @param block The block to build the patch.
* @return The created [RawResourcePatch].
*/
fun rawResourcePatch(
name: String? = null,
description: String? = null,
use: Boolean = true,
block: RawResourcePatchBuilder.() -> Unit = {},
) = RawResourcePatchBuilder(name, description, use).buildPatch(block) as RawResourcePatch
/**
* Create a new [ResourcePatch].
*
@@ -601,7 +639,7 @@ sealed class PatchLoader private constructor(
*/
private val Class<*>.patchFields
get() = fields.filter { field ->
field.type.isPatch && field.canAccess(null)
field.type.isPatch && field.canAccess()
}.map { field ->
field.get(null) as Patch<*>
}
@@ -611,7 +649,7 @@ sealed class PatchLoader private constructor(
*/
private val Class<*>.patchMethods
get() = methods.filter { method ->
method.returnType.isPatch && method.parameterCount == 0 && method.canAccess(null)
method.returnType.isPatch && method.parameterCount == 0 && method.canAccess()
}.map { method ->
method.invoke(null) as Patch<*>
}
@@ -635,6 +673,12 @@ sealed class PatchLoader private constructor(
it.name != null
}.toSet()
}
private fun Member.canAccess(): Boolean {
if (this is Method && parameterCount != 0) return false
return Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)
}
}
}

View File

@@ -179,7 +179,9 @@ internal object ClassMerger {
callback: MutableClass.() -> Unit,
) {
callback(targetClass)
this.classByType(targetClass.superclass ?: return)?.mutableClass?.let {
targetClass.superclass ?: return
this.classBy { targetClass.superclass == it.type }?.mutableClass?.let {
traverseClassHierarchy(it, callback)
}
}

View File

@@ -9,21 +9,13 @@ class MutableAnnotation(annotation: Annotation) : BaseAnnotation() {
private val type = annotation.type
private val _elements by lazy { annotation.elements.map { element -> element.toMutable() }.toMutableSet() }
override fun getType(): String {
return type
}
override fun getType(): String = type
override fun getElements(): MutableSet<MutableAnnotationElement> {
return _elements
}
override fun getElements(): MutableSet<MutableAnnotationElement> = _elements
override fun getVisibility(): Int {
return visibility
}
override fun getVisibility(): Int = visibility
companion object {
fun Annotation.toMutable(): MutableAnnotation {
return MutableAnnotation(this)
}
fun Annotation.toMutable(): MutableAnnotation = MutableAnnotation(this)
}
}

View File

@@ -18,17 +18,11 @@ class MutableAnnotationElement(annotationElement: AnnotationElement) : BaseAnnot
this.value = value
}
override fun getName(): String {
return name
}
override fun getName(): String = name
override fun getValue(): EncodedValue {
return value
}
override fun getValue(): EncodedValue = value
companion object {
fun AnnotationElement.toMutable(): MutableAnnotationElement {
return MutableAnnotationElement(this)
}
fun AnnotationElement.toMutable(): MutableAnnotationElement = MutableAnnotationElement(this)
}
}

View File

@@ -7,9 +7,10 @@ import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.util.FieldUtil
import com.android.tools.smali.dexlib2.util.MethodUtil
import com.google.common.collect.Iterables
class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
class MutableClass(classDef: ClassDef) :
BaseTypeReference(),
ClassDef {
// Class
private var type = classDef.type
private var sourceFile = classDef.sourceFile
@@ -23,13 +24,13 @@ class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
// Methods
private val _methods by lazy { classDef.methods.map { method -> method.toMutable() }.toMutableSet() }
private val _directMethods by lazy { Iterables.filter(_methods, MethodUtil.METHOD_IS_DIRECT).toMutableSet() }
private val _virtualMethods by lazy { Iterables.filter(_methods, MethodUtil.METHOD_IS_VIRTUAL).toMutableSet() }
private val _directMethods by lazy { _methods.filter { method -> MethodUtil.isDirect(method) }.toMutableSet() }
private val _virtualMethods by lazy { _methods.filter { method -> !MethodUtil.isDirect(method) }.toMutableSet() }
// Fields
private val _fields by lazy { classDef.fields.map { field -> field.toMutable() }.toMutableSet() }
private val _staticFields by lazy { Iterables.filter(_fields, FieldUtil.FIELD_IS_STATIC).toMutableSet() }
private val _instanceFields by lazy { Iterables.filter(_fields, FieldUtil.FIELD_IS_INSTANCE).toMutableSet() }
private val _staticFields by lazy { _fields.filter { field -> FieldUtil.isStatic(field) }.toMutableSet() }
private val _instanceFields by lazy { _fields.filter { field -> !FieldUtil.isStatic(field) }.toMutableSet() }
fun setType(type: String) {
this.type = type
@@ -47,57 +48,31 @@ class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
this.superclass = superclass
}
override fun getType(): String {
return type
}
override fun getType(): String = type
override fun getAccessFlags(): Int {
return accessFlags
}
override fun getAccessFlags(): Int = accessFlags
override fun getSourceFile(): String? {
return sourceFile
}
override fun getSourceFile(): String? = sourceFile
override fun getSuperclass(): String? {
return superclass
}
override fun getSuperclass(): String? = superclass
override fun getInterfaces(): MutableList<String> {
return _interfaces
}
override fun getInterfaces(): MutableList<String> = _interfaces
override fun getAnnotations(): MutableSet<MutableAnnotation> {
return _annotations
}
override fun getAnnotations(): MutableSet<MutableAnnotation> = _annotations
override fun getStaticFields(): MutableSet<MutableField> {
return _staticFields
}
override fun getStaticFields(): MutableSet<MutableField> = _staticFields
override fun getInstanceFields(): MutableSet<MutableField> {
return _instanceFields
}
override fun getInstanceFields(): MutableSet<MutableField> = _instanceFields
override fun getFields(): MutableSet<MutableField> {
return _fields
}
override fun getFields(): MutableSet<MutableField> = _fields
override fun getDirectMethods(): MutableSet<MutableMethod> {
return _directMethods
}
override fun getDirectMethods(): MutableSet<MutableMethod> = _directMethods
override fun getVirtualMethods(): MutableSet<MutableMethod> {
return _virtualMethods
}
override fun getVirtualMethods(): MutableSet<MutableMethod> = _virtualMethods
override fun getMethods(): MutableSet<MutableMethod> {
return _methods
}
override fun getMethods(): MutableSet<MutableMethod> = _methods
companion object {
fun ClassDef.toMutable(): MutableClass {
return MutableClass(this)
}
fun ClassDef.toMutable(): MutableClass = MutableClass(this)
}
}

View File

@@ -7,7 +7,9 @@ import com.android.tools.smali.dexlib2.HiddenApiRestriction
import com.android.tools.smali.dexlib2.base.reference.BaseFieldReference
import com.android.tools.smali.dexlib2.iface.Field
class MutableField(field: Field) : Field, BaseFieldReference() {
class MutableField(field: Field) :
BaseFieldReference(),
Field {
private var definingClass = field.definingClass
private var name = field.name
private var type = field.type
@@ -37,37 +39,21 @@ class MutableField(field: Field) : Field, BaseFieldReference() {
this.initialValue = initialValue
}
override fun getDefiningClass(): String {
return this.definingClass
}
override fun getDefiningClass(): String = this.definingClass
override fun getName(): String {
return this.name
}
override fun getName(): String = this.name
override fun getType(): String {
return this.type
}
override fun getType(): String = this.type
override fun getAnnotations(): MutableSet<MutableAnnotation> {
return this._annotations
}
override fun getAnnotations(): MutableSet<MutableAnnotation> = this._annotations
override fun getAccessFlags(): Int {
return this.accessFlags
}
override fun getAccessFlags(): Int = this.accessFlags
override fun getHiddenApiRestrictions(): MutableSet<HiddenApiRestriction> {
return this._hiddenApiRestrictions
}
override fun getHiddenApiRestrictions(): MutableSet<HiddenApiRestriction> = this._hiddenApiRestrictions
override fun getInitialValue(): MutableEncodedValue? {
return this.initialValue
}
override fun getInitialValue(): MutableEncodedValue? = this.initialValue
companion object {
fun Field.toMutable(): MutableField {
return MutableField(this)
}
fun Field.toMutable(): MutableField = MutableField(this)
}
}

View File

@@ -7,7 +7,9 @@ import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.Method
class MutableMethod(method: Method) : Method, BaseMethodReference() {
class MutableMethod(method: Method) :
BaseMethodReference(),
Method {
private var definingClass = method.definingClass
private var name = method.name
private var accessFlags = method.accessFlags
@@ -36,45 +38,25 @@ class MutableMethod(method: Method) : Method, BaseMethodReference() {
this.returnType = returnType
}
override fun getDefiningClass(): String {
return definingClass
}
override fun getDefiningClass(): String = definingClass
override fun getName(): String {
return name
}
override fun getName(): String = name
override fun getParameterTypes(): MutableList<CharSequence> {
return _parameterTypes
}
override fun getParameterTypes(): MutableList<CharSequence> = _parameterTypes
override fun getReturnType(): String {
return returnType
}
override fun getReturnType(): String = returnType
override fun getAnnotations(): MutableSet<MutableAnnotation> {
return _annotations
}
override fun getAnnotations(): MutableSet<MutableAnnotation> = _annotations
override fun getAccessFlags(): Int {
return accessFlags
}
override fun getAccessFlags(): Int = accessFlags
override fun getHiddenApiRestrictions(): MutableSet<HiddenApiRestriction> {
return _hiddenApiRestrictions
}
override fun getHiddenApiRestrictions(): MutableSet<HiddenApiRestriction> = _hiddenApiRestrictions
override fun getParameters(): MutableList<MutableMethodParameter> {
return _parameters
}
override fun getParameters(): MutableList<MutableMethodParameter> = _parameters
override fun getImplementation(): MutableMethodImplementation? {
return _implementation
}
override fun getImplementation(): MutableMethodImplementation? = _implementation
companion object {
fun Method.toMutable(): MutableMethod {
return MutableMethod(this)
}
fun Method.toMutable(): MutableMethod = MutableMethod(this)
}
}

View File

@@ -5,7 +5,9 @@ import com.android.tools.smali.dexlib2.base.BaseMethodParameter
import com.android.tools.smali.dexlib2.iface.MethodParameter
// TODO: finish overriding all members if necessary
class MutableMethodParameter(parameter: MethodParameter) : MethodParameter, BaseMethodParameter() {
class MutableMethodParameter(parameter: MethodParameter) :
BaseMethodParameter(),
MethodParameter {
private var type = parameter.type
private var name = parameter.name
private var signature = parameter.signature
@@ -13,25 +15,15 @@ class MutableMethodParameter(parameter: MethodParameter) : MethodParameter, Base
parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet()
}
override fun getType(): String {
return type
}
override fun getType(): String = type
override fun getName(): String? {
return name
}
override fun getName(): String? = name
override fun getSignature(): String? {
return signature
}
override fun getSignature(): String? = signature
override fun getAnnotations(): MutableSet<MutableAnnotation> {
return _annotations
}
override fun getAnnotations(): MutableSet<MutableAnnotation> = _annotations
companion object {
fun MethodParameter.toMutable(): MutableMethodParameter {
return MutableMethodParameter(this)
}
fun MethodParameter.toMutable(): MutableMethodParameter = MutableMethodParameter(this)
}
}

View File

@@ -14,21 +14,15 @@ class MutableAnnotationEncodedValue(annotationEncodedValue: AnnotationEncodedVal
annotationEncodedValue.elements.map { annotationElement -> annotationElement.toMutable() }.toMutableSet()
}
override fun getType(): String {
return this.type
}
override fun getType(): String = this.type
fun setType(type: String) {
this.type = type
}
override fun getElements(): MutableSet<out AnnotationElement> {
return _elements
}
override fun getElements(): MutableSet<out AnnotationElement> = _elements
companion object {
fun AnnotationEncodedValue.toMutable(): MutableAnnotationEncodedValue {
return MutableAnnotationEncodedValue(this)
}
fun AnnotationEncodedValue.toMutable(): MutableAnnotationEncodedValue = MutableAnnotationEncodedValue(this)
}
}

View File

@@ -5,18 +5,16 @@ import com.android.tools.smali.dexlib2.base.value.BaseArrayEncodedValue
import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue
import com.android.tools.smali.dexlib2.iface.value.EncodedValue
class MutableArrayEncodedValue(arrayEncodedValue: ArrayEncodedValue) : BaseArrayEncodedValue(), MutableEncodedValue {
class MutableArrayEncodedValue(arrayEncodedValue: ArrayEncodedValue) :
BaseArrayEncodedValue(),
MutableEncodedValue {
private val _value by lazy {
arrayEncodedValue.value.map { encodedValue -> encodedValue.toMutable() }.toMutableList()
}
override fun getValue(): MutableList<out EncodedValue> {
return _value
}
override fun getValue(): MutableList<out EncodedValue> = _value
companion object {
fun ArrayEncodedValue.toMutable(): MutableArrayEncodedValue {
return MutableArrayEncodedValue(this)
}
fun ArrayEncodedValue.toMutable(): MutableArrayEncodedValue = MutableArrayEncodedValue(this)
}
}

View File

@@ -8,17 +8,13 @@ class MutableBooleanEncodedValue(booleanEncodedValue: BooleanEncodedValue) :
MutableEncodedValue {
private var value = booleanEncodedValue.value
override fun getValue(): Boolean {
return this.value
}
override fun getValue(): Boolean = this.value
fun setValue(value: Boolean) {
this.value = value
}
companion object {
fun BooleanEncodedValue.toMutable(): MutableBooleanEncodedValue {
return MutableBooleanEncodedValue(this)
}
fun BooleanEncodedValue.toMutable(): MutableBooleanEncodedValue = MutableBooleanEncodedValue(this)
}
}

Some files were not shown because too many files have changed in this diff Show More