build(Needs bump): Bump dependencies (#2946)

Co-authored-by: Ushie <ushiekane@gmail.com>
Co-authored-by: aAbed <aabedhkhan@gmail.com>
Co-authored-by: CnC-Robert <CnC.Rob3rt@gmail.com>
This commit is contained in:
oSumAtrIX
2023-09-20 06:27:29 +02:00
co-authored by Ushie aAbed CnC-Robert
parent fe3a6fd4a4
commit 8c8dff9078
445 changed files with 4668 additions and 5477 deletions
@@ -1,32 +1,42 @@
package app.revanced.patches.youtube.misc.autorepeat.patch
package app.revanced.patches.youtube.misc.autorepeat
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFingerprint
import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParentFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch
@DependsOn([IntegrationsPatch::class])
@Name("Always autorepeat")
@Description("Always repeats the playing video again.")
@AutoRepeatCompatibility
class AutoRepeatPatch : BytecodePatch(
listOf(
AutoRepeatParentFingerprint
)
@Patch(
name = "Always autorepeat",
description = "Always repeats the playing video again.",
dependencies = [IntegrationsPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.16.37",
"18.19.35",
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
]
)
]
)
@Suppress("unused")
object AutoRepeatPatch : BytecodePatch(
setOf(AutoRepeatParentFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.autorepeat.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class AutoRepeatCompatibility
@@ -1,23 +1,22 @@
package app.revanced.patches.youtube.misc.debugging.patch
package app.revanced.patches.youtube.misc.debugging
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.debugging.annotations.DebuggingCompatibility
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
@Patch
@Name("Enable debugging")
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
@Description("Adds debugging options.")
@DebuggingCompatibility
class DebuggingPatch : ResourcePatch {
@Patch(
name = "Enable debugging",
description = "Adds debugging options.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [CompatiblePackage("com.google.android.youtube")]
)
@Suppress("unused")
object DebuggingPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
app.revanced.patches.shared.settings.preference.impl.PreferenceScreen(
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.debugging.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube")])
@Target(AnnotationTarget.CLASS)
internal annotation class DebuggingCompatibility
@@ -1,25 +1,24 @@
package app.revanced.patches.youtube.misc.fix.backtoexitgesture.patch
package app.revanced.patches.youtube.misc.fix.backtoexitgesture
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation.FixBackToExitGestureCompatibility
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.OnBackPressedFingerprint
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewScrollingFingerprint
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewTopScrollingFingerprint
import app.revanced.patches.youtube.misc.fix.backtoexitgesture.fingerprints.RecyclerViewTopScrollingParentFingerprint
@Description("Fixes the swipe back to exit gesture.")
@FixBackToExitGestureCompatibility
class FixBackToExitGesturePatch : BytecodePatch(
listOf(
@Patch(description = "Fixes the swipe back to exit gesture.")
@Suppress("unused")
object FixBackToExitGesturePatch : BytecodePatch(
setOf(
RecyclerViewTopScrollingParentFingerprint,
RecyclerViewScrollingFingerprint,
OnBackPressedFingerprint,
OnBackPressedFingerprint
)
) {
override fun execute(context: BytecodeContext) {
@@ -44,30 +43,28 @@ class FixBackToExitGesturePatch : BytecodePatch(
).forEach { (fingerprint, target) -> fingerprint.injectCall(target) }
}
private companion object {
/**
* A reference to a method from the integrations for [FixBackToExitGesturePatch].
*
* @param register The method registers.
* @param methodName The method name.
* @param parameterTypes The parameters of the method.
*/
data class IntegrationsMethod(
val register: String = "", val methodName: String, val parameterTypes: String = ""
) {
override fun toString() =
"invoke-static {$register}, Lapp/revanced/integrations/patches/FixBackToExitGesturePatch;->$methodName($parameterTypes)V"
}
/**
* Inject a call to a method from the integrations.
*
* @param targetMethod The target method to call.
*/
fun MethodFingerprint.injectCall(targetMethod: IntegrationsMethod) = result?.apply {
mutableMethod.addInstruction(
scanResult.patternScanResult!!.endIndex, targetMethod.toString()
)
} ?: throw this.exception
/**
* Inject a call to a method from the integrations.
*
* @param targetMethod The target method to call.
*/
fun MethodFingerprint.injectCall(targetMethod: IntegrationsMethod) = result?.apply {
mutableMethod.addInstruction(
scanResult.patternScanResult!!.endIndex, targetMethod.toString()
)
} ?: throw this.exception
/**
* A reference to a method from the integrations for [FixBackToExitGesturePatch].
*
* @param register The method registers.
* @param methodName The method name.
* @param parameterTypes The parameters of the method.
*/
data class IntegrationsMethod(
val register: String = "", val methodName: String, val parameterTypes: String = ""
) {
override fun toString() =
"invoke-static {$register}, Lapp/revanced/integrations/patches/FixBackToExitGesturePatch;->$methodName($parameterTypes)V"
}
}
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.fix.backtoexitgesture.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class FixBackToExitGestureCompatibility
@@ -1,26 +1,39 @@
package app.revanced.patches.youtube.misc.fix.playback.patch
package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.youtube.misc.fix.playback.annotations.ClientSpoofCompatibility
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.UserAgentHeaderBuilderFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch
@Name("Client spoof")
@Description("Spoofs the client to allow playback.")
@ClientSpoofCompatibility
@DependsOn([SpoofSignatureVerificationPatch::class])
class ClientSpoofPatch : BytecodePatch(
listOf(UserAgentHeaderBuilderFingerprint)
@Patch(
name = "Client spoof",
description = "Spoofs the client to allow playback.",
dependencies = [SpoofSignatureVerificationPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.16.37",
"18.19.35",
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
]
)
]
)
object ClientSpoofPatch : BytecodePatch(
setOf(UserAgentHeaderBuilderFingerprint)
) {
private const val ORIGINAL_PACKAGE_NAME = "com.google.android.youtube"
override fun execute(context: BytecodeContext) {
UserAgentHeaderBuilderFingerprint.result?.let { result ->
val insertIndex = result.scanResult.patternScanResult!!.endIndex
@@ -32,8 +45,4 @@ class ClientSpoofPatch : BytecodePatch(
} ?: throw UserAgentHeaderBuilderFingerprint.exception
}
private companion object {
private const val ORIGINAL_PACKAGE_NAME = "com.google.android.youtube"
}
}
@@ -1,38 +1,40 @@
package app.revanced.patches.youtube.misc.fix.playback.patch
package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ProtobufParameterBuilderFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ScrubbedPreviewLayoutFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailFingerprint
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailParentFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Name("Spoof signature verification")
@Description("Spoofs the client to prevent playback issues.")
@DependsOn([
SpoofSignatureVerificationResourcePatch::class,
IntegrationsPatch::class,
PlayerTypeHookPatch::class
])
class SpoofSignatureVerificationPatch : BytecodePatch(
listOf(
@Patch(
description = "Spoofs the client to prevent playback issues.",
dependencies = [
SpoofSignatureVerificationResourcePatch::class,
IntegrationsPatch::class,
PlayerTypeHookPatch::class
]
)
object SpoofSignatureVerificationPatch : BytecodePatch(
setOf(
ProtobufParameterBuilderFingerprint,
StoryboardThumbnailParentFingerprint,
ScrubbedPreviewLayoutFingerprint,
ScrubbedPreviewLayoutFingerprint
)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/SpoofSignatureVerificationPatch;"
override fun execute(context: BytecodeContext) {
// hook parameter
@@ -101,8 +103,4 @@ class SpoofSignatureVerificationPatch : BytecodePatch(
}
} ?: throw ScrubbedPreviewLayoutFingerprint.exception
}
private companion object {
const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SpoofSignatureVerificationPatch;"
}
}
@@ -1,15 +1,16 @@
package app.revanced.patches.youtube.misc.fix.playback.patch
package app.revanced.patches.youtube.misc.fix.playback
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
class SpoofSignatureVerificationResourcePatch : ResourcePatch {
@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class])
object SpoofSignatureVerificationResourcePatch : ResourcePatch() {
internal var scrubbedPreviewThumbnailResourceId: Long = -1
override fun execute(context: ResourceContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
@@ -32,8 +33,4 @@ class SpoofSignatureVerificationResourcePatch : ResourcePatch {
it.type == "id" && it.name == "thumbnail"
}.id
}
companion object {
var scrubbedPreviewThumbnailResourceId: Long = -1
}
}
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.fix.playback.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class ClientSpoofCompatibility
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.misc.fix.playback.patch.SpoofSignatureVerificationResourcePatch
import app.revanced.patches.youtube.misc.fix.playback.SpoofSignatureVerificationResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -23,5 +23,5 @@ object ScrubbedPreviewLayoutFingerprint : LiteralValueFingerprint(
Opcode.IPUT_OBJECT, // preview imageview
),
// This resource is used in ~ 40 different locations, but this method has a distinct list of parameters to match to.
literal = SpoofSignatureVerificationResourcePatch.scrubbedPreviewThumbnailResourceId
literalSupplier = { SpoofSignatureVerificationResourcePatch.scrubbedPreviewThumbnailResourceId }
)
@@ -1,15 +1,13 @@
package app.revanced.patches.youtube.misc.integrations.patch
package app.revanced.patches.youtube.misc.integrations
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch
import app.revanced.patches.youtube.misc.integrations.fingerprints.*
@Name("Integrations")
@RequiresIntegrations
class IntegrationsPatch : AbstractIntegrationsPatch(
@Patch(requiresIntegrations = true)
object IntegrationsPatch : AbstractIntegrationsPatch(
"Lapp/revanced/integrations/utils/ReVancedUtils;",
listOf(
setOf(
ApplicationInitFingerprint,
StandalonePlayerActivityFingerprint,
RemoteEmbeddedPlayerFingerprint,
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
@@ -1,6 +1,6 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
/**
* Hooks the context when the app is launched as a regular application (and is not an embedded video playback).
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
@@ -1,7 +1,7 @@
package app.revanced.patches.youtube.misc.integrations.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint
import app.revanced.patches.shared.integrations.AbstractIntegrationsPatch.IntegrationsFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
/**
@@ -1,15 +1,13 @@
package app.revanced.patches.youtube.misc.links.patch
package app.revanced.patches.youtube.misc.links
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.links.annotations.OpenLinksExternallyCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.patch.AbstractTransformInstructionsPatch
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
@@ -18,11 +16,13 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
@Patch
@Name("Open links externally")
@Description("Open links outside of the app directly in your browser.")
@OpenLinksExternallyCompatibility
class OpenLinksExternallyPatch : AbstractTransformInstructionsPatch<Pair<Int, Int>>(
@Patch(
name = "Open links externally",
description = "Open links outside of the app directly in your browser.",
compatiblePackages = [CompatiblePackage("com.google.android.youtube", ["18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"])]
)
@Suppress("unused")
object OpenLinksExternallyPatch : AbstractTransformInstructionsPatch<Pair<Int, Int>>(
) {
override fun filterMap(
classDef: ClassDef, method: Method, instruction: Instruction, instructionIndex: Int
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.links.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class OpenLinksExternallyCompatibility
@@ -1,7 +1,6 @@
package app.revanced.patches.youtube.misc.litho.filter.patch
package app.revanced.patches.youtube.misc.litho.filter
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@@ -12,9 +11,9 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.*
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
@@ -22,11 +21,30 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import java.io.Closeable
@DependsOn([IntegrationsPatch::class])
@Description("Hooks the method which parses the bytes into a ComponentContext to filter components.")
class LithoFilterPatch : BytecodePatch(
listOf(ComponentContextParserFingerprint, LithoFilterFingerprint, ProtobufBufferReferenceFingerprint)
@Patch(
description = "Hooks the method which parses the bytes into a ComponentContext to filter components.",
dependencies = [IntegrationsPatch::class]
)
@Suppress("unused")
object LithoFilterPatch : BytecodePatch(
setOf(ComponentContextParserFingerprint, LithoFilterFingerprint, ProtobufBufferReferenceFingerprint)
), Closeable {
private val MethodFingerprint.patternScanResult
get() = result!!.scanResult.patternScanResult!!
private val MethodFingerprint.patternScanEndIndex
get() = patternScanResult.endIndex
private val Instruction.descriptor
get() = (this as ReferenceInstruction).reference.toString()
const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/LithoFilterPatch;"
internal lateinit var addFilter: (String) -> Unit
private set
private var filterCount = 0
/**
* The following patch inserts a hook into the method that parses the bytes into a ComponentContext.
* This method contains a StringBuilder object that represents the pathBuilder of the component.
@@ -162,22 +180,4 @@ class LithoFilterPatch : BytecodePatch(
override fun close() = LithoFilterFingerprint.result!!
.mutableMethod.replaceInstruction(0, "const/16 v0, $filterCount")
companion object {
private val MethodFingerprint.patternScanResult
get() = result!!.scanResult.patternScanResult!!
private val MethodFingerprint.patternScanEndIndex
get() = patternScanResult.endIndex
private val Instruction.descriptor
get() = (this as ReferenceInstruction).reference.toString()
const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/LithoFilterPatch;"
internal lateinit var addFilter: (String) -> Unit
private set
private var filterCount = 0
}
}
@@ -1,34 +1,41 @@
package app.revanced.patches.youtube.misc.microg.patch.bytecode
package app.revanced.patches.youtube.misc.microg
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.fingerprints.WatchWhileActivityFingerprint
import app.revanced.patches.youtube.layout.buttons.cast.patch.HideCastButtonPatch
import app.revanced.patches.youtube.misc.fix.playback.patch.ClientSpoofPatch
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
import app.revanced.patches.youtube.layout.buttons.cast.HideCastButtonPatch
import app.revanced.patches.youtube.misc.fix.playback.ClientSpoofPatch
import app.revanced.patches.youtube.misc.microg.fingerprints.*
import app.revanced.patches.youtube.misc.microg.patch.resource.MicroGResourcePatch
import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
import app.revanced.util.microg.MicroGBytecodeHelper
@Patch
@DependsOn(
[
@Patch(
name = "Vanced MicroG support",
description = "Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.",
dependencies = [
MicroGResourcePatch::class,
HideCastButtonPatch::class,
ClientSpoofPatch::class
],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube", [
"18.16.37",
"18.19.35",
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
]
)
]
)
@Name("Vanced MicroG support")
@Description("Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.")
@MicroGPatchCompatibility
class MicroGBytecodePatch : BytecodePatch(
listOf(
@Suppress("unused")
object MicroGBytecodePatch : BytecodePatch(
setOf(
ServiceCheckFingerprint,
GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint,
@@ -1,8 +1,8 @@
package app.revanced.patches.youtube.misc.microg.patch.resource
package app.revanced.patches.youtube.misc.microg
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME
@@ -10,14 +10,13 @@ import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_APP_NA
import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME
import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_SIGNATURE
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.microg.Constants.MICROG_VENDOR
import app.revanced.util.microg.MicroGManifestHelper
import app.revanced.util.microg.MicroGResourceHelper
@DependsOn([SettingsResourcePatch::class])
class MicroGResourcePatch : ResourcePatch {
@Patch(dependencies = [SettingsPatch::class])
object MicroGResourcePatch : ResourcePatch() {
override fun execute(context: ResourceContext) {
SettingsPatch.addPreference(
Preference(
@@ -1,8 +0,0 @@
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("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class MicroGPatchCompatibility
@@ -1,47 +1,63 @@
package app.revanced.patches.youtube.misc.minimizedplayback.patch
package app.revanced.patches.youtube.misc.minimizedplayback
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.settings.preference.impl.NonInteractivePreference
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.KidsMinimizedPlaybackPolicyControllerFingerprint
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackSettingsFingerprint
import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackSettingsParentFingerprint
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch
@Name("Minimized playback")
@Description("Enables minimized and background playback.")
@DependsOn([IntegrationsPatch::class, PlayerTypeHookPatch::class, SettingsPatch::class])
@MinimizedPlaybackCompatibility
class MinimizedPlaybackPatch : BytecodePatch(
listOf(
@Patch(
name = "Minimized playback",
description = "Enables minimized and background playback.",
dependencies = [IntegrationsPatch::class, PlayerTypeHookPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.16.37",
"18.19.35",
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
]
)
]
)
@Suppress("unused")
object MinimizedPlaybackPatch : BytecodePatch(
setOf(
MinimizedPlaybackManagerFingerprint,
MinimizedPlaybackSettingsParentFingerprint,
KidsMinimizedPlaybackPolicyControllerFingerprint
)
) {
const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;"
override fun execute(context: BytecodeContext) {
// TODO: remove this empty preference sometime after mid 2023
SettingsPatch.PreferenceScreen.MISC.addPreferences(
NonInteractivePreference(
StringResource("revanced_minimized_playback_enabled_title", "Minimized playback"),
StringResource("revanced_minimized_playback_summary_on", "This setting can be found in Settings -> Background")
StringResource(
"revanced_minimized_playback_summary_on",
"This setting can be found in Settings -> Background"
)
)
)
@@ -58,7 +74,10 @@ class MinimizedPlaybackPatch : BytecodePatch(
// Enable minimized playback option in YouTube settings
MinimizedPlaybackSettingsParentFingerprint.result ?: throw MinimizedPlaybackSettingsParentFingerprint.exception
MinimizedPlaybackSettingsFingerprint.resolve(context, MinimizedPlaybackSettingsParentFingerprint.result!!.classDef)
MinimizedPlaybackSettingsFingerprint.resolve(
context,
MinimizedPlaybackSettingsParentFingerprint.result!!.classDef
)
MinimizedPlaybackSettingsFingerprint.result?.apply {
val booleanCalls = method.implementation!!.instructions.withIndex()
.filter { ((it.value as? ReferenceInstruction)?.reference as? MethodReference)?.returnType == "Z" }
@@ -86,8 +105,4 @@ class MinimizedPlaybackPatch : BytecodePatch(
)
} ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception
}
private companion object {
const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;"
}
}
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.minimizedplayback.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class MinimizedPlaybackCompatibility
@@ -0,0 +1,75 @@
package app.revanced.patches.youtube.misc.playercontrols
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.DomFileEditor
import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import java.io.Closeable
@Patch(dependencies = [ResourceMappingPatch::class])
object BottomControlsResourcePatch : ResourcePatch(), Closeable {
internal var bottomUiContainerResourceId: Long = -1
internal const val TARGET_RESOURCE_NAME = "youtube_controls_bottom_ui_container.xml"
private const val TARGET_RESOURCE = "res/layout/$TARGET_RESOURCE_NAME"
private lateinit var resourceContext: ResourceContext
private lateinit var targetXmlEditor: DomFileEditor
// The element to which to add the new elements to
private var lastLeftOf = "fullscreen_button"
override fun execute(context: ResourceContext) {
resourceContext = context
targetXmlEditor = context.xmlEditor[TARGET_RESOURCE]
bottomUiContainerResourceId = ResourceMappingPatch.resourceMappings
.single { it.type == "id" && it.name == "bottom_ui_container_stub" }.id
}
/**
* Add new controls to the bottom of the YouTube player.
* @param hostYouTubeControlsBottomUiResourceName The hosting resource name containing the elements.
*/
internal fun addControls(hostYouTubeControlsBottomUiResourceName: String) {
val sourceXmlEditor =
resourceContext.xmlEditor[this::class.java.classLoader.getResourceAsStream(
hostYouTubeControlsBottomUiResourceName
)!!]
val targetElement =
"android.support.constraint.ConstraintLayout"
val hostElements = sourceXmlEditor.file.getElementsByTagName(targetElement).item(0).childNodes
val destinationResourceFile = targetXmlEditor.file
val destinationElement =
destinationResourceFile.getElementsByTagName(targetElement).item(0)
for (index in 1 until hostElements.length) {
val element = hostElements.item(index).cloneNode(true)
// if the element has no attributes theres no point to adding it to the destination
if (!element.hasAttributes()) continue
// set the elements lastLeftOf attribute to the lastLeftOf value
val namespace = "@+id"
element.attributes.getNamedItem("yt:layout_constraintRight_toLeftOf").nodeValue =
"$namespace/$lastLeftOf"
// set lastLeftOf attribute to the current element
val nameSpaceLength = 5
lastLeftOf = element.attributes.getNamedItem("android:id").nodeValue.substring(nameSpaceLength)
// copy the element
destinationResourceFile.adoptNode(element)
destinationElement.appendChild(element)
}
sourceXmlEditor.close()
}
override fun close() {
targetXmlEditor.close()
}
}
@@ -0,0 +1,69 @@
package app.revanced.patches.youtube.misc.playercontrols
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
import app.revanced.patches.youtube.misc.playercontrols.fingerprints.BottomControlsInflateFingerprint
import app.revanced.patches.youtube.misc.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
description = "Manages the code for the player controls of the YouTube player.",
dependencies = [BottomControlsResourcePatch::class],
)
object PlayerControlsBytecodePatch : BytecodePatch(
setOf(LayoutConstructorFingerprint, BottomControlsInflateFingerprint)
) {
lateinit var showPlayerControlsFingerprintResult: MethodFingerprintResult
private var moveToRegisterInstructionIndex: Int = 0
private var viewRegister: Int = 0
override fun execute(context: BytecodeContext) {
LayoutConstructorFingerprint.result?.let {
if (!PlayerControlsVisibilityFingerprint.resolve(context, it.classDef))
throw LayoutConstructorFingerprint.exception
} ?: throw LayoutConstructorFingerprint.exception
showPlayerControlsFingerprintResult = PlayerControlsVisibilityFingerprint.result!!
inflateFingerprintResult = BottomControlsInflateFingerprint.result!!
}
private var inflateFingerprintResult: MethodFingerprintResult? = null
set(fingerprint) {
field = fingerprint!!.also {
moveToRegisterInstructionIndex = it.scanResult.patternScanResult!!.endIndex
viewRegister =
(it.mutableMethod.implementation!!.instructions[moveToRegisterInstructionIndex] as OneRegisterInstruction).registerA
}
}
/**
* Injects the code to change the visibility of controls.
* @param descriptor The descriptor of the method which should be called.
*/
fun injectVisibilityCheckCall(descriptor: String) {
showPlayerControlsFingerprintResult.mutableMethod.addInstruction(
0,
"""
invoke-static {p1}, $descriptor
"""
)
}
/**
* Injects the code to initialize the controls.
* @param descriptor The descriptor of the method which should be calleed.
*/
fun initializeControl(descriptor: String) {
inflateFingerprintResult!!.mutableMethod.addInstruction(
moveToRegisterInstructionIndex + 1,
"invoke-static {v$viewRegister}, $descriptor"
)
}
}
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.playercontrols.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerControlsCompatibility
@@ -1,79 +0,0 @@
package app.revanced.patches.youtube.misc.playercontrols.bytecode.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility
import app.revanced.patches.youtube.misc.playercontrols.fingerprints.BottomControlsInflateFingerprint
import app.revanced.patches.youtube.misc.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint
import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Name("Player controls bytecode patch")
@DependsOn([BottomControlsResourcePatch::class])
@Description("Manages the code for the player controls of the YouTube player.")
@PlayerControlsCompatibility
class PlayerControlsBytecodePatch : BytecodePatch(
listOf(
LayoutConstructorFingerprint,
BottomControlsInflateFingerprint
)
) {
override fun execute(context: BytecodeContext) {
LayoutConstructorFingerprint.result?.let {
if (!PlayerControlsVisibilityFingerprint.resolve(context, it.classDef))
throw LayoutConstructorFingerprint.exception
} ?: throw LayoutConstructorFingerprint.exception
showPlayerControlsFingerprintResult = PlayerControlsVisibilityFingerprint.result!!
inflateFingerprintResult = BottomControlsInflateFingerprint.result!!
}
internal companion object {
lateinit var showPlayerControlsFingerprintResult: MethodFingerprintResult
private var inflateFingerprintResult: MethodFingerprintResult? = null
set(fingerprint) {
field = fingerprint!!.also {
moveToRegisterInstructionIndex = it.scanResult.patternScanResult!!.endIndex
viewRegister =
(it.mutableMethod.implementation!!.instructions[moveToRegisterInstructionIndex] as OneRegisterInstruction).registerA
}
}
private var moveToRegisterInstructionIndex: Int = 0
private var viewRegister: Int = 0
/**
* Injects the code to change the visibility of controls.
* @param descriptor The descriptor of the method which should be called.
*/
fun injectVisibilityCheckCall(descriptor: String) {
showPlayerControlsFingerprintResult.mutableMethod.addInstruction(
0,
"""
invoke-static {p1}, $descriptor
"""
)
}
/**
* Injects the code to initialize the controls.
* @param descriptor The descriptor of the method which should be calleed.
*/
fun initializeControl(descriptor: String) {
inflateFingerprintResult!!.mutableMethod.addInstruction(
moveToRegisterInstructionIndex + 1,
"invoke-static {v$viewRegister}, $descriptor"
)
}
}
}
@@ -1,8 +1,8 @@
package app.revanced.patches.youtube.misc.playercontrols.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -15,5 +15,5 @@ object BottomControlsInflateFingerprint : LiteralValueFingerprint(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
literal = BottomControlsResourcePatch.bottomUiContainerResourceId
literalSupplier = { BottomControlsResourcePatch.bottomUiContainerResourceId }
)
@@ -1,77 +0,0 @@
package app.revanced.patches.youtube.misc.playercontrols.resource.patch
import app.revanced.patcher.util.DomFileEditor
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import java.io.Closeable
@DependsOn([ResourceMappingPatch::class])
class BottomControlsResourcePatch : ResourcePatch, Closeable {
override fun execute(context: ResourceContext) {
resourceContext = context
targetXmlEditor = context.xmlEditor[TARGET_RESOURCE]
bottomUiContainerResourceId = ResourceMappingPatch.resourceMappings
.single { it.type == "id" && it.name == "bottom_ui_container_stub" }.id
}
companion object {
internal var bottomUiContainerResourceId : Long = -1
internal const val TARGET_RESOURCE_NAME = "youtube_controls_bottom_ui_container.xml"
private const val TARGET_RESOURCE = "res/layout/$TARGET_RESOURCE_NAME"
private lateinit var resourceContext: ResourceContext
private lateinit var targetXmlEditor: DomFileEditor
// The element to which to add the new elements to
private var lastLeftOf = "fullscreen_button"
/**
* Add new controls to the bottom of the YouTube player.
* @param hostYouTubeControlsBottomUiResourceName The hosting resource name containing the elements.
*/
internal fun addControls(hostYouTubeControlsBottomUiResourceName: String) {
val sourceXmlEditor =
resourceContext.xmlEditor[this::class.java.classLoader.getResourceAsStream(
hostYouTubeControlsBottomUiResourceName
)!!]
val targetElement =
"android.support.constraint.ConstraintLayout"
val hostElements = sourceXmlEditor.file.getElementsByTagName(targetElement).item(0).childNodes
val destinationResourceFile = this.targetXmlEditor.file
val destinationElement =
destinationResourceFile.getElementsByTagName(targetElement).item(0)
for (index in 1 until hostElements.length) {
val element = hostElements.item(index).cloneNode(true)
// if the element has no attributes theres no point to adding it to the destination
if (!element.hasAttributes()) continue
// set the elements lastLeftOf attribute to the lastLeftOf value
val namespace = "@+id"
element.attributes.getNamedItem("yt:layout_constraintRight_toLeftOf").nodeValue =
"$namespace/$lastLeftOf"
// set lastLeftOf attribute to the current element
val nameSpaceLength = 5
lastLeftOf = element.attributes.getNamedItem("android:id").nodeValue.substring(nameSpaceLength)
// copy the element
destinationResourceFile.adoptNode(element)
destinationElement.appendChild(element)
}
sourceXmlEditor.close()
}
}
override fun close() {
targetXmlEditor.close()
}
}
@@ -1,23 +1,30 @@
package app.revanced.patches.youtube.misc.playeroverlay.patch
package app.revanced.patches.youtube.misc.playeroverlay
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.playeroverlay.annotation.PlayerOverlaysHookCompatibility
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.playeroverlay.fingerprint.PlayerOverlaysOnFinishInflateFingerprint
@Name("Player overlays hook")
@Description("Hook for adding custom overlays to the video player.")
@PlayerOverlaysHookCompatibility
@DependsOn([IntegrationsPatch::class])
class PlayerOverlaysHookPatch : BytecodePatch(
listOf(
PlayerOverlaysOnFinishInflateFingerprint
)
@Patch(
description = "Hook for adding custom overlays to the video player.",
dependencies = [IntegrationsPatch::class],
compatiblePackages = [
CompatiblePackage("com.google.android.youtube", [
"18.16.37",
"18.19.35",
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
])
]
)
@Suppress("unused")
object PlayerOverlaysHookPatch : BytecodePatch(
setOf(PlayerOverlaysOnFinishInflateFingerprint)
) {
override fun execute(context: BytecodeContext) {
// hook YouTubePlayerOverlaysLayout.onFinishInflate()
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.playeroverlay.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerOverlaysHookCompatibility
@@ -1,25 +1,27 @@
package app.revanced.patches.youtube.misc.playertype.patch
package app.revanced.patches.youtube.misc.playertype
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.playertype.fingerprint.PlayerTypeFingerprint
import app.revanced.patches.youtube.misc.playertype.fingerprint.VideoStateFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Name("Player type hook")
@Description("Hook to get the current player type and video playback state.")
@DependsOn([IntegrationsPatch::class])
class PlayerTypeHookPatch : BytecodePatch(
listOf(PlayerTypeFingerprint, VideoStateFingerprint)
@Patch(
description = "Hook to get the current player type and video playback state.",
dependencies = [IntegrationsPatch::class]
)
object PlayerTypeHookPatch : BytecodePatch(
setOf(PlayerTypeFingerprint, VideoStateFingerprint)
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/PlayerTypeHookPatch;"
override fun execute(context: BytecodeContext) {
PlayerTypeFingerprint.result?.mutableMethod?.addInstruction(
0,
@@ -41,10 +43,4 @@ class PlayerTypeHookPatch : BytecodePatch(
}
} ?: throw VideoStateFingerprint.exception
}
companion object {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/PlayerTypeHookPatch;"
}
}
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.playertype.annotation
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"))])
@Target(AnnotationTarget.CLASS)
internal annotation class PlayerTypeHookCompatibility
@@ -1,17 +1,22 @@
package app.revanced.patches.youtube.misc.recyclerviewtree.hook.patch
package app.revanced.patches.youtube.misc.recyclerviewtree.hook
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.recyclerviewtree.hook.fingerprints.RecyclerViewTreeObserverFingerprint
@DependsOn([IntegrationsPatch::class])
class RecyclerViewTreeHookPatch : BytecodePatch(
listOf(RecyclerViewTreeObserverFingerprint)
@Patch(
dependencies = [IntegrationsPatch::class]
)
object RecyclerViewTreeHookPatch : BytecodePatch(
setOf(RecyclerViewTreeObserverFingerprint)
) {
internal lateinit var addHook: (String) -> Unit
private set
override fun execute(context: BytecodeContext) {
RecyclerViewTreeObserverFingerprint.result?.let {
@@ -27,11 +32,5 @@ class RecyclerViewTreeHookPatch : BytecodePatch(
}
}
} ?: throw RecyclerViewTreeObserverFingerprint.exception
}
internal companion object {
internal lateinit var addHook: (String) -> Unit
private set
}
}
@@ -1,39 +1,42 @@
package app.revanced.patches.youtube.misc.settings.bytecode.patch
package app.revanced.patches.youtube.misc.settings
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.Preference
import app.revanced.patches.shared.settings.util.AbstractPreferenceScreen
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.LicenseActivityFingerprint
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.SetThemeFingerprint
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.fingerprints.LicenseActivityFingerprint
import app.revanced.patches.youtube.misc.settings.fingerprints.SetThemeFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.io.Closeable
@DependsOn([IntegrationsPatch::class, SettingsResourcePatch::class])
@Name("Settings")
@Description("Adds settings for ReVanced to YouTube.")
class SettingsPatch : BytecodePatch(
listOf(LicenseActivityFingerprint, SetThemeFingerprint)
@Patch(
description = "Adds settings for ReVanced to YouTube.",
dependencies = [IntegrationsPatch::class, SettingsResourcePatch::class]
)
object SettingsPatch : BytecodePatch(
setOf(LicenseActivityFingerprint, SetThemeFingerprint)
), Closeable {
private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations"
private const val SETTINGS_ACTIVITY_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settingsmenu/ReVancedSettingActivity;"
private const val THEME_HELPER_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/utils/ThemeHelper;"
private const val SET_THEME_METHOD_NAME = "setTheme"
override fun execute(context: BytecodeContext) {
// TODO: Remove this when it is only required at one place.
fun getSetThemeInstructionString(
registers: String = "v0",
classDescriptor: String = THEME_HELPER_DESCRIPTOR,
methodName: String = SET_THEME_METHOD_NAME,
parameters: String = "Ljava/lang/Object;"
registers: String = "v0",
classDescriptor: String = THEME_HELPER_DESCRIPTOR,
methodName: String = SET_THEME_METHOD_NAME,
parameters: String = "Ljava/lang/Object;"
) = "invoke-static { $registers }, $classDescriptor->$methodName($parameters)V"
SetThemeFingerprint.result?.mutableMethod?.let { setThemeMethod ->
@@ -64,10 +67,10 @@ class SettingsPatch : BytecodePatch(
LicenseActivityFingerprint.result!!.apply licenseActivity@{
mutableMethod.apply {
fun buildSettingsActivityInvokeString(
registers: String = "p0",
classDescriptor: String = SETTINGS_ACTIVITY_DESCRIPTOR,
methodName: String = "initializeSettings",
parameters: String = "Landroid/app/Activity;"
registers: String = "p0",
classDescriptor: String = SETTINGS_ACTIVITY_DESCRIPTOR,
methodName: String = "initializeSettings",
parameters: String = "Landroid/app/Activity;"
) = getSetThemeInstructionString(registers, classDescriptor, methodName, parameters)
// initialize the settings
@@ -88,34 +91,27 @@ class SettingsPatch : BytecodePatch(
}
internal companion object {
private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations"
private const val SETTINGS_ACTIVITY_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settingsmenu/ReVancedSettingActivity;"
private const val THEME_HELPER_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/utils/ThemeHelper;"
private const val SET_THEME_METHOD_NAME = "setTheme"
fun addString(identifier: String, value: String, formatted: Boolean = true) =
SettingsResourcePatch.addString(identifier, value, formatted)
fun addString(identifier: String, value: String, formatted: Boolean = true) =
SettingsResourcePatch.addString(identifier, value, formatted)
fun addPreferenceScreen(preferenceScreen: app.revanced.patches.shared.settings.preference.impl.PreferenceScreen) =
SettingsResourcePatch.addPreferenceScreen(preferenceScreen)
fun addPreferenceScreen(preferenceScreen: app.revanced.patches.shared.settings.preference.impl.PreferenceScreen) =
SettingsResourcePatch.addPreferenceScreen(preferenceScreen)
fun addPreference(preference: Preference) = SettingsResourcePatch.addPreference(preference)
fun addPreference(preference: Preference) = SettingsResourcePatch.addPreference(preference)
fun renameIntentsTargetPackage(newPackage: String) {
SettingsResourcePatch.overrideIntentsTargetPackage = newPackage
}
/**
* Creates an intent to open ReVanced settings of the given name
*/
fun createReVancedSettingsIntent(settingsName: String) = Preference.Intent(
"com.google.android.youtube",
settingsName,
"com.google.android.libraries.social.licenses.LicenseActivity"
)
fun renameIntentsTargetPackage(newPackage: String) {
SettingsResourcePatch.overrideIntentsTargetPackage = newPackage
}
/**
* Creates an intent to open ReVanced settings of the given name
*/
fun createReVancedSettingsIntent(settingsName: String) = Preference.Intent(
"com.google.android.youtube",
settingsName,
"com.google.android.libraries.social.licenses.LicenseActivity"
)
/**
* Preference screens patches should add their settings to.
*/
@@ -1,24 +1,39 @@
package app.revanced.patches.youtube.misc.settings.resource.patch
package app.revanced.patches.youtube.misc.settings
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.DomFileEditor
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
import app.revanced.patches.shared.mapping.misc.ResourceMappingPatch
import app.revanced.patches.shared.settings.AbstractSettingsResourcePatch
import app.revanced.patches.shared.settings.preference.addPreference
import app.revanced.patches.shared.settings.preference.impl.*
import app.revanced.patches.shared.settings.resource.patch.AbstractSettingsResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.util.resources.ResourceUtils
import app.revanced.util.resources.ResourceUtils.copyResources
import app.revanced.util.resources.ResourceUtils.mergeStrings
import org.w3c.dom.Element
import org.w3c.dom.Node
@DependsOn([ResourceMappingPatch::class])
class SettingsResourcePatch : AbstractSettingsResourcePatch(
@Patch(
dependencies = [ResourceMappingPatch::class]
)
object SettingsResourcePatch : AbstractSettingsResourcePatch(
"revanced_prefs",
"settings"
) {
// Used for a fingerprint from SettingsPatch.
internal var appearanceStringId = -1L
// if this is not null, all intents will be renamed to this
internal var overrideIntentsTargetPackage: String? = null
private var preferencesNode: Node? = null
private var preferencesEditor: DomFileEditor? = null
set(value) {
field = value
preferencesNode = value.getNode("PreferenceScreen")
}
override fun execute(context: ResourceContext) {
super.execute(context)
@@ -88,57 +103,6 @@ class SettingsResourcePatch : AbstractSettingsResourcePatch(
context.mergeStrings("settings/host/values/strings.xml")
}
internal companion object {
// Used for a fingerprint from SettingsPatch.
internal var appearanceStringId = -1L
// if this is not null, all intents will be renamed to this
var overrideIntentsTargetPackage: String? = null
private var preferencesNode: Node? = null
private var preferencesEditor: DomFileEditor? = null
set(value) {
field = value
preferencesNode = value.getNode("PreferenceScreen")
}
/* Companion delegates */
/**
* Add a preference fragment to the main preferences.
*
* @param preference The preference to add.
*/
fun addPreference(preference: Preference) =
preferencesNode!!.addPreference(preference) { it.include() }
/**
* Add a new string to the resources.
*
* @param identifier The key of the string.
* @param value The value of the string.
* @throws IllegalArgumentException if the string already exists.
*/
fun addString(identifier: String, value: String, formatted: Boolean) =
AbstractSettingsResourcePatch.addString(identifier, value, formatted)
/**
* Add an array to the resources.
*
* @param arrayResource The array resource to add.
*/
fun addArray(arrayResource: ArrayResource) = AbstractSettingsResourcePatch.addArray(arrayResource)
/**
* Add a preference to the settings.
*
* @param preferenceScreen The name of the preference screen.
*/
fun addPreferenceScreen(preferenceScreen: PreferenceScreen) = addPreference(preferenceScreen)
}
override fun close() {
super.close()
@@ -169,4 +133,36 @@ class SettingsResourcePatch : AbstractSettingsResourcePatch(
preferencesEditor?.close()
}
/**
* Add a preference fragment to the main preferences.
*
* @param preference The preference to add.
*/
internal fun addPreference(preference: Preference) =
preferencesNode!!.addPreference(preference) { it.include() }
/**
* Add a new string to the resources.
*
* @param identifier The key of the string.
* @param value The value of the string.
* @throws IllegalArgumentException if the string already exists.
*/
internal fun addString(identifier: String, value: String, formatted: Boolean) =
AbstractSettingsResourcePatch.addString(identifier, value, formatted)
/**
* Add an array to the resources.
*
* @param arrayResource The array resource to add.
*/
internal fun addArray(arrayResource: ArrayResource) = AbstractSettingsResourcePatch.addArray(arrayResource)
/**
* Add a preference to the settings.
*
* @param preferenceScreen The name of the preference screen.
*/
internal fun addPreferenceScreen(preferenceScreen: PreferenceScreen) = addPreference(preferenceScreen)
}
@@ -1,4 +1,4 @@
package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
package app.revanced.patches.youtube.misc.settings.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
@@ -1,8 +1,8 @@
package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints
package app.revanced.patches.youtube.misc.settings.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.misc.settings.SettingsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@@ -11,5 +11,5 @@ object SetThemeFingerprint : LiteralValueFingerprint(
returnType = "L",
parameters = listOf(),
opcodes = listOf(Opcode.RETURN_OBJECT),
literal = SettingsResourcePatch.appearanceStringId
literalSupplier = { SettingsResourcePatch.appearanceStringId }
)
@@ -1,27 +1,26 @@
package app.revanced.patches.youtube.misc.zoomhaptics.patch
package app.revanced.patches.youtube.misc.zoomhaptics
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.zoomhaptics.annotations.ZoomHapticsCompatibility
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.patches.youtube.misc.zoomhaptics.fingerprints.ZoomHapticsFingerprint
@Patch
@Name("Disable zoom haptics")
@Description("Disables haptics when zooming.")
@DependsOn([SettingsPatch::class])
@ZoomHapticsCompatibility
class ZoomHapticsPatch : BytecodePatch(
listOf(ZoomHapticsFingerprint)
@Patch(
name = "Disable zoom haptics",
description = "Disables haptics when zooming.",
dependencies = [SettingsPatch::class],
compatiblePackages = [CompatiblePackage("com.google.android.youtube")]
)
@Suppress("unused")
object ZoomHapticsPatch : BytecodePatch(
setOf(ZoomHapticsFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
@@ -1,8 +0,0 @@
package app.revanced.patches.youtube.misc.zoomhaptics.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube")])
@Target(AnnotationTarget.CLASS)
internal annotation class ZoomHapticsCompatibility