fix(YouTube/Disable auto captions): patch does not work when A/B testing is applied

This commit is contained in:
inotia00 2023-12-28 21:41:37 +09:00
parent 3974641760
commit ffd5cb1760
6 changed files with 75 additions and 86 deletions

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.general.autocaptions.fingerprints
package app.revanced.patches.shared.fingerprints.captions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -3,10 +3,15 @@ package app.revanced.patches.shared.fingerprints.captions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object SubtitleTrackFingerprint : MethodFingerprint(
returnType = "Z",
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
strings = listOf("DISABLE_CAPTIONS_OPTION")
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
),
strings = listOf("subtitleTrack is null")
)

View File

@ -0,0 +1,59 @@
package app.revanced.patches.shared.patch.captions
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.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.fingerprints.captions.StartVideoInformerFingerprint
import app.revanced.patches.shared.fingerprints.captions.SubtitleTrackFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.Opcode
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.MethodReference
abstract class AbstractAutoCaptionsPatch(
private val classDescriptor: String
) : BytecodePatch(
setOf(
StartVideoInformerFingerprint,
SubtitleTrackFingerprint
)
) {
override fun execute(context: BytecodeContext) {
StartVideoInformerFingerprint.result?.let {
it.mutableMethod.apply {
addInstruction(
0,
"invoke-static {}, $classDescriptor->prefetchSubtitleTrack()V"
)
}
} ?: throw StartVideoInformerFingerprint.exception
SubtitleTrackFingerprint.result?.let {
val targetMethod = context
.toMethodWalker(it.method)
.nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true)
.getMethod() as MutableMethod
targetMethod.apply {
val insertIndex = implementation!!.instructions.indexOfFirst { instruction ->
instruction.opcode == Opcode.INVOKE_VIRTUAL
&& ((instruction as? ReferenceInstruction)?.reference as? MethodReference)?.returnType == "Z"
} + 2
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $classDescriptor->disableAutoCaptions(Z)Z
move-result v$insertRegister
"""
)
}
} ?: throw SubtitleTrackFingerprint.exception
}
}

View File

@ -1,30 +1,19 @@
package app.revanced.patches.youtube.general.autocaptions
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
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.fingerprints.captions.SubtitleTrackFingerprint
import app.revanced.patches.youtube.general.autocaptions.fingerprints.StartVideoInformerFingerprint
import app.revanced.patches.youtube.utils.fingerprints.SubtitleButtonControllerFingerprint
import app.revanced.patches.shared.patch.captions.AbstractAutoCaptionsPatch
import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.util.exception
import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch
@Patch(
name = "Disable auto captions",
description = "Disables forced auto captions.",
dependencies = [
PlayerTypeHookPatch::class,
SettingsPatch::class,
SharedResourceIdPatch::class
VideoIdPatch::class
],
compatiblePackages = [
CompatiblePackage(
@ -54,41 +43,13 @@ import app.revanced.util.exception
]
)
@Suppress("unused")
object AutoCaptionsPatch : BytecodePatch(
setOf(
StartVideoInformerFingerprint,
SubtitleButtonControllerFingerprint,
SubtitleTrackFingerprint
)
object AutoCaptionsPatch : AbstractAutoCaptionsPatch(
GENERAL
) {
override fun execute(context: BytecodeContext) {
listOf(
StartVideoInformerFingerprint.toPatch(Status.DISABLED),
SubtitleButtonControllerFingerprint.toPatch(Status.ENABLED)
).forEach { (fingerprint, status) ->
fingerprint.result?.mutableMethod?.addInstructions(
0, """
const/4 v0, ${status.value}
sput-boolean v0, $GENERAL->captionsButtonStatus:Z
"""
) ?: throw fingerprint.exception
}
super.execute(context)
SubtitleTrackFingerprint.result?.let {
it.mutableMethod.apply {
addInstructionsWithLabels(
0, """
invoke-static {}, $GENERAL->disableAutoCaptions()Z
move-result v0
if-eqz v0, :auto_captions_shown
sget-boolean v0, $GENERAL->captionsButtonStatus:Z
if-nez v0, :auto_captions_shown
const/4 v0, 0x1
return v0
""", ExternalLabel("auto_captions_shown", getInstruction(0))
)
}
} ?: throw SubtitleTrackFingerprint.exception
VideoIdPatch.injectCall("$GENERAL->newVideoStarted(Ljava/lang/String;)V")
/**
* Add settings
@ -103,13 +64,4 @@ object AutoCaptionsPatch : BytecodePatch(
SettingsPatch.updatePatchStatus("Disable auto captions")
}
private fun MethodFingerprint.toPatch(visibility: Status) = SetStatus(this, visibility)
private data class SetStatus(val fingerprint: MethodFingerprint, val visibility: Status)
private enum class Status(val value: Int) {
ENABLED(1),
DISABLED(0)
}
}

View File

@ -1,25 +0,0 @@
package app.revanced.patches.youtube.utils.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccessibilityCaptionsButtonName
import app.revanced.util.fingerprint.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object SubtitleButtonControllerFingerprint : LiteralValueFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Lcom/google/android/libraries/youtube/player/subtitles/model/SubtitleTrack;"),
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.RETURN_VOID,
Opcode.IGET_BOOLEAN,
Opcode.CONST_4,
Opcode.IF_NEZ,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT
),
literalSupplier = { AccessibilityCaptionsButtonName }
)

View File

@ -15,7 +15,6 @@ import app.revanced.patches.shared.patch.mapping.ResourceType.STRING
@Patch(dependencies = [ResourceMappingPatch::class])
object SharedResourceIdPatch : ResourcePatch() {
var AccountSwitcherAccessibility: Long = -1
var AccessibilityCaptionsButtonName: Long = -1
var ActionBarRingo: Long = -1
var AdAttribution: Long = -1
var Appearance: Long = -1
@ -96,7 +95,6 @@ object SharedResourceIdPatch : ResourcePatch() {
?: -1
AccountSwitcherAccessibility = find(STRING, "account_switcher_accessibility_label")
AccessibilityCaptionsButtonName = find(STRING, "accessibility_captions_button_name")
ActionBarRingo = find(LAYOUT, "action_bar_ringo")
AdAttribution = find(ID, "ad_attribution")
Appearance = find(STRING, "app_theme_appearance_dark")