mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-09 10:53:55 +01:00
Compare commits
102 Commits
v1.0.0-dev
...
v1.0.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd1981a086 | ||
|
|
abf42a89c5 | ||
|
|
7dfcf3b730 | ||
|
|
dd0d58fc3b | ||
|
|
15630fe9f9 | ||
|
|
27f6aa5b7b | ||
|
|
a2038a0507 | ||
|
|
1748cd98a4 | ||
|
|
96e7aed843 | ||
|
|
96f76b2eb5 | ||
|
|
f25c8d2cd1 | ||
|
|
fa3f6e2f33 | ||
|
|
c2aa3b8365 | ||
|
|
e09f25cb75 | ||
|
|
0207d08c17 | ||
|
|
ae1127c02d | ||
|
|
e49fb3c969 | ||
|
|
80462bbe1c | ||
|
|
8043396ee4 | ||
|
|
70bfd792bf | ||
|
|
e6f3b3cd21 | ||
|
|
364155f683 | ||
|
|
24245b8d53 | ||
|
|
51aeebe1e8 | ||
|
|
6f72b84a32 | ||
|
|
2ea7ccdf43 | ||
|
|
2aa5c2d611 | ||
|
|
34f6dcfc63 | ||
|
|
a182ff5bdb | ||
|
|
8242fde8f1 | ||
|
|
923b0d9a01 | ||
|
|
98ce25d50f | ||
|
|
5cf23a72d2 | ||
|
|
7193575eee | ||
|
|
51a061fe2d | ||
|
|
c6dae56521 | ||
|
|
08b4294f5e | ||
|
|
5114ae1a2a | ||
|
|
385c278e05 | ||
|
|
529fa1edff | ||
|
|
a80fc38b60 | ||
|
|
d6d6438110 | ||
|
|
acdb44477c | ||
|
|
1a3fed3b65 | ||
|
|
5877714361 | ||
|
|
57f506dbfd | ||
|
|
c2e0e918d0 | ||
|
|
8b5d316ad3 | ||
|
|
2d1c3ee109 | ||
|
|
89d5b08d85 | ||
|
|
024ecb2fb0 | ||
|
|
54196e70ab | ||
|
|
b67dec3294 | ||
|
|
22d8791ac6 | ||
|
|
34449abe41 | ||
|
|
42253f016a | ||
|
|
89dcb56a9f | ||
|
|
0c16b51e93 | ||
|
|
d29329fb32 | ||
|
|
9cb59b44e3 | ||
|
|
9987679f66 | ||
|
|
38d77be08b | ||
|
|
f65199c028 | ||
|
|
a63db11046 | ||
|
|
78d1c97aa1 | ||
|
|
affd51d2c1 | ||
|
|
067d530901 | ||
|
|
c46c150629 | ||
|
|
5cb333d769 | ||
|
|
c3f5eec804 | ||
|
|
38761e8e26 | ||
|
|
a55fa685f6 | ||
|
|
c36c5f80b4 | ||
|
|
9fa44443fa | ||
|
|
858468dc1d | ||
|
|
dcc825088c | ||
|
|
f073388b9a | ||
|
|
97e1b65900 | ||
|
|
046d1f05f7 | ||
|
|
51c45c636f | ||
|
|
2f2a0ff5e3 | ||
|
|
0a57a1d1c1 | ||
|
|
dc59fe1b22 | ||
|
|
73a47dc3f6 | ||
|
|
d474d669e6 | ||
|
|
ecacfd72e8 | ||
|
|
fb4dc1dcfc | ||
|
|
af4d514038 | ||
|
|
cc558b35e9 | ||
|
|
ab234789cc | ||
|
|
61554ce809 | ||
|
|
65c6794a7c | ||
|
|
051e80cc2b | ||
|
|
f4d25aeea2 | ||
|
|
95be597eab | ||
|
|
9e49e71364 | ||
|
|
d01658c840 | ||
|
|
ba1103aca3 | ||
|
|
85236c57b8 | ||
|
|
bf2b2ae791 | ||
|
|
9e1dac57e7 | ||
|
|
790c84a00e |
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@@ -1,5 +1,6 @@
|
|||||||
name: Release
|
name: Release
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
@@ -20,7 +21,7 @@ jobs:
|
|||||||
- name: Setup JDK
|
- name: Setup JDK
|
||||||
uses: actions/setup-java@v2
|
uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
java-version: '8'
|
java-version: '17'
|
||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
cache: gradle
|
cache: gradle
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
@@ -32,7 +33,7 @@ jobs:
|
|||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: ./gradlew build
|
run: ./gradlew build clean
|
||||||
- name: Setup semantic-release
|
- name: Setup semantic-release
|
||||||
run: npm install -g semantic-release @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin -D
|
run: npm install -g semantic-release @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin -D
|
||||||
- name: Release
|
- name: Release
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -111,4 +111,7 @@ gradle-app.setting
|
|||||||
.gradletasknamecache
|
.gradletasknamecache
|
||||||
|
|
||||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||||
# gradle/wrapper/gradle-wrapper.properties
|
# gradle/wrapper/gradle-wrapper.properties
|
||||||
|
|
||||||
|
# Potentially copyrighted test APK
|
||||||
|
*.apk
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -4,5 +4,5 @@
|
|||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="azul-17" project-jdk-type="JavaSDK" />
|
||||||
</project>
|
</project>
|
||||||
11
.releaserc
11
.releaserc
@@ -20,6 +20,15 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@semantic-release/github"
|
[
|
||||||
|
"@semantic-release/github",
|
||||||
|
{
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"path": "build/libs/*.jar"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
110
CHANGELOG.md
110
CHANGELOG.md
@@ -1,3 +1,113 @@
|
|||||||
|
# [1.0.0-dev.10](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.9...v1.0.0-dev.10) (2022-05-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* `create-button-signature` ([a173f6e](https://github.com/revanced/revanced-patches/commit/a173f6e5a7e65943657e2072e8a72a4a680e5277))
|
||||||
|
* breaking changes by `revanced-patcher` dependency ([e12e484](https://github.com/revanced/revanced-patches/commit/e12e484e3796c5c9c8505b677838cdf8432f2e79))
|
||||||
|
* loop in `amoled` patch ([c4c86b6](https://github.com/revanced/revanced-patches/commit/c4c86b65fd8b2463c1d86ad2e46ec9f08e60d47c))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add `amoled` patch ([d61bac4](https://github.com/revanced/revanced-patches/commit/d61bac4f8243d0ef72ca91c7c1d5facd858d515e))
|
||||||
|
* update patches to latest version ([bad25de](https://github.com/revanced/revanced-patches/commit/bad25dec1d73137f8b7a1bf4daaceb2279b4d48c))
|
||||||
|
|
||||||
|
# [1.0.0-dev.9](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.8...v1.0.0-dev.9) (2022-05-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* clean after building ([a2df3fb](https://github.com/revanced/revanced-patches/commit/a2df3fbc9761b07f3010542fa8684ade00e4dc91))
|
||||||
|
|
||||||
|
# [1.0.0-dev.8](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.7...v1.0.0-dev.8) (2022-05-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* publish releases ([83916f9](https://github.com/revanced/revanced-patches/commit/83916f96d27989dcbb35c0ba6ef326a16b470501))
|
||||||
|
|
||||||
|
# [1.0.0-dev.7](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.6...v1.0.0-dev.7) (2022-05-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* use the latest version of patcher dependency ([fe4a439](https://github.com/revanced/revanced-patches/commit/fe4a439cb2bc5e385ae13e8e155f25bb15e74633))
|
||||||
|
|
||||||
|
# [1.0.0-dev.6](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.5...v1.0.0-dev.6) (2022-05-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* update patches ([91b8ec8](https://github.com/revanced/revanced-patches/commit/91b8ec81f33417798546c32db708fe09ada3930c))
|
||||||
|
|
||||||
|
# [1.0.0-dev.5](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.4...v1.0.0-dev.5) (2022-05-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* `enable-seekbar-tapping` patch ([52fd726](https://github.com/revanced/revanced-patches/commit/52fd726d9b0d2efbd0f9742fc84ad01ccdcff168))
|
||||||
|
* `Index` in wrong package ([2f9360f](https://github.com/revanced/revanced-patches/commit/2f9360f57cc8415564534fbbd8bd5e2a83a1b629))
|
||||||
|
* `minimized-playback` & `old-quality-layout` wrong opcodes ([b45d175](https://github.com/revanced/revanced-patches/commit/b45d175c6f1ece6da894ab16128c2644d262c9c7))
|
||||||
|
* `minimized-playback` patch ([55677a4](https://github.com/revanced/revanced-patches/commit/55677a44ff965c0b92c3f1d771bd68c12c142ad4))
|
||||||
|
* `SignatureChecker` not handling nullable field `methodMetadata` ([17bcf78](https://github.com/revanced/revanced-patches/commit/17bcf786a85ccf1f7d9f5a66a044a3c26def09bb))
|
||||||
|
* accidentally removed code in refactor ([0077e26](https://github.com/revanced/revanced-patches/commit/0077e26d23cc112b671a41614a55348fac2c88ca))
|
||||||
|
* add missing `trimIndent()` to string literals ([76d3c71](https://github.com/revanced/revanced-patches/commit/76d3c71b67edebd79f2cdb1bb28e4d2969d72223))
|
||||||
|
* add missing opcode for `create-button-method` ([0a398ef](https://github.com/revanced/revanced-patches/commit/0a398ef364f91a0dd9608df1a036a2515476ccf2))
|
||||||
|
* attempt on all patches ([3395d69](https://github.com/revanced/revanced-patches/commit/3395d69747103a4bdf314297aa0bfa6ef6a0fc36))
|
||||||
|
* breaking changes of the patcher ([1a49bbd](https://github.com/revanced/revanced-patches/commit/1a49bbdbc4ff6f427934259536218e161908b449))
|
||||||
|
* breaking patcher changes ([581d1b0](https://github.com/revanced/revanced-patches/commit/581d1b0ca7d15adcdb1ab6116ef035acfe701757))
|
||||||
|
* disable `hide-suggestions-patch` patch until fixed ([99099ea](https://github.com/revanced/revanced-patches/commit/99099ea0bc12f5f25896967db642442df69d0c4f))
|
||||||
|
* incorrect endIndex (fixed in Patcher) ([424788e](https://github.com/revanced/revanced-patches/commit/424788edd777110cdaff97500556d18628f33385))
|
||||||
|
* modified opcode for `show-video-ads-constructor` ([a0dcea3](https://github.com/revanced/revanced-patches/commit/a0dcea3a13f68cae449dfaf445b542e339c83ff0))
|
||||||
|
* multiple bugs in patches ([e37201d](https://github.com/revanced/revanced-patches/commit/e37201d0ceef474696857a0d8845950c888194d0))
|
||||||
|
* name for `IntegrationsPatch` ([e46ef02](https://github.com/revanced/revanced-patches/commit/e46ef02302825d62b57912b2747a25f858036bb7))
|
||||||
|
* print instruction index of warning ([9e29aee](https://github.com/revanced/revanced-patches/commit/9e29aeeeff222412f6c45cf7e4879f8ec53ca6ee))
|
||||||
|
* remove `HideSuggestionsPatch` from `Index` ([f32e474](https://github.com/revanced/revanced-patches/commit/f32e4747b512c675b807ff5eebfd0b8e66173fba))
|
||||||
|
* signature checker with changes of patcher ([e82459d](https://github.com/revanced/revanced-patches/commit/e82459d37759e1a5a860d3e7fcdf69d95b06858e))
|
||||||
|
* tests failing ([102793f](https://github.com/revanced/revanced-patches/commit/102793f24f8bf7c7fd254968b29d65da7b2b962f))
|
||||||
|
* update `HomeAdsPatch` ([62f1801](https://github.com/revanced/revanced-patches/commit/62f1801e9cbee53c0be3413c245161bd941e4aec))
|
||||||
|
* version in package metadata of music ([b299205](https://github.com/revanced/revanced-patches/commit/b299205aa7cde82f1f55fc598de3ff8d80b8bcb0))
|
||||||
|
* **VideoAds:** remove `istore1` opcode ([dc4ec57](https://github.com/revanced/revanced-patches/commit/dc4ec574414c5df959efa0ca8f1cd39a812fedf8))
|
||||||
|
* wrong access flag in signature for `Create button patch` ([9fbb89d](https://github.com/revanced/revanced-patches/commit/9fbb89d05336a256a0759eea6095e073946c45e5))
|
||||||
|
* wrong opcode for `create-button-method` ([3214650](https://github.com/revanced/revanced-patches/commit/32146506f139aebc44cd5faffb7706b8b9c21c3d))
|
||||||
|
* wrong opcode pattern for `create-button-method` ([f4d8a85](https://github.com/revanced/revanced-patches/commit/f4d8a8525bc64b90748b21979d463977a21dcd85))
|
||||||
|
* wrong opcode pattern for `enable-seekbar-tapping-signature` ([1d83395](https://github.com/revanced/revanced-patches/commit/1d833957ed3e01188770c85e3d84e483419bd797))
|
||||||
|
* wrong opcode pattern for signature in `Hide suggestions patch` ([535aee0](https://github.com/revanced/revanced-patches/commit/535aee08408b990c80f5966c13fa84666a8b35d0))
|
||||||
|
* wrong patches in `upgrade-tab-remover` ([5182290](https://github.com/revanced/revanced-patches/commit/518229031ceca049ad790f7b77b19405d39f0ce1))
|
||||||
|
* wrong signature for `hide-reels-signature` ([2d9ff2a](https://github.com/revanced/revanced-patches/commit/2d9ff2af0a991d7721f3741187716a3b08bb4029))
|
||||||
|
* wrong signatures for patch `Old Quality Layout Patch` ([823e503](https://github.com/revanced/revanced-patches/commit/823e503d84037bdf27b09f17e63383f963c76854))
|
||||||
|
* wrong versions of patches ([a112b22](https://github.com/revanced/revanced-patches/commit/a112b22ce6e685204caab6f95f511e26ef95806b))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* `hide-shorts-button` patch ([88352ee](https://github.com/revanced/revanced-patches/commit/88352ee6ecd23faa4a7fd9f7495e67fa1d3e33bd))
|
||||||
|
* `tastebuilder-remover` for music ([a6aeca3](https://github.com/revanced/revanced-patches/commit/a6aeca31bd80b8c4a8acd071e22faca6e136bdb0))
|
||||||
|
* Add (WIP) Signature Checker ([ae4c7b2](https://github.com/revanced/revanced-patches/commit/ae4c7b29f211c461de460f97f3a8656e795adafb))
|
||||||
|
* add home ads patch ([36cddd1](https://github.com/revanced/revanced-patches/commit/36cddd1488683e19e2b927e34c80a4f0f3cace35))
|
||||||
|
* added `codecs-unlock` patch ([e5fd7ce](https://github.com/revanced/revanced-patches/commit/e5fd7cece94b1ff5342178f59b29576db806e0f6))
|
||||||
|
* display metadata for each signature in `SignatureChecker` ([736a71f](https://github.com/revanced/revanced-patches/commit/736a71fac21a32dbb1eef9c3a9f0d3005e7d9ca0))
|
||||||
|
* get required register dynamically ([0924ca2](https://github.com/revanced/revanced-patches/commit/0924ca2ad30ae865dcc0fd484cb0da517e827352))
|
||||||
|
* integrations patch ([19c0b0d](https://github.com/revanced/revanced-patches/commit/19c0b0d194bb97c7248ea7a9b081176961653b9d))
|
||||||
|
* migrate to dalvik patches ([e088c67](https://github.com/revanced/revanced-patches/commit/e088c671081bcf75586ccc1c4bdbed9366e93874))
|
||||||
|
* Patches for YouTube Music ([b60c9d3](https://github.com/revanced/revanced-patches/commit/b60c9d33b611bb4d5b55bb419652bc14b0309792))
|
||||||
|
* remove obsolete patch `Hide suggestions patch` ([e65c6f2](https://github.com/revanced/revanced-patches/commit/e65c6f240ed23a54271d20a90fc57ec65cafc02d))
|
||||||
|
|
||||||
|
# [1.0.0-dev.4](https://github.com/ReVancedTeam/revanced-patches/compare/v1.0.0-dev.3...v1.0.0-dev.4) (2022-03-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* use supplier instead of KClass ([08af6e5](https://github.com/ReVancedTeam/revanced-patches/commit/08af6e54af79ef9ef4fb3372a348ce9b6fba4d20))
|
||||||
|
* use supplier instead of KClass ([91aa019](https://github.com/ReVancedTeam/revanced-patches/commit/91aa019f8d3d87fbf7affeb7abc2b02ba87af5c3))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* signature of patches was changed
|
||||||
|
* signature of patches was changed
|
||||||
|
|
||||||
# [1.0.0-dev.3](https://github.com/ReVancedTeam/revanced-patches/compare/v1.0.0-dev.2...v1.0.0-dev.3) (2022-03-21)
|
# [1.0.0-dev.3](https://github.com/ReVancedTeam/revanced-patches/compare/v1.0.0-dev.2...v1.0.0-dev.3) (2022-03-21)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.6.10"
|
kotlin("jvm") version "1.6.20"
|
||||||
java
|
java
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
}
|
}
|
||||||
@@ -8,8 +8,9 @@ group = "app.revanced"
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
maven {
|
maven {
|
||||||
url = uri("https://maven.pkg.github.com/ReVancedTeam/revanced-patcher") // note the "r"!
|
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher") // note the "r"!
|
||||||
credentials {
|
credentials {
|
||||||
// DO NOT set these variables in the project's gradle.properties.
|
// DO NOT set these variables in the project's gradle.properties.
|
||||||
// Instead, you should set them in:
|
// Instead, you should set them in:
|
||||||
@@ -22,14 +23,11 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.10")
|
implementation(kotlin("stdlib"))
|
||||||
|
testImplementation(kotlin("test"))
|
||||||
|
|
||||||
implementation("org.ow2.asm:asm:9.2")
|
implementation("app.revanced:revanced-patcher:1.+")
|
||||||
implementation("org.ow2.asm:asm-util:9.2")
|
implementation(kotlin("reflect"))
|
||||||
implementation("org.ow2.asm:asm-tree:9.2")
|
|
||||||
implementation("org.ow2.asm:asm-commons:9.2")
|
|
||||||
|
|
||||||
implementation("app.revanced:revanced-patcher:1.+") // use latest version.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@@ -37,15 +35,21 @@ java {
|
|||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isGitHubCI = System.getenv("GITHUB_ACTOR") != null
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
if (isGitHubCI) {
|
||||||
name = "GitHubPackages"
|
maven {
|
||||||
url = uri("https://maven.pkg.github.com/ReVancedTeam/revanced-patches") // note the "s"!
|
name = "GitHubPackages"
|
||||||
credentials {
|
url = uri("https://maven.pkg.github.com/revanced/revanced-patches") // note the "s"!
|
||||||
username = System.getenv("GITHUB_ACTOR")
|
credentials {
|
||||||
password = System.getenv("GITHUB_TOKEN")
|
username = System.getenv("GITHUB_ACTOR")
|
||||||
|
password = System.getenv("GITHUB_TOKEN")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mavenLocal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
publications {
|
publications {
|
||||||
@@ -53,4 +57,4 @@ publishing {
|
|||||||
from(components["java"])
|
from(components["java"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 1.0.0-dev.3
|
version = 1.0.0-dev.10
|
||||||
|
|||||||
14
src/main/kotlin/app/revanced/extensions/Extensions.kt
Normal file
14
src/main/kotlin/app/revanced/extensions/Extensions.kt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.extensions
|
||||||
|
|
||||||
|
import app.revanced.patcher.util.smali.toInstruction
|
||||||
|
import org.jf.dexlib2.builder.MutableMethodImplementation
|
||||||
|
|
||||||
|
internal fun MutableMethodImplementation.injectHideCall(
|
||||||
|
index: Int,
|
||||||
|
register: Int
|
||||||
|
) {
|
||||||
|
this.addInstruction(
|
||||||
|
index,
|
||||||
|
"invoke-static { v$register }, Lfi/razerman/youtube/XAdRemover;->HideView(Landroid/view/View;)V".toInstruction()
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package app.revanced.patches
|
|
||||||
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patches.ad.VideoAds
|
|
||||||
import app.revanced.patches.interaction.EnableSeekbarTapping
|
|
||||||
import app.revanced.patches.layout.*
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Index contains all the patches and should be imported when using this library.
|
|
||||||
*/
|
|
||||||
@Suppress("Unused")
|
|
||||||
object Index {
|
|
||||||
/**
|
|
||||||
* Array of patches.
|
|
||||||
* New patches should be added to the array.
|
|
||||||
*/
|
|
||||||
val patches: Array<KClass<out Patch>> = arrayOf(
|
|
||||||
VideoAds::class,
|
|
||||||
MinimizedPlayback::class,
|
|
||||||
CreateButtonRemover::class,
|
|
||||||
HideReels::class,
|
|
||||||
HideSuggestions::class,
|
|
||||||
OldQualityLayout::class,
|
|
||||||
EnableSeekbarTapping::class
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package app.revanced.patches.ad
|
|
||||||
|
|
||||||
import app.revanced.patcher.cache.Cache
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
|
||||||
import app.revanced.patcher.patch.PatchResultError
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
|
||||||
import app.revanced.patcher.signature.Signature
|
|
||||||
import app.revanced.patcher.writer.ASMWriter.insertAt
|
|
||||||
import org.objectweb.asm.Opcodes
|
|
||||||
import org.objectweb.asm.Type
|
|
||||||
import org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
import org.objectweb.asm.tree.VarInsnNode
|
|
||||||
|
|
||||||
class VideoAds : Patch("VideoAds") {
|
|
||||||
override fun execute(cache: Cache): PatchResult {
|
|
||||||
val showVideoAdsMethodData = cache.methods["show-video-ads"].findParentMethod(
|
|
||||||
Signature(
|
|
||||||
"method",
|
|
||||||
Type.VOID_TYPE,
|
|
||||||
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL,
|
|
||||||
arrayOf(Type.BOOLEAN_TYPE),
|
|
||||||
null
|
|
||||||
)
|
|
||||||
) ?: return PatchResultError("Could not find required method to patch")
|
|
||||||
|
|
||||||
showVideoAdsMethodData.method.instructions.insertAt(
|
|
||||||
0,
|
|
||||||
VarInsnNode(Opcodes.ISTORE, 1),
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKESTATIC,
|
|
||||||
"fi/vanced/libraries/youtube/whitelisting/Whitelist",
|
|
||||||
"shouldShowAds",
|
|
||||||
Type.getMethodDescriptor(Type.BOOLEAN_TYPE)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package app.revanced.patches.interaction
|
|
||||||
|
|
||||||
import app.revanced.patcher.cache.Cache
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
|
||||||
import app.revanced.patcher.writer.ASMWriter.insertAt
|
|
||||||
import org.objectweb.asm.Opcodes
|
|
||||||
import org.objectweb.asm.tree.*
|
|
||||||
|
|
||||||
class EnableSeekbarTapping : Patch("enable-seekbar-tapping") {
|
|
||||||
override fun execute(cache: Cache): PatchResult {
|
|
||||||
val patchData = cache.methods["enable-seekbar-tapping"]
|
|
||||||
val methodOPatchData = cache.methods["enable-seekbar-tapping-method-o"]
|
|
||||||
val methodPPatchData = cache.methods["enable-seekbar-tapping-method-p"]
|
|
||||||
|
|
||||||
val elseLabel = LabelNode()
|
|
||||||
patchData.method.instructions.insertAt(
|
|
||||||
patchData.scanData.endIndex,
|
|
||||||
InsnNode(Opcodes.ACONST_NULL),
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKESTATIC,
|
|
||||||
"fi/razerman/youtube/preferences/BooleanPreferences",
|
|
||||||
"isTapSeekingEnabled",
|
|
||||||
"()Z"
|
|
||||||
),
|
|
||||||
JumpInsnNode(Opcodes.IFEQ, elseLabel),
|
|
||||||
VarInsnNode(Opcodes.ALOAD, 0),
|
|
||||||
VarInsnNode(Opcodes.ILOAD, 6),
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKEVIRTUAL,
|
|
||||||
methodOPatchData.declaringClass.name,
|
|
||||||
methodOPatchData.method.name,
|
|
||||||
"(I)V"
|
|
||||||
),
|
|
||||||
VarInsnNode(Opcodes.ALOAD, 0),
|
|
||||||
VarInsnNode(Opcodes.ILOAD, 6),
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKEVIRTUAL,
|
|
||||||
methodPPatchData.declaringClass.name,
|
|
||||||
methodPPatchData.method.name,
|
|
||||||
"(I)V"
|
|
||||||
),
|
|
||||||
elseLabel
|
|
||||||
)
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package app.revanced.patches.layout
|
|
||||||
|
|
||||||
import app.revanced.patcher.cache.Cache
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
|
||||||
import app.revanced.patcher.writer.ASMWriter.insertAt
|
|
||||||
import org.objectweb.asm.Opcodes
|
|
||||||
import org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
import org.objectweb.asm.tree.VarInsnNode
|
|
||||||
|
|
||||||
class CreateButtonRemover : Patch("create-button-remover") {
|
|
||||||
override fun execute(cache: Cache): PatchResult {
|
|
||||||
val patchData = cache.methods["create-button-patch"]
|
|
||||||
|
|
||||||
patchData.method.instructions.insertAt(
|
|
||||||
patchData.scanData.endIndex - 1,
|
|
||||||
VarInsnNode(
|
|
||||||
Opcodes.ALOAD,
|
|
||||||
6
|
|
||||||
),
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKESTATIC,
|
|
||||||
"fi/razerman/youtube/XAdRemover",
|
|
||||||
"hideCreateButton",
|
|
||||||
"(Landroid/view/View;)V"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package app.revanced.patches.layout
|
|
||||||
|
|
||||||
import app.revanced.patcher.cache.Cache
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
|
||||||
import app.revanced.patcher.writer.ASMWriter.insertAt
|
|
||||||
import org.objectweb.asm.Opcodes
|
|
||||||
import org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
import org.objectweb.asm.tree.VarInsnNode
|
|
||||||
|
|
||||||
class HideReels : Patch("hide-reels") {
|
|
||||||
override fun execute(cache: Cache): PatchResult {
|
|
||||||
val patchData = cache.methods["hide-reel-patch"]
|
|
||||||
|
|
||||||
patchData.method.instructions.insertAt(
|
|
||||||
patchData.scanData.endIndex + 1,
|
|
||||||
VarInsnNode(Opcodes.ALOAD, 18),
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKESTATIC,
|
|
||||||
"fi/razerman/youtube/XAdRemover",
|
|
||||||
"HideReels",
|
|
||||||
"(Landroid/view/View;)V"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package app.revanced.patches.layout
|
|
||||||
|
|
||||||
import app.revanced.patcher.cache.Cache
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
|
||||||
import app.revanced.patcher.patch.PatchResultError
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
|
||||||
import app.revanced.patcher.signature.Signature
|
|
||||||
import app.revanced.patcher.writer.ASMWriter.insertAt
|
|
||||||
import org.objectweb.asm.Opcodes
|
|
||||||
import org.objectweb.asm.Type
|
|
||||||
import org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
import org.objectweb.asm.tree.VarInsnNode
|
|
||||||
|
|
||||||
class HideSuggestions : Patch("hide-suggestions") {
|
|
||||||
override fun execute(cache: Cache): PatchResult {
|
|
||||||
val method = cache.methods["hide-suggestions-patch"].findParentMethod(
|
|
||||||
Signature(
|
|
||||||
"hide-suggestions-method",
|
|
||||||
Type.VOID_TYPE,
|
|
||||||
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL,
|
|
||||||
arrayOf(Type.BOOLEAN_TYPE),
|
|
||||||
arrayOf(
|
|
||||||
Opcodes.ALOAD,
|
|
||||||
Opcodes.ILOAD,
|
|
||||||
Opcodes.PUTFIELD,
|
|
||||||
Opcodes.ALOAD,
|
|
||||||
Opcodes.GETFIELD
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) ?: return PatchResultError("Parent method hide-suggestions-method has not been found")
|
|
||||||
|
|
||||||
method.method.instructions.insertAt(
|
|
||||||
0,
|
|
||||||
VarInsnNode(Opcodes.ILOAD, 1),
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKESTATIC,
|
|
||||||
"java/lang/Boolean",
|
|
||||||
"valueOf",
|
|
||||||
"(Z)Ljava/lang/Boolean"
|
|
||||||
),
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKESTATIC,
|
|
||||||
"fi/razerman/youtube/XAdRemover",
|
|
||||||
"HideReels",
|
|
||||||
"(Landroid/view/View;)V"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package app.revanced.patches.layout
|
|
||||||
|
|
||||||
import app.revanced.patcher.cache.Cache
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
|
||||||
|
|
||||||
class MinimizedPlayback : Patch("minimized-playback") {
|
|
||||||
override fun execute(cache: Cache): PatchResult {
|
|
||||||
cache.methods["minimized-playback-manager"].method.instructions.clear()
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package app.revanced.patches.layout
|
|
||||||
|
|
||||||
import app.revanced.patcher.cache.Cache
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
|
||||||
import app.revanced.patcher.patch.PatchResultError
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
|
||||||
import app.revanced.patcher.signature.Signature
|
|
||||||
import app.revanced.patcher.util.ExtraTypes
|
|
||||||
import app.revanced.patcher.writer.ASMWriter.insertAt
|
|
||||||
import org.objectweb.asm.Opcodes
|
|
||||||
import org.objectweb.asm.tree.JumpInsnNode
|
|
||||||
import org.objectweb.asm.tree.MethodInsnNode
|
|
||||||
import org.objectweb.asm.tree.VarInsnNode
|
|
||||||
|
|
||||||
class OldQualityLayout : Patch("old-quality-restore") {
|
|
||||||
override fun execute(cache: Cache): PatchResult {
|
|
||||||
val method = cache.methods["old-quality-patch"].findParentMethod(
|
|
||||||
Signature(
|
|
||||||
"old-quality-patch-method",
|
|
||||||
ExtraTypes.Any,
|
|
||||||
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL,
|
|
||||||
arrayOf(),
|
|
||||||
arrayOf(
|
|
||||||
Opcodes.ALOAD,
|
|
||||||
Opcodes.GETFIELD,
|
|
||||||
Opcodes.ISTORE,
|
|
||||||
Opcodes.ICONST_3,
|
|
||||||
Opcodes.ISTORE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) ?: return PatchResultError("Parent method old-quality-patch-method has not been found")
|
|
||||||
|
|
||||||
method.method.instructions.insertAt(
|
|
||||||
0,
|
|
||||||
MethodInsnNode(
|
|
||||||
Opcodes.INVOKESTATIC,
|
|
||||||
"fi/razerman/youtube/XGlobals",
|
|
||||||
"useOldStyleQualitySettings",
|
|
||||||
"()Z"
|
|
||||||
),
|
|
||||||
VarInsnNode(Opcodes.ISTORE, 1),
|
|
||||||
VarInsnNode(Opcodes.ILOAD, 1),
|
|
||||||
JumpInsnNode(
|
|
||||||
Opcodes.IFNE,
|
|
||||||
(method.method.instructions[method.scanData.endIndex + 3] as JumpInsnNode).label
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.music.audio.codecs.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.apps.youtube.music", arrayOf("5.03.50")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class CodecsUnlockCompatibility
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package app.revanced.patches.music.audio.codecs.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.data.implementation.toMethodWalker
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstruction
|
||||||
|
import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
|
||||||
|
import app.revanced.patches.music.audio.codecs.signatures.AllCodecsReferenceSignature
|
||||||
|
import app.revanced.patches.music.audio.codecs.signatures.CodecsLockSignature
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("codecs-unlock")
|
||||||
|
@Description("Enables more audio codecs. Usually results in better audio quality but may depend on song and device.")
|
||||||
|
@CodecsUnlockCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class CodecsUnlockPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
CodecsLockSignature, AllCodecsReferenceSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
var result = signatures.first().result!!
|
||||||
|
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
|
||||||
|
val instructionIndex = result.scanResult.startIndex
|
||||||
|
|
||||||
|
result = signatures.last().result!!
|
||||||
|
val codecMethod = data.toMethodWalker(result.immutableMethod).walk(result.scanResult.startIndex).getMethod()
|
||||||
|
|
||||||
|
implementation.replaceInstruction(
|
||||||
|
instructionIndex,
|
||||||
|
"invoke-static {}, ${codecMethod.definingClass}->${codecMethod.name}()Ljava/util/Set;".toInstruction()
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package app.revanced.patches.music.audio.codecs.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("all-codecs-reference-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Laari;",
|
||||||
|
"b",
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@CodecsUnlockCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object AllCodecsReferenceSignature : MethodSignature(
|
||||||
|
"J", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf(
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.IPUT_BOOLEAN,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.IPUT_BOOLEAN,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.MOVE_EXCEPTION,
|
||||||
|
Opcode.INVOKE_SUPER,
|
||||||
|
Opcode.MOVE_RESULT_WIDE,
|
||||||
|
Opcode.RETURN_WIDE
|
||||||
|
), listOf("itag")
|
||||||
|
)
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package app.revanced.patches.music.audio.codecs.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("codec-lock-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Labwj;",
|
||||||
|
"a",
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@CodecsUnlockCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object CodecsLockSignature : MethodSignature(
|
||||||
|
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L", "L", "L"), listOf(
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.RETURN_OBJECT
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.music.audio.exclusiveaudio.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.apps.youtube.music", arrayOf("5.03.50")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class ExclusiveAudioCompatibility
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package app.revanced.patches.music.audio.exclusiveaudio.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultError
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.DirectPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patcher.util.smali.toInstruction
|
||||||
|
import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility
|
||||||
|
import app.revanced.patches.music.audio.exclusiveaudio.signatures.ExclusiveAudioSignature
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("exclusive-audio-playback")
|
||||||
|
@Description("Add the option to play music without video.")
|
||||||
|
@ExclusiveAudioCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class ExclusiveAudioPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
ExclusiveAudioSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result = signatures.first().result!!.findParentMethod(@Name("audio-only-enabler-method") @MatchingMethod(
|
||||||
|
"Lgmd;",
|
||||||
|
"d"
|
||||||
|
) @DirectPatternScanMethod @ExclusiveAudioCompatibility @Version(
|
||||||
|
"0.0.1"
|
||||||
|
) object : MethodSignature(
|
||||||
|
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.RETURN
|
||||||
|
)
|
||||||
|
) {}) ?: return PatchResultError("Required parent method could not be found.")
|
||||||
|
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
implementation.replaceInstruction(
|
||||||
|
implementation.instructions.count() - 1, "const/4 v0, 0x1".toInstruction()
|
||||||
|
)
|
||||||
|
implementation.addInstruction(
|
||||||
|
"return v0".toInstruction()
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package app.revanced.patches.music.audio.exclusiveaudio.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("exclusive-audio-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lgmd;", "c"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@ExclusiveAudioCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object ExclusiveAudioSignature : MethodSignature(
|
||||||
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
listOf("L", "Z"),
|
||||||
|
listOf(
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_EQ,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.NOP,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.RETURN_VOID
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.music.layout.tastebuilder.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.apps.youtube.music", arrayOf("5.03.50")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class RemoveTasteBuilderCompatibility
|
||||||
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package app.revanced.patches.music.layout.tastebuilder.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility
|
||||||
|
import app.revanced.patches.music.layout.tastebuilder.signatures.TasteBuilderConstructorSignature
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("tasteBuilder-remover")
|
||||||
|
@Description("Removes the \"Tell us which artists you like\" card from the Home screen. The same functionality can be triggered from the settings anyway.")
|
||||||
|
@RemoveTasteBuilderCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class RemoveTasteBuilderPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
TasteBuilderConstructorSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result = signatures.first().result!!
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
|
||||||
|
val insertIndex = result.scanResult.endIndex - 8
|
||||||
|
|
||||||
|
val register = (implementation.instructions[insertIndex] as Instruction22c).registerA
|
||||||
|
|
||||||
|
val instructionList = """
|
||||||
|
const/16 v1, 0x8
|
||||||
|
invoke-virtual {v${register}, v1}, Landroid/view/View;->setVisibility(I)V
|
||||||
|
""".trimIndent().toInstructions().toMutableList()
|
||||||
|
|
||||||
|
implementation.addInstructions(
|
||||||
|
insertIndex, instructionList
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package app.revanced.patches.music.layout.tastebuilder.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("taste-builder-constructor")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lkyu;", "<init>"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@RemoveTasteBuilderCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object TasteBuilderConstructorSignature : MethodSignature(
|
||||||
|
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L"), listOf(
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.music.layout.upgradebutton.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.apps.youtube.music", arrayOf("5.03.50")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class RemoveUpgradeButtonCompatibility
|
||||||
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package app.revanced.patches.music.layout.upgradebutton.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility
|
||||||
|
import app.revanced.patches.music.layout.upgradebutton.signatures.PivotBarConstructorSignature
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction22t
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("upgrade-button-remover")
|
||||||
|
@Description("Remove the upgrade tab from t he pivot bar in YouTube music.")
|
||||||
|
@RemoveUpgradeButtonCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class RemoveUpgradeButtonPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
PivotBarConstructorSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result = signatures.first().result!!
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
|
||||||
|
val pivotBarElementFieldRef =
|
||||||
|
(implementation.instructions[result.scanResult.endIndex - 1] as Instruction22c).reference
|
||||||
|
|
||||||
|
val register = (implementation.instructions.first() as Instruction35c).registerC
|
||||||
|
// first compile all the needed instructions
|
||||||
|
val instructionList = """
|
||||||
|
invoke-interface { v0 }, Ljava/util/List;->size()I
|
||||||
|
move-result v1
|
||||||
|
const/4 v2, 0x3
|
||||||
|
invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
|
||||||
|
iput-object v0, v$register, $pivotBarElementFieldRef
|
||||||
|
""".trimIndent().toInstructions().toMutableList()
|
||||||
|
|
||||||
|
|
||||||
|
// replace the instruction to retain the label at given index
|
||||||
|
implementation.replaceInstruction(
|
||||||
|
result.scanResult.endIndex - 1, instructionList[0] // invoke-interface
|
||||||
|
)
|
||||||
|
// do not forget to remove this instruction since we added it already
|
||||||
|
instructionList.removeFirst()
|
||||||
|
|
||||||
|
val exitInstruction = instructionList.last() // iput-object
|
||||||
|
implementation.addInstruction(
|
||||||
|
result.scanResult.endIndex, exitInstruction
|
||||||
|
)
|
||||||
|
// do not forget to remove this instruction since we added it already
|
||||||
|
instructionList.removeLast()
|
||||||
|
|
||||||
|
// add the necessary if statement to remove the upgrade tab button in case it exists
|
||||||
|
instructionList.add(
|
||||||
|
2, // if-le
|
||||||
|
BuilderInstruction22t(
|
||||||
|
Opcode.IF_LE, 1, 2, implementation.newLabelForIndex(result.scanResult.endIndex)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
implementation.addInstructions(
|
||||||
|
result.scanResult.endIndex, instructionList
|
||||||
|
)
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package app.revanced.patches.music.layout.upgradebutton.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("pivot-bar-constructor")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lhfu;", "<init2>"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@RemoveUpgradeButtonCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object PivotBarConstructorSignature : MethodSignature(
|
||||||
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
listOf("L", "Z"),
|
||||||
|
listOf(
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_BOOLEAN,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.IF_NE,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.IF_NE,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.NOP,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.RETURN_VOID
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.music.premium.backgroundplay.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.apps.youtube.music", arrayOf("5.03.50")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class BackgroundPlayCompatibility
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package app.revanced.patches.music.premium.backgroundplay.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility
|
||||||
|
import app.revanced.patches.music.premium.backgroundplay.signatures.BackgroundPlaybackDisableSignature
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("background-play")
|
||||||
|
@Description("Enable playing music in the background.")
|
||||||
|
@BackgroundPlayCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class BackgroundPlayPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
BackgroundPlaybackDisableSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
signatures.first().result!!.method.implementation!!.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x1
|
||||||
|
return v0
|
||||||
|
""".trimIndent().toInstructions()
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package app.revanced.patches.music.premium.backgroundplay.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("background-playback-disabler-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lafgf;", "e"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@BackgroundPlayCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object BackgroundPlaybackDisableSignature : MethodSignature(
|
||||||
|
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), listOf(
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.AND_INT_LIT16,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.IF_NE,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.IF_NE,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.RETURN,
|
||||||
|
Opcode.RETURN,
|
||||||
|
Opcode.RETURN
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.youtube.ad.home.annotation
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.03.38", "17.14.35", "17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class PromotionsCompatibility
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
|||||||
|
package app.revanced.patches.youtube.ad.home.patch
|
||||||
|
|
||||||
|
import app.revanced.extensions.injectHideCall
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.data.implementation.toMethodWalker
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultError
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.DirectPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
|
import app.revanced.patches.youtube.ad.home.annotation.PromotionsCompatibility
|
||||||
|
import app.revanced.patches.youtube.ad.home.signatures.PromotedDiscoveryActionParentSignature
|
||||||
|
import app.revanced.patches.youtube.ad.home.signatures.PromotedDiscoveryAppParentSignature
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction11x
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("home-promo-ads")
|
||||||
|
@Description("Patch to remove promoted ads in YouTube.")
|
||||||
|
@PromotionsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class PromotionsPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
PromotedDiscoveryAppParentSignature, PromotedDiscoveryActionParentSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
for (signature in signatures) {
|
||||||
|
val result = signature.result!!
|
||||||
|
|
||||||
|
val requiredMethod =
|
||||||
|
result.findParentMethod(@Name("promotion-ads-signature") @MatchingMethod(name = "d") @DirectPatternScanMethod @PromotionsCompatibility @Version(
|
||||||
|
"0.0.1"
|
||||||
|
) object : MethodSignature(
|
||||||
|
"V", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("Z", "Z"), null
|
||||||
|
) {}) ?: return PatchResultError("Required parent method could not be found.")
|
||||||
|
|
||||||
|
val toBePatchedInvokeOffset =
|
||||||
|
requiredMethod.immutableMethod.implementation!!.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_DIRECT }
|
||||||
|
val toBePatchedMethod =
|
||||||
|
data.toMethodWalker(requiredMethod.immutableMethod).walk(toBePatchedInvokeOffset, true)
|
||||||
|
.getMethod() as MutableMethod
|
||||||
|
|
||||||
|
val implementation = toBePatchedMethod.implementation!!
|
||||||
|
val invokeVirtualOffset = implementation.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_VIRTUAL }
|
||||||
|
|
||||||
|
val moveResultInstruction = implementation.instructions[invokeVirtualOffset + 1]
|
||||||
|
if (moveResultInstruction.opcode != Opcode.MOVE_RESULT_OBJECT) return PatchResultError("The toBePatchedInvokeOffset offset was wrong in ${(this::class.annotations.find { it is Name } as Name).name}")
|
||||||
|
|
||||||
|
val register = (moveResultInstruction as Instruction11x).registerA
|
||||||
|
implementation.injectHideCall(invokeVirtualOffset + 2, register)
|
||||||
|
}
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package app.revanced.patches.youtube.ad.home.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.ad.home.annotation.PromotionsCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("promoted-discovery-app-parent-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Ljqb;", "lG"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@PromotionsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object PromotedDiscoveryActionParentSignature : MethodSignature(
|
||||||
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC,
|
||||||
|
listOf("L", "L"),
|
||||||
|
listOf(
|
||||||
|
Opcode.MOVE_OBJECT_FROM16,
|
||||||
|
Opcode.MOVE_OBJECT_FROM16,
|
||||||
|
Opcode.MOVE_OBJECT_FROM16,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.INVOKE_VIRTUAL_RANGE,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.XOR_INT_2ADDR,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package app.revanced.patches.youtube.ad.home.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.ad.home.annotation.PromotionsCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("promoted-discovery-action-parent-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Ljqj;",
|
||||||
|
"lG"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@PromotionsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
|
||||||
|
object PromotedDiscoveryAppParentSignature : MethodSignature(
|
||||||
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC,
|
||||||
|
listOf("L", "L"),
|
||||||
|
listOf(
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.NEW_ARRAY,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_GE,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.APUT_OBJECT,
|
||||||
|
Opcode.ADD_INT_LIT8,
|
||||||
|
Opcode.GOTO
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.youtube.ad.video.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class VideoAdsCompatibility
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package app.revanced.patches.youtube.ad.video.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultError
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.DirectPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility
|
||||||
|
import app.revanced.patches.youtube.ad.video.signatures.ShowVideoAdsConstructorSignature
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("video-ads")
|
||||||
|
@Description("Patch to remove ads in the YouTube video player.")
|
||||||
|
@VideoAdsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class VideoAdsPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
ShowVideoAdsConstructorSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result =
|
||||||
|
signatures.first().result!!.findParentMethod(@Name("show-video-ads-method-signature") @MatchingMethod(
|
||||||
|
definingClass = "zai"
|
||||||
|
) @DirectPatternScanMethod @VideoAdsCompatibility @Version("0.0.1") object : MethodSignature(
|
||||||
|
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), null
|
||||||
|
) {}) ?: return PatchResultError("Required parent method could not be found.")
|
||||||
|
|
||||||
|
|
||||||
|
// Override the parameter by calling shouldShowAds and setting the parameter to the result
|
||||||
|
result.method.implementation!!.addInstructions(
|
||||||
|
0, """
|
||||||
|
invoke-static { }, Lfi/vanced/libraries/youtube/whitelisting/Whitelist;->shouldShowAds()Z
|
||||||
|
move-result v1
|
||||||
|
""".trimIndent().toInstructions()
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package app.revanced.patches.youtube.ad.video.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("show-video-ads-constructor-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Laair",
|
||||||
|
"<init>",
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@VideoAdsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object ShowVideoAdsConstructorSignature : MethodSignature(
|
||||||
|
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf(
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
null, // either CONST_4 or CONST_16
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.IPUT_BOOLEAN,
|
||||||
|
Opcode.RETURN_VOID
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app.revanced.patches.youtube.interaction.seekbar.annotation
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class SeekbarTappingCompatibility
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package app.revanced.patches.youtube.interaction.seekbar.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultError
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
|
||||||
|
import app.revanced.patches.youtube.interaction.seekbar.signatures.SeekbarTappingParentSignature
|
||||||
|
import app.revanced.patches.youtube.interaction.seekbar.signatures.SeekbarTappingSignature
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||||
|
import org.jf.dexlib2.iface.Method
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction11n
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("seekbar-tapping")
|
||||||
|
@Description("Enable tapping on the seekbar of the YouTube player.")
|
||||||
|
@SeekbarTappingCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class EnableSeekbarTappingPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
SeekbarTappingParentSignature, SeekbarTappingSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
var result = signatures.first().result!!
|
||||||
|
|
||||||
|
val tapSeekMethods = mutableMapOf<String, Method>()
|
||||||
|
|
||||||
|
// find the methods which tap the seekbar
|
||||||
|
for (it in result.definingClassProxy.immutableClass.methods) {
|
||||||
|
if (it.implementation == null) continue
|
||||||
|
|
||||||
|
val instructions = it.implementation!!.instructions
|
||||||
|
// here we make sure we actually find the method because it has more then 7 instructions
|
||||||
|
if (instructions.count() < 7) continue
|
||||||
|
|
||||||
|
// we know that the 7th instruction has the opcode CONST_4
|
||||||
|
val instruction = instructions.elementAt(6)
|
||||||
|
if (instruction.opcode != Opcode.CONST_4) continue
|
||||||
|
|
||||||
|
// the literal for this instruction has to be either 1 or 2
|
||||||
|
val literal = (instruction as Instruction11n).narrowLiteral
|
||||||
|
|
||||||
|
// method founds
|
||||||
|
if (literal == 1) tapSeekMethods["P"] = it
|
||||||
|
if (literal == 2) tapSeekMethods["O"] = it
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace map because we dont need the upper one anymore
|
||||||
|
result = signatures.last().result!!
|
||||||
|
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
|
||||||
|
// if tap-seeking is enabled, do not invoke the two methods below
|
||||||
|
val pMethod = tapSeekMethods["P"]!!
|
||||||
|
val oMethod = tapSeekMethods["O"]!!
|
||||||
|
|
||||||
|
// get the required register
|
||||||
|
val instruction = implementation.instructions[result.scanResult.endIndex]
|
||||||
|
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register")
|
||||||
|
val register = (instruction as Instruction35c).registerC
|
||||||
|
|
||||||
|
// the instructions are written in reverse order.
|
||||||
|
implementation.addInstructions(
|
||||||
|
result.scanResult.endIndex + 1, """
|
||||||
|
invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V
|
||||||
|
invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V
|
||||||
|
""".trimIndent().toInstructions()
|
||||||
|
)
|
||||||
|
|
||||||
|
// if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label
|
||||||
|
val elseLabel = implementation.newLabelForIndex(result.scanResult.endIndex + 1)
|
||||||
|
implementation.addInstruction(
|
||||||
|
result.scanResult.endIndex + 1, BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel)
|
||||||
|
)
|
||||||
|
implementation.addInstructions(
|
||||||
|
result.scanResult.endIndex + 1, """
|
||||||
|
invoke-static { }, Lfi/razerman/youtube/preferences/BooleanPreferences;->isTapSeekingEnabled()Z
|
||||||
|
move-result v0
|
||||||
|
""".trimIndent().toInstructions()
|
||||||
|
)
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package app.revanced.patches.youtube.interaction.seekbar.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("enable-seekbar-tapping-parent")
|
||||||
|
@MatchingMethod("Lzmx;", "I")
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@SeekbarTappingCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object SeekbarTappingParentSignature : MethodSignature(
|
||||||
|
"L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.NEW_ARRAY,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_WIDE,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.APUT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_WIDE,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.APUT_OBJECT,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.RETURN_OBJECT
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package app.revanced.patches.youtube.interaction.seekbar.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("enable-seekbar-tapping-signature")
|
||||||
|
@MatchingMethod("Lfbl;", "onTouchEvent")
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@SeekbarTappingCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object SeekbarTappingSignature : MethodSignature(
|
||||||
|
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf(
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_WIDE,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.DIV_INT_2ADDR,
|
||||||
|
Opcode.ADD_INT,
|
||||||
|
Opcode.SUB_INT_2ADDR,
|
||||||
|
Opcode.INT_TO_FLOAT,
|
||||||
|
Opcode.CMPG_FLOAT,
|
||||||
|
Opcode.IF_GTZ,
|
||||||
|
Opcode.INT_TO_FLOAT,
|
||||||
|
Opcode.CMPG_FLOAT,
|
||||||
|
Opcode.IF_GTZ,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.amoled.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class AmoledCompatibility
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.amoled.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.ResourceData
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.ResourcePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patches.youtube.layout.amoled.annotations.AmoledCompatibility
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("amoled")
|
||||||
|
@Description("Enables pure black theme.")
|
||||||
|
@AmoledCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class AmoledPatch : ResourcePatch() {
|
||||||
|
override fun execute(data: ResourceData): PatchResult {
|
||||||
|
data.getXmlEditor("res${File.separator}values${File.separator}colors.xml").use { editor ->
|
||||||
|
val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element
|
||||||
|
|
||||||
|
for (i in 0 until resourcesNode.childNodes.length) {
|
||||||
|
val node = resourcesNode.childNodes.item(i)
|
||||||
|
if (node !is Element) continue
|
||||||
|
|
||||||
|
val element = resourcesNode.childNodes.item(i) as Element
|
||||||
|
element.textContent = when (element.getAttribute("name")) {
|
||||||
|
"yt_black1", "yt_black1_opacity95", "yt_black2", "yt_black3", "yt_black4", "yt_status_bar_background_dark" -> "@android:color/black"
|
||||||
|
"yt_selected_nav_label_dark" -> "#ffdf0000"
|
||||||
|
else -> continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.createbutton.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class CreateButtonCompatibility
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.createbutton.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultError
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstruction
|
||||||
|
import app.revanced.patches.youtube.layout.createbutton.annotations.CreateButtonCompatibility
|
||||||
|
import app.revanced.patches.youtube.layout.createbutton.signatures.CreateButtonSignature
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("disable-create-button")
|
||||||
|
@Description("Disable the create button.")
|
||||||
|
@CreateButtonCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class CreateButtonRemoverPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
CreateButtonSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result = signatures.first().result!!
|
||||||
|
|
||||||
|
// Get the required register which holds the view object we need to pass to the method hideCreateButton
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
val instruction = implementation.instructions[result.scanResult.endIndex + 1]
|
||||||
|
if (instruction.opcode != Opcode.INVOKE_STATIC)
|
||||||
|
return PatchResultError("Could not find the correct register")
|
||||||
|
val register = (instruction as Instruction35c).registerC
|
||||||
|
|
||||||
|
// Hide the button view via proxy by passing it to the hideCreateButton method
|
||||||
|
implementation.addInstruction(
|
||||||
|
result.scanResult.endIndex + 1,
|
||||||
|
"invoke-static { v$register }, Lfi/razerman/youtube/XAdRemover;->hideCreateButton(Landroid/view/View;)V".toInstruction()
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.createbutton.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.layout.createbutton.annotations.CreateButtonCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("create-button-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lknw", "z"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@CreateButtonCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object CreateButtonSignature : MethodSignature(
|
||||||
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
listOf("Z"),
|
||||||
|
listOf(
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.MOVE_OBJECT,
|
||||||
|
Opcode.MOVE_OBJECT,
|
||||||
|
Opcode.INVOKE_DIRECT_RANGE,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.minimizedplayback.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class MinimizedPlaybackCompatibility
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.minimizedplayback.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||||
|
import app.revanced.patches.youtube.layout.minimizedplayback.signatures.MinimizedPlaybackManagerSignature
|
||||||
|
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("minimized-playback")
|
||||||
|
@Description("Enable minimized and background playback.")
|
||||||
|
@MinimizedPlaybackCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
|
||||||
|
class MinimizedPlaybackPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
MinimizedPlaybackManagerSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
// Instead of removing all instructions like Vanced,
|
||||||
|
// we return the method at the beginning instead
|
||||||
|
signatures.first().result!!.method.implementation!!.addInstructions(
|
||||||
|
0, """
|
||||||
|
const/4 v0, 0x1
|
||||||
|
return v0
|
||||||
|
""".trimIndent().toInstructions()
|
||||||
|
)
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.minimizedplayback.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("minimized-playback-manager-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lyuf", "n"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@MinimizedPlaybackCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object MinimizedPlaybackManagerSignature : MethodSignature(
|
||||||
|
"Z",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
listOf("L"),
|
||||||
|
listOf(
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.AND_INT_LIT16,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.IF_NE,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.IF_NE,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.IF_EQZ
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.oldqualitylayout.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class OldQualityLayoutCompatibility
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.oldqualitylayout.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultError
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
|
||||||
|
import app.revanced.patches.youtube.layout.oldqualitylayout.signatures.OldQualityParentSignature
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("old-quality-layout")
|
||||||
|
@Description("Enable the original quality flyout menu.")
|
||||||
|
@OldQualityLayoutCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class OldQualityLayoutPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
OldQualityParentSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result = signatures.first().result!!.findParentMethod(@Name("old-quality-signature") @MatchingMethod(
|
||||||
|
definingClass = "Libh"
|
||||||
|
) @FuzzyPatternScanMethod(2) @OldQualityLayoutCompatibility @Version("0.0.1") object : MethodSignature(
|
||||||
|
"L", AccessFlags.FINAL or AccessFlags.PRIVATE, listOf("Z"), listOf(
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.GOTO,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
)
|
||||||
|
) {}) ?: return PatchResultError("Required parent method could not be found.")
|
||||||
|
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
|
||||||
|
// if useOldStyleQualitySettings == true, jump over all instructions
|
||||||
|
val jmpInstruction = BuilderInstruction21t(
|
||||||
|
Opcode.IF_NEZ, 0, implementation.instructions[result.scanResult.endIndex].location.labels.first()
|
||||||
|
)
|
||||||
|
implementation.addInstruction(5, jmpInstruction)
|
||||||
|
implementation.addInstructions(
|
||||||
|
0, """
|
||||||
|
invoke-static { }, Lfi/razerman/youtube/XGlobals;->useOldStyleQualitySettings()Z
|
||||||
|
move-result v0
|
||||||
|
""".trimIndent().toInstructions()
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.oldqualitylayout.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("old-quality-parent-method-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Libh", "<init>"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@OldQualityLayoutCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object OldQualityParentSignature : MethodSignature(
|
||||||
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
listOf("L", "L", "L", "L", "L", "L", "L"),
|
||||||
|
listOf(
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.reels.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class HideReelsCompatibility
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.reels.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstruction
|
||||||
|
import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility
|
||||||
|
import app.revanced.patches.youtube.layout.reels.signatures.HideReelsSignature
|
||||||
|
|
||||||
|
//@Patch TODO: converted to litho
|
||||||
|
@Name("hide-reels")
|
||||||
|
@Description("Hide reels on the page.")
|
||||||
|
@HideReelsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class HideReelsPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
HideReelsSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result = signatures.first().result!!
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
|
||||||
|
// HideReel will hide the reel view before it is being used,
|
||||||
|
// so we pass the view to the HideReel method
|
||||||
|
implementation.addInstruction(
|
||||||
|
result.scanResult.endIndex,
|
||||||
|
"invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->HideReel(Landroid/view/View;)V".toInstruction()
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.reels.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
@Name("hide-reels-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Ljvy", "<init>"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(3) // FIXME: Test this threshold and find the best value.
|
||||||
|
@HideReelsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object HideReelsSignature : MethodSignature(
|
||||||
|
null, AccessFlags.PROTECTED or AccessFlags.FINAL, listOf("L", "L"), null,
|
||||||
|
listOf("multiReelDismissalCallback", "reelItemRenderers", "reelDismissalInfo")
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.shorts.button.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class ShortsButtonCompatibility
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.shorts.button.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.smali.toInstruction
|
||||||
|
import app.revanced.patches.youtube.layout.shorts.button.annotations.ShortsButtonCompatibility
|
||||||
|
import app.revanced.patches.youtube.layout.shorts.button.signatures.PivotBarButtonTabenumSignature
|
||||||
|
import app.revanced.patches.youtube.layout.shorts.button.signatures.PivotBarButtonsViewSignature
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction11x
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("shorts-button")
|
||||||
|
@Description("Hide the shorts button.")
|
||||||
|
@ShortsButtonCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class ShortsButtonRemoverPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
PivotBarButtonTabenumSignature, PivotBarButtonsViewSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result1 = signatures.first().result!!
|
||||||
|
val implementation1 = result1.method.implementation!!
|
||||||
|
val moveEnumInstruction = implementation1.instructions[result1.scanResult.endIndex]
|
||||||
|
val enumRegister = (moveEnumInstruction as Instruction11x).registerA
|
||||||
|
|
||||||
|
val result2 = signatures.last().result!!
|
||||||
|
val implementation2 = result2.method.implementation!!
|
||||||
|
val moveViewInstruction = implementation2.instructions[result2.scanResult.endIndex]
|
||||||
|
val viewRegister = (moveViewInstruction as Instruction11x).registerA
|
||||||
|
|
||||||
|
// Save the tab enum in XGlobals to avoid smali/register workarounds
|
||||||
|
implementation1.addInstruction(
|
||||||
|
result1.scanResult.endIndex + 1,
|
||||||
|
"sput-object v$enumRegister, Lfi/razerman/youtube/XGlobals;->lastPivotTab:Ljava/lang/Enum;".toInstruction()
|
||||||
|
)
|
||||||
|
|
||||||
|
// Hide the button view via proxy by passing it to the hideShortsButton method
|
||||||
|
// It only hides it if the last tab name is "TAB_SHORTS"
|
||||||
|
implementation2.addInstruction(
|
||||||
|
result2.scanResult.endIndex + 2,
|
||||||
|
"invoke-static { v$viewRegister }, Lfi/razerman/youtube/XAdRemover;->hideShortsButton(Landroid/view/View;)V".toInstruction()
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.shorts.button.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.layout.shorts.button.annotations.ShortsButtonCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("pivotbar-buttons-tabenum-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lknw", "z"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@ShortsButtonCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object PivotBarButtonTabenumSignature : MethodSignature(
|
||||||
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
listOf("Z"),
|
||||||
|
listOf(
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.CHECK_CAST,
|
||||||
|
Opcode.IGET_OBJECT,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IGET,
|
||||||
|
Opcode.INVOKE_STATIC, // SomeEnum.fromValue(tabOrdinal)
|
||||||
|
Opcode.MOVE_RESULT_OBJECT
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package app.revanced.patches.youtube.layout.shorts.button.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.layout.shorts.button.annotations.ShortsButtonCompatibility
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Name("pivotbar-buttons-view-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lknw", "z"
|
||||||
|
)
|
||||||
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
|
@ShortsButtonCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object PivotBarButtonsViewSignature : MethodSignature(
|
||||||
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
listOf("Z"),
|
||||||
|
listOf(
|
||||||
|
Opcode.NEW_INSTANCE, // new StateListDrawable()
|
||||||
|
Opcode.INVOKE_DIRECT,
|
||||||
|
Opcode.NEW_ARRAY,
|
||||||
|
Opcode.CONST,
|
||||||
|
Opcode.CONST_16,
|
||||||
|
Opcode.APUT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_OBJECT,
|
||||||
|
Opcode.MOVE_OBJECT,
|
||||||
|
Opcode.MOVE,
|
||||||
|
Opcode.MOVE_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL_RANGE, // pivotBar.getView(drawable, tabName, z, i, map, akebVar, optional)
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.integrations.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.03.38", "17.14.35", "17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class IntegrationsCompatibility
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.integrations.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.BytecodeData
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.signatures.InitSignature
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.immutable.ImmutableMethod
|
||||||
|
import org.jf.dexlib2.immutable.ImmutableMethodImplementation
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("integrations")
|
||||||
|
@Description("Applies mandatory patches to implement the ReVanced integrations into the application.")
|
||||||
|
@IntegrationsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class IntegrationsPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
InitSignature
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
val result = signatures.first().result!!
|
||||||
|
|
||||||
|
val implementation = result.method.implementation!!
|
||||||
|
val count = implementation.registerCount - 1
|
||||||
|
|
||||||
|
implementation.addInstructions(
|
||||||
|
result.scanResult.endIndex + 1, """
|
||||||
|
invoke-static {v$count}, Lpl/jakubweg/StringRef;->setContext(Landroid/content/Context;)V
|
||||||
|
sput-object v$count, Lapp/revanced/integrations/Globals;->context:Landroid/content/Context;
|
||||||
|
""".trimIndent().toInstructions()
|
||||||
|
)
|
||||||
|
|
||||||
|
val classDef = result.definingClassProxy.resolve()
|
||||||
|
classDef.methods.add(
|
||||||
|
ImmutableMethod(
|
||||||
|
classDef.type,
|
||||||
|
"getAppContext",
|
||||||
|
null,
|
||||||
|
"Landroid/content/Context;",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
ImmutableMethodImplementation(
|
||||||
|
1, """
|
||||||
|
invoke-static { }, Lapp/revanced/integrations/Globals;->getAppContext()Landroid/content/Context;
|
||||||
|
move-result-object v0
|
||||||
|
return-object v0
|
||||||
|
""".trimIndent().toInstructions(), null, null
|
||||||
|
)
|
||||||
|
).toMutable()
|
||||||
|
)
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.integrations.signatures
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.signature.implementation.method.MethodSignature
|
||||||
|
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
|
||||||
|
import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility
|
||||||
|
|
||||||
|
@Name("init-signature")
|
||||||
|
@MatchingMethod(
|
||||||
|
"Lacuu", "onCreate"
|
||||||
|
)
|
||||||
|
@IntegrationsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
object InitSignature : MethodSignature(
|
||||||
|
null, null, null, null,
|
||||||
|
listOf("Application creation")
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.manifest.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[Package(
|
||||||
|
"com.google.android.youtube", arrayOf("17.14.35", "17.17.34", "17.19.36")
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class FixLocaleConfigErrorCompatibility
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package app.revanced.patches.youtube.misc.manifest.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.implementation.ResourceData
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.patch.implementation.ResourcePatch
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResult
|
||||||
|
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
|
||||||
|
import app.revanced.patches.youtube.misc.manifest.annotations.FixLocaleConfigErrorCompatibility
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("locale-config-fix")
|
||||||
|
@Description("Fix an error when building the resources by patching the manifest file.")
|
||||||
|
@FixLocaleConfigErrorCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class FixLocaleConfigErrorPatch : ResourcePatch() {
|
||||||
|
override fun execute(data: ResourceData): PatchResult {
|
||||||
|
// create an xml editor instance
|
||||||
|
val editor = data.getXmlEditor("AndroidManifest.xml")
|
||||||
|
|
||||||
|
// edit the application nodes attribute...
|
||||||
|
val applicationNode = editor
|
||||||
|
.file
|
||||||
|
.getElementsByTagName("application")
|
||||||
|
.item(0) as Element
|
||||||
|
|
||||||
|
// by replacing the attributes name
|
||||||
|
val attribute = "android:localeConfig"
|
||||||
|
applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute))
|
||||||
|
applicationNode.removeAttribute("android:localeConfig")
|
||||||
|
|
||||||
|
// close & save the modified file
|
||||||
|
editor.close()
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user