fix(YouTube - Change live ring click action): Channel does not open when the live ring of Shorts live stream is clicked

This commit is contained in:
inotia00
2025-01-29 19:25:07 +09:00
parent 21b8b48e47
commit 1151a9a5be
8 changed files with 197 additions and 88 deletions

View File

@ -4,15 +4,19 @@ 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.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.engagement.engagementPanelHookPatch
import app.revanced.patches.youtube.utils.engagement.hookEngagementPanelState
import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_PATH
import app.revanced.patches.youtube.utils.patch.PatchList.CHANGE_LIVE_RING_CLICK_ACTION
import app.revanced.patches.youtube.utils.playservice.is_19_25_or_greater
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
import app.revanced.patches.youtube.utils.settings.settingsPatch
import app.revanced.patches.youtube.video.playbackstart.PLAYBACK_START_DESCRIPTOR_CLASS_DESCRIPTOR
import app.revanced.patches.youtube.video.playbackstart.playbackStartDescriptorPatch
import app.revanced.patches.youtube.video.playbackstart.playbackStartVideoIdReference
import app.revanced.patches.youtube.video.playbackstart.shortsPlaybackStartIntentFingerprint
import app.revanced.patches.youtube.video.playbackstart.shortsPlaybackStartIntentLegacyFingerprint
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
@ -20,7 +24,10 @@ import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
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.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
private const val EXTENSION_CLASS_DESCRIPTOR =
"$GENERAL_PATH/OpenChannelOfLiveAvatarPatch;"
@ -35,13 +42,11 @@ val openChannelOfLiveAvatarPatch = bytecodePatch(
dependsOn(
settingsPatch,
playbackStartDescriptorPatch,
engagementPanelHookPatch,
versionCheckPatch,
)
execute {
hookEngagementPanelState(EXTENSION_CLASS_DESCRIPTOR)
clientSettingEndpointFingerprint.methodOrThrow().apply {
val eqzIndex = indexOfFirstInstructionReversedOrThrow(Opcode.IF_EQZ)
var freeIndex = indexOfFirstInstructionReversedOrThrow(eqzIndex, Opcode.NEW_INSTANCE)
@ -49,7 +54,7 @@ val openChannelOfLiveAvatarPatch = bytecodePatch(
addInstructionsWithLabels(
eqzIndex, """
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->openChannelOfLiveAvatar()Z
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->openChannel()Z
move-result v$freeRegister
if-eqz v$freeRegister, :ignore
return-void
@ -76,11 +81,82 @@ val openChannelOfLiveAvatarPatch = bytecodePatch(
playbackStartIndex + 1, """
invoke-virtual { v$playbackStartRegister }, $playbackStartVideoIdReference
move-result-object v$freeRegister
invoke-static { v$mapRegister, v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->openChannelOfLiveAvatar(Ljava/util/Map;Ljava/lang/String;)V
invoke-static { v$mapRegister, v$freeRegister }, $EXTENSION_CLASS_DESCRIPTOR->fetchChannelId(Ljava/util/Map;Ljava/lang/String;)V
"""
)
}
fun MutableMethod.openChannel() =
implementation!!.instructions
.withIndex()
.filter { (_, instruction) ->
val reference = (instruction as? ReferenceInstruction)?.reference
instruction.opcode == Opcode.NEW_INSTANCE &&
reference is TypeReference &&
reference.type == "Landroid/os/Bundle;"
}
.map { (index, _) -> index }
.reversed()
.forEach { index ->
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructionsWithLabels(
index, """
invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->openChannel()Z
move-result v$register
if-eqz v$register, :ignore
return-void
:ignore
nop
"""
)
}
fun fetchChannelIdInstructions(
playbackStartRegister: Int,
mapRegister: Int,
videoIdRegister: Int,
) =
"""
invoke-virtual { v$playbackStartRegister }, $playbackStartVideoIdReference
move-result-object v$videoIdRegister
invoke-static { v$mapRegister, v$videoIdRegister }, $EXTENSION_CLASS_DESCRIPTOR->fetchChannelId(Ljava/util/Map;Ljava/lang/String;)V
"""
if (is_19_25_or_greater) {
shortsPlaybackStartIntentFingerprint.methodOrThrow().apply {
openChannel()
addInstructionsWithLabels(
0, """
move-object/from16 v0, p1
move-object/from16 v1, p2
${fetchChannelIdInstructions(0, 1, 2)}
"""
)
}
} else {
shortsPlaybackStartIntentLegacyFingerprint.methodOrThrow().apply {
openChannel()
val playbackStartIndex = indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.returnType == PLAYBACK_START_DESCRIPTOR_CLASS_DESCRIPTOR
}
val mapIndex = indexOfFirstInstructionReversedOrThrow(playbackStartIndex, Opcode.IPUT)
val mapRegister = getInstruction<TwoRegisterInstruction>(mapIndex).registerA
val playbackStartRegister = getInstruction<OneRegisterInstruction>(playbackStartIndex + 1).registerA
val videoIdRegister = getInstruction<FiveRegisterInstruction>(playbackStartIndex).registerC
addInstructionsWithLabels(
playbackStartIndex + 2, """
move-object/from16 v$mapRegister, p2
${fetchChannelIdInstructions(playbackStartRegister, mapRegister, videoIdRegister)}
"""
)
}
}
// region add settings
addPreference(

View File

@ -187,41 +187,3 @@ internal val shortsFullscreenFeatureFingerprint = legacyFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
literals = listOf(FULLSCREEN_FEATURE_FLAG),
)
// Pre 19.25
internal val shortsPlaybackIntentLegacyFingerprint = legacyFingerprint(
name = "shortsPlaybackIntentLegacyFingerprint",
returnType = "V",
parameters = listOf(
"L",
"Ljava/util/Map;",
"J",
"Ljava/lang/String;",
"Z",
"Ljava/util/Map;"
),
strings = listOf(
// None of these strings are unique.
"com.google.android.apps.youtube.app.endpoint.flags",
"ReelWatchFragmentArgs",
"reels_fragment_descriptor"
)
)
internal val shortsPlaybackIntentFingerprint = legacyFingerprint(
name = "shortsPlaybackIntentFingerprint",
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
returnType = "V",
parameters = listOf(
"Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;",
"Ljava/util/Map;",
"J",
"Ljava/lang/String;"
),
strings = listOf(
// None of these strings are unique.
"com.google.android.apps.youtube.app.endpoint.flags",
"ReelWatchFragmentArgs",
"reels_fragment_descriptor"
)
)

View File

@ -65,6 +65,8 @@ import app.revanced.patches.youtube.video.information.videoInformationPatch
import app.revanced.patches.youtube.video.playbackstart.PLAYBACK_START_DESCRIPTOR_CLASS_DESCRIPTOR
import app.revanced.patches.youtube.video.playbackstart.playbackStartDescriptorPatch
import app.revanced.patches.youtube.video.playbackstart.playbackStartVideoIdReference
import app.revanced.patches.youtube.video.playbackstart.shortsPlaybackStartIntentFingerprint
import app.revanced.patches.youtube.video.playbackstart.shortsPlaybackStartIntentLegacyFingerprint
import app.revanced.patches.youtube.video.videoid.hookPlayerResponseVideoId
import app.revanced.patches.youtube.video.videoid.videoIdPatch
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
@ -894,7 +896,7 @@ val shortsComponentPatch = bytecodePatch(
"""
if (is_19_25_or_greater) {
shortsPlaybackIntentFingerprint.methodOrThrow().addInstructionsWithLabels(
shortsPlaybackStartIntentFingerprint.methodOrThrow().addInstructionsWithLabels(
0,
"""
move-object/from16 v0, p1
@ -902,7 +904,7 @@ val shortsComponentPatch = bytecodePatch(
"""
)
} else {
shortsPlaybackIntentLegacyFingerprint.methodOrThrow().apply {
shortsPlaybackStartIntentLegacyFingerprint.methodOrThrow().apply {
val index = indexOfFirstInstructionOrThrow {
getReference<MethodReference>()?.returnType == PLAYBACK_START_DESCRIPTOR_CLASS_DESCRIPTOR
}

View File

@ -1,6 +1,8 @@
package app.revanced.patches.youtube.video.playbackstart
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
const val PLAYBACK_START_DESCRIPTOR_CLASS_DESCRIPTOR =
"Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;"
@ -16,4 +18,42 @@ internal val playbackStartFeatureFlagFingerprint = legacyFingerprint(
literals = listOf(45380134L)
)
internal val shortsPlaybackStartIntentFingerprint = legacyFingerprint(
name = "shortsPlaybackStartIntentFingerprint",
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
returnType = "V",
parameters = listOf(
"Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;",
"Ljava/util/Map;",
"J",
"Ljava/lang/String;"
),
strings = listOf(
// None of these strings are unique.
"com.google.android.apps.youtube.app.endpoint.flags",
"ReelWatchFragmentArgs",
"reels_fragment_descriptor"
)
)
// Pre 19.25
internal val shortsPlaybackStartIntentLegacyFingerprint = legacyFingerprint(
name = "shortsPlaybackStartIntentLegacyFingerprint",
returnType = "V",
parameters = listOf(
"L",
"Ljava/util/Map;",
"J",
"Ljava/lang/String;",
"Z",
"Ljava/util/Map;"
),
strings = listOf(
// None of these strings are unique.
"com.google.android.apps.youtube.app.endpoint.flags",
"ReelWatchFragmentArgs",
"reels_fragment_descriptor"
)
)

View File

@ -2,7 +2,7 @@ package app.revanced.patches.youtube.video.playbackstart
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
@ -15,7 +15,7 @@ internal lateinit var playbackStartVideoIdReference: Reference
val playbackStartDescriptorPatch = bytecodePatch(
description = "playbackStartDescriptorPatch"
) {
dependsOn(sharedResourceIdPatch)
dependsOn(sharedExtensionPatch)
execute {
// Find the obfuscated method name for PlaybackStartDescriptor.videoId()