mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-05 17:14:35 +02:00
feat(YouTube): Add support version 20.02.38
This commit is contained in:
parent
316038cd75
commit
c8cc8c4bda
@ -61,6 +61,10 @@ public class ShortsPatch {
|
|||||||
return Settings.DISABLE_RESUMING_SHORTS_PLAYER.get();
|
return Settings.DISABLE_RESUMING_SHORTS_PLAYER.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean disableResumingStartupShortsPlayer(boolean original) {
|
||||||
|
return !Settings.DISABLE_RESUMING_SHORTS_PLAYER.get() && original;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean enableShortsTimeStamp(boolean original) {
|
public static boolean enableShortsTimeStamp(boolean original) {
|
||||||
return ENABLE_TIME_STAMP || original;
|
return ENABLE_TIME_STAMP || original;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import app.revanced.util.fingerprint.methodOrThrow
|
|||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstStringInstruction
|
||||||
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
||||||
import app.revanced.util.or
|
import app.revanced.util.or
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
@ -27,6 +28,7 @@ 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.instruction.TwoRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
@ -42,6 +44,8 @@ private var filterCount = 0
|
|||||||
internal lateinit var addLithoFilter: (String) -> Unit
|
internal lateinit var addLithoFilter: (String) -> Unit
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
internal var emptyComponentLabel = ""
|
||||||
|
|
||||||
val lithoFilterPatch = bytecodePatch(
|
val lithoFilterPatch = bytecodePatch(
|
||||||
description = "lithoFilterPatch",
|
description = "lithoFilterPatch",
|
||||||
) {
|
) {
|
||||||
@ -73,6 +77,8 @@ val lithoFilterPatch = bytecodePatch(
|
|||||||
return-object v0
|
return-object v0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
emptyComponentLabel = label
|
||||||
|
|
||||||
Pair(this, label)
|
Pair(this, label)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,17 +127,25 @@ val lithoFilterPatch = bytecodePatch(
|
|||||||
val stringBuilderRegister =
|
val stringBuilderRegister =
|
||||||
getInstruction<TwoRegisterInstruction>(stringBuilderIndex).registerA
|
getInstruction<TwoRegisterInstruction>(stringBuilderIndex).registerA
|
||||||
|
|
||||||
val emptyStringIndex = indexOfFirstStringInstructionOrThrow("")
|
val emptyStringIndex = indexOfFirstStringInstruction("")
|
||||||
|
val relativeIndex = if (emptyStringIndex > -1) {
|
||||||
|
emptyStringIndex
|
||||||
|
} else {
|
||||||
|
val separatorIndex = indexOfFirstStringInstructionOrThrow("|")
|
||||||
|
indexOfFirstInstructionOrThrow(separatorIndex) {
|
||||||
|
opcode == Opcode.NEW_INSTANCE &&
|
||||||
|
getReference<TypeReference>()?.type == "Ljava/lang/StringBuilder;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val identifierRegister = getInstruction<TwoRegisterInstruction>(
|
val identifierRegister = getInstruction<TwoRegisterInstruction>(
|
||||||
indexOfFirstInstructionReversedOrThrow(emptyStringIndex) {
|
indexOfFirstInstructionReversedOrThrow(relativeIndex) {
|
||||||
opcode == Opcode.IPUT_OBJECT
|
opcode == Opcode.IPUT_OBJECT
|
||||||
&& getReference<FieldReference>()?.type == "Ljava/lang/String;"
|
&& getReference<FieldReference>()?.type == "Ljava/lang/String;"
|
||||||
}
|
}
|
||||||
).registerA
|
).registerA
|
||||||
val objectRegister = getInstruction<FiveRegisterInstruction>(
|
val objectRegister = getInstruction<FiveRegisterInstruction>(
|
||||||
indexOfFirstInstructionOrThrow(emptyStringIndex) {
|
indexOfFirstInstructionOrThrow(relativeIndex, Opcode.INVOKE_VIRTUAL)
|
||||||
opcode == Opcode.INVOKE_VIRTUAL
|
|
||||||
}
|
|
||||||
).registerC
|
).registerC
|
||||||
|
|
||||||
val insertIndex = stringBuilderIndex + 1
|
val insertIndex = stringBuilderIndex + 1
|
||||||
|
@ -16,6 +16,7 @@ import app.revanced.util.indexOfFirstInstruction
|
|||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
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.ReferenceInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
@ -40,11 +41,11 @@ val textComponentPatch = bytecodePatch(
|
|||||||
spannedIndex = indexOfSpannableStringInstruction(this)
|
spannedIndex = indexOfSpannableStringInstruction(this)
|
||||||
spannedRegister = getInstruction<FiveRegisterInstruction>(spannedIndex).registerC
|
spannedRegister = getInstruction<FiveRegisterInstruction>(spannedIndex).registerC
|
||||||
spannedContextRegister =
|
spannedContextRegister =
|
||||||
getInstruction<TwoRegisterInstruction>(0).registerA
|
getInstruction<OneRegisterInstruction>(spannedIndex + 1).registerA
|
||||||
|
|
||||||
replaceInstruction(
|
replaceInstruction(
|
||||||
spannedIndex,
|
spannedIndex,
|
||||||
"nop"
|
"move-object/from16 v$spannedContextRegister, p0"
|
||||||
)
|
)
|
||||||
addInstruction(
|
addInstruction(
|
||||||
++spannedIndex,
|
++spannedIndex,
|
||||||
|
@ -10,6 +10,7 @@ import app.revanced.patcher.patch.bytecodePatch
|
|||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.shared.litho.addLithoFilter
|
import app.revanced.patches.shared.litho.addLithoFilter
|
||||||
|
import app.revanced.patches.shared.litho.emptyComponentLabel
|
||||||
import app.revanced.patches.shared.mainactivity.onCreateMethod
|
import app.revanced.patches.shared.mainactivity.onCreateMethod
|
||||||
import app.revanced.patches.youtube.utils.bottomsheet.bottomSheetHookPatch
|
import app.revanced.patches.youtube.utils.bottomsheet.bottomSheetHookPatch
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
@ -21,6 +22,9 @@ import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch
|
|||||||
import app.revanced.patches.youtube.utils.navigation.navigationBarHookPatch
|
import app.revanced.patches.youtube.utils.navigation.navigationBarHookPatch
|
||||||
import app.revanced.patches.youtube.utils.patch.PatchList.HIDE_FEED_COMPONENTS
|
import app.revanced.patches.youtube.utils.patch.PatchList.HIDE_FEED_COMPONENTS
|
||||||
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.is_18_34_or_greater
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||||
import app.revanced.patches.youtube.utils.resourceid.bar
|
import app.revanced.patches.youtube.utils.resourceid.bar
|
||||||
import app.revanced.patches.youtube.utils.resourceid.captionToggleContainer
|
import app.revanced.patches.youtube.utils.resourceid.captionToggleContainer
|
||||||
import app.revanced.patches.youtube.utils.resourceid.channelListSubMenu
|
import app.revanced.patches.youtube.utils.resourceid.channelListSubMenu
|
||||||
@ -78,6 +82,7 @@ val feedComponentsPatch = bytecodePatch(
|
|||||||
sharedResourceIdPatch,
|
sharedResourceIdPatch,
|
||||||
settingsPatch,
|
settingsPatch,
|
||||||
bottomSheetHookPatch,
|
bottomSheetHookPatch,
|
||||||
|
versionCheckPatch,
|
||||||
)
|
)
|
||||||
execute {
|
execute {
|
||||||
|
|
||||||
@ -223,19 +228,22 @@ val feedComponentsPatch = bytecodePatch(
|
|||||||
|
|
||||||
// region patch for hide subscriptions channel section for tablet
|
// region patch for hide subscriptions channel section for tablet
|
||||||
|
|
||||||
arrayOf(
|
// Integrated as a litho component since YouTube 20.02.
|
||||||
channelListSubMenuTabletFingerprint,
|
if (!is_20_02_or_greater) {
|
||||||
channelListSubMenuTabletSyntheticFingerprint
|
arrayOf(
|
||||||
).forEach { fingerprint ->
|
channelListSubMenuTabletFingerprint,
|
||||||
fingerprint.methodOrThrow().apply {
|
channelListSubMenuTabletSyntheticFingerprint
|
||||||
addInstructionsWithLabels(
|
).forEach { fingerprint ->
|
||||||
0, """
|
fingerprint.methodOrThrow().apply {
|
||||||
invoke-static {}, $FEED_CLASS_DESCRIPTOR->hideSubscriptionsChannelSection()Z
|
addInstructionsWithLabels(
|
||||||
move-result v0
|
0, """
|
||||||
if-eqz v0, :show
|
invoke-static {}, $FEED_CLASS_DESCRIPTOR->hideSubscriptionsChannelSection()Z
|
||||||
return-void
|
move-result v0
|
||||||
""", ExternalLabel("show", getInstruction(0))
|
if-eqz v0, :show
|
||||||
)
|
return-void
|
||||||
|
""", ExternalLabel("show", getInstruction(0))
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,29 +295,27 @@ val feedComponentsPatch = bytecodePatch(
|
|||||||
it.method.apply {
|
it.method.apply {
|
||||||
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||||
val insertIndex = indexOfFirstInstructionOrThrow {
|
val insertIndex = indexOfFirstInstructionOrThrow {
|
||||||
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
|
val reference = getReference<MethodReference>()
|
||||||
|
|
||||||
reference?.parameterTypes?.size == 1 &&
|
reference?.parameterTypes?.size == 1 &&
|
||||||
reference.parameterTypes.first() == "[B" &&
|
reference.parameterTypes.first() == "[B" &&
|
||||||
reference.returnType.startsWith("L")
|
reference.returnType.startsWith("L")
|
||||||
}
|
}
|
||||||
|
|
||||||
val objectIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_OBJECT)
|
val objectOpcode = if (is_18_34_or_greater)
|
||||||
|
Opcode.IGET_OBJECT
|
||||||
|
else
|
||||||
|
Opcode.MOVE_OBJECT
|
||||||
|
val objectIndex = indexOfFirstInstructionReversedOrThrow(insertIndex, objectOpcode)
|
||||||
val objectRegister = getInstruction<TwoRegisterInstruction>(objectIndex).registerA
|
val objectRegister = getInstruction<TwoRegisterInstruction>(objectIndex).registerA
|
||||||
|
|
||||||
val jumpIndex = it.patternMatch!!.startIndex
|
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
addInstructionsWithLabels(
|
||||||
insertIndex, """
|
insertIndex, """
|
||||||
invoke-static {v$objectRegister, v$freeRegister}, $FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
|
invoke-static {v$objectRegister, p3}, $FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z
|
||||||
move-result v$freeRegister
|
move-result v$freeRegister
|
||||||
if-nez v$freeRegister, :filter
|
if-eqz v$freeRegister, :ignore
|
||||||
""", ExternalLabel("filter", getInstruction(jumpIndex))
|
""" + emptyComponentLabel,
|
||||||
)
|
ExternalLabel("ignore", getInstruction(insertIndex))
|
||||||
|
|
||||||
addInstruction(
|
|
||||||
0,
|
|
||||||
"move-object/from16 v$freeRegister, p3"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,6 @@ internal val floatingMicrophoneFingerprint = legacyFingerprint(
|
|||||||
opcodes = listOf(
|
opcodes = listOf(
|
||||||
Opcode.IGET_BOOLEAN,
|
Opcode.IGET_BOOLEAN,
|
||||||
Opcode.IF_EQZ,
|
Opcode.IF_EQZ,
|
||||||
Opcode.RETURN_VOID
|
|
||||||
),
|
),
|
||||||
literals = listOf(fab),
|
literals = listOf(fab),
|
||||||
)
|
)
|
||||||
|
@ -20,6 +20,7 @@ import app.revanced.patches.youtube.utils.patch.PatchList.HIDE_LAYOUT_COMPONENTS
|
|||||||
import app.revanced.patches.youtube.utils.playservice.is_19_25_or_greater
|
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.playservice.versionCheckPatch
|
||||||
import app.revanced.patches.youtube.utils.resourceid.accountSwitcherAccessibility
|
import app.revanced.patches.youtube.utils.resourceid.accountSwitcherAccessibility
|
||||||
|
import app.revanced.patches.youtube.utils.resourceid.fab
|
||||||
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
|
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
|
||||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||||
@ -154,18 +155,17 @@ val layoutComponentsPatch = bytecodePatch(
|
|||||||
|
|
||||||
// region patch for hide floating microphone
|
// region patch for hide floating microphone
|
||||||
|
|
||||||
floatingMicrophoneFingerprint.matchOrThrow().let {
|
floatingMicrophoneFingerprint.methodOrThrow().apply {
|
||||||
it.method.apply {
|
val literalIndex = indexOfFirstLiteralInstructionOrThrow(fab)
|
||||||
val insertIndex = it.patternMatch!!.startIndex
|
val booleanIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.IGET_BOOLEAN)
|
||||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
val insertRegister = getInstruction<TwoRegisterInstruction>(booleanIndex).registerA
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
insertIndex + 1, """
|
booleanIndex + 1, """
|
||||||
invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingMicrophone(Z)Z
|
invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingMicrophone(Z)Z
|
||||||
move-result v$register
|
move-result v$insertRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -15,6 +15,7 @@ import app.revanced.patches.youtube.utils.castbutton.hookToolBarCastButton
|
|||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.patch.PatchList.TOOLBAR_COMPONENTS
|
import app.revanced.patches.youtube.utils.patch.PatchList.TOOLBAR_COMPONENTS
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.is_19_46_or_greater
|
||||||
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||||
import app.revanced.patches.youtube.utils.resourceid.actionBarRingoBackground
|
import app.revanced.patches.youtube.utils.resourceid.actionBarRingoBackground
|
||||||
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||||
@ -265,7 +266,11 @@ val toolBarComponentsPatch = bytecodePatch(
|
|||||||
// region patch for hide search term thumbnail
|
// region patch for hide search term thumbnail
|
||||||
|
|
||||||
createSearchSuggestionsFingerprint.methodOrThrow().apply {
|
createSearchSuggestionsFingerprint.methodOrThrow().apply {
|
||||||
val relativeIndex = indexOfFirstLiteralInstructionOrThrow(40L)
|
val literal = if (is_19_46_or_greater)
|
||||||
|
32L
|
||||||
|
else
|
||||||
|
40L
|
||||||
|
val relativeIndex = indexOfFirstLiteralInstructionOrThrow(literal)
|
||||||
val replaceIndex = indexOfFirstInstructionReversedOrThrow(relativeIndex) {
|
val replaceIndex = indexOfFirstInstructionReversedOrThrow(relativeIndex) {
|
||||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
getReference<MethodReference>()?.toString() == "Landroid/widget/ImageView;->setVisibility(I)V"
|
getReference<MethodReference>()?.toString() == "Landroid/widget/ImageView;->setVisibility(I)V"
|
||||||
|
@ -23,6 +23,8 @@ import app.revanced.patches.youtube.utils.extension.Constants.SPANS_PATH
|
|||||||
import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedVideoEndScreenPatch
|
import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedVideoEndScreenPatch
|
||||||
import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS
|
import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS
|
||||||
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||||
import app.revanced.patches.youtube.utils.resourceid.darkBackground
|
import app.revanced.patches.youtube.utils.resourceid.darkBackground
|
||||||
import app.revanced.patches.youtube.utils.resourceid.fadeDurationFast
|
import app.revanced.patches.youtube.utils.resourceid.fadeDurationFast
|
||||||
import app.revanced.patches.youtube.utils.resourceid.scrimOverlay
|
import app.revanced.patches.youtube.utils.resourceid.scrimOverlay
|
||||||
@ -278,9 +280,15 @@ val playerComponentsPatch = bytecodePatch(
|
|||||||
speedOverlayPatch,
|
speedOverlayPatch,
|
||||||
suggestedVideoEndScreenPatch,
|
suggestedVideoEndScreenPatch,
|
||||||
videoInformationPatch,
|
videoInformationPatch,
|
||||||
|
versionCheckPatch,
|
||||||
)
|
)
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
|
var settingArray = arrayOf(
|
||||||
|
"PREFERENCE_SCREEN: PLAYER",
|
||||||
|
"SETTINGS: PLAYER_COMPONENTS"
|
||||||
|
)
|
||||||
|
|
||||||
fun MutableMethod.getAllLiteralComponent(
|
fun MutableMethod.getAllLiteralComponent(
|
||||||
startIndex: Int,
|
startIndex: Int,
|
||||||
endIndex: Int
|
endIndex: Int
|
||||||
@ -563,30 +571,34 @@ val playerComponentsPatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
youtubeControlsOverlayFingerprint.methodOrThrow().apply {
|
if (!is_20_02_or_greater) {
|
||||||
val insertIndex =
|
youtubeControlsOverlayFingerprint.methodOrThrow().apply {
|
||||||
indexOfFirstLiteralInstructionOrThrow(seekUndoEduOverlayStub)
|
val insertIndex =
|
||||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
indexOfFirstLiteralInstructionOrThrow(seekUndoEduOverlayStub)
|
||||||
|
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||||
|
|
||||||
val onClickListenerIndex = indexOfFirstInstructionOrThrow(insertIndex) {
|
val onClickListenerIndex = indexOfFirstInstructionOrThrow(insertIndex) {
|
||||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
getReference<MethodReference>()?.name == "setOnClickListener"
|
getReference<MethodReference>()?.name == "setOnClickListener"
|
||||||
}
|
}
|
||||||
val constComponent = getFirstLiteralComponent(insertIndex, onClickListenerIndex - 1)
|
val constComponent = getFirstLiteralComponent(insertIndex, onClickListenerIndex - 1)
|
||||||
|
|
||||||
if (constComponent.isNotEmpty()) {
|
if (constComponent.isNotEmpty()) {
|
||||||
addInstruction(
|
addInstruction(
|
||||||
onClickListenerIndex + 2,
|
onClickListenerIndex + 2,
|
||||||
constComponent
|
constComponent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
insertIndex, """
|
||||||
|
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideSeekUndoMessage()Z
|
||||||
|
move-result v$insertRegister
|
||||||
|
if-nez v$insertRegister, :default
|
||||||
|
""", ExternalLabel("default", getInstruction(onClickListenerIndex + 1))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
settingArray += "SETTINGS: HIDE_SEEK_UNDO_MESSAGE"
|
||||||
}
|
}
|
||||||
addInstructionsWithLabels(
|
|
||||||
insertIndex, """
|
|
||||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideSeekUndoMessage()Z
|
|
||||||
move-result v$insertRegister
|
|
||||||
if-nez v$insertRegister, :default
|
|
||||||
""", ExternalLabel("default", getInstruction(onClickListenerIndex + 1))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
@ -652,10 +664,7 @@ val playerComponentsPatch = bytecodePatch(
|
|||||||
// region add settings
|
// region add settings
|
||||||
|
|
||||||
addPreference(
|
addPreference(
|
||||||
arrayOf(
|
settingArray,
|
||||||
"PREFERENCE_SCREEN: PLAYER",
|
|
||||||
"SETTINGS: PLAYER_COMPONENTS"
|
|
||||||
),
|
|
||||||
PLAYER_COMPONENTS
|
PLAYER_COMPONENTS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import app.revanced.patches.youtube.utils.resourceid.quickActionsElementContaine
|
|||||||
import app.revanced.util.fingerprint.legacyFingerprint
|
import app.revanced.util.fingerprint.legacyFingerprint
|
||||||
import app.revanced.util.or
|
import app.revanced.util.or
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||||
|
|
||||||
internal val broadcastReceiverFingerprint = legacyFingerprint(
|
internal val broadcastReceiverFingerprint = legacyFingerprint(
|
||||||
name = "broadcastReceiverFingerprint",
|
name = "broadcastReceiverFingerprint",
|
||||||
@ -45,12 +46,15 @@ internal val playerTitleViewFingerprint = legacyFingerprint(
|
|||||||
literals = listOf(playerVideoTitleView),
|
literals = listOf(playerVideoTitleView),
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val quickActionsElementFingerprint = legacyFingerprint(
|
internal val quickActionsElementSyntheticFingerprint = legacyFingerprint(
|
||||||
name = "quickActionsElementFingerprint",
|
name = "quickActionsElementSyntheticFingerprint",
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = listOf("Landroid/view/View;"),
|
parameters = listOf("Landroid/view/View;"),
|
||||||
literals = listOf(quickActionsElementContainer),
|
literals = listOf(quickActionsElementContainer),
|
||||||
|
customFingerprint = { _, classDef ->
|
||||||
|
AccessFlags.SYNTHETIC.isSet(classDef.accessFlags)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val relatedEndScreenResultsFingerprint = legacyFingerprint(
|
internal val relatedEndScreenResultsFingerprint = legacyFingerprint(
|
||||||
|
@ -19,6 +19,7 @@ import app.revanced.patches.youtube.utils.extension.Constants.PATCH_STATUS_CLASS
|
|||||||
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_PATH
|
import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_PATH
|
||||||
import app.revanced.patches.youtube.utils.fullscreen.fullscreenButtonHookPatch
|
import app.revanced.patches.youtube.utils.fullscreen.fullscreenButtonHookPatch
|
||||||
|
import app.revanced.patches.youtube.utils.indexOfFocusableInTouchModeInstruction
|
||||||
import app.revanced.patches.youtube.utils.layoutConstructorFingerprint
|
import app.revanced.patches.youtube.utils.layoutConstructorFingerprint
|
||||||
import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch
|
import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch
|
||||||
import app.revanced.patches.youtube.utils.patch.PatchList.FULLSCREEN_COMPONENTS
|
import app.revanced.patches.youtube.utils.patch.PatchList.FULLSCREEN_COMPONENTS
|
||||||
@ -101,7 +102,6 @@ val fullscreenComponentsPatch = bytecodePatch(
|
|||||||
"invoke-static {v$targetRegister}, " +
|
"invoke-static {v$targetRegister}, " +
|
||||||
"$PLAYER_CLASS_DESCRIPTOR->disableEngagementPanels(Landroidx/coordinatorlayout/widget/CoordinatorLayout;)V"
|
"$PLAYER_CLASS_DESCRIPTOR->disableEngagementPanels(Landroidx/coordinatorlayout/widget/CoordinatorLayout;)V"
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
playerTitleViewFingerprint.methodOrThrow().apply {
|
playerTitleViewFingerprint.methodOrThrow().apply {
|
||||||
@ -190,7 +190,7 @@ val fullscreenComponentsPatch = bytecodePatch(
|
|||||||
|
|
||||||
// region patch for quick actions
|
// region patch for quick actions
|
||||||
|
|
||||||
quickActionsElementFingerprint.methodOrThrow().apply {
|
quickActionsElementSyntheticFingerprint.methodOrThrow().apply {
|
||||||
val containerCalls = implementation!!.instructions.withIndex()
|
val containerCalls = implementation!!.instructions.withIndex()
|
||||||
.filter { instruction ->
|
.filter { instruction ->
|
||||||
(instruction.value as? WideLiteralInstruction)?.wideLiteral == quickActionsElementContainer
|
(instruction.value as? WideLiteralInstruction)?.wideLiteral == quickActionsElementContainer
|
||||||
@ -219,11 +219,13 @@ val fullscreenComponentsPatch = bytecodePatch(
|
|||||||
// region patch for compact control overlay
|
// region patch for compact control overlay
|
||||||
|
|
||||||
youtubeControlsOverlayFingerprint.methodOrThrow().apply {
|
youtubeControlsOverlayFingerprint.methodOrThrow().apply {
|
||||||
val targetIndex = indexOfFirstInstructionOrThrow {
|
val targetIndex = indexOfFocusableInTouchModeInstruction(this)
|
||||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
val walkerIndex = indexOfFirstInstructionOrThrow(targetIndex) {
|
||||||
getReference<MethodReference>()?.name == "setFocusableInTouchMode"
|
val reference = getReference<MethodReference>()
|
||||||
|
opcode == Opcode.INVOKE_STATIC &&
|
||||||
|
reference?.returnType == "Z" &&
|
||||||
|
reference.parameterTypes.size == 1
|
||||||
}
|
}
|
||||||
val walkerIndex = indexOfFirstInstructionOrThrow(targetIndex, Opcode.INVOKE_STATIC)
|
|
||||||
|
|
||||||
val walkerMethod = getWalkerMethod(walkerIndex)
|
val walkerMethod = getWalkerMethod(walkerIndex)
|
||||||
walkerMethod.apply {
|
walkerMethod.apply {
|
||||||
|
@ -10,7 +10,7 @@ import com.android.tools.smali.dexlib2.iface.Method
|
|||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This fingerprint is compatible with all YouTube versions after v18.15.40.
|
* YouTube v18.15.40 ~ YouTube 19.46.42
|
||||||
*/
|
*/
|
||||||
internal val userWasInShortsABConfigFingerprint = legacyFingerprint(
|
internal val userWasInShortsABConfigFingerprint = legacyFingerprint(
|
||||||
name = "userWasInShortsABConfigFingerprint",
|
name = "userWasInShortsABConfigFingerprint",
|
||||||
@ -27,10 +27,35 @@ internal fun indexOfOptionalInstruction(method: Method) =
|
|||||||
getReference<MethodReference>().toString() == "Lj${'$'}/util/Optional;->of(Ljava/lang/Object;)Lj${'$'}/util/Optional;"
|
getReference<MethodReference>().toString() == "Lj${'$'}/util/Optional;->of(Ljava/lang/Object;)Lj${'$'}/util/Optional;"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* YouTube 19.47.53 ~
|
||||||
|
*/
|
||||||
|
internal val userWasInShortsABConfigAlternativeFingerprint = legacyFingerprint(
|
||||||
|
name = "userWasInShortsABConfigAlternativeFingerprint",
|
||||||
|
returnType = "V",
|
||||||
|
parameters = listOf("I"),
|
||||||
|
opcodes = listOf(Opcode.OR_INT_LIT8),
|
||||||
|
strings = listOf("alias", "null"),
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ~ YouTube 19.50.42
|
||||||
|
*/
|
||||||
internal val userWasInShortsFingerprint = legacyFingerprint(
|
internal val userWasInShortsFingerprint = legacyFingerprint(
|
||||||
name = "userWasInShortsFingerprint",
|
name = "userWasInShortsFingerprint",
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = listOf("Ljava/lang/Object;"),
|
parameters = listOf("Ljava/lang/Object;"),
|
||||||
strings = listOf("Failed to read user_was_in_shorts proto after successful warmup")
|
strings = listOf("Failed to read user_was_in_shorts proto after successful warmup")
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* YouTube 20.02.08 ~
|
||||||
|
*/
|
||||||
|
internal val userWasInShortsAlternativeFingerprint = legacyFingerprint(
|
||||||
|
name = "userWasInShortsAlternativeFingerprint",
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = listOf("Ljava/lang/Object;"),
|
||||||
|
strings = listOf("userIsInShorts: ")
|
||||||
)
|
)
|
@ -1,20 +1,28 @@
|
|||||||
package app.revanced.patches.youtube.shorts.startupshortsreset
|
package app.revanced.patches.youtube.shorts.startupshortsreset
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.SHORTS_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.extension.Constants.SHORTS_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.patch.PatchList.DISABLE_RESUMING_SHORTS_ON_STARTUP
|
import app.revanced.patches.youtube.utils.patch.PatchList.DISABLE_RESUMING_SHORTS_ON_STARTUP
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.is_19_46_or_greater
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.is_20_02_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.ResourceUtils.addPreference
|
||||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||||
|
import app.revanced.util.fingerprint.matchOrThrow
|
||||||
import app.revanced.util.fingerprint.methodOrThrow
|
import app.revanced.util.fingerprint.methodOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
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.OneRegisterInstruction
|
||||||
@ -27,12 +35,14 @@ val resumingShortsOnStartupPatch = bytecodePatch(
|
|||||||
) {
|
) {
|
||||||
compatibleWith(COMPATIBLE_PACKAGE)
|
compatibleWith(COMPATIBLE_PACKAGE)
|
||||||
|
|
||||||
dependsOn(settingsPatch)
|
dependsOn(
|
||||||
|
settingsPatch,
|
||||||
|
versionCheckPatch,
|
||||||
|
)
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
|
|
||||||
userWasInShortsABConfigFingerprint.methodOrThrow().apply {
|
fun MutableMethod.hookUserWasInShortsABConfig(startIndex: Int) {
|
||||||
val startIndex = indexOfOptionalInstruction(this)
|
|
||||||
val walkerIndex = implementation!!.instructions.let {
|
val walkerIndex = implementation!!.instructions.let {
|
||||||
val subListIndex =
|
val subListIndex =
|
||||||
it.subList(startIndex, startIndex + 20).indexOfFirst { instruction ->
|
it.subList(startIndex, startIndex + 20).indexOfFirst { instruction ->
|
||||||
@ -64,29 +74,65 @@ val resumingShortsOnStartupPatch = bytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userWasInShortsFingerprint.methodOrThrow().apply {
|
if (is_19_46_or_greater) {
|
||||||
val listenableInstructionIndex = indexOfFirstInstructionOrThrow {
|
userWasInShortsABConfigAlternativeFingerprint.methodOrThrow().apply {
|
||||||
opcode == Opcode.INVOKE_INTERFACE &&
|
val stringIndex = indexOfFirstStringInstructionOrThrow("null")
|
||||||
getReference<MethodReference>()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" &&
|
val startIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.OR_INT_LIT8)
|
||||||
getReference<MethodReference>()?.name == "isDone"
|
hookUserWasInShortsABConfig(startIndex)
|
||||||
}
|
}
|
||||||
val originalInstructionRegister =
|
} else {
|
||||||
getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC
|
userWasInShortsABConfigFingerprint.methodOrThrow().apply {
|
||||||
val freeRegister =
|
val startIndex = indexOfOptionalInstruction(this)
|
||||||
getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA
|
hookUserWasInShortsABConfig(startIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
if (is_20_02_or_greater) {
|
||||||
listenableInstructionIndex + 1,
|
userWasInShortsAlternativeFingerprint.matchOrThrow().let {
|
||||||
"""
|
it.method.apply {
|
||||||
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
|
val stringIndex = it.stringMatches!!.first().index
|
||||||
move-result v$freeRegister
|
val booleanValueIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) {
|
||||||
if-eqz v$freeRegister, :show
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
return-void
|
getReference<MethodReference>()?.name == "booleanValue"
|
||||||
:show
|
}
|
||||||
invoke-interface {v$originalInstructionRegister}, Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z
|
val booleanValueRegister =
|
||||||
|
getInstruction<OneRegisterInstruction>(booleanValueIndex + 1).registerA
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
booleanValueIndex + 2, """
|
||||||
|
invoke-static {v$booleanValueRegister}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer(Z)Z
|
||||||
|
move-result v$booleanValueRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
userWasInShortsFingerprint.methodOrThrow().apply {
|
||||||
|
val listenableInstructionIndex = indexOfFirstInstructionOrThrow {
|
||||||
|
val reference = getReference<MethodReference>()
|
||||||
|
opcode == Opcode.INVOKE_INTERFACE &&
|
||||||
|
reference?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" &&
|
||||||
|
reference.name == "isDone"
|
||||||
|
}
|
||||||
|
val originalInstructionRegister =
|
||||||
|
getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC
|
||||||
|
val freeRegister =
|
||||||
|
getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA
|
||||||
|
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
listenableInstructionIndex + 1,
|
||||||
"""
|
"""
|
||||||
)
|
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
|
||||||
removeInstruction(listenableInstructionIndex)
|
move-result v$freeRegister
|
||||||
|
if-eqz v$freeRegister, :show
|
||||||
|
return-void
|
||||||
|
:show
|
||||||
|
invoke-interface {v$originalInstructionRegister}, Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
removeInstruction(listenableInstructionIndex)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// region add settings
|
// region add settings
|
||||||
|
@ -27,14 +27,12 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|||||||
|
|
||||||
internal val bottomSheetMenuItemBuilderFingerprint = legacyFingerprint(
|
internal val bottomSheetMenuItemBuilderFingerprint = legacyFingerprint(
|
||||||
name = "bottomSheetMenuItemBuilderFingerprint",
|
name = "bottomSheetMenuItemBuilderFingerprint",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
returnType = "L",
|
returnType = "L",
|
||||||
parameters = listOf("L"),
|
parameters = listOf("L"),
|
||||||
opcodes = listOf(
|
opcodes = listOf(
|
||||||
Opcode.INVOKE_STATIC,
|
Opcode.IGET,
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
Opcode.AND_INT_LIT16,
|
||||||
Opcode.INVOKE_STATIC,
|
Opcode.IF_EQZ,
|
||||||
Opcode.MOVE_RESULT_OBJECT
|
|
||||||
),
|
),
|
||||||
strings = listOf("Text missing for BottomSheetMenuItem."),
|
strings = listOf("Text missing for BottomSheetMenuItem."),
|
||||||
customFingerprint = { method, _ ->
|
customFingerprint = { method, _ ->
|
||||||
@ -251,9 +249,19 @@ internal val youtubeControlsOverlayFingerprint = legacyFingerprint(
|
|||||||
fadeDurationFast,
|
fadeDurationFast,
|
||||||
insetOverlayViewLayout,
|
insetOverlayViewLayout,
|
||||||
scrimOverlay,
|
scrimOverlay,
|
||||||
seekUndoEduOverlayStub
|
// Removed in YouTube 20.02.38+
|
||||||
|
// seekUndoEduOverlayStub
|
||||||
),
|
),
|
||||||
|
customFingerprint = { method, _ ->
|
||||||
|
indexOfFocusableInTouchModeInstruction(method) >= 0
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal fun indexOfFocusableInTouchModeInstruction(method: Method) =
|
||||||
|
method.indexOfFirstInstruction {
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
getReference<MethodReference>()?.name == "setFocusableInTouchMode"
|
||||||
|
}
|
||||||
|
|
||||||
const val PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR =
|
const val PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR =
|
||||||
"Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
"Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
@ -15,7 +15,8 @@ internal object Constants {
|
|||||||
"18.48.39", // This is the last version that do not use Rolling Number.
|
"18.48.39", // This is the last version that do not use Rolling Number.
|
||||||
"19.05.36", // This is the last version with the least YouTube experimental flag.
|
"19.05.36", // This is the last version with the least YouTube experimental flag.
|
||||||
"19.16.39", // This is the last version where the 'Restore old seekbar thumbnails' setting works.
|
"19.16.39", // This is the last version where the 'Restore old seekbar thumbnails' setting works.
|
||||||
"19.44.39", // This is the latest version supported by the RVX patch.
|
"19.44.39", // This is the last supported version for 2024.
|
||||||
|
"20.02.38", // This is the latest version supported by the RVX patch.
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -7,56 +7,91 @@ import app.revanced.patcher.patch.bytecodePatch
|
|||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.EXTENSION_PATH
|
import app.revanced.patches.youtube.utils.extension.Constants.EXTENSION_PATH
|
||||||
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
|
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater
|
||||||
|
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||||
import app.revanced.util.addStaticFieldToExtension
|
import app.revanced.util.addStaticFieldToExtension
|
||||||
import app.revanced.util.findMethodOrThrow
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.fingerprint.methodOrThrow
|
import app.revanced.util.fingerprint.methodOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.getWalkerMethod
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
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.ReferenceInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||||
|
import kotlin.collections.mutableListOf
|
||||||
|
|
||||||
private const val EXTENSION_VIDEO_UTILS_CLASS_DESCRIPTOR =
|
private const val EXTENSION_VIDEO_UTILS_CLASS_DESCRIPTOR =
|
||||||
"$EXTENSION_PATH/utils/VideoUtils;"
|
"$EXTENSION_PATH/utils/VideoUtils;"
|
||||||
|
|
||||||
internal lateinit var enterFullscreenMethod: MutableMethod
|
internal var enterFullscreenMethods = mutableListOf<MutableMethod>()
|
||||||
|
|
||||||
val fullscreenButtonHookPatch = bytecodePatch(
|
val fullscreenButtonHookPatch = bytecodePatch(
|
||||||
description = "fullscreenButtonHookPatch"
|
description = "fullscreenButtonHookPatch"
|
||||||
) {
|
) {
|
||||||
|
|
||||||
dependsOn(sharedExtensionPatch)
|
dependsOn(
|
||||||
|
sharedExtensionPatch,
|
||||||
|
versionCheckPatch,
|
||||||
|
)
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
val (referenceClass, fullscreenActionClass) = with(
|
fun getParameters(): Pair<MutableMethod, String> {
|
||||||
nextGenWatchLayoutFullscreenModeFingerprint.methodOrThrow()
|
nextGenWatchLayoutFullscreenModeFingerprint.methodOrThrow().apply {
|
||||||
) {
|
val methodIndex = indexOfFirstInstructionReversedOrThrow {
|
||||||
val targetIndex = indexOfFirstInstructionReversedOrThrow {
|
opcode == Opcode.INVOKE_DIRECT &&
|
||||||
opcode == Opcode.INVOKE_DIRECT &&
|
getReference<MethodReference>()?.parameterTypes?.size == 2
|
||||||
getReference<MethodReference>()?.parameterTypes?.size == 2
|
}
|
||||||
}
|
val fieldIndex =
|
||||||
val targetReference =
|
indexOfFirstInstructionReversedOrThrow(methodIndex, Opcode.IGET_OBJECT)
|
||||||
getInstruction<ReferenceInstruction>(targetIndex).reference as MethodReference
|
val fullscreenActionClass =
|
||||||
|
(getInstruction<ReferenceInstruction>(fieldIndex).reference as FieldReference).type
|
||||||
|
|
||||||
Pair(targetReference.definingClass, targetReference.parameterTypes[1].toString())
|
if (is_20_02_or_greater) {
|
||||||
|
val setAnimatorListenerIndex =
|
||||||
|
indexOfFirstInstructionOrThrow(methodIndex, Opcode.INVOKE_VIRTUAL)
|
||||||
|
getWalkerMethod(setAnimatorListenerIndex).apply {
|
||||||
|
val addListenerIndex = indexOfFirstInstructionOrThrow {
|
||||||
|
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
getReference<MethodReference>()?.name == "addListener"
|
||||||
|
}
|
||||||
|
val animatorListenerAdapterClass = getInstruction<ReferenceInstruction>(
|
||||||
|
indexOfFirstInstructionReversedOrThrow(addListenerIndex, Opcode.NEW_INSTANCE)
|
||||||
|
).reference.toString()
|
||||||
|
return Pair(
|
||||||
|
findMethodOrThrow(animatorListenerAdapterClass) { parameters.isEmpty() },
|
||||||
|
fullscreenActionClass
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val animatorListenerClass =
|
||||||
|
(getInstruction<ReferenceInstruction>(methodIndex).reference as MethodReference).definingClass
|
||||||
|
return Pair(
|
||||||
|
findMethodOrThrow(animatorListenerClass) { parameters == listOf("I") },
|
||||||
|
fullscreenActionClass
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val (animatorListenerMethod, fullscreenActionClass) = getParameters()
|
||||||
|
|
||||||
val (enterFullscreenReference, exitFullscreenReference, opcodeName) =
|
val (enterFullscreenReference, exitFullscreenReference, opcodeName) =
|
||||||
with(findMethodOrThrow(referenceClass) { parameters == listOf("I") }) {
|
with(animatorListenerMethod) {
|
||||||
val enterFullscreenIndex = indexOfFirstInstructionOrThrow {
|
val enterFullscreenIndex = indexOfFirstInstructionOrThrow {
|
||||||
val reference = getReference<MethodReference>()
|
val reference = getReference<MethodReference>()
|
||||||
reference?.returnType == "V" &&
|
reference?.returnType == "V" &&
|
||||||
reference.definingClass == fullscreenActionClass &&
|
reference.definingClass == fullscreenActionClass &&
|
||||||
reference.parameterTypes.size == 0
|
reference.parameterTypes.isEmpty()
|
||||||
}
|
}
|
||||||
val exitFullscreenIndex = indexOfFirstInstructionReversedOrThrow {
|
val exitFullscreenIndex = indexOfFirstInstructionReversedOrThrow {
|
||||||
val reference = getReference<MethodReference>()
|
val reference = getReference<MethodReference>()
|
||||||
reference?.returnType == "V" &&
|
reference?.returnType == "V" &&
|
||||||
reference.definingClass == fullscreenActionClass &&
|
reference.definingClass == fullscreenActionClass &&
|
||||||
reference.parameterTypes.size == 0
|
reference.parameterTypes.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
val enterFullscreenReference =
|
val enterFullscreenReference =
|
||||||
@ -68,18 +103,28 @@ val fullscreenButtonHookPatch = bytecodePatch(
|
|||||||
val enterFullscreenClass =
|
val enterFullscreenClass =
|
||||||
(enterFullscreenReference as MethodReference).definingClass
|
(enterFullscreenReference as MethodReference).definingClass
|
||||||
|
|
||||||
enterFullscreenMethod = if (opcode == Opcode.INVOKE_INTERFACE) {
|
if (opcode == Opcode.INVOKE_INTERFACE) {
|
||||||
classes.find { classDef -> classDef.interfaces.contains(enterFullscreenClass) }
|
classes.forEach { classDef ->
|
||||||
?.let { classDef ->
|
if (enterFullscreenMethods.size >= 2)
|
||||||
|
return@forEach
|
||||||
|
if (!classDef.interfaces.contains(enterFullscreenClass))
|
||||||
|
return@forEach
|
||||||
|
|
||||||
|
val enterFullscreenMethod =
|
||||||
proxy(classDef)
|
proxy(classDef)
|
||||||
.mutableClass
|
.mutableClass
|
||||||
.methods
|
.methods
|
||||||
.find { method -> method.name == enterFullscreenReference.name }
|
.find { method -> method.name == enterFullscreenReference.name }
|
||||||
} ?: throw PatchException("No matching classes: $enterFullscreenClass")
|
?: throw PatchException("No matching classes: $enterFullscreenClass")
|
||||||
} else {
|
|
||||||
findMethodOrThrow(enterFullscreenClass) {
|
enterFullscreenMethods.add(enterFullscreenMethod)
|
||||||
name == enterFullscreenReference.name
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
val enterFullscreenMethod =
|
||||||
|
findMethodOrThrow(enterFullscreenClass) {
|
||||||
|
name == enterFullscreenReference.name
|
||||||
|
}
|
||||||
|
enterFullscreenMethods.add(enterFullscreenMethod)
|
||||||
}
|
}
|
||||||
|
|
||||||
Triple(
|
Triple(
|
||||||
|
@ -9,7 +9,7 @@ import app.revanced.patcher.patch.resourcePatch
|
|||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patches.youtube.utils.extension.Constants.UTILS_PATH
|
import app.revanced.patches.youtube.utils.extension.Constants.UTILS_PATH
|
||||||
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
|
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
|
||||||
import app.revanced.patches.youtube.utils.fullscreen.enterFullscreenMethod
|
import app.revanced.patches.youtube.utils.fullscreen.enterFullscreenMethods
|
||||||
import app.revanced.patches.youtube.utils.fullscreen.fullscreenButtonHookPatch
|
import app.revanced.patches.youtube.utils.fullscreen.fullscreenButtonHookPatch
|
||||||
import app.revanced.patches.youtube.utils.playerButtonsResourcesFingerprint
|
import app.revanced.patches.youtube.utils.playerButtonsResourcesFingerprint
|
||||||
import app.revanced.patches.youtube.utils.playerButtonsVisibilityFingerprint
|
import app.revanced.patches.youtube.utils.playerButtonsVisibilityFingerprint
|
||||||
@ -122,10 +122,12 @@ private val playerControlsBytecodePatch = bytecodePatch(
|
|||||||
|
|
||||||
// Reproduced only in RVX
|
// Reproduced only in RVX
|
||||||
if (is_19_23_or_greater) {
|
if (is_19_23_or_greater) {
|
||||||
enterFullscreenMethod.addInstruction(
|
enterFullscreenMethods.forEach { method ->
|
||||||
0,
|
method.addInstruction(
|
||||||
"invoke-static {}, $EXTENSION_PLAYER_CONTROLS_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediately()V"
|
0,
|
||||||
)
|
"invoke-static {}, $EXTENSION_PLAYER_CONTROLS_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediately()V"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -51,6 +51,8 @@ var is_19_44_or_greater = false
|
|||||||
private set
|
private set
|
||||||
var is_19_46_or_greater = false
|
var is_19_46_or_greater = false
|
||||||
private set
|
private set
|
||||||
|
var is_20_02_or_greater = false
|
||||||
|
private set
|
||||||
|
|
||||||
val versionCheckPatch = resourcePatch(
|
val versionCheckPatch = resourcePatch(
|
||||||
description = "versionCheckPatch",
|
description = "versionCheckPatch",
|
||||||
@ -89,5 +91,6 @@ val versionCheckPatch = resourcePatch(
|
|||||||
is_19_43_or_greater = 244405000 <= playStoreServicesVersion
|
is_19_43_or_greater = 244405000 <= playStoreServicesVersion
|
||||||
is_19_44_or_greater = 244505000 <= playStoreServicesVersion
|
is_19_44_or_greater = 244505000 <= playStoreServicesVersion
|
||||||
is_19_46_or_greater = 244705000 <= playStoreServicesVersion
|
is_19_46_or_greater = 244705000 <= playStoreServicesVersion
|
||||||
|
is_20_02_or_greater = 250299000 <= playStoreServicesVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ package app.revanced.patches.youtube.utils.settings
|
|||||||
|
|
||||||
import app.revanced.patches.youtube.utils.resourceid.appearance
|
import app.revanced.patches.youtube.utils.resourceid.appearance
|
||||||
import app.revanced.util.fingerprint.legacyFingerprint
|
import app.revanced.util.fingerprint.legacyFingerprint
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal val themeSetterSystemFingerprint = legacyFingerprint(
|
internal val themeSetterSystemFingerprint = legacyFingerprint(
|
||||||
name = "themeSetterSystemFingerprint",
|
name = "themeSetterSystemFingerprint",
|
||||||
returnType = "L",
|
returnType = "L",
|
||||||
opcodes = listOf(Opcode.RETURN_OBJECT),
|
|
||||||
literals = listOf(appearance),
|
literals = listOf(appearance),
|
||||||
)
|
)
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package app.revanced.patches.youtube.utils.settings
|
package app.revanced.patches.youtube.utils.settings
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patcher.patch.resourcePatch
|
import app.revanced.patcher.patch.resourcePatch
|
||||||
import app.revanced.patcher.patch.stringOption
|
import app.revanced.patcher.patch.stringOption
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
|
||||||
import app.revanced.patches.shared.extension.Constants.EXTENSION_UTILS_CLASS_DESCRIPTOR
|
import app.revanced.patches.shared.extension.Constants.EXTENSION_UTILS_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.shared.extension.Constants.EXTENSION_UTILS_PATH
|
import app.revanced.patches.shared.extension.Constants.EXTENSION_UTILS_PATH
|
||||||
import app.revanced.patches.shared.mainactivity.injectConstructorMethodCall
|
import app.revanced.patches.shared.mainactivity.injectConstructorMethodCall
|
||||||
@ -23,11 +20,14 @@ import app.revanced.patches.youtube.utils.patch.PatchList.SETTINGS_FOR_YOUTUBE
|
|||||||
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
|
||||||
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||||
import app.revanced.util.ResourceGroup
|
import app.revanced.util.ResourceGroup
|
||||||
|
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||||
import app.revanced.util.copyResources
|
import app.revanced.util.copyResources
|
||||||
import app.revanced.util.copyXmlNode
|
import app.revanced.util.copyXmlNode
|
||||||
import app.revanced.util.fingerprint.matchOrThrow
|
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||||
|
import app.revanced.util.fingerprint.methodOrThrow
|
||||||
import app.revanced.util.removeStringsElements
|
import app.revanced.util.removeStringsElements
|
||||||
import app.revanced.util.valueOrThrow
|
import app.revanced.util.valueOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
@ -50,23 +50,16 @@ private val settingsBytecodePatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
execute {
|
execute {
|
||||||
fun MutableMethod.injectCall(index: Int) {
|
|
||||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
index + 1, """
|
|
||||||
invoke-static {v$register}, $EXTENSION_THEME_METHOD_DESCRIPTOR
|
|
||||||
return-object v$register
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
removeInstruction(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply the current theme of the settings page
|
// apply the current theme of the settings page
|
||||||
themeSetterSystemFingerprint.matchOrThrow().let {
|
themeSetterSystemFingerprint.methodOrThrow().apply {
|
||||||
it.method.apply {
|
findInstructionIndicesReversedOrThrow(Opcode.RETURN_OBJECT).forEach { index ->
|
||||||
injectCall(implementation!!.instructions.size - 1)
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
injectCall(it.patternMatch!!.startIndex)
|
|
||||||
|
addInstructionsAtControlFlowLabel(
|
||||||
|
index,
|
||||||
|
"invoke-static { v$register }, $EXTENSION_THEME_METHOD_DESCRIPTOR"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,11 +249,13 @@ val videoInformationPatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(45368273L)
|
val literalIndex = indexOfFirstLiteralInstructionOrThrow(45368273L)
|
||||||
val walkerIndex =
|
val walkerIndex = indexOfFirstInstructionReversedOrThrow(literalIndex) {
|
||||||
indexOfFirstInstructionReversedOrThrow(
|
val reference = getReference<MethodReference>()
|
||||||
literalIndex,
|
(opcode == Opcode.INVOKE_VIRTUAL || opcode == Opcode.INVOKE_VIRTUAL_RANGE) &&
|
||||||
Opcode.INVOKE_VIRTUAL_RANGE
|
reference?.definingClass == definingClass &&
|
||||||
)
|
reference.parameterTypes.isEmpty() &&
|
||||||
|
reference.returnType == "V"
|
||||||
|
}
|
||||||
|
|
||||||
videoEndMethod = getWalkerMethod(walkerIndex)
|
videoEndMethod = getWalkerMethod(walkerIndex)
|
||||||
}
|
}
|
||||||
|
@ -13,20 +13,12 @@ private val PLAYER_PARAMETER_STARTS_WITH_PARAMETER_LIST = listOf(
|
|||||||
"I",
|
"I",
|
||||||
"I"
|
"I"
|
||||||
)
|
)
|
||||||
private val PLAYER_PARAMETER_ENDS_WITH_PARAMETER_LIST = listOf(
|
|
||||||
"Ljava/util/Set;",
|
|
||||||
"Ljava/lang/String;",
|
|
||||||
"Ljava/lang/String;",
|
|
||||||
"L",
|
|
||||||
"Z", // Appears to indicate if the video id is being opened or is currently playing.
|
|
||||||
"Z",
|
|
||||||
"Z"
|
|
||||||
)
|
|
||||||
|
|
||||||
internal val playerParameterBuilderFingerprint = legacyFingerprint(
|
internal val playerParameterBuilderFingerprint = legacyFingerprint(
|
||||||
name = "playerParameterBuilderFingerprint",
|
name = "playerParameterBuilderFingerprint",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
returnType = "L",
|
returnType = "L",
|
||||||
|
strings = listOf("psps"),
|
||||||
// 19.22 and earlier parameters are:
|
// 19.22 and earlier parameters are:
|
||||||
// "Ljava/lang/String;", // VideoId.
|
// "Ljava/lang/String;", // VideoId.
|
||||||
// "[B",
|
// "[B",
|
||||||
@ -60,20 +52,41 @@ internal val playerParameterBuilderFingerprint = legacyFingerprint(
|
|||||||
customFingerprint = custom@{ method, _ ->
|
customFingerprint = custom@{ method, _ ->
|
||||||
val parameterTypes = method.parameterTypes
|
val parameterTypes = method.parameterTypes
|
||||||
val parameterSize = parameterTypes.size
|
val parameterSize = parameterTypes.size
|
||||||
if (parameterSize != 13 && parameterSize != 14) {
|
if (parameterSize < 13) {
|
||||||
return@custom false
|
return@custom false
|
||||||
}
|
}
|
||||||
|
|
||||||
val startsWithMethodParameterList = parameterTypes.slice(0..5)
|
val startsWithMethodParameterList = parameterTypes.slice(0..5)
|
||||||
val endsWithMethodParameterList = parameterTypes.slice(parameterSize - 7..<parameterSize)
|
|
||||||
|
|
||||||
parametersEqual(
|
parametersEqual(
|
||||||
PLAYER_PARAMETER_STARTS_WITH_PARAMETER_LIST,
|
PLAYER_PARAMETER_STARTS_WITH_PARAMETER_LIST,
|
||||||
startsWithMethodParameterList
|
startsWithMethodParameterList
|
||||||
) &&
|
)
|
||||||
parametersEqual(
|
|
||||||
PLAYER_PARAMETER_ENDS_WITH_PARAMETER_LIST,
|
|
||||||
endsWithMethodParameterList
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For targets 19.22 and earlier.
|
||||||
|
*/
|
||||||
|
private val PLAYER_PARAMETER_LEGACY_LIST = listOf(
|
||||||
|
"Ljava/lang/String;", // VideoId.
|
||||||
|
"[B",
|
||||||
|
"Ljava/lang/String;", // Player parameters proto buffer.
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
"I",
|
||||||
|
"I",
|
||||||
|
"Ljava/util/Set;",
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
"Ljava/lang/String;",
|
||||||
|
"L",
|
||||||
|
"Z", // Appears to indicate if the video id is being opened or is currently playing.
|
||||||
|
"Z",
|
||||||
|
"Z",
|
||||||
|
)
|
||||||
|
|
||||||
|
internal val playerParameterBuilderLegacyFingerprint = legacyFingerprint(
|
||||||
|
name = "playerParameterBuilderLegacyFingerprint",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
returnType = "L",
|
||||||
|
parameters = PLAYER_PARAMETER_LEGACY_LIST,
|
||||||
)
|
)
|
@ -35,7 +35,7 @@ val playerResponseMethodHookPatch = bytecodePatch(
|
|||||||
execute {
|
execute {
|
||||||
playerParameterBuilderFingerprint.methodOrThrow().apply {
|
playerParameterBuilderFingerprint.methodOrThrow().apply {
|
||||||
playerResponseMethod = this
|
playerResponseMethod = this
|
||||||
parameterIsShortAndOpeningOrPlaying = parameters.size - 2
|
parameterIsShortAndOpeningOrPlaying = parameterTypes.indexOfFirst { it == "Z" } + 1
|
||||||
// On some app targets the method has too many registers pushing the parameters past v15.
|
// On some app targets the method has too many registers pushing the parameters past v15.
|
||||||
// If needed, move the parameters to 4-bit registers so they can be passed to extension.
|
// If needed, move the parameters to 4-bit registers so they can be passed to extension.
|
||||||
playerResponseMethodCopyRegisters = implementation!!.registerCount -
|
playerResponseMethodCopyRegisters = implementation!!.registerCount -
|
||||||
|
Loading…
x
Reference in New Issue
Block a user