Compare commits

...

40 Commits

Author SHA1 Message Date
semantic-release-bot
771f237990 chore(release): 1.0.0-dev.15 [skip ci]
# [1.0.0-dev.15](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.14...v1.0.0-dev.15) (2022-06-05)

### Bug Fixes

* remove unused patches ([7a0ae2d](7a0ae2d56a))
2022-06-05 05:27:17 +00:00
oSumAtrIX
4d17ff4fb4 style: move extension and utility methods to their own classes 2022-06-05 07:25:51 +02:00
oSumAtrIX
7a0ae2d56a fix: remove unused patches 2022-06-05 07:25:40 +02:00
semantic-release-bot
71a08ca5eb chore(release): 1.0.0-dev.14 [skip ci]
# [1.0.0-dev.14](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.13...v1.0.0-dev.14) (2022-06-04)

### Bug Fixes

* spelling mistake ([eb97257](eb97257c41))

### Features

* `Dependencies` annotation ([73adc6f](73adc6f98c))
* `GeneralBytecodeAds` and `GeneralResourceAds` patch ([05ee34c](05ee34c756))
2022-06-04 00:34:59 +00:00
oSumAtrIX
4ba5b324a6 chore: bump patcher dependency 2022-06-04 02:33:08 +02:00
oSumAtrIX
05ee34c756 feat: GeneralBytecodeAds and GeneralResourceAds patch 2022-06-04 02:27:02 +02:00
oSumAtrIX
73adc6f98c feat: Dependencies annotation 2022-06-03 17:52:30 +02:00
oSumAtrIX
eb97257c41 fix: spelling mistake 2022-06-03 17:38:56 +02:00
semantic-release-bot
9d99df6f31 chore(release): 1.0.0-dev.13 [skip ci]
# [1.0.0-dev.13](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.12...v1.0.0-dev.13) (2022-05-31)

### Bug Fixes

* migrate patches to latest patcher api changes ([39cf505](39cf505d84))
* missing extension method `doRecursively` ([62c6543](62c6543485))
2022-05-31 23:53:49 +00:00
oSumAtrIX
62c6543485 fix: missing extension method doRecursively 2022-06-01 01:50:01 +02:00
oSumAtrIX
39cf505d84 fix: migrate patches to latest patcher api changes 2022-06-01 01:40:57 +02:00
semantic-release-bot
f55ad46322 chore(release): 1.0.0-dev.12 [skip ci]
# [1.0.0-dev.12](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.11...v1.0.0-dev.12) (2022-05-28)

### Bug Fixes

* wrong annotation and signature in patches ([a91432f](a91432f6ca))
2022-05-28 12:33:20 +00:00
oSumAtrIX
a91432f6ca fix: wrong annotation and signature in patches 2022-05-28 14:31:20 +02:00
semantic-release-bot
15cf96aac7 chore(release): 1.0.0-dev.11 [skip ci]
# [1.0.0-dev.11](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.10...v1.0.0-dev.11) (2022-05-26)

### Bug Fixes

* breaking changes by `revanced-patcher` dependency ([1136371](113637183a))
* breaking patcher changes ([6655f4b](6655f4b5e5))
* breaking patcher changes ([32d828f](32d828fc67))
* bugfixes in `microg` ([f4e289c](f4e289c8df))
* write while reading resources and remove checking for "." in resource extensions ([017bcfa](017bcfa04d))

### Features

* begin `MicroG Patch` ([e757e13](e757e13987))
* update MicroG patch to latest version ([45c75cf](45c75cfb0e))
2022-05-26 02:22:41 +00:00
semantic-release-bot
813529944b chore(release): 1.0.0-dev.11 [skip ci]
# [1.0.0-dev.11](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.10...v1.0.0-dev.11) (2022-05-26)

### Bug Fixes

* breaking changes by `revanced-patcher` dependency ([1136371](113637183a))
* breaking patcher changes ([6655f4b](6655f4b5e5))
* breaking patcher changes ([32d828f](32d828fc67))
* bugfixes in `microg` ([f4e289c](f4e289c8df))
* write while reading resources and remove checking for "." in resource extensions ([017bcfa](017bcfa04d))

### Features

* begin `MicroG Patch` ([e757e13](e757e13987))
* update MicroG patch to latest version ([45c75cf](45c75cfb0e))
2022-05-26 02:19:09 +00:00
oSumAtrIX
eef7d863cb chore: update gradlew wrapper 2022-05-26 03:54:01 +02:00
oSumAtrIX
255f00dd63 chore: update dependencies 2022-05-26 03:53:56 +02:00
oSumAtrIX
f4e289c8df fix: bugfixes in microg 2022-05-26 03:47:11 +02:00
oSumAtrIX
017bcfa04d fix: write while reading resources and remove checking for "." in resource extensions
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-24 02:02:39 +02:00
oSumAtrIX
da81df06ff chore: update kotlin jvm
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-24 00:17:01 +02:00
oSumAtrIX
38c06e2d6f chore: update matching method names for microg patch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-23 21:14:43 +02:00
oSumAtrIX
e9fe8d4d12 Merge branch 'dev' into microg-dalvik-patch 2022-05-23 21:07:08 +02:00
oSumAtrIX
bb356cb71c chore: update dependencies
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-23 21:00:27 +02:00
oSumAtrIX
45c75cfb0e feat: update MicroG patch to latest version
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-22 17:41:59 +02:00
oSumAtrIX
08aad61b61 Merge branch 'dev' into microg-dalvik-patch
# Conflicts:
#	src/main/kotlin/app/revanced/patches/Index.kt
#	src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt
#	src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt
#	src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt
#	src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt
#	src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/home/annotation/PromotionsCompatibility.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/home/patch/HomeAdsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/home/patch/PromotionsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/home/signatures/PromotedDiscoveryActionParentSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/home/signatures/PromotedDiscoveryAppParentSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/ad/video/signatures/ShowVideoAdsConstructorSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/signatures/SeekbarTappingParentSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/signatures/SeekbarTappingSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/annotations/CreateButtonCompatibility.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/patch/CreateButtonRemoverPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/signatures/CreateButtonSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/signatures/MinimizedPlaybackManagerSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/reels/patch/HideReelsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/reels/signatures/HideReelsSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/annotations/ShortsButtonCompatibility.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/patch/ShortsButtonRemoverPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/signatures/PivotBarButtonTabenumSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/signatures/PivotBarButtonsViewSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/integrations/signatures/InitSignature.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt
#	src/test/kotlin/app/revanced/patches/SignatureChecker.kt
2022-05-22 17:38:18 +02:00
oSumAtrIX
0c3b512fe3 Merge branch 'annotations' into microg-dalvik-patch 2022-05-21 20:46:28 +02:00
oSumAtrIX
113637183a fix: breaking changes by revanced-patcher dependency
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-18 23:58:54 +02:00
oSumAtrIX
595e0ed37e Merge remote-tracking branch 'origin/microg-dalvik-patch' into microg-dalvik-patch
# Conflicts:
#	src/main/kotlin/app/revanced/patches/Index.kt
2022-05-18 03:16:40 +02:00
oSumAtrIX
6655f4b5e5 fix: breaking patcher changes
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-18 03:16:07 +02:00
oSumAtrIX
8798780d22 refactor: furthermore implement logic for MicroGPatch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-18 03:15:02 +02:00
oSumAtrIX
edbd40563f refactor: MicroGPatch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-18 03:15:00 +02:00
oSumAtrIX
cc5634851a Merge branch 'dev' into microg-dalvik-patch 2022-05-07 18:09:42 +02:00
oSumAtrIX
1d1a20f7aa Merge branch 'dalvik-patches' into microg-dalvik-patch 2022-05-06 16:53:07 +02:00
oSumAtrIX
32d828fc67 fix: breaking patcher changes
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-05 00:04:14 +02:00
oSumAtrIX
927e12791b Merge branch 'dalvik-patches' into microg-dalvik-patch
# Conflicts:
#	src/main/kotlin/app/revanced/patches/Index.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/MicroGPatch.kt
2022-05-05 00:02:03 +02:00
oSumAtrIX
2fbefea52c Merge branch 'dalvik-patches' into microg-dalvik-patch 2022-04-21 19:44:55 +02:00
oSumAtrIX
291441c5d7 refactor: furthermore implement logic for MicroGPatch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-04-20 02:44:56 +02:00
oSumAtrIX
a08c4429d0 Merge branch 'dalvik-patches' into microg-dalvik-patch 2022-04-19 20:01:18 +02:00
oSumAtrIX
426597889f refactor: MicroGPatch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-04-19 20:00:50 +02:00
oSumAtrIX
e757e13987 feat: begin MicroG Patch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-04-19 02:00:48 +02:00
34 changed files with 1401 additions and 1926 deletions

View File

@@ -1,3 +1,72 @@
# [1.0.0-dev.15](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.14...v1.0.0-dev.15) (2022-06-05)
### Bug Fixes
* remove unused patches ([d12e92a](https://github.com/revanced/revanced-patches/commit/d12e92aead677fefa9dcb48748d783225b65fab1))
# [1.0.0-dev.14](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.13...v1.0.0-dev.14) (2022-06-04)
### Bug Fixes
* spelling mistake ([52f9147](https://github.com/revanced/revanced-patches/commit/52f9147ee8d591f786397d174dc02a141d9250a9))
### Features
* `Dependencies` annotation ([85806bb](https://github.com/revanced/revanced-patches/commit/85806bb355e342ecb33d4ee1e76f9edf89b2c2ee))
* `GeneralBytecodeAds` and `GeneralResourceAds` patch ([f99bbef](https://github.com/revanced/revanced-patches/commit/f99bbef4c911ac2492166c7a3792ea11ffceffab))
# [1.0.0-dev.13](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.12...v1.0.0-dev.13) (2022-05-31)
### Bug Fixes
* migrate patches to latest patcher api changes ([8a0ee03](https://github.com/revanced/revanced-patches/commit/8a0ee03a71cf4a000c9a7246d0e64ed8291a5127))
* missing extension method `doRecursively` ([e9c9460](https://github.com/revanced/revanced-patches/commit/e9c946008ee912652d288e515b83b52ae2d239d8))
# [1.0.0-dev.12](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.11...v1.0.0-dev.12) (2022-05-28)
### Bug Fixes
* wrong annotation and signature in patches ([a0fdee8](https://github.com/revanced/revanced-patches/commit/a0fdee81a6d6773603520e7c3040ae8637642d58))
# [1.0.0-dev.11](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.10...v1.0.0-dev.11) (2022-05-26)
### Bug Fixes
* breaking changes by `revanced-patcher` dependency ([7e485b4](https://github.com/revanced/revanced-patches/commit/7e485b4ffe204d724809aeb9bd9f693a35ded94d))
* breaking patcher changes ([50f9cc5](https://github.com/revanced/revanced-patches/commit/50f9cc52acfd5bc23330ecd23d8d85678a9d3eee))
* breaking patcher changes ([cbb9e2c](https://github.com/revanced/revanced-patches/commit/cbb9e2cd1fa829e1d1dd92dbd40131b11ae6a05b))
* bugfixes in `microg` ([a43b33b](https://github.com/revanced/revanced-patches/commit/a43b33bdbb2b36e0a8f991fa11dfeeec34de01f9))
* write while reading resources and remove checking for "." in resource extensions ([7bc6094](https://github.com/revanced/revanced-patches/commit/7bc60943cb2350e89dac091ec9c98c5effd0b8a9))
### Features
* begin `MicroG Patch` ([91474ba](https://github.com/revanced/revanced-patches/commit/91474ba07376c13e7a71685dfd8b6e6913ed5ee9))
* update MicroG patch to latest version ([c24f806](https://github.com/revanced/revanced-patches/commit/c24f8063a04f89aea2d2f7087a435738de7dfeae))
# [1.0.0-dev.11](https://github.com/revanced/revanced-patches/compare/v1.0.0-dev.10...v1.0.0-dev.11) (2022-05-26)
### Bug Fixes
* breaking changes by `revanced-patcher` dependency ([7e485b4](https://github.com/revanced/revanced-patches/commit/7e485b4ffe204d724809aeb9bd9f693a35ded94d))
* breaking patcher changes ([50f9cc5](https://github.com/revanced/revanced-patches/commit/50f9cc52acfd5bc23330ecd23d8d85678a9d3eee))
* breaking patcher changes ([cbb9e2c](https://github.com/revanced/revanced-patches/commit/cbb9e2cd1fa829e1d1dd92dbd40131b11ae6a05b))
* bugfixes in `microg` ([a43b33b](https://github.com/revanced/revanced-patches/commit/a43b33bdbb2b36e0a8f991fa11dfeeec34de01f9))
* write while reading resources and remove checking for "." in resource extensions ([7bc6094](https://github.com/revanced/revanced-patches/commit/7bc60943cb2350e89dac091ec9c98c5effd0b8a9))
### Features
* begin `MicroG Patch` ([91474ba](https://github.com/revanced/revanced-patches/commit/91474ba07376c13e7a71685dfd8b6e6913ed5ee9))
* update MicroG patch to latest version ([c24f806](https://github.com/revanced/revanced-patches/commit/c24f8063a04f89aea2d2f7087a435738de7dfeae))
# [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)

View File

@@ -1,5 +1,5 @@
plugins {
kotlin("jvm") version "1.6.20"
kotlin("jvm") version "1.6.21"
java
`maven-publish`
}
@@ -23,11 +23,10 @@ repositories {
}
dependencies {
implementation(kotlin("stdlib"))
testImplementation(kotlin("test"))
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.21")
implementation("app.revanced:revanced-patcher:1.+")
implementation(kotlin("reflect"))
implementation("app.revanced:revanced-patcher:1.0.0-dev.18")
implementation("org.jetbrains.kotlin:kotlin-reflect:1.6.21")
}
java {

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official
version = 1.0.0-dev.10
version = 1.0.0-dev.15

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -2,6 +2,7 @@ package app.revanced.extensions
import app.revanced.patcher.util.smali.toInstruction
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.w3c.dom.Node
internal fun MutableMethodImplementation.injectHideCall(
index: Int,
@@ -12,3 +13,24 @@ internal fun MutableMethodImplementation.injectHideCall(
"invoke-static { v$register }, Lfi/razerman/youtube/XAdRemover;->HideView(Landroid/view/View;)V".toInstruction()
)
}
internal fun Node.doRecursively(action: (Node) -> Unit) {
action(this)
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
}
internal fun String.startsWithAny(vararg prefix: String): Boolean {
for (_prefix in prefix)
if (this.startsWith(_prefix))
return true
return false
}
internal fun String.containsAny(vararg others: String): Boolean {
for (other in others)
if (this.contains(other))
return true
return false
}

View File

@@ -32,7 +32,8 @@ class CodecsUnlockPatch : BytecodePatch(
val instructionIndex = result.scanResult.startIndex
result = signatures.last().result!!
val codecMethod = data.toMethodWalker(result.immutableMethod).walk(result.scanResult.startIndex).getMethod()
val codecMethod =
data.toMethodWalker(result.immutableMethod).nextMethod(result.scanResult.startIndex).getMethod()
implementation.replaceInstruction(
instructionIndex,

View File

@@ -1,14 +1,14 @@
package app.revanced.patches.youtube.ad.home.annotation
package app.revanced.patches.youtube.ad.general.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")
"com.google.android.youtube", arrayOf("17.19.36", "17.20.37")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class PromotionsCompatibility
internal annotation class GeneralAdsCompatibility

View File

@@ -0,0 +1,64 @@
package app.revanced.patches.youtube.ad.general.bytecode.extensions
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.softCompareTo
import app.revanced.patcher.patch.implementation.misc.PatchResultError
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import org.jf.dexlib2.builder.BuilderInstruction
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.iface.reference.Reference
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
internal object MethodExtensions {
internal fun MutableMethodImplementation.insertBlocks(
startIndex: Int,
vararg blocks: List<BuilderInstruction>,
) {
blocks.reversed().forEach {
this.addInstructions(
startIndex, it
)
}
}
internal fun MutableClass.addMethod(mutableMethod: MutableMethod) {
this.methods.add(mutableMethod)
}
internal fun MutableClass.findMutableMethodOf(
method: Method
) = this.methods.first {
it.softCompareTo(
ImmutableMethodReference(
method.definingClass, method.name, method.parameters, method.returnType
)
)
}
internal inline fun <reified T : Reference> Instruction.toDescriptor(): String {
val reference = (this as ReferenceInstruction).reference
return when (T::class) {
MethodReference::class -> {
val methodReference = reference as MethodReference
"${methodReference.definingClass}->${methodReference.name}(${
methodReference.parameterTypes.joinToString(
""
) { it }
})${methodReference.returnType}"
}
FieldReference::class -> {
val fieldReference = reference as FieldReference
"${fieldReference.definingClass}->${fieldReference.name}:${fieldReference.type}"
}
else -> throw PatchResultError("Unsupported reference type")
}
}
}

View File

@@ -0,0 +1,430 @@
package app.revanced.patches.youtube.ad.general.bytecode.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.proxy
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.annotations.Dependencies
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.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.toInstructions
import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.addMethod
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.findMutableMethodOf
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.insertBlocks
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.toDescriptor
import app.revanced.patches.youtube.ad.general.bytecode.utils.MethodUtils.createMutableMethod
import app.revanced.patches.youtube.ad.general.resource.patch.GeneralResourceAdsPatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.builder.instruction.*
import org.jf.dexlib2.iface.MethodImplementation
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
@Patch
@Dependencies(
dependencies = [ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class, GeneralResourceAdsPatch::class]
)
@Name("general-bytecode-ads")
@Description("Patch to remove general ads in bytecode.")
@GeneralAdsCompatibility
@Version("0.0.1")
class GeneralBytecodeAdsPatch : BytecodePatch(
listOf()
) {
// a constant used by litho
private val lithoConstant = 0xaed2868
// list of resource names to get the id of
private val resourceIds = arrayOf(
"ad_attribution",
"reel_multiple_items_shelf",
"info_cards_drawer_header",
"endscreen_element_layout_video",
"endscreen_element_layout_circle",
"endscreen_element_layout_icon",
"promoted_video_item_land",
"promoted_video_item_full_bleed",
).map {
ResourceIdMappingProviderResourcePatch.resourceMappings[it]!!
}
private val stringReferences = arrayOf(
"Claiming to use more elements than provided",
"loadVideo() called on LocalDirector in wrong state",
"LoggingProperties are not in proto format"
)
override fun execute(data: BytecodeData): PatchResult {
// iterating through all classes is expensive
for (classDef in data.classes) {
var mutableClass: MutableClass? = null
method@ for (method in classDef.methods) {
var mutableMethod: MutableMethod? = null
if (method.implementation == null) continue@method
val instructions = method.implementation!!.instructions
instructions.forEachIndexed { index, instruction ->
when (instruction.opcode) {
Opcode.CONST -> {
// TODO: find a way to de-duplicate code.
// The issue is we need to save mutableClass and mutableMethod to the existing fields
when ((instruction as Instruction31i).wideLiteral) {
resourceIds[0] -> { // general ads
// and is followed by an instruction with the mnemonic INVOKE_VIRTUAL
val insertIndex = index + 1
val invokeInstruction = instructions.elementAt(insertIndex)
if (invokeInstruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed
// create proxied method, make sure to not re-resolve() the current class
if (mutableClass == null) mutableClass = data.proxy(classDef).resolve()
if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method)
// insert hide call to hide the view corresponding to the resource
val viewRegister = (invokeInstruction as Instruction35c).registerC
mutableMethod!!.implementation!!.injectHideCall(insertIndex, viewRegister)
}
resourceIds[1] -> { // reel ads
// and is followed by an instruction at insertIndex with the mnemonic IPUT_OBJECT
val insertIndex = index + 4
val iPutInstruction = instructions.elementAt(insertIndex)
if (iPutInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed
// create proxied method, make sure to not re-resolve() the current class
if (mutableClass == null) mutableClass = data.proxy(classDef).resolve()
if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method)
val viewRegister = (iPutInstruction as Instruction22c).registerA
mutableMethod!!.implementation!!.injectHideCall(insertIndex, viewRegister)
}
resourceIds[2] -> { // info cards ads
// and is followed by an instruction with the mnemonic INVOKE_VIRTUAL
val removeIndex = index - 1
val invokeInstruction = instructions.elementAt(removeIndex)
if (invokeInstruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed
// create proxied method, make sure to not re-resolve() the current class
if (mutableClass == null) mutableClass = data.proxy(classDef).resolve()
if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method)
mutableMethod!!.implementation!!.removeInstruction(removeIndex)
}
resourceIds[3], resourceIds[4], resourceIds[5] -> { // end screen ads
// and is followed by an instruction with the mnemonic IPUT_OBJECT
val insertIndex = index + 7
val invokeInstruction = instructions.elementAt(insertIndex)
if (invokeInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed
// create proxied method, make sure to not re-resolve() the current class
if (mutableClass == null) mutableClass = data.proxy(classDef).resolve()
if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method)
// TODO: dynamically get registers
mutableMethod!!.implementation!!.addInstructions(
insertIndex, """
const/16 v1, 0x8
invoke-virtual {v0,v1}, Landroid/widget/FrameLayout;->setVisibility(I)V
""".trimIndent().toInstructions()
)
}
resourceIds[6] -> {
// and is followed by an instruction with the mnemonic INVOKE_DIRECT
val insertIndex = index + 3
val invokeInstruction = instructions.elementAt(insertIndex)
if (invokeInstruction.opcode != Opcode.INVOKE_DIRECT) return@forEachIndexed
// create proxied method, make sure to not re-resolve() the current class
if (mutableClass == null) mutableClass = data.proxy(classDef).resolve()
if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method)
// insert hide call to hide the view corresponding to the resource
val viewRegister = (invokeInstruction as Instruction35c).registerE
mutableMethod!!.implementation!!.injectHideCall(insertIndex, viewRegister)
}
resourceIds[7] -> {
// TODO, go to class, hide the inflated view
}
}
}
Opcode.CONST_STRING -> {
when (((instruction as Instruction21c).reference as StringReference).string) {
stringReferences[0] -> {
val stringInstruction = instructions.elementAt(3)
if (stringInstruction.opcode == Opcode.CONST_STRING) return@forEachIndexed
// create proxied method, make sure to not re-resolve() the current class
if (mutableClass == null) mutableClass = data.proxy(classDef).resolve()
if (mutableMethod == null) mutableMethod =
mutableClass!!.findMutableMethodOf(method)
// return the method
val insertIndex = 1 // after super constructor
mutableMethod!!.implementation!!.addInstruction(
insertIndex, BuilderInstruction10x(Opcode.RETURN_VOID)
)
}
stringReferences[1] -> {
// TODO: migrate video ads patch to here if necessary
}
stringReferences[2] -> { // Litho ads
// create proxied method.
val proxy = data.proxy(classDef)
val mutableClass = proxy.resolve()
// add getIsEmpty method
mutableClass.addGetIsEmptyMethod()
// get required method to patch and get references from
val lithoMethod = getLithoMethod(mutableClass)
?: return PatchResultError("Could not find required litho method to patch.")
val lithoMethodImplementation = lithoMethod.implementation!!
// create and add getTemplateName method
val getTemplateMethod =
mutableClass.createGetTemplateNameMethod(lithoMethodImplementation)
mutableClass.addMethod(getTemplateMethod)
val lithoInstructions = lithoMethodImplementation.instructions
val thisType = mutableClass.type
val templateNameParameterType = getTemplateMethod.parameterTypes.first()
// get reference descriptors
val indexOfReference1 = lithoInstructions.indexOfFirst {
it.opcode == Opcode.INVOKE_STATIC_RANGE
}
val descriptor1 =
lithoInstructions.elementAt(indexOfReference1).toDescriptor<MethodReference>()
val descriptor2 = lithoInstructions.elementAt(indexOfReference1 + 2)
.toDescriptor<FieldReference>()
// create label
val lithoRemoveLabel = lithoMethodImplementation.newLabelForIndex(0)
// create branch instructions
val ifEqzFirstInstruction =
BuilderInstruction21t(Opcode.IF_EQZ, 0, lithoRemoveLabel)
val ifEqzSecondInstruction =
BuilderInstruction21t(Opcode.IF_EQZ, 1, lithoRemoveLabel)
// create blocks
val parameters = lithoMethod.parameterTypes.joinToString("") { it }
val registers = lithoMethodImplementation.registerCount
val block1 = """
invoke-static/range {p3}, $thisType->getTemplateName($templateNameParameterType)Ljava/lang/String;
move-result-object v0
""".trimIndent().toInstructions(parameters, registers, false)
val block2 = """
move-object/from16 v1, p3
iget-object v2, v1, $templateNameParameterType->b:Ljava/nio/ByteBuffer;
invoke-static {v0, v2}, Lfi/razerman/youtube/litho/LithoAdRemoval;->containsAd(Ljava/lang/String;Ljava/nio/ByteBuffer;)Z
move-result v1
""".trimIndent().toInstructions(parameters, registers, false)
val block3 = """
move-object/from16 v2, p1
invoke-static {v2}, $descriptor1
move-result-object v0
iget-object v0, v0, $descriptor2
return-object v0
""".trimIndent().toInstructions(parameters, registers, false)
// insert blocks and branch instructions
lithoMethodImplementation.insertBlocks(
0,
block1,
listOf(ifEqzFirstInstruction),
block2,
listOf(ifEqzSecondInstruction),
block3,
)
}
}
}
else -> return@forEachIndexed
}
}
}
}
return PatchResultSuccess()
}
private fun getLithoMethod(mutableClass: MutableClass) = mutableClass.methods.firstOrNull {
it.implementation?.instructions?.any { instruction ->
instruction.opcode == Opcode.CONST && (instruction as Instruction31i).narrowLiteral == lithoConstant
} ?: false
}
private fun MutableClass.addGetIsEmptyMethod() {
val getIsEmptyImplementation = MutableMethodImplementation(1)
// create target instructions
val firstTargetInstruction = BuilderInstruction11n(Opcode.CONST_4, 0, 1)
val secondTargetInstruction = BuilderInstruction11n(Opcode.CONST_4, 0, 0)
// add instructions to the instruction list
getIsEmptyImplementation.addInstructions(
0, listOf(
// BuilderInstruction21t(Opcode.IF_EQZ, 0, first),
BuilderInstruction35c(
Opcode.INVOKE_VIRTUAL,
1,
0,
0,
0,
0,
0,
ImmutableMethodReference("Ljava/lang/String;", "isEmpty", null, "Z")
),
BuilderInstruction11x(Opcode.MOVE_RESULT, 0),
// BuilderInstruction21t(Opcode.IF_EQZ, 0, second),
// BuilderInstruction10t(Opcode.GOTO, first),
secondTargetInstruction,
BuilderInstruction11x(Opcode.RETURN, 0),
firstTargetInstruction,
BuilderInstruction11x(Opcode.RETURN, 0),
)
)
val getIsEmptyInstructions = getIsEmptyImplementation.instructions
// create labels for the target instructions
val firstLabel =
getIsEmptyImplementation.newLabelForIndex(getIsEmptyInstructions.indexOf(firstTargetInstruction))
val secondLabel =
getIsEmptyImplementation.newLabelForIndex(getIsEmptyInstructions.indexOf(secondTargetInstruction))
// create branch instructions to the labels
val ifEqzFirstInstruction = BuilderInstruction21t(Opcode.IF_EQZ, 0, firstLabel)
val ifEqzSecondInstruction = BuilderInstruction21t(Opcode.IF_EQZ, 0, secondLabel)
val gotoInstruction = BuilderInstruction10t(Opcode.GOTO, firstLabel)
// insert remaining branch instructions, order of adding those instructions is important
getIsEmptyImplementation.addInstructions(
2, listOf(
ifEqzSecondInstruction, gotoInstruction
)
)
getIsEmptyImplementation.addInstruction(
0, ifEqzFirstInstruction
)
this.addMethod(
createMutableMethod(
this.type, "getIsEmpty", "Z", "Ljava/lang/String;", getIsEmptyImplementation
)
)
}
private fun MutableClass.createGetTemplateNameMethod(lithoMethodImplementation: MethodImplementation): MutableMethod {
var counter = 1
val descriptors = buildList {
for (instruction in lithoMethodImplementation.instructions) {
if (instruction !is ReferenceInstruction) continue
if (counter++ > 4) break
add(instruction.toDescriptor<MethodReference>())
}
}
val getTemplateNameImplementation = MutableMethodImplementation(2)
// create code blocks
val block1 = """
invoke-virtual {p0}, ${descriptors[0]}
move-result-object p0
const v0, $lithoConstant
invoke-static {p0, v0}, ${descriptors[1]}
move-result-object p0
""".trimIndent().toInstructions()
val block2 = """
invoke-static {p0}, ${descriptors[2]}
move-result-object p0
invoke-virtual {p0}, ${descriptors[3]}
move-result-object v0
invoke-static {v0}, ${this.type}->getIsEmpty(Ljava/lang/String;)Z
move-result v0
""".trimIndent().toInstructions()
val block3 = """
invoke-virtual {p0}, ${descriptors[3]}
move-result-object p0
return-object p0
""".trimIndent().toInstructions()
// create target instruction
val targetInstruction = BuilderInstruction11n(Opcode.CONST_4, 1, 0)
// and remaining instruction
val returnInstruction = BuilderInstruction11x(Opcode.RETURN_OBJECT, 1)
// insert blocks and instructions
getTemplateNameImplementation.insertBlocks(
0,
block1,
block2,
block3,
listOf(
targetInstruction, returnInstruction
),
)
// create label for target instruction
val targetInstructionLabel =
getTemplateNameImplementation.newLabelForIndex(getTemplateNameImplementation.instructions.size - 2)
// create branch instructions to the label
val ifEqzInstruction = BuilderInstruction21t(Opcode.IF_EQZ, 1, targetInstructionLabel)
val ifNezInstruction = BuilderInstruction21t(Opcode.IF_NEZ, 0, targetInstructionLabel)
// insert branch instructions
getTemplateNameImplementation.addInstruction(
block1.size, ifEqzInstruction
)
getTemplateNameImplementation.addInstruction(
block1.size + block2.size + 1, ifNezInstruction
)
// create the method
return createMutableMethod(
this.type,
"getTemplateName",
"Ljava/lang/String;",
descriptors[0].split("->")[0], // a bit weird to get the type this way,
getTemplateNameImplementation
)
}
}

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.youtube.ad.general.bytecode.utils
import app.revanced.patcher.extensions.or
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.iface.MethodImplementation
import org.jf.dexlib2.immutable.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodParameter
internal object MethodUtils {
internal fun createMutableMethod(
definingClass: String, name: String, returnType: String, parameter: String, implementation: MethodImplementation
) = ImmutableMethod(
definingClass, name, listOf(
ImmutableMethodParameter(
parameter, null, null
)
), returnType, AccessFlags.PRIVATE or AccessFlags.STATIC, null, null, implementation
).toMutable()
}

View File

@@ -0,0 +1,60 @@
package app.revanced.patches.youtube.ad.general.resource.patch
import app.revanced.extensions.doRecursively
import app.revanced.extensions.startsWithAny
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.Dependencies
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.ad.general.annotation.GeneralAdsCompatibility
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
import org.w3c.dom.Element
@Dependencies(dependencies = [FixLocaleConfigErrorPatch::class])
@Name("general-resource-ads")
@Description("Patch to remove general ads in resources.")
@GeneralAdsCompatibility
@Version("0.0.1")
class GeneralResourceAdsPatch : ResourcePatch() {
// list of resource file names which need to be hidden
private val resourceFileNames = arrayOf(
"compact_promoted_video_item.xml",
"inline_muted_metadata_swap.xml",
"interstitial_promo_view.xml",
"pip_ad_overlay.xml",
"promoted_",
"watch_metadata_companion_cards.xml",
//"watch_while_activity.xml" // FIXME: find out why patching this resource fails
)
// the attributes to change the value of
private val replacements = arrayOf(
"height",
"width",
"marginTop",
)
override fun execute(data: ResourceData): PatchResult {
data.forEach {
if (!it.name.startsWithAny(*resourceFileNames)) return@forEach
// for each file in the "layouts" directory replace all necessary attributes content
data.getXmlEditor(it.absolutePath).use { editor ->
editor.file.doRecursively { node ->
replacements.forEach replacement@{ replacement ->
if (node !is Element) return@replacement
node.getAttributeNode("android:layout_$replacement")?.let { attribute ->
attribute.textContent = "1.0dip"
}
}
}
}
}
return PatchResultSuccess()
}
}

View File

@@ -1,65 +0,0 @@
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()
}
}

View File

@@ -1,58 +0,0 @@
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
)
)

View File

@@ -1,61 +0,0 @@
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
)
)

View File

@@ -6,6 +6,7 @@ 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.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.misc.PatchResult
@@ -17,9 +18,11 @@ import app.revanced.patcher.signature.implementation.method.annotation.MatchingM
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 app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.AccessFlags
@Patch
@Dependencies(dependencies = [IntegrationsPatch::class])
@Name("video-ads")
@Description("Patch to remove ads in the YouTube video player.")
@VideoAdsCompatibility
@@ -37,7 +40,6 @@ class VideoAdsPatch : BytecodePatch(
"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, """

View File

@@ -5,6 +5,7 @@ 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.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.misc.PatchResult
@@ -14,14 +15,15 @@ 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 app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
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
@Dependencies(dependencies = [IntegrationsPatch::class])
@Name("seekbar-tapping")
@Description("Enable tapping on the seekbar of the YouTube player.")
@SeekbarTappingCompatibility

View File

@@ -4,15 +4,22 @@ 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.Dependencies
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 app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
import org.w3c.dom.Element
import java.io.File
@Patch
@Dependencies(
dependencies = [
FixLocaleConfigErrorPatch::class
]
)
@Name("amoled")
@Description("Enables pure black theme.")
@AmoledCompatibility

View File

@@ -4,6 +4,7 @@ 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.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.misc.PatchResult
@@ -12,10 +13,12 @@ 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 app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
@Dependencies(dependencies = [IntegrationsPatch::class])
@Name("disable-create-button")
@Description("Disable the create button.")
@CreateButtonCompatibility
@@ -31,8 +34,7 @@ class CreateButtonRemoverPatch : BytecodePatch(
// 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")
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

View File

@@ -19,7 +19,6 @@ import app.revanced.patches.youtube.layout.minimizedplayback.signatures.Minimize
@Description("Enable minimized and background playback.")
@MinimizedPlaybackCompatibility
@Version("0.0.1")
class MinimizedPlaybackPatch : BytecodePatch(
listOf(
MinimizedPlaybackManagerSignature

View File

@@ -6,6 +6,7 @@ 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.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.misc.PatchResult
@@ -17,11 +18,13 @@ import app.revanced.patcher.signature.implementation.method.annotation.MatchingM
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 app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
@Patch
@Dependencies(dependencies = [IntegrationsPatch::class])
@Name("old-quality-layout")
@Description("Enable the original quality flyout menu.")
@OldQualityLayoutCompatibility

View File

@@ -4,6 +4,7 @@ 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.Dependencies
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.misc.PatchResult
@@ -12,9 +13,11 @@ 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 app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.iface.instruction.formats.Instruction11x
@Patch
@Dependencies(dependencies = [IntegrationsPatch::class])
@Name("shorts-button")
@Description("Hide the shorts button.")
@ShortsButtonCompatibility

View File

@@ -6,9 +6,9 @@ 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.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.smali.toInstructions
@@ -18,7 +18,6 @@ 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
@@ -29,6 +28,9 @@ class IntegrationsPatch : BytecodePatch(
)
) {
override fun execute(data: BytecodeData): PatchResult {
if (data.findClass("Lapp/revanced/integrations/Globals") == null)
return PatchResultError("Integrations have not been merged yet. This patch can not succeed without the integrations.")
val result = signatures.first().result!!
val implementation = result.method.implementation!!

View File

@@ -4,14 +4,12 @@ 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
@@ -19,21 +17,20 @@ import org.w3c.dom.Element
class FixLocaleConfigErrorPatch : ResourcePatch() {
override fun execute(data: ResourceData): PatchResult {
// create an xml editor instance
val editor = data.getXmlEditor("AndroidManifest.xml")
data.getXmlEditor("AndroidManifest.xml").use {
// edit the application nodes attribute...
val applicationNode = it
.file
.getElementsByTagName("application")
.item(0) as Element
// 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")
// 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()
}

View File

@@ -0,0 +1,36 @@
package app.revanced.patches.youtube.misc.mapping.patch
import app.revanced.extensions.doRecursively
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.implementation.ResourcePatch
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import org.w3c.dom.Element
@Name("resource-id-mapping-provider-resource-patch-dependency")
@Description("This patch acts as a provider/ dependency for resource mappings.")
@Version("0.0.1")
class ResourceIdMappingProviderResourcePatch : ResourcePatch() {
companion object {
internal lateinit var resourceMappings: Map<String, Long>
private set
}
override fun execute(data: ResourceData): PatchResult {
data.getXmlEditor("res/values/public.xml").use { editor ->
resourceMappings = buildMap {
editor.file.documentElement.doRecursively { node ->
if (node !is Element) return@doRecursively
val nameAttribute = node.getAttribute("name")
if (node.nodeName != "public" || nameAttribute.startsWith("APKTOOL")) return@doRecursively
this[nameAttribute] = node.getAttribute("id").substring(2).toLong(16)
}
}
}
return PatchResultSuccess()
}
}

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.misc.microg.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf("17.14.35", "17.19.36")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class MicroGPatchCompatibility

View File

@@ -0,0 +1,169 @@
package app.revanced.patches.youtube.misc.microg.patch.bytecode
import app.revanced.extensions.containsAny
import app.revanced.extensions.startsWithAny
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.proxy
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
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.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.MutableClass
import app.revanced.patcher.util.smali.toInstruction
import app.revanced.patcher.util.smali.toInstructions
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
import app.revanced.patches.youtube.misc.microg.patch.resource.enum.StringReplaceMode
import app.revanced.patches.youtube.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.signatures.GooglePlayUtilitySignature
import app.revanced.patches.youtube.misc.microg.signatures.IntegrityCheckSignature
import app.revanced.patches.youtube.misc.microg.signatures.PrimeSignature
import app.revanced.patches.youtube.misc.microg.signatures.ServiceCheckSignature
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
// @Patch TODO: finish patch
@Name("microg-bytecode-patch")
@Description("Patch to allow YouTube ReVanced to run without root and under a different package name.")
@MicroGPatchCompatibility
@Version("0.0.1")
class MicroGBytecodePatch : BytecodePatch(
listOf(
IntegrityCheckSignature, ServiceCheckSignature, GooglePlayUtilitySignature, PrimeSignature
)
) {
override fun execute(data: BytecodeData): PatchResult {
// smali patches
disablePlayServiceChecks()
data.classes.forEach { classDef ->
var proxiedClass: MutableClass? = null
classDef.methods.forEach methodLoop@{ method ->
val implementation = method.implementation ?: return@methodLoop
var proxiedImplementation: MutableMethodImplementation? = null
implementation.instructions.forEachIndexed { i, instruction ->
if (instruction.opcode != Opcode.CONST_STRING) return@forEachIndexed
val stringValue = ((instruction as Instruction21c).reference as StringReference).string
val replaceMode =
if (stringValue == "com.google" || stringValue == "com.google.android.gms" ||
stringValue.startsWithAny(
"com.google.iid",
"com.google.android.gms.chimera",
"com.google.android.c2dm",
) || stringValue.containsAny(
"com.google.android.gms.auth.accounts",
"com.google.android.gsf",
"content://com.google.settings"
)
) {
StringReplaceMode.REPLACE_WITH_MICROG
} else if (stringValue.startsWith("com.google.android.gms.chimera.container")) // https://github.com/TeamVanced/VancedMicroG/pull/139/file
StringReplaceMode.DO_NOT_REPLACE
else if (stringValue.startsWithAny(
"com.google.android.youtube.SuggestionsProvider",
"com.google.android.youtube.fileprovider"
)
) {
StringReplaceMode.REPLACE_WITH_REVANCED
} else {
StringReplaceMode.DO_NOT_REPLACE
}
if (replaceMode != StringReplaceMode.DO_NOT_REPLACE) {
if (proxiedClass == null) {
proxiedClass = data.proxy(classDef).resolve()
}
if (proxiedImplementation == null) {
proxiedImplementation = proxiedClass!!.methods.first {
it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes)
}.implementation!!
}
val newString = if (replaceMode == StringReplaceMode.REPLACE_WITH_REVANCED) stringValue.replace(
"com.google.android.youtube", REVANCED_PACKAGE_NAME
)
else stringValue.replace("com.google", BASE_MICROG_PACKAGE_NAME)
proxiedImplementation!!.replaceInstruction(
i, BuilderInstruction21c(
Opcode.CONST_STRING, instruction.registerA, ImmutableStringReference(newString)
)
)
}
}
}
}
// replace string back
val implementation =
signatures.elementAt(2).result!!.findParentMethod(@Name("do-not-replace-method") @MatchingMethod(
"Llpe;", "c"
) @DirectPatternScanMethod @MicroGPatchCompatibility @Version("0.0.1") object : MethodSignature(
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), null, listOf("com.google.android.gms")
) {})!!.method.implementation!!
implementation.replaceInstruction(
implementation.instructions.indexOfFirst { it.opcode == Opcode.CONST_STRING },
"const-string v0, \"com.google.android.gms\"".toInstruction()
)
return PatchResultSuccess()
}
private fun disablePlayServiceChecks() {
for (i in 0 until signatures.count() - 1) {
val result = signatures.elementAt(i).result!!
val stringInstructions = when (result.immutableMethod.returnType.first()) {
'L' -> """
const/4 v0, 0x0
return-object v0
"""
'V' -> "return-void"
'I' -> """
const/4 v0, 0x0
return v0
"""
else -> throw Exception("This case should never happen.")
}
result.method.implementation!!.addInstructions(
0, stringInstructions.trimIndent().toInstructions()
)
}
val implementation = signatures.last().result!!.method.implementation!!
var register = 2
val index = implementation.instructions.indexOfFirst {
if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false
val instructionString = ((it as Instruction21c).reference as StringReference).string
if (instructionString != "com.google.android.youtube") return@indexOfFirst false
register = it.registerA
return@indexOfFirst true
}
implementation.replaceInstruction(
index, "const-string v$register, \"$REVANCED_PACKAGE_NAME\"".toInstruction()
)
}
}

View File

@@ -0,0 +1,69 @@
package app.revanced.patches.youtube.misc.microg.patch.resource
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.implementation.ResourcePatch
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
import app.revanced.patches.youtube.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
// @Patch TODO: finish patch
@Name("microg-resource-patch")
@Description("Resource patch to allow YouTube ReVanced to run without root and under a different package name.")
@MicroGPatchCompatibility
@Version("0.0.1")
class MicroGResourcePatch : ResourcePatch() {
override fun execute(data: ResourceData): PatchResult {
val manifest = data.get("AndroidManifest.xml").readText()
data.get("AndroidManifest.xml").writeText(
manifest.replace(
"package=\"com.google.android.youtube\"", "package=\"$REVANCED_PACKAGE_NAME\""
).replace(
" android:label=\"@string/application_name\" ", " android:label=\"{APP_NAME}\" "
).replace(
"<uses-permission android:name=\"com.google.android.youtube.permission.C2D_MESSAGE\"",
"<uses-permission android:name=\"$REVANCED_PACKAGE_NAME.permission.C2D_MESSAGE\""
).replace(
"<permission android:name=\"com.google.android.youtube.permission.C2D_MESSAGE\"",
"<permission android:name=\"$REVANCED_PACKAGE_NAME.permission.C2D_MESSAGE\""
).replace(
"<provider android:authorities=\"com.google.android.youtube.lifecycle-trojan\"",
"<provider android:authorities=\"$REVANCED_PACKAGE_NAME.lifecycle-trojan\""
).replace(
"\"com.google.android.youtube.fileprovider\"", "\"$REVANCED_PACKAGE_NAME.fileprovider\""
).replace(
"<provider android:authorities=\"com.google.android.youtube.photopicker_images\"",
"<provider android:authorities=\"$REVANCED_PACKAGE_NAME.photopicker_images\""
).replace("com.google.android.c2dm", "$BASE_MICROG_PACKAGE_NAME.android.c2dm").replace(
" </queries>",
" <package android:name=\"$BASE_MICROG_PACKAGE_NAME.android.gms\"/>\n </queries>"
)
)
val replacement = arrayOf(
Pair(
"com.google.android.youtube.SuggestionProvider", "$REVANCED_PACKAGE_NAME.SuggestionProvider"
), Pair(
"com.google.android.youtube.fileprovider", "$REVANCED_PACKAGE_NAME.fileprovider"
)
)
data.forEach {
if (it.extension != "xml") return@forEach
// TODO: use a reader and only replace strings where needed instead of reading & writing the entire file
var content = it.readText()
replacement.filter { translation -> content.contains(translation.first) }.forEach { translation ->
content = content.replace(translation.first, translation.second)
}
it.writeText(content)
}
return PatchResultSuccess()
}
}

View File

@@ -0,0 +1,5 @@
package app.revanced.patches.youtube.misc.microg.patch.resource.enum
enum class StringReplaceMode {
REPLACE_WITH_MICROG, REPLACE_WITH_REVANCED, DO_NOT_REPLACE
}

View File

@@ -0,0 +1,6 @@
package app.revanced.patches.youtube.misc.microg.shared
object Constants {
internal const val BASE_MICROG_PACKAGE_NAME = "com.mgoogle"
internal const val REVANCED_PACKAGE_NAME = "app.revanced.android.youtube"
}

View File

@@ -0,0 +1,239 @@
package app.revanced.patches.youtube.misc.microg.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.misc.microg.annotations.MicroGPatchCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("google-play-utility-signature")
@MatchingMethod(
"Llss;", "b"
)
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
@MicroGPatchCompatibility
@Version("0.0.1")
object GooglePlayUtilitySignature : MethodSignature(
"I", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.GOTO,
Opcode.CONST_STRING,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.CONST_4,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.MONITOR_ENTER,
Opcode.SGET_BOOLEAN,
Opcode.IF_EQZ,
Opcode.MONITOR_EXIT,
Opcode.GOTO,
Opcode.SPUT_BOOLEAN,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.MONITOR_EXIT,
Opcode.GOTO,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.SPUT,
Opcode.GOTO,
Opcode.MOVE_EXCEPTION,
Opcode.CONST_STRING,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MONITOR_EXIT,
Opcode.SGET,
Opcode.IF_EQZ,
Opcode.CONST,
Opcode.IF_NE,
Opcode.GOTO,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.THROW,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.THROW,
Opcode.MOVE_EXCEPTION,
Opcode.MONITOR_EXIT,
Opcode.THROW,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.CONST_4,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IF_NEZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.SPUT_OBJECT,
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_16,
Opcode.IF_EQZ,
Opcode.CONST_STRING,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.GOTO,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.CONST_16,
Opcode.GOTO_16,
Opcode.CONST_4,
Opcode.CONST_STRING,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.GOTO,
Opcode.IF_EQZ,
Opcode.INVOKE_STATIC,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.GOTO,
Opcode.IF_EQZ,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.AGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.AGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.GOTO,
Opcode.IGET,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_GE,
Opcode.IGET,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.GOTO,
Opcode.MOVE_EXCEPTION,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.GOTO,
Opcode.IGET_BOOLEAN,
Opcode.IF_NEZ,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.RETURN,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.RETURN
), listOf("This should never happen.", "MetadataValueReader", "com.google.android.gms")
)

View File

@@ -0,0 +1,82 @@
package app.revanced.patches.youtube.misc.microg.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.misc.microg.annotations.MicroGPatchCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("google-play-sig-check-signature")
@MatchingMethod(
"Ldwn;", "d"
)
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
@MicroGPatchCompatibility
@Version("0.0.1")
object IntegrityCheckSignature : MethodSignature(
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf(
Opcode.MOVE_OBJECT_FROM16,
Opcode.CONST_STRING,
Opcode.CONST_STRING,
Opcode.NEW_INSTANCE,
Opcode.MOVE_OBJECT_FROM16,
Opcode.INVOKE_DIRECT,
Opcode.CONST_4,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IF_EQ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.SGET,
Opcode.IGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_WIDE,
Opcode.CONST_WIDE,
Opcode.CONST_STRING,
Opcode.CONST_4,
Opcode.CONST_STRING,
Opcode.CONST_4,
Opcode.CMP_LONG,
Opcode.IF_GEZ,
Opcode.CONST_16,
Opcode.GOTO_16,
Opcode.CONST_STRING,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.GOTO,
Opcode.MOVE_EXCEPTION,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.CONST_4,
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.CONST,
Opcode.IF_NE,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.SGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.GOTO,
Opcode.NEW_ARRAY
), listOf("This should never happen.", "GooglePlayServicesUtil", "Google Play Store signature invalid.")
)

View File

@@ -0,0 +1,19 @@
package app.revanced.patches.youtube.misc.microg.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.DirectPatternScanMethod
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
@Name("google-play-prime-signature")
@MatchingMethod(
"Lpag;", "d"
)
@DirectPatternScanMethod
@MicroGPatchCompatibility
@Version("0.0.1")
object PrimeSignature : MethodSignature(
null, null, null, null, listOf("com.google.android.GoogleCamera", "com.android.vending")
)

View File

@@ -0,0 +1,49 @@
package app.revanced.patches.youtube.misc.microg.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.misc.microg.annotations.MicroGPatchCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("google-play-service-checker-signature")
@MatchingMethod(
"Llss;", "d"
)
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
@MicroGPatchCompatibility
@Version("0.0.1")
object ServiceCheckSignature : MethodSignature(
"V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), listOf(
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.SGET_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.IF_NEZ,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.THROW,
Opcode.NEW_INSTANCE,
Opcode.CONST_STRING,
Opcode.INVOKE_DIRECT,
Opcode.THROW,
Opcode.RETURN_VOID
), listOf("Google Play Services not available")
)