Merge remote-tracking branch 'upstream/dev' into feat/patcher_instruction_filters

# Conflicts:
#	patches/src/main/kotlin/app/revanced/patches/instagram/hide/navigation/Fingerprints.kt
#	patches/src/main/kotlin/app/revanced/patches/music/misc/extension/hooks/ApplicationInitHook.kt
#	patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt
This commit is contained in:
LisoUseInAIKyrios 2025-09-23 22:07:21 +04:00
commit c4e6e62e71
29 changed files with 433 additions and 201 deletions

View file

@ -2,28 +2,22 @@
package app.revanced.patches.instagram.hide.navigation
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.Opcode
import app.revanced.patcher.patch.BytecodePatchContext
internal val tabCreateButtonsLoopStartFingerprint by fingerprint {
returns("V")
strings("InstagramMainActivity.createTabButtons")
opcodes(
//Loop Start
Opcode.IF_GE, // Check if index is finished (index, size)
//Injection
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT
)
internal val initializeNavigationButtonsListFingerprint = fingerprint {
strings("Nav3")
parameters("Lcom/instagram/common/session/UserSession;", "Z")
returns("Ljava/util/List;")
}
internal val tabCreateButtonsLoopEndFingerprint by fingerprint {
returns("V")
strings("InstagramMainActivity.createTabButtons")
opcodes(
Opcode.IPUT_OBJECT,
// Injection Jump
Opcode.ADD_INT_LIT8, //Increase Index
Opcode.GOTO // Jump to loopStart
// LoopEnd
)
private val navigationButtonsEnumClassDef by fingerprint {
strings("FEED", "fragment_feed", "SEARCH", "fragment_search")
}
context(BytecodePatchContext)
internal val navigationButtonsEnumInitFingerprint get() = fingerprint {
custom { method, classDef ->
method.name == "<init>"
&& classDef == navigationButtonsEnumClassDef.classDef
}
}

View file

@ -1,21 +1,28 @@
package app.revanced.patches.instagram.hide.navigation
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.booleanOption
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.util.addInstructionsAtControlFlowLabel
import app.revanced.util.findFreeRegister
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import java.util.logging.Logger
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/instagram/hide/navigation/HideNavigationButtonsPatch;"
@Suppress("unused")
val hideNavigationButtonsPatch = bytecodePatch(
name = "Hide navigation buttons",
description = "Hides navigation bar buttons, such as the Reels and Create button.",
use = false
) {
compatibleWith("com.instagram.android"("397.1.0.52.81"))
compatibleWith("com.instagram.android")
val hideReels by booleanOption(
key = "hideReels",
@ -38,43 +45,44 @@ val hideNavigationButtonsPatch = bytecodePatch(
)
}
tabCreateButtonsLoopStartFingerprint.method.apply {
// Check the current loop index, and skip over adding the
// navigation button view if the index matches a given button.
val enumNameField: String
val startIndex = tabCreateButtonsLoopStartFingerprint.patternMatch!!.startIndex
val endIndex = tabCreateButtonsLoopEndFingerprint.patternMatch!!.endIndex
val insertIndex = startIndex + 1
val loopIndexRegister = getInstruction<TwoRegisterInstruction>(startIndex).registerA
val freeRegister = findFreeRegister(insertIndex, loopIndexRegister)
val instruction = getInstruction(endIndex - 1)
val instructions = buildString {
if (hideCreate!!) {
appendLine(
"""
const v$freeRegister, 0x2
if-eq v$freeRegister, v$loopIndexRegister, :skipAddView
"""
)
}
if (hideReels!!) {
appendLine(
"""
const v$freeRegister, 0x3
if-eq v$freeRegister, v$loopIndexRegister, :skipAddView
"""
)
}
}
addInstructionsWithLabels(
insertIndex,
instructions,
ExternalLabel("skipAddView", instruction)
)
// Get the field name which contains the name of the enum for the navigation button ("fragment_clips", "fragment_share", ...)
with(navigationButtonsEnumInitFingerprint.method) {
enumNameField = indexOfFirstInstructionOrThrow {
opcode == Opcode.IPUT_OBJECT &&
(this as TwoRegisterInstruction).registerA == 2 // The p2 register
}.let {
getInstruction(it).getReference<FieldReference>()!!.name
}
}
}
initializeNavigationButtonsListFingerprint.method.apply {
val returnIndex = indexOfFirstInstructionOrThrow(Opcode.RETURN_OBJECT)
val buttonsListRegister = getInstruction<OneRegisterInstruction>(returnIndex).registerA
val freeRegister = findFreeRegister(returnIndex)
val freeRegister2 = findFreeRegister(returnIndex, freeRegister)
fun instructionsRemoveButtonByName(buttonEnumName: String): String {
return """
const-string v$freeRegister, "$buttonEnumName"
const-string v$freeRegister2, "$enumNameField"
invoke-static { v$buttonsListRegister, v$freeRegister, v$freeRegister2 }, $EXTENSION_CLASS_DESCRIPTOR->removeNavigationButtonByName(Ljava/util/List;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
move-result-object v$buttonsListRegister
"""
}
if (hideReels!!)
addInstructionsAtControlFlowLabel(
returnIndex,
instructionsRemoveButtonByName("fragment_clips")
)
if (hideCreate!!)
addInstructionsAtControlFlowLabel(
returnIndex,
instructionsRemoveButtonByName("fragment_share")
)
}
}
}

View file

@ -0,0 +1,22 @@
package app.revanced.patches.music.misc.dns
import app.revanced.patches.music.misc.extension.sharedExtensionPatch
import app.revanced.patches.music.shared.mainActivityOnCreateFingerprint
import app.revanced.patches.shared.misc.dns.checkWatchHistoryDomainNameResolutionPatch
val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameResolutionPatch(
block = {
dependsOn(
sharedExtensionPatch
)
compatibleWith(
"com.google.android.apps.youtube.music"(
"7.29.52",
"8.10.52"
)
)
},
mainActivityFingerprint = mainActivityOnCreateFingerprint
)

View file

@ -1,9 +1,10 @@
package app.revanced.patches.music.misc.extension
import app.revanced.patches.music.misc.extension.hooks.applicationInitHook
import app.revanced.patches.music.misc.extension.hooks.applicationInitOnCreateHook
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
val sharedExtensionPatch = sharedExtensionPatch(
"music",
applicationInitHook,
applicationInitHook, applicationInitOnCreateHook
)

View file

@ -1,5 +1,6 @@
package app.revanced.patches.music.misc.extension.hooks
import app.revanced.patches.music.shared.YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE
import app.revanced.patcher.string
import app.revanced.patches.shared.misc.extension.extensionHook
@ -11,3 +12,11 @@ internal val applicationInitHook = extensionHook {
)
custom { method, _ -> method.name == "onCreate" }
}
internal val applicationInitOnCreateHook = extensionHook {
returns("V")
parameters("Landroid/os/Bundle;")
custom { method, classDef ->
method.name == "onCreate" && classDef.type == YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE
}
}

View file

@ -0,0 +1,13 @@
package app.revanced.patches.music.shared
import app.revanced.patcher.fingerprint
internal const val YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE = "Lcom/google/android/apps/youtube/music/activities/MusicActivity;"
internal val mainActivityOnCreateFingerprint = fingerprint {
returns("V")
parameters("Landroid/os/Bundle;")
custom { method, classDef ->
method.name == "onCreate" && classDef.type == YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE
}
}

View file

@ -0,0 +1,36 @@
package app.revanced.patches.shared.misc.dns
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/patches/CheckWatchHistoryDomainNameResolutionPatch;"
/**
* Patch shared with YouTube and YT Music.
*/
internal fun checkWatchHistoryDomainNameResolutionPatch(
block: BytecodePatchBuilder.() -> Unit = {},
executeBlock: BytecodePatchContext.() -> Unit = {},
mainActivityFingerprint: Fingerprint
) = bytecodePatch(
name = "Check watch history domain name resolution",
description = "Checks if the device DNS server is preventing user watch history from being saved.",
) {
block()
execute {
executeBlock()
addResources("shared", "misc.dns.checkWatchHistoryDomainNameResolutionPatch")
mainActivityFingerprint.method.addInstruction(
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V",
)
}
}

View file

@ -1,39 +1,23 @@
package app.revanced.patches.youtube.misc.dns
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.dns.checkWatchHistoryDomainNameResolutionPatch
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/CheckWatchHistoryDomainNameResolutionPatch;"
val checkWatchHistoryDomainNameResolutionPatch = bytecodePatch(
name = "Check watch history domain name resolution",
description = "Checks if the device DNS server is preventing user watch history from being saved.",
) {
dependsOn(
sharedExtensionPatch,
addResourcesPatch
)
compatibleWith(
"com.google.android.youtube"(
"19.34.42",
"20.07.39",
"20.13.41",
"20.14.43",
val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameResolutionPatch(
block = {
dependsOn(
sharedExtensionPatch
)
)
execute {
addResources("youtube", "misc.dns.checkWatchHistoryDomainNameResolutionPatch")
mainActivityOnCreateFingerprint.method.addInstruction(
0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->checkDnsResolver(Landroid/app/Activity;)V",
compatibleWith(
"com.google.android.youtube"(
"19.34.42",
"20.07.39",
"20.13.41",
"20.14.43",
)
)
}
}
},
mainActivityFingerprint = mainActivityOnCreateFingerprint
)

View file

@ -0,0 +1,87 @@
package app.revanced.patches.youtube.video.codecs
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/DisableVideoCodecsPatch;"
@Suppress("unused")
val disableVideoCodecsPatch = bytecodePatch(
name = "disable video codecs",
description = "Adds options to disable HDR and VP9 codecs.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
/**
* Override all calls of `getSupportedHdrTypes`.
*/
transformInstructionsPatch(
filterMap = filterMap@{ classDef, _, instruction, instructionIndex ->
if (classDef.type.startsWith("Lapp/revanced/")) {
return@filterMap null
}
val reference = instruction.getReference<MethodReference>()
if (reference?.definingClass =="Landroid/view/Display\$HdrCapabilities;"
&& reference.name == "getSupportedHdrTypes") {
return@filterMap instruction to instructionIndex
}
return@filterMap null
},
transform = { method, entry ->
val (instruction, index) = entry
val register = (instruction as FiveRegisterInstruction).registerC
method.replaceInstruction(
index,
"invoke-static/range { v$register .. v$register }, $EXTENSION_CLASS_DESCRIPTOR->" +
"disableHdrVideo(Landroid/view/Display\$HdrCapabilities;)[I",
)
}
)
)
compatibleWith(
"com.google.android.youtube"(
"19.34.42",
"20.07.39",
"20.13.41",
"20.14.43",
)
)
execute {
addResources("youtube", "video.codecs.disableVideoCodecsPatch")
PreferenceScreen.VIDEO.addPreferences(
SwitchPreference("revanced_disable_hdr_video"),
SwitchPreference("revanced_force_avc_codec")
)
vp9CapabilityFingerprint.method.addInstructionsWithLabels(
0,
"""
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->allowVP9()Z
move-result v0
if-nez v0, :default
return v0
:default
nop
"""
)
}
}

View file

@ -0,0 +1,13 @@
package app.revanced.patches.youtube.video.codecs
import app.revanced.patcher.fingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal val vp9CapabilityFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Z")
strings(
"vp9_supported",
"video/x-vnd.on2.vp9"
)
}

View file

@ -1,71 +1,10 @@
package app.revanced.patches.youtube.video.hdr
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.util.getReference
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/DisableHdrPatch;"
import app.revanced.patches.youtube.video.codecs.disableVideoCodecsPatch
@Deprecated("Patch was renamed", ReplaceWith("disableVideoCodecsPatch"))
@Suppress("unused")
val disableHdrPatch = bytecodePatch(
name = "Disable HDR video",
description = "Adds an option to disable video HDR.",
) {
dependsOn(
sharedExtensionPatch,
settingsPatch,
addResourcesPatch,
// Override all calls of `getSupportedHdrTypes`.
transformInstructionsPatch(
filterMap = filterMap@{ classDef, _, instruction, instructionIndex ->
if (classDef.type.startsWith("Lapp/revanced/")) {
return@filterMap null
}
val reference = instruction.getReference<MethodReference>()
if (reference?.definingClass =="Landroid/view/Display\$HdrCapabilities;"
&& reference.name == "getSupportedHdrTypes") {
return@filterMap instruction to instructionIndex
}
return@filterMap null
},
transform = { method, entry ->
val (instruction, index) = entry
val register = (instruction as FiveRegisterInstruction).registerC
method.replaceInstruction(
index,
"invoke-static/range { v$register .. v$register }, $EXTENSION_CLASS_DESCRIPTOR->" +
"disableHdrVideo(Landroid/view/Display\$HdrCapabilities;)[I",
)
}
)
)
compatibleWith(
"com.google.android.youtube"(
"19.34.42",
"20.07.39",
"20.13.41",
"20.14.43",
)
)
execute {
addResources("youtube", "video.hdr.disableHdrPatch")
PreferenceScreen.VIDEO.addPreferences(
SwitchPreference("revanced_disable_hdr_video")
)
}
}
val disableHdrPatch = bytecodePatch{
dependsOn(disableVideoCodecsPatch)
}

View file

@ -29,7 +29,6 @@ internal val videoQualityItemOnClickFingerprint by fingerprint {
}
}
internal val videoQualityMenuOptionsFingerprint by fingerprint {
accessFlags(AccessFlags.STATIC)
returns("[L")

View file

@ -14,12 +14,13 @@ internal val settingsMenuVideoQualityGroup = mutableSetOf<BasePreference>()
@Suppress("unused")
val videoQualityPatch = bytecodePatch(
name = "Video quality",
description = "Adds options to use the advanced video quality menu and set default video qualities."
description = "Adds options to use the advanced video quality menu, set default video qualities, " +
"and disable video codecs such as VP9/HDR."
) {
dependsOn(
rememberVideoQualityPatch,
advancedVideoQualityMenuPatch,
videoQualityDialogButtonPatch,
videoQualityDialogButtonPatch
)
compatibleWith(

View file

@ -30,6 +30,11 @@ Second \"item\" text"</string>
<string name="revanced_check_environment_not_near_patch_time_days">Patched %s days ago</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">APK build date is corrupted</string>
</patch>
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
<string name="revanced_check_watch_history_domain_name_dialog_title">Warning</string>
<string name="revanced_check_watch_history_domain_name_dialog_message">Your watch history is not being saved.&lt;br>&lt;br>This most likely is caused by a DNS ad blocker or network proxy.&lt;br>&lt;br>To fix this, whitelist &lt;b>s.youtube.com&lt;/b> or turn off all DNS blockers and proxies.</string>
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Do not show again</string>
</patch>
<patch id="misc.settings.settingsResourcePatch">
<string name="revanced_settings_submenu_title">Settings</string>
<string name="revanced_settings_title" translatable="false">ReVanced</string>
@ -1528,11 +1533,6 @@ Tap here to learn more about DeArrow"</string>
<string name="revanced_announcements_connection_failed">Failed connecting to announcements provider</string>
<string name="revanced_announcements_dialog_dismiss">Dismiss</string>
</patch>
<patch id="misc.dns.checkWatchHistoryDomainNameResolutionPatch">
<string name="revanced_check_watch_history_domain_name_dialog_title">Warning</string>
<string name="revanced_check_watch_history_domain_name_dialog_message">Your watch history is not being saved.&lt;br>&lt;br>This most likely is caused by a DNS ad blocker or network proxy.&lt;br>&lt;br>To fix this, whitelist &lt;b>s.youtube.com&lt;/b> or turn off all DNS blockers and proxies.</string>
<string name="revanced_check_watch_history_domain_name_dialog_ignore">Do not show again</string>
</patch>
<patch id="misc.loopvideo.loopVideoPatch">
<string name="revanced_loop_video_title">Enable loop video</string>
<string name="revanced_loop_video_summary_on">Video will loop</string>
@ -1647,10 +1647,22 @@ Enabling this can unlock higher video qualities"</string>
<string name="revanced_playback_speed_default_title">Default playback speed</string>
<string name="revanced_remember_playback_speed_toast">Changed default speed to: %s</string>
</patch>
<patch id="video.hdr.disableHdrPatch">
<patch id="video.codecs.disableVideoCodecsPatch">
<string name="revanced_disable_hdr_video_title">Disable HDR video</string>
<string name="revanced_disable_hdr_video_summary_on">HDR video is disabled</string>
<string name="revanced_disable_hdr_video_summary_off">HDR video is enabled</string>
<string name="revanced_force_avc_codec_title">Force AVC (H.264)</string>
<string name="revanced_force_avc_codec_summary_on">Video codec is forced to AVC (H.264)</string>
<string name="revanced_force_avc_codec_summary_off">Video codec is determined automatically</string>
<string name="revanced_force_avc_codec_user_dialog_message">"Benefits:
• Can improve battery life.
• Can restore missing video resolutions on older device.
Limitations:
• Maximum resolution is 1080p.
• Video playback will use more internet data than VP9 or AV1.
• HDR videos may not use AVC.
• Some devices cannot force AVC."</string>
</patch>
<patch id="video.quality.advancedVideoQualityMenuPatch">
<string name="revanced_advanced_video_quality_menu_title">Show advanced video quality menu</string>