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();
|
||||
}
|
||||
|
||||
public static boolean disableResumingStartupShortsPlayer(boolean original) {
|
||||
return !Settings.DISABLE_RESUMING_SHORTS_PLAYER.get() && original;
|
||||
}
|
||||
|
||||
public static boolean enableShortsTimeStamp(boolean 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.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
import app.revanced.util.indexOfFirstStringInstruction
|
||||
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
||||
import app.revanced.util.or
|
||||
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.reference.FieldReference
|
||||
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.util.MethodUtil
|
||||
|
||||
@ -42,6 +44,8 @@ private var filterCount = 0
|
||||
internal lateinit var addLithoFilter: (String) -> Unit
|
||||
private set
|
||||
|
||||
internal var emptyComponentLabel = ""
|
||||
|
||||
val lithoFilterPatch = bytecodePatch(
|
||||
description = "lithoFilterPatch",
|
||||
) {
|
||||
@ -73,6 +77,8 @@ val lithoFilterPatch = bytecodePatch(
|
||||
return-object v0
|
||||
"""
|
||||
|
||||
emptyComponentLabel = label
|
||||
|
||||
Pair(this, label)
|
||||
}
|
||||
}
|
||||
@ -121,17 +127,25 @@ val lithoFilterPatch = bytecodePatch(
|
||||
val stringBuilderRegister =
|
||||
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>(
|
||||
indexOfFirstInstructionReversedOrThrow(emptyStringIndex) {
|
||||
indexOfFirstInstructionReversedOrThrow(relativeIndex) {
|
||||
opcode == Opcode.IPUT_OBJECT
|
||||
&& getReference<FieldReference>()?.type == "Ljava/lang/String;"
|
||||
}
|
||||
).registerA
|
||||
val objectRegister = getInstruction<FiveRegisterInstruction>(
|
||||
indexOfFirstInstructionOrThrow(emptyStringIndex) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL
|
||||
}
|
||||
indexOfFirstInstructionOrThrow(relativeIndex, Opcode.INVOKE_VIRTUAL)
|
||||
).registerC
|
||||
|
||||
val insertIndex = stringBuilderIndex + 1
|
||||
|
@ -16,6 +16,7 @@ import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
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.FieldReference
|
||||
@ -40,11 +41,11 @@ val textComponentPatch = bytecodePatch(
|
||||
spannedIndex = indexOfSpannableStringInstruction(this)
|
||||
spannedRegister = getInstruction<FiveRegisterInstruction>(spannedIndex).registerC
|
||||
spannedContextRegister =
|
||||
getInstruction<TwoRegisterInstruction>(0).registerA
|
||||
getInstruction<OneRegisterInstruction>(spannedIndex + 1).registerA
|
||||
|
||||
replaceInstruction(
|
||||
spannedIndex,
|
||||
"nop"
|
||||
"move-object/from16 v$spannedContextRegister, p0"
|
||||
)
|
||||
addInstruction(
|
||||
++spannedIndex,
|
||||
|
@ -10,6 +10,7 @@ import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
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.youtube.utils.bottomsheet.bottomSheetHookPatch
|
||||
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.patch.PatchList.HIDE_FEED_COMPONENTS
|
||||
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.captionToggleContainer
|
||||
import app.revanced.patches.youtube.utils.resourceid.channelListSubMenu
|
||||
@ -78,6 +82,7 @@ val feedComponentsPatch = bytecodePatch(
|
||||
sharedResourceIdPatch,
|
||||
settingsPatch,
|
||||
bottomSheetHookPatch,
|
||||
versionCheckPatch,
|
||||
)
|
||||
execute {
|
||||
|
||||
@ -223,19 +228,22 @@ val feedComponentsPatch = bytecodePatch(
|
||||
|
||||
// region patch for hide subscriptions channel section for tablet
|
||||
|
||||
arrayOf(
|
||||
channelListSubMenuTabletFingerprint,
|
||||
channelListSubMenuTabletSyntheticFingerprint
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.methodOrThrow().apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $FEED_CLASS_DESCRIPTOR->hideSubscriptionsChannelSection()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
// Integrated as a litho component since YouTube 20.02.
|
||||
if (!is_20_02_or_greater) {
|
||||
arrayOf(
|
||||
channelListSubMenuTabletFingerprint,
|
||||
channelListSubMenuTabletSyntheticFingerprint
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.methodOrThrow().apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $FEED_CLASS_DESCRIPTOR->hideSubscriptionsChannelSection()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,29 +295,27 @@ val feedComponentsPatch = bytecodePatch(
|
||||
it.method.apply {
|
||||
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||
val insertIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
val reference = getReference<MethodReference>()
|
||||
|
||||
reference?.parameterTypes?.size == 1 &&
|
||||
reference.parameterTypes.first() == "[B" &&
|
||||
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 jumpIndex = it.patternMatch!!.startIndex
|
||||
|
||||
addInstructionsWithLabels(
|
||||
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
|
||||
if-nez v$freeRegister, :filter
|
||||
""", ExternalLabel("filter", getInstruction(jumpIndex))
|
||||
)
|
||||
|
||||
addInstruction(
|
||||
0,
|
||||
"move-object/from16 v$freeRegister, p3"
|
||||
if-eqz v$freeRegister, :ignore
|
||||
""" + emptyComponentLabel,
|
||||
ExternalLabel("ignore", getInstruction(insertIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,6 @@ internal val floatingMicrophoneFingerprint = legacyFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_BOOLEAN,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.RETURN_VOID
|
||||
),
|
||||
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.versionCheckPatch
|
||||
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.settings.ResourceUtils.addPreference
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
@ -154,18 +155,17 @@ val layoutComponentsPatch = bytecodePatch(
|
||||
|
||||
// region patch for hide floating microphone
|
||||
|
||||
floatingMicrophoneFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
val insertIndex = it.patternMatch!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
floatingMicrophoneFingerprint.methodOrThrow().apply {
|
||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(fab)
|
||||
val booleanIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.IGET_BOOLEAN)
|
||||
val insertRegister = getInstruction<TwoRegisterInstruction>(booleanIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex + 1, """
|
||||
invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingMicrophone(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
addInstructions(
|
||||
booleanIndex + 1, """
|
||||
invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingMicrophone(Z)Z
|
||||
move-result v$insertRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// 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.extension.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
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.resourceid.actionBarRingoBackground
|
||||
import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||
@ -265,7 +266,11 @@ val toolBarComponentsPatch = bytecodePatch(
|
||||
// region patch for hide search term thumbnail
|
||||
|
||||
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) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
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.patch.PatchList.PLAYER_COMPONENTS
|
||||
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.fadeDurationFast
|
||||
import app.revanced.patches.youtube.utils.resourceid.scrimOverlay
|
||||
@ -278,9 +280,15 @@ val playerComponentsPatch = bytecodePatch(
|
||||
speedOverlayPatch,
|
||||
suggestedVideoEndScreenPatch,
|
||||
videoInformationPatch,
|
||||
versionCheckPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
var settingArray = arrayOf(
|
||||
"PREFERENCE_SCREEN: PLAYER",
|
||||
"SETTINGS: PLAYER_COMPONENTS"
|
||||
)
|
||||
|
||||
fun MutableMethod.getAllLiteralComponent(
|
||||
startIndex: Int,
|
||||
endIndex: Int
|
||||
@ -563,30 +571,34 @@ val playerComponentsPatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
youtubeControlsOverlayFingerprint.methodOrThrow().apply {
|
||||
val insertIndex =
|
||||
indexOfFirstLiteralInstructionOrThrow(seekUndoEduOverlayStub)
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
if (!is_20_02_or_greater) {
|
||||
youtubeControlsOverlayFingerprint.methodOrThrow().apply {
|
||||
val insertIndex =
|
||||
indexOfFirstLiteralInstructionOrThrow(seekUndoEduOverlayStub)
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
val onClickListenerIndex = indexOfFirstInstructionOrThrow(insertIndex) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "setOnClickListener"
|
||||
}
|
||||
val constComponent = getFirstLiteralComponent(insertIndex, onClickListenerIndex - 1)
|
||||
val onClickListenerIndex = indexOfFirstInstructionOrThrow(insertIndex) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "setOnClickListener"
|
||||
}
|
||||
val constComponent = getFirstLiteralComponent(insertIndex, onClickListenerIndex - 1)
|
||||
|
||||
if (constComponent.isNotEmpty()) {
|
||||
addInstruction(
|
||||
onClickListenerIndex + 2,
|
||||
constComponent
|
||||
if (constComponent.isNotEmpty()) {
|
||||
addInstruction(
|
||||
onClickListenerIndex + 2,
|
||||
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
|
||||
@ -652,10 +664,7 @@ val playerComponentsPatch = bytecodePatch(
|
||||
// region add settings
|
||||
|
||||
addPreference(
|
||||
arrayOf(
|
||||
"PREFERENCE_SCREEN: PLAYER",
|
||||
"SETTINGS: PLAYER_COMPONENTS"
|
||||
),
|
||||
settingArray,
|
||||
PLAYER_COMPONENTS
|
||||
)
|
||||
|
||||
|
@ -7,6 +7,7 @@ import app.revanced.patches.youtube.utils.resourceid.quickActionsElementContaine
|
||||
import app.revanced.util.fingerprint.legacyFingerprint
|
||||
import app.revanced.util.or
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
internal val broadcastReceiverFingerprint = legacyFingerprint(
|
||||
name = "broadcastReceiverFingerprint",
|
||||
@ -45,12 +46,15 @@ internal val playerTitleViewFingerprint = legacyFingerprint(
|
||||
literals = listOf(playerVideoTitleView),
|
||||
)
|
||||
|
||||
internal val quickActionsElementFingerprint = legacyFingerprint(
|
||||
name = "quickActionsElementFingerprint",
|
||||
internal val quickActionsElementSyntheticFingerprint = legacyFingerprint(
|
||||
name = "quickActionsElementSyntheticFingerprint",
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Landroid/view/View;"),
|
||||
literals = listOf(quickActionsElementContainer),
|
||||
customFingerprint = { _, classDef ->
|
||||
AccessFlags.SYNTHETIC.isSet(classDef.accessFlags)
|
||||
}
|
||||
)
|
||||
|
||||
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_PATH
|
||||
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.mainactivity.mainActivityResolvePatch
|
||||
import app.revanced.patches.youtube.utils.patch.PatchList.FULLSCREEN_COMPONENTS
|
||||
@ -101,7 +102,6 @@ val fullscreenComponentsPatch = bytecodePatch(
|
||||
"invoke-static {v$targetRegister}, " +
|
||||
"$PLAYER_CLASS_DESCRIPTOR->disableEngagementPanels(Landroidx/coordinatorlayout/widget/CoordinatorLayout;)V"
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
playerTitleViewFingerprint.methodOrThrow().apply {
|
||||
@ -190,7 +190,7 @@ val fullscreenComponentsPatch = bytecodePatch(
|
||||
|
||||
// region patch for quick actions
|
||||
|
||||
quickActionsElementFingerprint.methodOrThrow().apply {
|
||||
quickActionsElementSyntheticFingerprint.methodOrThrow().apply {
|
||||
val containerCalls = implementation!!.instructions.withIndex()
|
||||
.filter { instruction ->
|
||||
(instruction.value as? WideLiteralInstruction)?.wideLiteral == quickActionsElementContainer
|
||||
@ -219,11 +219,13 @@ val fullscreenComponentsPatch = bytecodePatch(
|
||||
// region patch for compact control overlay
|
||||
|
||||
youtubeControlsOverlayFingerprint.methodOrThrow().apply {
|
||||
val targetIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "setFocusableInTouchMode"
|
||||
val targetIndex = indexOfFocusableInTouchModeInstruction(this)
|
||||
val walkerIndex = indexOfFirstInstructionOrThrow(targetIndex) {
|
||||
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)
|
||||
walkerMethod.apply {
|
||||
|
@ -10,7 +10,7 @@ import com.android.tools.smali.dexlib2.iface.Method
|
||||
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(
|
||||
name = "userWasInShortsABConfigFingerprint",
|
||||
@ -27,6 +27,20 @@ internal fun indexOfOptionalInstruction(method: Method) =
|
||||
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(
|
||||
name = "userWasInShortsFingerprint",
|
||||
returnType = "V",
|
||||
@ -34,3 +48,14 @@ internal val userWasInShortsFingerprint = legacyFingerprint(
|
||||
parameters = listOf("Ljava/lang/Object;"),
|
||||
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
|
||||
|
||||
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.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
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.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.settingsPatch
|
||||
import app.revanced.util.fingerprint.matchOrThrow
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getWalkerMethod
|
||||
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.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
@ -27,12 +35,14 @@ val resumingShortsOnStartupPatch = bytecodePatch(
|
||||
) {
|
||||
compatibleWith(COMPATIBLE_PACKAGE)
|
||||
|
||||
dependsOn(settingsPatch)
|
||||
dependsOn(
|
||||
settingsPatch,
|
||||
versionCheckPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
userWasInShortsABConfigFingerprint.methodOrThrow().apply {
|
||||
val startIndex = indexOfOptionalInstruction(this)
|
||||
fun MutableMethod.hookUserWasInShortsABConfig(startIndex: Int) {
|
||||
val walkerIndex = implementation!!.instructions.let {
|
||||
val subListIndex =
|
||||
it.subList(startIndex, startIndex + 20).indexOfFirst { instruction ->
|
||||
@ -64,29 +74,65 @@ val resumingShortsOnStartupPatch = bytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
userWasInShortsFingerprint.methodOrThrow().apply {
|
||||
val listenableInstructionIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_INTERFACE &&
|
||||
getReference<MethodReference>()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" &&
|
||||
getReference<MethodReference>()?.name == "isDone"
|
||||
if (is_19_46_or_greater) {
|
||||
userWasInShortsABConfigAlternativeFingerprint.methodOrThrow().apply {
|
||||
val stringIndex = indexOfFirstStringInstructionOrThrow("null")
|
||||
val startIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.OR_INT_LIT8)
|
||||
hookUserWasInShortsABConfig(startIndex)
|
||||
}
|
||||
val originalInstructionRegister =
|
||||
getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC
|
||||
val freeRegister =
|
||||
getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA
|
||||
} else {
|
||||
userWasInShortsABConfigFingerprint.methodOrThrow().apply {
|
||||
val startIndex = indexOfOptionalInstruction(this)
|
||||
hookUserWasInShortsABConfig(startIndex)
|
||||
}
|
||||
}
|
||||
|
||||
addInstructionsWithLabels(
|
||||
listenableInstructionIndex + 1,
|
||||
"""
|
||||
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :show
|
||||
return-void
|
||||
:show
|
||||
invoke-interface {v$originalInstructionRegister}, Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z
|
||||
if (is_20_02_or_greater) {
|
||||
userWasInShortsAlternativeFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
val stringIndex = it.stringMatches!!.first().index
|
||||
val booleanValueIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "booleanValue"
|
||||
}
|
||||
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,
|
||||
"""
|
||||
)
|
||||
removeInstruction(listenableInstructionIndex)
|
||||
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
|
||||
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
|
||||
|
@ -27,14 +27,12 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal val bottomSheetMenuItemBuilderFingerprint = legacyFingerprint(
|
||||
name = "bottomSheetMenuItemBuilderFingerprint",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "L",
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
Opcode.IGET,
|
||||
Opcode.AND_INT_LIT16,
|
||||
Opcode.IF_EQZ,
|
||||
),
|
||||
strings = listOf("Text missing for BottomSheetMenuItem."),
|
||||
customFingerprint = { method, _ ->
|
||||
@ -251,9 +249,19 @@ internal val youtubeControlsOverlayFingerprint = legacyFingerprint(
|
||||
fadeDurationFast,
|
||||
insetOverlayViewLayout,
|
||||
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 =
|
||||
"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.
|
||||
"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.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.patches.youtube.utils.extension.Constants.EXTENSION_PATH
|
||||
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.findMethodOrThrow
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
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.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
import kotlin.collections.mutableListOf
|
||||
|
||||
private const val EXTENSION_VIDEO_UTILS_CLASS_DESCRIPTOR =
|
||||
"$EXTENSION_PATH/utils/VideoUtils;"
|
||||
|
||||
internal lateinit var enterFullscreenMethod: MutableMethod
|
||||
internal var enterFullscreenMethods = mutableListOf<MutableMethod>()
|
||||
|
||||
val fullscreenButtonHookPatch = bytecodePatch(
|
||||
description = "fullscreenButtonHookPatch"
|
||||
) {
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
dependsOn(
|
||||
sharedExtensionPatch,
|
||||
versionCheckPatch,
|
||||
)
|
||||
|
||||
execute {
|
||||
val (referenceClass, fullscreenActionClass) = with(
|
||||
nextGenWatchLayoutFullscreenModeFingerprint.methodOrThrow()
|
||||
) {
|
||||
val targetIndex = indexOfFirstInstructionReversedOrThrow {
|
||||
opcode == Opcode.INVOKE_DIRECT &&
|
||||
getReference<MethodReference>()?.parameterTypes?.size == 2
|
||||
}
|
||||
val targetReference =
|
||||
getInstruction<ReferenceInstruction>(targetIndex).reference as MethodReference
|
||||
fun getParameters(): Pair<MutableMethod, String> {
|
||||
nextGenWatchLayoutFullscreenModeFingerprint.methodOrThrow().apply {
|
||||
val methodIndex = indexOfFirstInstructionReversedOrThrow {
|
||||
opcode == Opcode.INVOKE_DIRECT &&
|
||||
getReference<MethodReference>()?.parameterTypes?.size == 2
|
||||
}
|
||||
val fieldIndex =
|
||||
indexOfFirstInstructionReversedOrThrow(methodIndex, Opcode.IGET_OBJECT)
|
||||
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) =
|
||||
with(findMethodOrThrow(referenceClass) { parameters == listOf("I") }) {
|
||||
with(animatorListenerMethod) {
|
||||
val enterFullscreenIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.returnType == "V" &&
|
||||
reference.definingClass == fullscreenActionClass &&
|
||||
reference.parameterTypes.size == 0
|
||||
reference.parameterTypes.isEmpty()
|
||||
}
|
||||
val exitFullscreenIndex = indexOfFirstInstructionReversedOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.returnType == "V" &&
|
||||
reference.definingClass == fullscreenActionClass &&
|
||||
reference.parameterTypes.size == 0
|
||||
reference.parameterTypes.isEmpty()
|
||||
}
|
||||
|
||||
val enterFullscreenReference =
|
||||
@ -68,18 +103,28 @@ val fullscreenButtonHookPatch = bytecodePatch(
|
||||
val enterFullscreenClass =
|
||||
(enterFullscreenReference as MethodReference).definingClass
|
||||
|
||||
enterFullscreenMethod = if (opcode == Opcode.INVOKE_INTERFACE) {
|
||||
classes.find { classDef -> classDef.interfaces.contains(enterFullscreenClass) }
|
||||
?.let { classDef ->
|
||||
if (opcode == Opcode.INVOKE_INTERFACE) {
|
||||
classes.forEach { classDef ->
|
||||
if (enterFullscreenMethods.size >= 2)
|
||||
return@forEach
|
||||
if (!classDef.interfaces.contains(enterFullscreenClass))
|
||||
return@forEach
|
||||
|
||||
val enterFullscreenMethod =
|
||||
proxy(classDef)
|
||||
.mutableClass
|
||||
.methods
|
||||
.find { method -> method.name == enterFullscreenReference.name }
|
||||
} ?: throw PatchException("No matching classes: $enterFullscreenClass")
|
||||
} else {
|
||||
findMethodOrThrow(enterFullscreenClass) {
|
||||
name == enterFullscreenReference.name
|
||||
?: throw PatchException("No matching classes: $enterFullscreenClass")
|
||||
|
||||
enterFullscreenMethods.add(enterFullscreenMethod)
|
||||
}
|
||||
} else {
|
||||
val enterFullscreenMethod =
|
||||
findMethodOrThrow(enterFullscreenClass) {
|
||||
name == enterFullscreenReference.name
|
||||
}
|
||||
enterFullscreenMethods.add(enterFullscreenMethod)
|
||||
}
|
||||
|
||||
Triple(
|
||||
|
@ -9,7 +9,7 @@ import app.revanced.patcher.patch.resourcePatch
|
||||
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.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.playerButtonsResourcesFingerprint
|
||||
import app.revanced.patches.youtube.utils.playerButtonsVisibilityFingerprint
|
||||
@ -122,10 +122,12 @@ private val playerControlsBytecodePatch = bytecodePatch(
|
||||
|
||||
// Reproduced only in RVX
|
||||
if (is_19_23_or_greater) {
|
||||
enterFullscreenMethod.addInstruction(
|
||||
0,
|
||||
"invoke-static {}, $EXTENSION_PLAYER_CONTROLS_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediately()V"
|
||||
)
|
||||
enterFullscreenMethods.forEach { method ->
|
||||
method.addInstruction(
|
||||
0,
|
||||
"invoke-static {}, $EXTENSION_PLAYER_CONTROLS_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediately()V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
@ -51,6 +51,8 @@ var is_19_44_or_greater = false
|
||||
private set
|
||||
var is_19_46_or_greater = false
|
||||
private set
|
||||
var is_20_02_or_greater = false
|
||||
private set
|
||||
|
||||
val versionCheckPatch = resourcePatch(
|
||||
description = "versionCheckPatch",
|
||||
@ -89,5 +91,6 @@ val versionCheckPatch = resourcePatch(
|
||||
is_19_43_or_greater = 244405000 <= playStoreServicesVersion
|
||||
is_19_44_or_greater = 244505000 <= 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.util.fingerprint.legacyFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val themeSetterSystemFingerprint = legacyFingerprint(
|
||||
name = "themeSetterSystemFingerprint",
|
||||
returnType = "L",
|
||||
opcodes = listOf(Opcode.RETURN_OBJECT),
|
||||
literals = listOf(appearance),
|
||||
)
|
||||
|
@ -1,12 +1,9 @@
|
||||
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.removeInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.resourcePatch
|
||||
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_PATH
|
||||
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.resourceid.sharedResourceIdPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.addInstructionsAtControlFlowLabel
|
||||
import app.revanced.util.copyResources
|
||||
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.valueOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.w3c.dom.Element
|
||||
import java.nio.file.Files
|
||||
@ -50,23 +50,16 @@ private val settingsBytecodePatch = bytecodePatch(
|
||||
)
|
||||
|
||||
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
|
||||
themeSetterSystemFingerprint.matchOrThrow().let {
|
||||
it.method.apply {
|
||||
injectCall(implementation!!.instructions.size - 1)
|
||||
injectCall(it.patternMatch!!.startIndex)
|
||||
themeSetterSystemFingerprint.methodOrThrow().apply {
|
||||
findInstructionIndicesReversedOrThrow(Opcode.RETURN_OBJECT).forEach { index ->
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructionsAtControlFlowLabel(
|
||||
index,
|
||||
"invoke-static { v$register }, $EXTENSION_THEME_METHOD_DESCRIPTOR"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -249,11 +249,13 @@ val videoInformationPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
val literalIndex = indexOfFirstLiteralInstructionOrThrow(45368273L)
|
||||
val walkerIndex =
|
||||
indexOfFirstInstructionReversedOrThrow(
|
||||
literalIndex,
|
||||
Opcode.INVOKE_VIRTUAL_RANGE
|
||||
)
|
||||
val walkerIndex = indexOfFirstInstructionReversedOrThrow(literalIndex) {
|
||||
val reference = getReference<MethodReference>()
|
||||
(opcode == Opcode.INVOKE_VIRTUAL || opcode == Opcode.INVOKE_VIRTUAL_RANGE) &&
|
||||
reference?.definingClass == definingClass &&
|
||||
reference.parameterTypes.isEmpty() &&
|
||||
reference.returnType == "V"
|
||||
}
|
||||
|
||||
videoEndMethod = getWalkerMethod(walkerIndex)
|
||||
}
|
||||
|
@ -13,20 +13,12 @@ private val PLAYER_PARAMETER_STARTS_WITH_PARAMETER_LIST = listOf(
|
||||
"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(
|
||||
name = "playerParameterBuilderFingerprint",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "L",
|
||||
strings = listOf("psps"),
|
||||
// 19.22 and earlier parameters are:
|
||||
// "Ljava/lang/String;", // VideoId.
|
||||
// "[B",
|
||||
@ -60,20 +52,41 @@ internal val playerParameterBuilderFingerprint = legacyFingerprint(
|
||||
customFingerprint = custom@{ method, _ ->
|
||||
val parameterTypes = method.parameterTypes
|
||||
val parameterSize = parameterTypes.size
|
||||
if (parameterSize != 13 && parameterSize != 14) {
|
||||
if (parameterSize < 13) {
|
||||
return@custom false
|
||||
}
|
||||
|
||||
val startsWithMethodParameterList = parameterTypes.slice(0..5)
|
||||
val endsWithMethodParameterList = parameterTypes.slice(parameterSize - 7..<parameterSize)
|
||||
|
||||
parametersEqual(
|
||||
PLAYER_PARAMETER_STARTS_WITH_PARAMETER_LIST,
|
||||
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 {
|
||||
playerParameterBuilderFingerprint.methodOrThrow().apply {
|
||||
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.
|
||||
// If needed, move the parameters to 4-bit registers so they can be passed to extension.
|
||||
playerResponseMethodCopyRegisters = implementation!!.registerCount -
|
||||
|
Loading…
x
Reference in New Issue
Block a user