Compare commits

..

15 Commits

Author SHA1 Message Date
semantic-release-bot
1023936a26 chore(release): 2.36.2 [skip ci]
## [2.36.2](https://github.com/revanced/revanced-patches/compare/v2.36.1...v2.36.2) (2022-08-14)

### Bug Fixes

* disable cast modules in YouTube Music ([#337](https://github.com/revanced/revanced-patches/issues/337)) ([98e5dbc](98e5dbcc73))
2022-08-14 21:15:11 +00:00
Canny
98e5dbcc73 fix: disable cast modules in YouTube Music (#337) 2022-08-14 23:13:16 +02:00
semantic-release-bot
353806828b chore(release): 2.36.1 [skip ci]
## [2.36.1](https://github.com/revanced/revanced-patches/compare/v2.36.0...v2.36.1) (2022-08-14)

### Bug Fixes

* add missing switch for tablet mini-player ([1ad69e3](1ad69e350c))
2022-08-14 20:36:40 +00:00
oSumAtrIX
1ad69e350c fix: add missing switch for tablet mini-player 2022-08-14 22:34:44 +02:00
semantic-release-bot
42c562cff7 chore(release): 2.36.0 [skip ci]
# [2.36.0](https://github.com/revanced/revanced-patches/compare/v2.35.0...v2.36.0) (2022-08-14)

### Features

* `swipe-controls` override volume button behaviour ([#285](https://github.com/revanced/revanced-patches/issues/285)) ([155121f](155121f891))
2022-08-14 20:22:07 +00:00
Chris
155121f891 feat: swipe-controls override volume button behaviour (#285) 2022-08-14 22:19:54 +02:00
semantic-release-bot
c684a1c846 chore(release): 2.35.0 [skip ci]
# [2.35.0](https://github.com/revanced/revanced-patches/compare/v2.34.0...v2.35.0) (2022-08-14)

### Features

* `tiktok-ads` patch ([#335](https://github.com/revanced/revanced-patches/issues/335)) ([49ddc0a](49ddc0a2ed))
2022-08-14 20:18:06 +00:00
oSumAtrIX
49ddc0a2ed feat: tiktok-ads patch (#335) 2022-08-14 22:16:25 +02:00
semantic-release-bot
221b61acc7 chore(release): 2.34.0 [skip ci]
# [2.34.0](https://github.com/revanced/revanced-patches/compare/v2.33.2...v2.34.0) (2022-08-14)

### Features

* `tablet-mini-player` patch ([aab39cb](aab39cbe93))
2022-08-14 15:35:33 +00:00
oSumAtrIX
c133d495c3 build: bump patcher dependency version 2022-08-14 17:33:13 +02:00
oSumAtrIX
aab39cbe93 feat: tablet-mini-player patch 2022-08-14 17:32:32 +02:00
semantic-release-bot
bdab92faf2 chore(release): 2.33.2 [skip ci]
## [2.33.2](https://github.com/revanced/revanced-patches/compare/v2.33.1...v2.33.2) (2022-08-07)
2022-08-07 20:42:34 +00:00
oSumAtrIX
50acd3d3b5 refactor: remove unused parameter 2022-08-07 22:40:07 +02:00
oSumAtrIX
49a369a340 refactor: un-shadow variable name 2022-08-07 22:39:53 +02:00
oSumAtrIX
be8620bf91 build: bump patcher dependency version 2022-08-07 22:36:02 +02:00
25 changed files with 523 additions and 29 deletions

View File

@@ -1,3 +1,40 @@
## [2.36.2](https://github.com/revanced/revanced-patches/compare/v2.36.1...v2.36.2) (2022-08-14)
### Bug Fixes
* disable cast modules in YouTube Music ([#337](https://github.com/revanced/revanced-patches/issues/337)) ([86eaba8](https://github.com/revanced/revanced-patches/commit/86eaba8248100987f46540a224956099bcf9da2c))
## [2.36.1](https://github.com/revanced/revanced-patches/compare/v2.36.0...v2.36.1) (2022-08-14)
### Bug Fixes
* add missing switch for tablet mini-player ([b824d35](https://github.com/revanced/revanced-patches/commit/b824d35960df9e99c2a2d248356c3c9342cfe130))
# [2.36.0](https://github.com/revanced/revanced-patches/compare/v2.35.0...v2.36.0) (2022-08-14)
### Features
* `swipe-controls` override volume button behaviour ([#285](https://github.com/revanced/revanced-patches/issues/285)) ([69465f3](https://github.com/revanced/revanced-patches/commit/69465f3a9934973a2449605a248a462510e10ff6))
# [2.35.0](https://github.com/revanced/revanced-patches/compare/v2.34.0...v2.35.0) (2022-08-14)
### Features
* `tiktok-ads` patch ([#335](https://github.com/revanced/revanced-patches/issues/335)) ([81bef57](https://github.com/revanced/revanced-patches/commit/81bef57742bfaefcdfe02fd290cca6923341149a))
# [2.34.0](https://github.com/revanced/revanced-patches/compare/v2.33.2...v2.34.0) (2022-08-14)
### Features
* `tablet-mini-player` patch ([dae41f1](https://github.com/revanced/revanced-patches/commit/dae41f1c59d26d00b1ba821dbe1521e68226f47c))
## [2.33.2](https://github.com/revanced/revanced-patches/compare/v2.33.1...v2.33.2) (2022-08-07)
## [2.33.1](https://github.com/revanced/revanced-patches/compare/v2.33.0...v2.33.1) (2022-08-07) ## [2.33.1](https://github.com/revanced/revanced-patches/compare/v2.33.0...v2.33.1) (2022-08-07)

View File

@@ -45,6 +45,14 @@ Official patches by ReVanced
| `promo-code-unlock` | Disables the validation of promo code. Any code will work to unlock all features. | all | | `promo-code-unlock` | Disables the validation of promo code. Any code will work to unlock all features. | all |
</details> </details>
### 📦 `com.ss.android.ugc.trill`
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `tiktok-ads` | Removes ads from TikTok. | all |
</details>
### 📦 `com.google.android.youtube` ### 📦 `com.google.android.youtube`
<details> <details>
@@ -66,6 +74,7 @@ Official patches by ReVanced
| `hide-watermark` | Hides creator's watermarks on videos. | 17.29.34 | | `hide-watermark` | Hides creator's watermarks on videos. | 17.29.34 |
| `sponsorblock` | Integrate SponsorBlock. | 17.29.34 | | `sponsorblock` | Integrate SponsorBlock. | 17.29.34 |
| `enable-wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 17.29.34 | | `enable-wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 17.29.34 |
| `tablet-mini-player` | Enables the tablet mini player layout. | 17.29.34 |
| `custom-video-buffer` | Lets you change the buffers of videos. | 17.29.34 | | `custom-video-buffer` | Lets you change the buffers of videos. | 17.29.34 |
| `always-autorepeat` | Always repeats the playing video again. | 17.29.34 | | `always-autorepeat` | Always repeats the playing video again. | 17.29.34 |
| `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG | 17.29.34 | | `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG | 17.29.34 |

View File

@@ -22,7 +22,7 @@ repositories {
dependencies { dependencies {
implementation(kotlin("stdlib")) implementation(kotlin("stdlib"))
implementation("app.revanced:revanced-patcher:3.3.1") implementation("app.revanced:revanced-patcher:3.3.3")
implementation("app.revanced:multidexlib2:2.5.2.r2") implementation("app.revanced:multidexlib2:2.5.2.r2")
} }

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official kotlin.code.style = official
version = 2.33.1 version = 2.36.2

View File

@@ -1,8 +1,10 @@
package app.revanced.extensions package app.revanced.extensions
import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.data.impl.ResourceData import app.revanced.patcher.data.impl.ResourceData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.toInstruction import app.revanced.patcher.util.smali.toInstruction
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
@@ -27,6 +29,30 @@ internal fun MutableMethodImplementation.injectHideCall(
) )
} }
/**
* traverse the class hierarchy starting from the given root class
*
* @param targetClass the class to start traversing the class hierarchy from
* @param callback function that is called for every class in the hierarchy
*/
fun BytecodeData.traverseClassHierarchy(targetClass: MutableClass, callback: MutableClass.() -> Unit) {
callback(targetClass)
this.findClass(targetClass.superclass ?: return)?.resolve()?.let {
traverseClassHierarchy(it, callback)
}
}
/**
* apply a transform to all methods of the class
*
* @param transform the transformation function. original method goes in, transformed method goes out
*/
fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
val transformedMethods = methods.map { it.transform() }
methods.clear()
methods.addAll(transformedMethods)
}
/** /**
* Insert an event hook at the top of the method. If the hook returns true, the event is consumed and the method will return with true * Insert an event hook at the top of the method. If the hook returns true, the event is consumed and the method will return with true
* *

View File

@@ -5,7 +5,7 @@ import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import app.revanced.patcher.extensions.PatchExtensions.description import app.revanced.patcher.extensions.PatchExtensions.description
import app.revanced.patcher.extensions.PatchExtensions.patchName import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.util.patch.implementation.JarPatchBundle import app.revanced.patcher.util.patch.impl.JarPatchBundle
import java.io.File import java.io.File
object Generator { object Generator {

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.music.misc.microg.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
@Name("cast-context-fetch-fingerprint")
@MatchingMethod(
"Lvvz;", "a"
)
@DirectPatternScanMethod
@MicroGPatchCompatibility
@Version("0.0.1")
object CastContextFetchFingerprint : MethodFingerprint(
null, null, null, null,
listOf("Error fetching CastContext.")
)

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.music.misc.microg.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
@Name("cast-module-fingerprint")
@MatchingMethod(
"Llqh;", "c"
)
@DirectPatternScanMethod
@MicroGPatchCompatibility
@Version("0.0.1")
object CastDynamiteModuleFingerprint : MethodFingerprint(
null, null, null, null,
listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl")
)

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.music.misc.microg.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
@Name("cast-context-fetch-fingerprint")
@MatchingMethod(
"Lmcf;", "c"
)
@DirectPatternScanMethod
@MicroGPatchCompatibility
@Version("0.0.1")
object CastDynamiteModuleV2Fingerprint : MethodFingerprint(
null, null, null, null,
listOf("Failed to load module via V2: ")
)

View File

@@ -36,6 +36,9 @@ class MusicMicroGBytecodePatch : BytecodePatch(
listOf( listOf(
ServiceCheckFingerprint, ServiceCheckFingerprint,
GooglePlayUtilityFingerprint, GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint,
PrimeFingerprint, PrimeFingerprint,
) )
) { ) {
@@ -122,9 +125,17 @@ class MusicMicroGBytecodePatch : BytecodePatch(
listOf( listOf(
ServiceCheckFingerprint, ServiceCheckFingerprint,
GooglePlayUtilityFingerprint, GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint,
).forEach { fingerprint -> ).forEach { fingerprint ->
val result = fingerprint.result!! val result = fingerprint.result!!
val stringInstructions = when (result.method.returnType.first()) { val stringInstructions = when (result.method.returnType.first()) {
'L' -> """
const/4 v0, 0x0
return-object v0
"""
'V' -> "return-void" 'V' -> "return-void"
'I' -> """ 'I' -> """
const/4 v0, 0x0 const/4 v0, 0x0

View File

@@ -0,0 +1,14 @@
package app.revanced.patches.tiktok.ad.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[
Package("com.ss.android.ugc.trill", arrayOf()),
Package("com.zhiliaoapp.musically", arrayOf())
]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class TiktokAdsCompatibility

View File

@@ -0,0 +1,20 @@
package app.revanced.patches.tiktok.ad.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.tiktok.ad.annotations.TiktokAdsCompatibility
@Name("feed-item-clone-fingerprint")
@MatchingMethod(
"Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;",
"clone",
)
@TiktokAdsCompatibility
@Version("0.0.1")
object FeedItemListCloneFingerprint : MethodFingerprint(
null, null, null, null,null, { methodDef ->
methodDef.definingClass.endsWith("/FeedItemList;") && methodDef.name == "clone"
}
)

View File

@@ -0,0 +1,48 @@
package app.revanced.patches.tiktok.ad.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.tiktok.ad.annotations.TiktokAdsCompatibility
import app.revanced.patches.tiktok.ad.fingerprints.FeedItemListCloneFingerprint
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
import org.jf.dexlib2.iface.reference.FieldReference
@Patch
@Name("tiktok-ads")
@Description("Removes ads from TikTok.")
@TiktokAdsCompatibility
@Version("0.0.1")
class TiktokAdsPatch : BytecodePatch(
listOf(FeedItemListCloneFingerprint)
) {
override fun execute(data: BytecodeData): PatchResult {
val method = FeedItemListCloneFingerprint.result!!.mutableMethod
// iterate all instructions in the clone method
for ((index, instruction) in method.implementation!!.instructions.withIndex()) {
// conditions for the instruction we need
if (instruction.opcode.ordinal != Opcode.IPUT_OBJECT.ordinal) continue
val clonePreloadAdsFieldInstruction = (instruction as? ReferenceInstruction)
if ((clonePreloadAdsFieldInstruction?.reference as? FieldReference)?.name != "preloadAds") continue
// set null instead of the field "preloadAds"
val overrideRegister = (clonePreloadAdsFieldInstruction as TwoRegisterInstruction).registerA
method.addInstruction(
index,
"const/4 v$overrideRegister, 0x0"
)
return PatchResultSuccess()
}
return PatchResultError("Could not find required instruction.")
}
}

View File

@@ -174,7 +174,6 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
} }
Opcode.CONST_STRING -> { Opcode.CONST_STRING -> {
when (((instruction as Instruction21c).reference as StringReference).string) { when (((instruction as Instruction21c).reference as StringReference).string) {
stringReferences[0] -> { stringReferences[0] -> {
val stringInstruction = instructions.elementAt(3) val stringInstruction = instructions.elementAt(3)
@@ -200,23 +199,23 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
stringReferences[2] -> { // Litho ads stringReferences[2] -> { // Litho ads
// create proxied method. // create proxied method.
val proxy = data.proxy(classDef) val proxy = data.proxy(classDef)
val mutableClass = proxy.resolve() val proxiedClass = proxy.resolve()
// add getIsEmpty method // add getIsEmpty method
mutableClass.addGetIsEmptyMethod() proxiedClass.addGetIsEmptyMethod()
// get required method to patch and get references from // get required method to patch and get references from
val lithoMethod = getLithoMethod(mutableClass) val lithoMethod = getLithoMethod(proxiedClass)
?: return PatchResultError("Could not find required litho method to patch.") ?: return PatchResultError("Could not find required litho method to patch.")
val lithoMethodImplementation = lithoMethod.implementation!! val lithoMethodImplementation = lithoMethod.implementation!!
// create and add getTemplateName method // create and add getTemplateName method
val getTemplateMethod = val getTemplateMethod =
mutableClass.createGetTemplateNameMethod(lithoMethodImplementation) proxiedClass.createGetTemplateNameMethod(lithoMethodImplementation)
mutableClass.addMethod(getTemplateMethod) proxiedClass.addMethod(getTemplateMethod)
val lithoInstructions = lithoMethodImplementation.instructions val lithoInstructions = lithoMethodImplementation.instructions
val thisType = mutableClass.type val thisType = proxiedClass.type
val templateNameParameterType = getTemplateMethod.parameterTypes.first() val templateNameParameterType = getTemplateMethod.parameterTypes.first()
// get reference descriptors // get reference descriptors

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.youtube.interaction.swipecontrols.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
@Name("swipe-controls-host-activity-fingerprint")
@MatchingMethod(
"Lapp/revanced/integrations/swipecontrols/SwipeControlsHostActivity;", "<init>"
)
@DirectPatternScanMethod
@SwipeControlsCompatibility
@Version("0.0.1")
object SwipeControlsHostActivityFingerprint : MethodFingerprint(
null, null, null, null, null, { methodDef ->
methodDef.definingClass == "Lapp/revanced/integrations/swipecontrols/SwipeControlsHostActivity;" && methodDef.name == "<init>"
}
)

View File

@@ -7,15 +7,15 @@ import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
@Name("watch-while-onStart-fingerprint") @Name("watch-while-activity-fingerprint")
@MatchingMethod( @MatchingMethod(
"LWatchWhileActivity;", "onCreate" "LWatchWhileActivity;", "<init>"
) )
@DirectPatternScanMethod @DirectPatternScanMethod
@SwipeControlsCompatibility @SwipeControlsCompatibility
@Version("0.0.1") @Version("0.0.1")
object WatchWhileOnStartFingerprint : MethodFingerprint( object WatchWhileActivityFingerprint : MethodFingerprint(
null, null, null, null, null, { methodDef -> null, null, null, null, null, { methodDef ->
methodDef.definingClass.endsWith("WatchWhileActivity;") && methodDef.name == "onStart" methodDef.definingClass.endsWith("WatchWhileActivity;") && methodDef.name == "<init>"
} }
) )

View File

@@ -1,45 +1,69 @@
package app.revanced.patches.youtube.interaction.swipecontrols.patch.bytecode package app.revanced.patches.youtube.interaction.swipecontrols.patch.bytecode
import app.revanced.extensions.transformMethods
import app.revanced.extensions.traverseClassHierarchy
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.BytecodeData import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility
import app.revanced.patches.youtube.interaction.swipecontrols.fingerprints.WatchWhileOnStartFingerprint import app.revanced.patches.youtube.interaction.swipecontrols.fingerprints.SwipeControlsHostActivityFingerprint
import app.revanced.patches.youtube.interaction.swipecontrols.fingerprints.WatchWhileActivityFingerprint
import app.revanced.patches.youtube.interaction.swipecontrols.patch.resource.SwipeControlsResourcePatch import app.revanced.patches.youtube.interaction.swipecontrols.patch.resource.SwipeControlsResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playeroverlay.patch.PlayerOverlaysHookPatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.immutable.ImmutableMethod
@Patch @Patch
@Name("swipe-controls") @Name("swipe-controls")
@Description("Adds volume and brightness swipe controls.") @Description("Adds volume and brightness swipe controls.")
@SwipeControlsCompatibility @SwipeControlsCompatibility
@Version("0.0.2") @Version("0.0.3")
@DependsOn( @DependsOn(
[ [
IntegrationsPatch::class, IntegrationsPatch::class,
PlayerTypeHookPatch::class, PlayerTypeHookPatch::class,
PlayerOverlaysHookPatch::class,
SwipeControlsResourcePatch::class SwipeControlsResourcePatch::class
] ]
) )
class SwipeControlsBytecodePatch : BytecodePatch( class SwipeControlsBytecodePatch : BytecodePatch(
listOf( listOf(
WatchWhileOnStartFingerprint WatchWhileActivityFingerprint,
SwipeControlsHostActivityFingerprint
) )
) { ) {
override fun execute(data: BytecodeData): PatchResult { override fun execute(data: BytecodeData): PatchResult {
WatchWhileOnStartFingerprint.result!!.mutableMethod.addInstruction( val wrapperClass = SwipeControlsHostActivityFingerprint.result!!.mutableClass
0, val targetClass = WatchWhileActivityFingerprint.result!!.mutableClass
"invoke-static { p0 }, Lapp/revanced/integrations/patches/SwipeControlsPatch;->WatchWhileActivity_onStartHookEX(Ljava/lang/Object;)V"
) // inject the wrapper class from integrations into the class hierarchy of WatchWhileActivity
wrapperClass.setSuperClass(targetClass.superclass)
targetClass.setSuperClass(wrapperClass.type)
// ensure all classes and methods in the hierarchy are non-final, so we can override them in integrations
data.traverseClassHierarchy(targetClass) {
accessFlags = accessFlags and AccessFlags.FINAL.value.inv()
transformMethods {
ImmutableMethod(
definingClass,
name,
parameters,
returnType,
accessFlags and AccessFlags.FINAL.value.inv(),
annotations,
hiddenApiRestrictions,
implementation
).toMutable()
}
}
return PatchResultSuccess() return PatchResultSuccess()
} }
} }

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility(
[Package(
"com.google.android.youtube", arrayOf("17.26.35", "17.29.34")
)]
)
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
internal annotation class TabletMiniPlayerCompatibility

View File

@@ -0,0 +1,41 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("mini-player-dimensions-calculator-fingerprint")
@MatchingMethod(
"Lkkr;", "pM"
)
@FuzzyPatternScanMethod(2) // TODO: Find a good threshold value
@TabletMiniPlayerCompatibility
@Version("0.0.1")
object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint(
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("L"),
listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.MUL_FLOAT,
Opcode.INVOKE_INTERFACE,
Opcode.IGET_BOOLEAN,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.INVOKE_DIRECT,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.FLOAT_TO_DOUBLE,
Opcode.CONST_WIDE_HIGH16,
Opcode.CMPL_DOUBLE,
)
)

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("mini-player-override-fingerprint")
@MatchingMethod(
"Lkkr;", "j"
)
@TabletMiniPlayerCompatibility
@Version("0.0.1")
object MiniPlayerOverrideFingerprint : MethodFingerprint(
"Z", AccessFlags.STATIC or AccessFlags.PUBLIC ,null,
listOf(Opcode.RETURN), // anchor to insert the instruction
)

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("mini-player-override-no-context-fingerprint")
@MatchingMethod(
"Lkkr;", "k"
)
@TabletMiniPlayerCompatibility
@Version("0.0.1")
object MiniPlayerOverrideNoContextFingerprint : MethodFingerprint(
"Z", AccessFlags.FINAL or AccessFlags.PRIVATE ,null,
listOf(Opcode.RETURN), // anchor to insert the instruction
)

View File

@@ -0,0 +1,37 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@Name("mini-player-response-model-size-check-fingerprint")
@MatchingMethod(
"Lenv;", "a"
)
@TabletMiniPlayerCompatibility
@Version("0.0.1")
object MiniPlayerResponseModelSizeCheckFingerprint : MethodFingerprint(
"L",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("L", "L"),
listOf(
Opcode.OR_INT_LIT8,
Opcode.IPUT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.RETURN_OBJECT,
Opcode.RETURN_OBJECT,
Opcode.CHECK_CAST,
Opcode.CHECK_CAST,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
),
null
)

View File

@@ -0,0 +1,92 @@
package app.revanced.patches.youtube.layout.tabletminiplayer.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerDimensionsCalculatorFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideNoContextFingerprint
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerResponseModelSizeCheckFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch
@DependsOn([IntegrationsPatch::class])
@Name("tablet-mini-player")
@Description("Enables the tablet mini player layout.")
@TabletMiniPlayerCompatibility
@Version("0.0.1")
class TabletMiniPlayerPatch : BytecodePatch(
listOf(
MiniPlayerDimensionsCalculatorFingerprint,
MiniPlayerResponseModelSizeCheckFingerprint
)
) {
override fun execute(data: BytecodeData): PatchResult {
// first resolve the fingerprints via the parent fingerprint
val miniPlayerClass = MiniPlayerDimensionsCalculatorFingerprint.result!!.classDef
/*
* no context parameter method
*/
MiniPlayerOverrideNoContextFingerprint.resolve(data, miniPlayerClass)
val (method, _, parameterRegister) = MiniPlayerOverrideNoContextFingerprint.addProxyCall()
// - 1 means to insert before the return instruction
val secondInsertIndex = method.implementation!!.instructions.size - 1
method.insertOverride(secondInsertIndex, parameterRegister /** same register used to return **/)
/*
* method with context parameter
*/
MiniPlayerOverrideFingerprint.resolve(data, miniPlayerClass)
val (_, _, _) = MiniPlayerOverrideFingerprint.addProxyCall()
/*
* size check return value override
*/
val (_, _, _) = MiniPlayerResponseModelSizeCheckFingerprint.addProxyCall()
return PatchResultSuccess()
}
// helper methods
private companion object {
fun MethodFingerprint.addProxyCall(): Triple<MutableMethod, Int, Int> {
val (method, scanIndex, parameterRegister) = this.unwrap()
method.insertOverride(scanIndex, parameterRegister)
return Triple(method, scanIndex, parameterRegister)
}
fun MutableMethod.insertOverride(index: Int, overrideRegister: Int) {
this.addInstructions(
index,
"""
invoke-static {v$overrideRegister}, Lapp/revanced/integrations/patches/TabletMiniPlayerOverridePatch;->getTabletMiniPlayerOverride(Z)Z
move-result v$overrideRegister
"""
)
}
fun MethodFingerprint.unwrap(): Triple<MutableMethod, Int, Int> {
val result = this.result!!
val scanIndex = result.patternScanResult!!.endIndex
val method = result.mutableMethod
val instructions = method.implementation!!.instructions
val parameterRegister = (instructions[scanIndex] as OneRegisterInstruction).registerA
return Triple(method, scanIndex, parameterRegister)
}
}
}

View File

@@ -26,13 +26,13 @@ class CustomVideoBufferPatch : BytecodePatch(
) )
) { ) {
override fun execute(data: BytecodeData): PatchResult { override fun execute(data: BytecodeData): PatchResult {
execMaxBuffer(data) execMaxBuffer()
execPlaybackBuffer(data) execPlaybackBuffer(data)
execReBuffer(data) execReBuffer(data)
return PatchResultSuccess() return PatchResultSuccess()
} }
private fun execMaxBuffer(data: BytecodeData) { private fun execMaxBuffer() {
val result = MaxBufferFingerprint.result!! val result = MaxBufferFingerprint.result!!
val method = result.mutableMethod val method = result.mutableMethod
val index = result.patternScanResult!!.endIndex - 1 val index = result.patternScanResult!!.endIndex - 1

View File

@@ -139,7 +139,7 @@
<SwitchPreference android:title="@string/revanced_branding_watermark_title" android:key="revanced_branding_watermark_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_branding_watermark_summary_on" android:summaryOff="@string/revanced_branding_watermark_summary_off" /> <SwitchPreference android:title="@string/revanced_branding_watermark_title" android:key="revanced_branding_watermark_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_branding_watermark_summary_on" android:summaryOff="@string/revanced_branding_watermark_summary_off" />
<SwitchPreference android:title="@string/revanced_cast_button_title" android:key="revanced_cast_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_cast_button_summary_on" android:summaryOff="@string/revanced_cast_button_summary_off" /> <SwitchPreference android:title="@string/revanced_cast_button_title" android:key="revanced_cast_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_cast_button_summary_on" android:summaryOff="@string/revanced_cast_button_summary_off" />
<SwitchPreference android:title="@string/revanced_autoplay_button_title" android:key="revanced_autoplay_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_autoplay_button_summary_on" android:summaryOff="@string/revanced_autoplay_button_summary_off" /> <SwitchPreference android:title="@string/revanced_autoplay_button_title" android:key="revanced_autoplay_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_autoplay_button_summary_on" android:summaryOff="@string/revanced_autoplay_button_summary_off" />
<!--<SwitchPreference android:title="@string/revanced_tablet_miniplayer_title" android:key="revanced_tablet_miniplayer" android:defaultValue="false" android:summaryOn="@string/revanced_tablet_miniplayer_summary_on" android:summaryOff="@string/revanced_tablet_miniplayer_summary_off" />--> <SwitchPreference android:title="@string/revanced_tablet_miniplayer_title" android:key="revanced_tablet_miniplayer" android:defaultValue="false" android:summaryOn="@string/revanced_tablet_miniplayer_summary_on" android:summaryOff="@string/revanced_tablet_miniplayer_summary_off" />
<SwitchPreference android:title="@string/revanced_create_button_title" android:key="revanced_create_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_create_button_summary_on" android:summaryOff="@string/revanced_create_button_summary_off" /> <SwitchPreference android:title="@string/revanced_create_button_title" android:key="revanced_create_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_create_button_summary_on" android:summaryOff="@string/revanced_create_button_summary_off" />
<SwitchPreference android:title="@string/revanced_new_actionbar_title" android:key="revanced_new_actionbar" android:defaultValue="false" android:summaryOn="@string/revanced_new_actionbar_summary_on" android:summaryOff="@string/revanced_new_actionbar_summary_off" /> <SwitchPreference android:title="@string/revanced_new_actionbar_title" android:key="revanced_new_actionbar" android:defaultValue="false" android:summaryOn="@string/revanced_new_actionbar_summary_on" android:summaryOff="@string/revanced_new_actionbar_summary_off" />
<SwitchPreference android:title="@string/revanced_shorts_button_title" android:key="revanced_shorts_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_shorts_button_summary_on" android:summaryOff="@string/revanced_shorts_button_summary_off" /> <SwitchPreference android:title="@string/revanced_shorts_button_title" android:key="revanced_shorts_button_enabled" android:defaultValue="false" android:summaryOn="@string/revanced_shorts_button_summary_on" android:summaryOff="@string/revanced_shorts_button_summary_off" />