mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-06-13 05:37:40 +02:00
chore: remove obsolete code
This commit is contained in:
@ -5,7 +5,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
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.patch.PatchException
|
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.music.flyoutmenu.components.fingerprints.DialogSolidFingerprint
|
import app.revanced.patches.music.flyoutmenu.components.fingerprints.DialogSolidFingerprint
|
||||||
import app.revanced.patches.music.flyoutmenu.components.fingerprints.EndButtonsContainerFingerprint
|
import app.revanced.patches.music.flyoutmenu.components.fingerprints.EndButtonsContainerFingerprint
|
||||||
@ -20,11 +19,13 @@ import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH
|
|||||||
import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR
|
import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.EndButtonsContainer
|
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.EndButtonsContainer
|
||||||
|
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TrimSilenceSwitch
|
||||||
import app.revanced.patches.music.utils.settings.CategoryType
|
import app.revanced.patches.music.utils.settings.CategoryType
|
||||||
import app.revanced.patches.music.utils.settings.SettingsPatch
|
import app.revanced.patches.music.utils.settings.SettingsPatch
|
||||||
import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch
|
import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch
|
||||||
import app.revanced.patches.music.video.information.VideoInformationPatch
|
import app.revanced.patches.music.video.information.VideoInformationPatch
|
||||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
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
|
||||||
@ -95,40 +96,40 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
|
|||||||
TrimSilenceSwitchFingerprint.resultOrThrow().let {
|
TrimSilenceSwitchFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val constIndex =
|
val constIndex =
|
||||||
indexOfFirstWideLiteralInstructionValueOrThrow(SharedResourceIdPatch.TrimSilenceSwitch)
|
indexOfFirstWideLiteralInstructionValueOrThrow(TrimSilenceSwitch)
|
||||||
val onCheckedChangedListenerIndex =
|
val onCheckedChangedListenerIndex =
|
||||||
indexOfFirstInstructionOrThrow(constIndex, Opcode.INVOKE_DIRECT)
|
indexOfFirstInstructionOrThrow(constIndex, Opcode.INVOKE_DIRECT)
|
||||||
val onCheckedChangedListenerReference =
|
val onCheckedChangedListenerReference =
|
||||||
getInstruction<ReferenceInstruction>(onCheckedChangedListenerIndex).reference
|
getInstruction<ReferenceInstruction>(onCheckedChangedListenerIndex).reference
|
||||||
val onCheckedChangedListenerDefiningClass =
|
val onCheckedChangedListenerDefiningClass =
|
||||||
(onCheckedChangedListenerReference as MethodReference).definingClass
|
(onCheckedChangedListenerReference as MethodReference).definingClass
|
||||||
val onCheckedChangedListenerClass =
|
|
||||||
context.findClass(onCheckedChangedListenerDefiningClass)!!.mutableClass
|
|
||||||
|
|
||||||
onCheckedChangedListenerClass.methods.find { method -> method.name == "onCheckedChanged" }
|
val onCheckedChangedMethod =
|
||||||
?.apply {
|
context.findMethodOrThrow(onCheckedChangedListenerDefiningClass) {
|
||||||
val walkerIndex = indexOfFirstInstructionOrThrow {
|
name == "onCheckedChanged"
|
||||||
val reference =
|
}
|
||||||
((this as? ReferenceInstruction)?.reference as? MethodReference)
|
|
||||||
|
|
||||||
opcode == Opcode.INVOKE_VIRTUAL
|
val onCheckedChangedWalkerIndex =
|
||||||
&& reference?.returnType == "V"
|
onCheckedChangedMethod.indexOfFirstInstructionOrThrow {
|
||||||
&& reference.parameterTypes.size == 1
|
val reference = getReference<MethodReference>()
|
||||||
&& reference.parameterTypes[0] == "Z"
|
opcode == Opcode.INVOKE_VIRTUAL
|
||||||
}
|
&& reference?.returnType == "V"
|
||||||
getWalkerMethod(context, walkerIndex).apply {
|
&& reference.parameterTypes.size == 1
|
||||||
val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT)
|
&& reference.parameterTypes[0] == "Z"
|
||||||
val insertRegister =
|
}
|
||||||
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
|
||||||
|
|
||||||
addInstructions(
|
getWalkerMethod(context, onCheckedChangedWalkerIndex).apply {
|
||||||
insertIndex + 1, """
|
val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT)
|
||||||
invoke-static {v$insertRegister}, $FLYOUT_CLASS_DESCRIPTOR->enableTrimSilenceSwitch(Z)Z
|
val insertRegister =
|
||||||
move-result v$insertRegister
|
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||||
"""
|
|
||||||
)
|
addInstructions(
|
||||||
}
|
insertIndex + 1, """
|
||||||
} ?: throw PatchException("onClickClass not found!")
|
invoke-static {v$insertRegister}, $FLYOUT_CLASS_DESCRIPTOR->enableTrimSilenceSwitch(Z)Z
|
||||||
|
move-result v$insertRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch
|
|||||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||||
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
||||||
import app.revanced.util.alsoResolve
|
import app.revanced.util.alsoResolve
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
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
|
||||||
@ -539,7 +540,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
opcode == Opcode.INVOKE_VIRTUAL
|
opcode == Opcode.INVOKE_VIRTUAL
|
||||||
&& reference?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;"
|
&& reference?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;"
|
||||||
&& reference.parameterTypes.first() == "Z"
|
&& reference.parameterTypes.first() == "Z"
|
||||||
}
|
}
|
||||||
val freeRegister =
|
val freeRegister =
|
||||||
getInstruction<FiveRegisterInstruction>(bottomSheetBehaviorIndex).registerD
|
getInstruction<FiveRegisterInstruction>(bottomSheetBehaviorIndex).registerD
|
||||||
|
|
||||||
@ -908,7 +909,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
MppWatchWhileLayoutFingerprint.resultOrThrow().mutableMethod.apply {
|
MppWatchWhileLayoutFingerprint.resultOrThrow().mutableMethod.apply {
|
||||||
val callableIndex =
|
val callableIndex =
|
||||||
MppWatchWhileLayoutFingerprint.indexOfCallableInstruction(this)
|
MppWatchWhileLayoutFingerprint.indexOfCallableInstruction(this)
|
||||||
val insertIndex = indexOfFirstInstructionReversedOrThrow(callableIndex, Opcode.NEW_INSTANCE)
|
val insertIndex =
|
||||||
|
indexOfFirstInstructionReversedOrThrow(callableIndex, Opcode.NEW_INSTANCE)
|
||||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
addInstructionsWithLabels(
|
||||||
@ -929,7 +931,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
).let {
|
).let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex
|
val targetIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
val targetRegister =
|
||||||
|
getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
targetIndex + 1, """
|
targetIndex + 1, """
|
||||||
@ -1095,16 +1098,13 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
val onClickReference = getInstruction<ReferenceInstruction>(onClickIndex).reference
|
val onClickReference = getInstruction<ReferenceInstruction>(onClickIndex).reference
|
||||||
val onClickReferenceDefiningClass = (onClickReference as MethodReference).definingClass
|
val onClickReferenceDefiningClass = (onClickReference as MethodReference).definingClass
|
||||||
|
|
||||||
val onClickClass =
|
context.findMethodOrThrow(onClickReferenceDefiningClass)
|
||||||
context.findClass(onClickReferenceDefiningClass)!!.mutableClass
|
.apply {
|
||||||
|
|
||||||
onClickClass.methods.find { method -> method.name == "<init>" }
|
|
||||||
?.apply {
|
|
||||||
addInstruction(
|
addInstruction(
|
||||||
implementation!!.instructions.lastIndex,
|
implementation!!.instructions.lastIndex,
|
||||||
"sput-object p0, $PLAYER_CLASS_DESCRIPTOR->$fieldName:$onClickReferenceDefiningClass"
|
"sput-object p0, $PLAYER_CLASS_DESCRIPTOR->$fieldName:$onClickReferenceDefiningClass"
|
||||||
)
|
)
|
||||||
} ?: throw PatchException("onClickClass not found!")
|
}
|
||||||
|
|
||||||
PlayerPatchConstructorFingerprint.resultOrThrow().let {
|
PlayerPatchConstructorFingerprint.resultOrThrow().let {
|
||||||
val mutableClass = it.mutableClass
|
val mutableClass = it.mutableClass
|
||||||
|
@ -6,7 +6,7 @@ import app.revanced.patcher.patch.annotation.Patch
|
|||||||
import app.revanced.patches.music.utils.flyoutmenu.fingerprints.PlaybackRateBottomSheetClassFingerprint
|
import app.revanced.patches.music.utils.flyoutmenu.fingerprints.PlaybackRateBottomSheetClassFingerprint
|
||||||
import app.revanced.patches.music.utils.integrations.Constants.INTEGRATIONS_PATH
|
import app.revanced.patches.music.utils.integrations.Constants.INTEGRATIONS_PATH
|
||||||
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.util.addFieldAndInstructions
|
import app.revanced.util.addStaticFieldToIntegration
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
@ -31,15 +31,12 @@ object FlyoutMenuHookPatch : BytecodePatch(
|
|||||||
return-void
|
return-void
|
||||||
"""
|
"""
|
||||||
|
|
||||||
context.findClass(
|
context.addStaticFieldToIntegration(
|
||||||
INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR
|
INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR,
|
||||||
)!!.mutableClass.addFieldAndInstructions(
|
|
||||||
context,
|
|
||||||
"showPlaybackSpeedFlyoutMenu",
|
"showPlaybackSpeedFlyoutMenu",
|
||||||
"playbackRateBottomSheetClass",
|
"playbackRateBottomSheetClass",
|
||||||
definingClass,
|
definingClass,
|
||||||
smaliInstructions,
|
smaliInstructions
|
||||||
true
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ import app.revanced.patches.shared.mapping.ResourceMappingPatch
|
|||||||
import app.revanced.patches.shared.mapping.ResourceMappingPatch.getId
|
import app.revanced.patches.shared.mapping.ResourceMappingPatch.getId
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.BOOL
|
import app.revanced.patches.shared.mapping.ResourceType.BOOL
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.COLOR
|
import app.revanced.patches.shared.mapping.ResourceType.COLOR
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.DRAWABLE
|
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.DIMEN
|
import app.revanced.patches.shared.mapping.ResourceType.DIMEN
|
||||||
|
import app.revanced.patches.shared.mapping.ResourceType.DRAWABLE
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.ID
|
import app.revanced.patches.shared.mapping.ResourceType.ID
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.LAYOUT
|
import app.revanced.patches.shared.mapping.ResourceType.LAYOUT
|
||||||
import app.revanced.patches.shared.mapping.ResourceType.STRING
|
import app.revanced.patches.shared.mapping.ResourceType.STRING
|
||||||
|
@ -61,11 +61,13 @@ object SponsorBlockBytecodePatch : BytecodePatch(
|
|||||||
RectangleFieldInvalidatorFingerprint.alsoResolve(
|
RectangleFieldInvalidatorFingerprint.alsoResolve(
|
||||||
context, SeekBarConstructorFingerprint
|
context, SeekBarConstructorFingerprint
|
||||||
).let {
|
).let {
|
||||||
with (it.mutableMethod) {
|
with(it.mutableMethod) {
|
||||||
val invalidateIndex = RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction(this)
|
val invalidateIndex =
|
||||||
val rectangleIndex = indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) {
|
RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction(this)
|
||||||
getReference<FieldReference>()?.type == "Landroid/graphics/Rect;"
|
val rectangleIndex =
|
||||||
}
|
indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) {
|
||||||
|
getReference<FieldReference>()?.type == "Landroid/graphics/Rect;"
|
||||||
|
}
|
||||||
val rectangleReference =
|
val rectangleReference =
|
||||||
getInstruction<ReferenceInstruction>(rectangleIndex).reference
|
getInstruction<ReferenceInstruction>(rectangleIndex).reference
|
||||||
|
|
||||||
@ -116,7 +118,7 @@ object SponsorBlockBytecodePatch : BytecodePatch(
|
|||||||
*/
|
*/
|
||||||
rectangleFieldName =
|
rectangleFieldName =
|
||||||
MusicPlaybackControlsTimeBarOnMeasureFingerprint.resultOrThrow().let {
|
MusicPlaybackControlsTimeBarOnMeasureFingerprint.resultOrThrow().let {
|
||||||
with (it.mutableMethod) {
|
with(it.mutableMethod) {
|
||||||
val rectangleIndex = it.scanResult.patternScanResult!!.startIndex
|
val rectangleIndex = it.scanResult.patternScanResult!!.startIndex
|
||||||
val rectangleReference =
|
val rectangleReference =
|
||||||
getInstruction<ReferenceInstruction>(rectangleIndex).reference
|
getInstruction<ReferenceInstruction>(rectangleIndex).reference
|
||||||
|
@ -9,7 +9,6 @@ import app.revanced.patcher.fingerprint.MethodFingerprintResult
|
|||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
import app.revanced.patcher.util.smali.toInstructions
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
@ -24,7 +23,7 @@ import app.revanced.patches.music.video.information.fingerprints.VideoQualityLis
|
|||||||
import app.revanced.patches.music.video.information.fingerprints.VideoQualityTextFingerprint
|
import app.revanced.patches.music.video.information.fingerprints.VideoQualityTextFingerprint
|
||||||
import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint
|
import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint
|
||||||
import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint
|
import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint
|
||||||
import app.revanced.util.addFieldAndInstructions
|
import app.revanced.util.addStaticFieldToIntegration
|
||||||
import app.revanced.util.alsoResolve
|
import app.revanced.util.alsoResolve
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
@ -82,7 +81,6 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
private var seekSourceEnumType = ""
|
private var seekSourceEnumType = ""
|
||||||
private var seekSourceMethodName = ""
|
private var seekSourceMethodName = ""
|
||||||
|
|
||||||
private lateinit var videoInformationMutableClass: MutableClass
|
|
||||||
private lateinit var context: BytecodeContext
|
private lateinit var context: BytecodeContext
|
||||||
|
|
||||||
private lateinit var playerConstructorMethod: MutableMethod
|
private lateinit var playerConstructorMethod: MutableMethod
|
||||||
@ -138,21 +136,18 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
return v0
|
return v0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
videoInformationMutableClass.addFieldAndInstructions(
|
context.addStaticFieldToIntegration(
|
||||||
context,
|
INTEGRATIONS_CLASS_DESCRIPTOR,
|
||||||
methodName,
|
methodName,
|
||||||
fieldName,
|
fieldName,
|
||||||
definingClass,
|
definingClass,
|
||||||
smaliInstructions,
|
smaliInstructions
|
||||||
true
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
this.context = context
|
this.context = context
|
||||||
videoInformationMutableClass =
|
|
||||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
|
||||||
|
|
||||||
VideoEndFingerprint.resultOrThrow().let {
|
VideoEndFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
@ -211,9 +206,9 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
|
|
||||||
PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR =
|
PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR =
|
||||||
getInstruction(playerResponseModelIndex)
|
getInstruction(playerResponseModelIndex)
|
||||||
.getReference<MethodReference>()
|
.getReference<MethodReference>()
|
||||||
?.definingClass
|
?.definingClass
|
||||||
?: throw PatchException("Could not find Player Response Model class")
|
?: throw PatchException("Could not find Player Response Model class")
|
||||||
|
|
||||||
videoIdMethodCall =
|
videoIdMethodCall =
|
||||||
VideoIdFingerprint.getPlayerResponseInstruction("Ljava/lang/String;")
|
VideoIdFingerprint.getPlayerResponseInstruction("Ljava/lang/String;")
|
||||||
@ -302,13 +297,12 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
return-void
|
return-void
|
||||||
"""
|
"""
|
||||||
|
|
||||||
videoInformationMutableClass.addFieldAndInstructions(
|
VideoInformationPatch.context.addStaticFieldToIntegration(
|
||||||
context,
|
INTEGRATIONS_CLASS_DESCRIPTOR,
|
||||||
"overrideVideoQuality",
|
"overrideVideoQuality",
|
||||||
"videoQualityClass",
|
"videoQualityClass",
|
||||||
videoQualityClass,
|
videoQualityClass,
|
||||||
smaliInstructions,
|
smaliInstructions
|
||||||
true
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,13 @@ import app.revanced.patches.music.utils.settings.SettingsPatch
|
|||||||
import app.revanced.patches.music.video.information.VideoInformationPatch
|
import app.revanced.patches.music.video.information.VideoInformationPatch
|
||||||
import app.revanced.patches.music.video.playback.fingerprints.PlaybackSpeedBottomSheetFingerprint
|
import app.revanced.patches.music.video.playback.fingerprints.PlaybackSpeedBottomSheetFingerprint
|
||||||
import app.revanced.patches.music.video.playback.fingerprints.UserQualityChangeFingerprint
|
import app.revanced.patches.music.video.playback.fingerprints.UserQualityChangeFingerprint
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c
|
|
||||||
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.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@ -84,19 +85,14 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
|||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
val qualityChangedClass =
|
val qualityChangedClass =
|
||||||
context.findClass(
|
getInstruction<ReferenceInstruction>(endIndex).reference.toString()
|
||||||
(getInstruction<BuilderInstruction21c>(endIndex))
|
|
||||||
.reference.toString()
|
|
||||||
)!!
|
|
||||||
.mutableClass
|
|
||||||
|
|
||||||
val onItemClickMethod =
|
context.findMethodOrThrow(qualityChangedClass) {
|
||||||
qualityChangedClass.methods.find { method -> method.name == "onItemClick" }
|
name == "onItemClick"
|
||||||
|
}.addInstruction(
|
||||||
onItemClickMethod?.addInstruction(
|
|
||||||
0,
|
0,
|
||||||
"invoke-static {}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userSelectedVideoQuality()V"
|
"invoke-static {}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userSelectedVideoQuality()V"
|
||||||
) ?: throw PatchException("Failed to find onItemClick method")
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,7 @@ abstract class BaseAdsPatch(
|
|||||||
MusicAdsFingerprint.resultOrThrow().let {
|
MusicAdsFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val targetIndex = indexOfFirstInstructionOrThrow {
|
val targetIndex = indexOfFirstInstructionOrThrow {
|
||||||
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
|
val reference = getReference<MethodReference>()
|
||||||
|
|
||||||
opcode == Opcode.INVOKE_VIRTUAL
|
opcode == Opcode.INVOKE_VIRTUAL
|
||||||
&& reference?.returnType == "V"
|
&& reference?.returnType == "V"
|
||||||
&& reference.parameterTypes.size == 1
|
&& reference.parameterTypes.size == 1
|
||||||
|
@ -4,9 +4,9 @@ import app.revanced.patcher.data.BytecodeContext
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patches.shared.integrations.BaseIntegrationsPatch.IntegrationsFingerprint.IRegisterResolver
|
import app.revanced.patches.shared.integrations.BaseIntegrationsPatch.IntegrationsFingerprint.IRegisterResolver
|
||||||
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
|
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.isDeprecated
|
import app.revanced.util.isDeprecated
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
@ -18,11 +18,7 @@ abstract class BaseIntegrationsPatch(
|
|||||||
) : BytecodePatch(hooks) {
|
) : BytecodePatch(hooks) {
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
if (context.findClass(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) == null) {
|
context.findMethodOrThrow(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR)
|
||||||
throw PatchException(
|
|
||||||
"Integrations have not been merged yet. This patch can not succeed without merging the integrations.",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
hooks.forEach { hook ->
|
hooks.forEach { hook ->
|
||||||
hook.invoke(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR)
|
hook.invoke(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR)
|
||||||
|
@ -7,7 +7,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
|
|||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
@ -15,6 +14,7 @@ import app.revanced.patches.shared.integrations.Constants.COMPONENTS_PATH
|
|||||||
import app.revanced.patches.shared.litho.fingerprints.ByteBufferFingerprint
|
import app.revanced.patches.shared.litho.fingerprints.ByteBufferFingerprint
|
||||||
import app.revanced.patches.shared.litho.fingerprints.EmptyComponentsFingerprint
|
import app.revanced.patches.shared.litho.fingerprints.EmptyComponentsFingerprint
|
||||||
import app.revanced.patches.shared.litho.fingerprints.PathBuilderFingerprint
|
import app.revanced.patches.shared.litho.fingerprints.PathBuilderFingerprint
|
||||||
|
import app.revanced.util.findMethodsOrThrow
|
||||||
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
|
||||||
@ -156,10 +156,8 @@ object LithoFilterPatch : BytecodePatch(
|
|||||||
// Create a new method to get the filter array to avoid register conflicts.
|
// Create a new method to get the filter array to avoid register conflicts.
|
||||||
// This fixes an issue with Integrations compiled with Android Gradle Plugin 8.3.0+.
|
// This fixes an issue with Integrations compiled with Android Gradle Plugin 8.3.0+.
|
||||||
// https://github.com/ReVanced/revanced-patches/issues/2818
|
// https://github.com/ReVanced/revanced-patches/issues/2818
|
||||||
val lithoFilterMethods = context.findClass(INTEGRATIONS_LITHO_FILER_CLASS_DESCRIPTOR)
|
val lithoFilterMethods =
|
||||||
?.mutableClass
|
context.findMethodsOrThrow(INTEGRATIONS_LITHO_FILER_CLASS_DESCRIPTOR)
|
||||||
?.methods
|
|
||||||
?: throw PatchException("LithoFilterPatch class not found.")
|
|
||||||
|
|
||||||
lithoFilterMethods
|
lithoFilterMethods
|
||||||
.first { it.name == "<clinit>" }
|
.first { it.name == "<clinit>" }
|
||||||
|
@ -3,12 +3,12 @@ package app.revanced.patches.shared.viewgroup
|
|||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
|
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.shared.viewgroup.fingerprints.ViewGroupMarginFingerprint
|
import app.revanced.patches.shared.viewgroup.fingerprints.ViewGroupMarginFingerprint
|
||||||
import app.revanced.patches.shared.viewgroup.fingerprints.ViewGroupMarginParentFingerprint
|
import app.revanced.patches.shared.viewgroup.fingerprints.ViewGroupMarginParentFingerprint
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.alsoResolve
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
description = "Hook YouTube or YouTube Music to use ViewGroup.MarginLayoutParams in the integration.",
|
description = "Hook YouTube or YouTube Music to use ViewGroup.MarginLayoutParams in the integration.",
|
||||||
@ -18,26 +18,21 @@ object ViewGroupMarginLayoutParamsHookPatch : BytecodePatch(
|
|||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
val method =
|
val setViewGroupMarginCall = with(
|
||||||
context.findClass(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
|
ViewGroupMarginFingerprint.alsoResolve(
|
||||||
method.name == "hideViewGroupByMarginLayoutParams"
|
context, ViewGroupMarginParentFingerprint
|
||||||
} ?: throw PatchException("Could not find hideViewGroupByMarginLayoutParams method")
|
).mutableMethod
|
||||||
|
) {
|
||||||
ViewGroupMarginFingerprint.resolve(
|
"$definingClass->$name(Landroid/view/View;II)V"
|
||||||
context,
|
|
||||||
ViewGroupMarginParentFingerprint.resultOrThrow().classDef
|
|
||||||
)
|
|
||||||
ViewGroupMarginFingerprint.resultOrThrow().let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val setViewGroupMarginCall = "$definingClass->$name(Landroid/view/View;II)V"
|
|
||||||
|
|
||||||
method.addInstructions(
|
|
||||||
0, """
|
|
||||||
const/4 v0, 0x0
|
|
||||||
invoke-static {p0, v0, v0}, $setViewGroupMarginCall
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.findMethodOrThrow(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) {
|
||||||
|
name == "hideViewGroupByMarginLayoutParams"
|
||||||
|
}.addInstructions(
|
||||||
|
0, """
|
||||||
|
const/4 v0, 0x0
|
||||||
|
invoke-static {p0, v0, v0}, $setViewGroupMarginCall
|
||||||
|
"""
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,6 +19,7 @@ import app.revanced.patches.youtube.utils.pip.PiPStateHookPatch
|
|||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
import app.revanced.util.alsoResolve
|
import app.revanced.util.alsoResolve
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
@ -87,23 +88,22 @@ object DownloadActionsPatch : BaseBytecodePatch(
|
|||||||
?: throw PatchException("Could not find onClickListenerClass")
|
?: throw PatchException("Could not find onClickListenerClass")
|
||||||
}
|
}
|
||||||
|
|
||||||
context.findClass(onClickListenerClass)
|
context.findMethodOrThrow(onClickListenerClass) {
|
||||||
?.mutableClass
|
name == "onClick"
|
||||||
?.methods
|
}.apply {
|
||||||
?.first { method -> method.name == "onClick" }?.apply {
|
val insertIndex = indexOfFirstInstructionOrThrow {
|
||||||
val insertIndex = indexOfFirstInstructionOrThrow {
|
opcode == Opcode.INVOKE_STATIC
|
||||||
opcode == Opcode.INVOKE_STATIC
|
&& getReference<MethodReference>()?.name == "isEmpty"
|
||||||
&& getReference<MethodReference>()?.name == "isEmpty"
|
}
|
||||||
}
|
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||||
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
insertIndex, """
|
insertIndex, """
|
||||||
invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadButtonOnClick(Ljava/lang/String;)Ljava/lang/String;
|
invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadButtonOnClick(Ljava/lang/String;)Ljava/lang/String;
|
||||||
move-result-object v$insertRegister
|
move-result-object v$insertRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
} ?: throw PatchException("Could not find class $onClickListenerClass")
|
}
|
||||||
|
|
||||||
OfflinePlaylistEndpointFingerprint.resultOrThrow().mutableMethod.apply {
|
OfflinePlaylistEndpointFingerprint.resultOrThrow().mutableMethod.apply {
|
||||||
val playlistIdParameter = parameterTypes.indexOf("Ljava/lang/String;") + 1
|
val playlistIdParameter = parameterTypes.indexOf("Ljava/lang/String;") + 1
|
||||||
|
@ -11,6 +11,7 @@ import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_PATH
|
|||||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addEntryValues
|
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addEntryValues
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsBytecodePatch
|
import app.revanced.patches.youtube.utils.settings.SettingsBytecodePatch
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
@ -39,13 +40,15 @@ object YouTubeMusicActionsPatch : BaseBytecodePatch(
|
|||||||
AppDeepLinkFingerprint.resultOrThrow().let {
|
AppDeepLinkFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val packageNameIndex = it.scanResult.patternScanResult!!.startIndex
|
val packageNameIndex = it.scanResult.patternScanResult!!.startIndex
|
||||||
val packageNameField = getInstruction<ReferenceInstruction>(packageNameIndex).reference.toString()
|
val packageNameField =
|
||||||
|
getInstruction<ReferenceInstruction>(packageNameIndex).reference.toString()
|
||||||
|
|
||||||
implementation!!.instructions
|
implementation!!.instructions
|
||||||
.withIndex()
|
.withIndex()
|
||||||
.filter { (_, instruction) ->
|
.filter { (_, instruction) ->
|
||||||
instruction.opcode == Opcode.IGET_OBJECT &&
|
instruction.opcode == Opcode.IGET_OBJECT &&
|
||||||
instruction.getReference<FieldReference>()?.toString() == packageNameField
|
instruction.getReference<FieldReference>()
|
||||||
|
?.toString() == packageNameField
|
||||||
}
|
}
|
||||||
.map { (index, _) -> index }
|
.map { (index, _) -> index }
|
||||||
.reversed()
|
.reversed()
|
||||||
@ -78,30 +81,28 @@ object YouTubeMusicActionsPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
if (SettingsPatch.containsPatch("GmsCore support")) {
|
if (SettingsPatch.containsPatch("GmsCore support")) {
|
||||||
|
val musicPackageName = PackageNameYouTubeMusic.valueOrThrow()
|
||||||
SettingsPatch.contexts.addEntryValues(
|
SettingsPatch.contexts.addEntryValues(
|
||||||
"revanced_third_party_youtube_music_label",
|
"revanced_third_party_youtube_music_label",
|
||||||
"RVX Music"
|
"RVX Music"
|
||||||
)
|
)
|
||||||
SettingsPatch.contexts.addEntryValues(
|
SettingsPatch.contexts.addEntryValues(
|
||||||
"revanced_third_party_youtube_music_package_name",
|
"revanced_third_party_youtube_music_package_name",
|
||||||
PackageNameYouTubeMusic.valueOrThrow()
|
musicPackageName
|
||||||
)
|
)
|
||||||
|
|
||||||
SettingsBytecodePatch.contexts
|
SettingsBytecodePatch.contexts.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) {
|
||||||
.findClass { classDef -> classDef.type == INTEGRATIONS_CLASS_DESCRIPTOR }
|
name == "getRVXMusicPackageName"
|
||||||
?.mutableClass
|
}.apply {
|
||||||
?.methods
|
val replaceIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING)
|
||||||
?.first { method -> method.name == "getRVXMusicPackageName" }
|
val replaceRegister =
|
||||||
?.apply {
|
getInstruction<OneRegisterInstruction>(replaceIndex).registerA
|
||||||
val replaceIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING)
|
|
||||||
val replaceRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(replaceIndex).registerA
|
|
||||||
|
|
||||||
replaceInstruction(
|
replaceInstruction(
|
||||||
replaceIndex,
|
replaceIndex,
|
||||||
"const-string v$replaceRegister, \"${PackageNameYouTubeMusic.valueOrThrow()}\""
|
"const-string v$replaceRegister, \"$musicPackageName\""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -89,12 +89,12 @@ object NavigationBarComponentsPatch : BaseBytecodePatch(
|
|||||||
AutoMotiveFingerprint.resultOrThrow().let {
|
AutoMotiveFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val insertIndex = indexOfFirstStringInstructionOrThrow("Android Automotive") - 1
|
val insertIndex = indexOfFirstStringInstructionOrThrow("Android Automotive") - 1
|
||||||
val register = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
insertIndex, """
|
insertIndex, """
|
||||||
invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->switchCreateWithNotificationButton(Z)Z
|
invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->switchCreateWithNotificationButton(Z)Z
|
||||||
move-result v$register
|
move-result v$insertRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ import app.revanced.patches.youtube.utils.toolbar.ToolBarHookPatch
|
|||||||
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
||||||
import app.revanced.util.alsoResolve
|
import app.revanced.util.alsoResolve
|
||||||
import app.revanced.util.doRecursively
|
import app.revanced.util.doRecursively
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
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
|
||||||
@ -114,8 +115,8 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
|||||||
val attributeResolverMethodCall =
|
val attributeResolverMethodCall =
|
||||||
attributeResolverMethod.definingClass + "->" + attributeResolverMethod.name + "(Landroid/content/Context;I)Landroid/graphics/drawable/Drawable;"
|
attributeResolverMethod.definingClass + "->" + attributeResolverMethod.name + "(Landroid/content/Context;I)Landroid/graphics/drawable/Drawable;"
|
||||||
|
|
||||||
context.findClass(GENERAL_CLASS_DESCRIPTOR)!!.mutableClass.methods.single { method ->
|
context.findMethodOrThrow(GENERAL_CLASS_DESCRIPTOR) {
|
||||||
method.name == "getHeaderDrawable"
|
name == "getHeaderDrawable"
|
||||||
}.addInstructions(
|
}.addInstructions(
|
||||||
0, """
|
0, """
|
||||||
invoke-static {p0, p1}, $attributeResolverMethodCall
|
invoke-static {p0, p1}, $attributeResolverMethodCall
|
||||||
@ -381,15 +382,14 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
ToolBarHookPatch.hook("$GENERAL_CLASS_DESCRIPTOR->replaceCreateButton")
|
ToolBarHookPatch.hook("$GENERAL_CLASS_DESCRIPTOR->replaceCreateButton")
|
||||||
|
|
||||||
val settingsClass = context.findClass("Shell_SettingsActivity")
|
context.findMethodOrThrow(
|
||||||
?: throw PatchException("Shell_SettingsActivity class not found.")
|
"Lcom/google/android/apps/youtube/app/application/Shell_SettingsActivity;"
|
||||||
|
) {
|
||||||
settingsClass.mutableClass.methods.find { it.name == "onCreate" }?.apply {
|
name == "onCreate"
|
||||||
addInstruction(
|
}.addInstruction(
|
||||||
0,
|
0,
|
||||||
"invoke-static {p0}, $GENERAL_CLASS_DESCRIPTOR->setShellActivityTheme(Landroid/app/Activity;)V"
|
"invoke-static {p0}, $GENERAL_CLASS_DESCRIPTOR->setShellActivityTheme(Landroid/app/Activity;)V"
|
||||||
)
|
)
|
||||||
} ?: throw PatchException("onCreate method not found.")
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
@ -141,7 +141,10 @@ object ChangeHeaderPatch : BaseResourcePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (customBrandingIconType == "youtube_minimal_header") {
|
if (customBrandingIconType == "youtube_minimal_header") {
|
||||||
SettingsBytecodePatch.contexts.updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "MinimalHeader")
|
SettingsBytecodePatch.contexts.updatePatchStatus(
|
||||||
|
PATCH_STATUS_CLASS_DESCRIPTOR,
|
||||||
|
"MinimalHeader"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println(warnings)
|
println(warnings)
|
||||||
|
@ -3,13 +3,13 @@ package app.revanced.patches.youtube.player.ambientmode
|
|||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
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.patch.PatchException
|
|
||||||
import app.revanced.patches.youtube.player.ambientmode.fingerprints.AmbientModeInFullscreenFingerprint
|
import app.revanced.patches.youtube.player.ambientmode.fingerprints.AmbientModeInFullscreenFingerprint
|
||||||
import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveModeBroadcastReceiverFingerprint
|
import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveModeBroadcastReceiverFingerprint
|
||||||
import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveModeSyntheticFingerprint
|
import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveModeSyntheticFingerprint
|
||||||
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.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
||||||
@ -19,7 +19,6 @@ import app.revanced.util.resultOrThrow
|
|||||||
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.instruction.formats.Instruction35c
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@ -60,27 +59,30 @@ object AmbientModeSwitchPatch : BaseBytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
syntheticClassList.distinct().forEach { className ->
|
syntheticClassList.distinct().forEach { className ->
|
||||||
context.findClass(className)?.mutableClass?.methods?.first { method ->
|
context.findMethodOrThrow(className) {
|
||||||
method.name == "accept"
|
name == "accept"
|
||||||
}?.apply {
|
}.apply {
|
||||||
for (index in implementation!!.instructions.size - 1 downTo 0) {
|
implementation!!.instructions
|
||||||
val instruction = getInstruction(index)
|
.withIndex()
|
||||||
if (instruction.opcode != Opcode.INVOKE_VIRTUAL)
|
.filter { (_, instruction) ->
|
||||||
continue
|
val reference = (instruction as? ReferenceInstruction)?.reference
|
||||||
|
instruction.opcode == Opcode.INVOKE_VIRTUAL &&
|
||||||
|
reference is MethodReference &&
|
||||||
|
reference.name == "isPowerSaveMode"
|
||||||
|
}
|
||||||
|
.map { (index, _) -> index }
|
||||||
|
.reversed()
|
||||||
|
.forEach { index ->
|
||||||
|
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||||
|
|
||||||
if (((instruction as Instruction35c).reference as MethodReference).name != "isPowerSaveMode")
|
addInstructions(
|
||||||
continue
|
index + 2, """
|
||||||
|
invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->bypassAmbientModeRestrictions(Z)Z
|
||||||
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
move-result v$register
|
||||||
|
"""
|
||||||
addInstructions(
|
)
|
||||||
index + 2, """
|
}
|
||||||
invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->bypassAmbientModeRestrictions(Z)Z
|
}
|
||||||
move-result v$register
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} ?: throw PatchException("Could not find $className")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -48,6 +48,7 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TapBl
|
|||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||||
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
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
|
||||||
@ -146,15 +147,13 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
|||||||
hookInitVideoPanel(1)
|
hookInitVideoPanel(1)
|
||||||
} else {
|
} else {
|
||||||
val syntheticIndex =
|
val syntheticIndex =
|
||||||
indexOfFirstInstructionOrThrow(opcode = Opcode.NEW_INSTANCE)
|
indexOfFirstInstructionOrThrow(Opcode.NEW_INSTANCE)
|
||||||
val syntheticReference =
|
val syntheticReference =
|
||||||
getInstruction<ReferenceInstruction>(syntheticIndex).reference.toString()
|
getInstruction<ReferenceInstruction>(syntheticIndex).reference.toString()
|
||||||
val syntheticClass =
|
|
||||||
context.findClass(syntheticReference)!!.mutableClass
|
|
||||||
|
|
||||||
syntheticClass.methods.find { method -> method.name == "onClick" }
|
context.findMethodOrThrow(syntheticReference) {
|
||||||
?.hookInitVideoPanel(0)
|
name == "onClick"
|
||||||
?: throw PatchException("Could not find onClick method in $syntheticReference")
|
}.hookInitVideoPanel(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AutoN
|
|||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenEngagementPanel
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenEngagementPanel
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.QuickActionsElementContainer
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.QuickActionsElementContainer
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
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
|
||||||
@ -253,18 +254,16 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
|
|||||||
val invokeIndex =
|
val invokeIndex =
|
||||||
indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_INTERFACE)
|
indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_INTERFACE)
|
||||||
val targetIndex = indexOfFirstInstructionOrThrow(invokeIndex, Opcode.CHECK_CAST)
|
val targetIndex = indexOfFirstInstructionOrThrow(invokeIndex, Opcode.CHECK_CAST)
|
||||||
val targetClass = context
|
val targetClass =
|
||||||
.findClass(getInstruction<ReferenceInstruction>(targetIndex).reference.toString())!!
|
getInstruction<ReferenceInstruction>(targetIndex).reference.toString()
|
||||||
.mutableClass
|
|
||||||
|
|
||||||
// add an instruction to check the vertical video
|
// add an instruction to check the vertical video
|
||||||
targetClass.methods.find { method -> method.parameters == listOf("I", "I", "Z") }
|
context.findMethodOrThrow(targetClass) {
|
||||||
?.apply {
|
parameters == listOf("I", "I", "Z")
|
||||||
addInstruction(
|
}.addInstruction(
|
||||||
1,
|
1,
|
||||||
"invoke-static {p1, p2}, $PLAYER_CLASS_DESCRIPTOR->setVideoPortrait(II)V"
|
"invoke-static {p1, p2}, $PLAYER_CLASS_DESCRIPTOR->setVideoPortrait(II)V"
|
||||||
)
|
)
|
||||||
} ?: throw PatchException("Could not find targetMethod")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,14 +280,11 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val walkerMethod = getWalkerMethod(context, walkerIndex)
|
val walkerMethod = getWalkerMethod(context, walkerIndex)
|
||||||
val targetClass =
|
val constructorMethod =
|
||||||
context.findClass(walkerMethod.definingClass)!!.mutableClass
|
context.findMethodOrThrow(walkerMethod.definingClass) {
|
||||||
val constructorMethod = targetClass
|
name == "<init>" &&
|
||||||
.methods
|
parameterTypes == listOf("Landroid/app/Activity;")
|
||||||
.find { method ->
|
}
|
||||||
method.name == "<init>"
|
|
||||||
&& method.parameterTypes == listOf("Landroid/app/Activity;")
|
|
||||||
} ?: throw PatchException("Constructor method not found!")
|
|
||||||
|
|
||||||
arrayOf(
|
arrayOf(
|
||||||
walkerMethod,
|
walkerMethod,
|
||||||
|
@ -30,6 +30,7 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelT
|
|||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts
|
||||||
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||||
|
import app.revanced.util.findMethodsOrThrow
|
||||||
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
|
||||||
@ -38,8 +39,6 @@ import app.revanced.util.injectLiteralInstructionBooleanCall
|
|||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c
|
|
||||||
import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedMethodReference
|
|
||||||
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.NarrowLiteralInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
@ -84,14 +83,15 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
|
|||||||
SeekbarTappingFingerprint.resultOrThrow().let {
|
SeekbarTappingFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val tapSeekIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
val tapSeekIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||||
val tapSeekReference = getInstruction<BuilderInstruction35c>(tapSeekIndex).reference
|
val tapSeekClass = getInstruction(tapSeekIndex)
|
||||||
val tapSeekClass =
|
.getReference<MethodReference>()!!
|
||||||
context
|
.definingClass
|
||||||
.findClass((tapSeekReference as DexBackedMethodReference).definingClass)!!
|
|
||||||
.mutableClass
|
|
||||||
val tapSeekMethods = mutableMapOf<String, MutableMethod>()
|
|
||||||
|
|
||||||
for (method in tapSeekClass.methods) {
|
val tapSeekMethods = context.findMethodsOrThrow(tapSeekClass)
|
||||||
|
var pMethodCall = ""
|
||||||
|
var oMethodCall = ""
|
||||||
|
|
||||||
|
for (method in tapSeekMethods) {
|
||||||
if (method.implementation == null)
|
if (method.implementation == null)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -110,15 +110,17 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
|
|||||||
|
|
||||||
// method founds
|
// method founds
|
||||||
if (literal == 1)
|
if (literal == 1)
|
||||||
tapSeekMethods["P"] = method
|
pMethodCall = "${method.definingClass}->${method.name}(I)V"
|
||||||
else if (literal == 2)
|
else if (literal == 2)
|
||||||
tapSeekMethods["O"] = method
|
oMethodCall = "${method.definingClass}->${method.name}(I)V"
|
||||||
}
|
}
|
||||||
|
|
||||||
val pMethod = tapSeekMethods["P"]
|
if (pMethodCall.isEmpty()) {
|
||||||
?: throw PatchException("pMethod not found")
|
throw PatchException("pMethod not found")
|
||||||
val oMethod = tapSeekMethods["O"]
|
}
|
||||||
?: throw PatchException("oMethod not found")
|
if (oMethodCall.isEmpty()) {
|
||||||
|
throw PatchException("oMethod not found")
|
||||||
|
}
|
||||||
|
|
||||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
|
val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
|
||||||
|
|
||||||
@ -127,8 +129,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
|
|||||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSeekbarTapping()Z
|
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSeekbarTapping()Z
|
||||||
move-result v0
|
move-result v0
|
||||||
if-eqz v0, :disabled
|
if-eqz v0, :disabled
|
||||||
invoke-virtual { p0, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V
|
invoke-virtual { p0, v2 }, $pMethodCall
|
||||||
invoke-virtual { p0, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V
|
invoke-virtual { p0, v2 }, $oMethodCall
|
||||||
""", ExternalLabel("disabled", getInstruction(insertIndex))
|
""", ExternalLabel("disabled", getInstruction(insertIndex))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ 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.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
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
|
||||||
@ -20,7 +19,9 @@ import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverla
|
|||||||
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.util.alsoResolve
|
import app.revanced.util.alsoResolve
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
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 app.revanced.util.injectLiteralInstructionBooleanCall
|
import app.revanced.util.injectLiteralInstructionBooleanCall
|
||||||
@ -33,7 +34,6 @@ 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.util.MethodUtil
|
|
||||||
|
|
||||||
@Patch(dependencies = [SharedResourceIdPatch::class])
|
@Patch(dependencies = [SharedResourceIdPatch::class])
|
||||||
object SpeedOverlayPatch : BytecodePatch(
|
object SpeedOverlayPatch : BytecodePatch(
|
||||||
@ -135,16 +135,11 @@ object SpeedOverlayPatch : BytecodePatch(
|
|||||||
|
|
||||||
hook(insertIndex, insertRegister, jumpIndex)
|
hook(insertIndex, insertRegister, jumpIndex)
|
||||||
|
|
||||||
val slideToSeekBooleanMethod = context.toMethodWalker(it.mutableMethod)
|
val slideToSeekBooleanMethod =
|
||||||
.nextMethod(scanResult.startIndex + 1, true)
|
getWalkerMethod(context, scanResult.startIndex + 1)
|
||||||
.getMethod() as MutableMethod
|
|
||||||
|
|
||||||
val slideToSeekConstructorMethod =
|
val slideToSeekConstructorMethod =
|
||||||
context.findClass { classDef -> classDef.type == slideToSeekBooleanMethod.definingClass }
|
context.findMethodOrThrow(slideToSeekBooleanMethod.definingClass)
|
||||||
?.mutableClass
|
|
||||||
?.methods
|
|
||||||
?.find { method -> MethodUtil.isConstructor(method) }
|
|
||||||
?: throw PatchException("Could not find constructor method")
|
|
||||||
|
|
||||||
val slideToSeekSyntheticIndex = slideToSeekConstructorMethod
|
val slideToSeekSyntheticIndex = slideToSeekConstructorMethod
|
||||||
.indexOfFirstInstructionReversedOrThrow {
|
.indexOfFirstInstructionReversedOrThrow {
|
||||||
@ -157,11 +152,9 @@ object SpeedOverlayPatch : BytecodePatch(
|
|||||||
.toString()
|
.toString()
|
||||||
|
|
||||||
val slideToSeekSyntheticMethod =
|
val slideToSeekSyntheticMethod =
|
||||||
context.findClass { classDef -> classDef.type == slideToSeekSyntheticClass }
|
context.findMethodOrThrow(slideToSeekSyntheticClass) {
|
||||||
?.mutableClass
|
name == "run"
|
||||||
?.methods
|
}
|
||||||
?.find { method -> method.name == "run" }
|
|
||||||
?: throw PatchException("Could not find synthetic method")
|
|
||||||
|
|
||||||
Pair(slideToSeekBooleanMethod, slideToSeekSyntheticMethod)
|
Pair(slideToSeekBooleanMethod, slideToSeekSyntheticMethod)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ 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.extensions.InstructionExtensions.removeInstruction
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patches.youtube.utils.castbutton.fingerprints.MenuItemInitializeFingerprint
|
import app.revanced.patches.youtube.utils.castbutton.fingerprints.MenuItemInitializeFingerprint
|
||||||
@ -18,6 +17,7 @@ import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DE
|
|||||||
import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH
|
import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.util.alsoResolve
|
import app.revanced.util.alsoResolve
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
@ -50,17 +50,14 @@ object CastButtonPatch : BytecodePatch(
|
|||||||
|
|
||||||
playerButtonMethod = PlayerButtonFingerprint.resultOrThrow().mutableMethod
|
playerButtonMethod = PlayerButtonFingerprint.resultOrThrow().mutableMethod
|
||||||
|
|
||||||
val buttonClass = context.findClass("MediaRouteButton")
|
context.findMethodOrThrow("Landroidx/mediarouter/app/MediaRouteButton;") {
|
||||||
?: throw PatchException("MediaRouteButton class not found.")
|
name == "setVisibility"
|
||||||
|
}.addInstructions(
|
||||||
buttonClass.mutableClass.methods.find { it.name == "setVisibility" }?.apply {
|
0, """
|
||||||
addInstructions(
|
invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideCastButton(I)I
|
||||||
0, """
|
move-result p1
|
||||||
invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideCastButton(I)I
|
"""
|
||||||
move-result p1
|
)
|
||||||
"""
|
|
||||||
)
|
|
||||||
} ?: throw PatchException("setVisibility method not found.")
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import app.revanced.patches.youtube.utils.fingerprints.PlaybackRateBottomSheetBu
|
|||||||
import app.revanced.patches.youtube.utils.flyoutmenu.fingerprints.VideoQualityBottomSheetClassFingerprint
|
import app.revanced.patches.youtube.utils.flyoutmenu.fingerprints.VideoQualityBottomSheetClassFingerprint
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH
|
import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.util.addFieldAndInstructions
|
import app.revanced.util.addStaticFieldToIntegration
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
@ -25,10 +25,6 @@ object FlyoutMenuHookPatch : BytecodePatch(
|
|||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
|
||||||
val videoUtilsMutableClass = context.findClass(
|
|
||||||
INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR
|
|
||||||
)!!.mutableClass
|
|
||||||
|
|
||||||
PlaybackRateBottomSheetBuilderFingerprint.resultOrThrow().let {
|
PlaybackRateBottomSheetBuilderFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val smaliInstructions =
|
val smaliInstructions =
|
||||||
@ -39,13 +35,12 @@ object FlyoutMenuHookPatch : BytecodePatch(
|
|||||||
return-void
|
return-void
|
||||||
"""
|
"""
|
||||||
|
|
||||||
videoUtilsMutableClass.addFieldAndInstructions(
|
context.addStaticFieldToIntegration(
|
||||||
context,
|
INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR,
|
||||||
"showPlaybackSpeedFlyoutMenu",
|
"showPlaybackSpeedFlyoutMenu",
|
||||||
"playbackRateBottomSheetClass",
|
"playbackRateBottomSheetClass",
|
||||||
definingClass,
|
definingClass,
|
||||||
smaliInstructions,
|
smaliInstructions
|
||||||
true
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,13 +56,12 @@ object FlyoutMenuHookPatch : BytecodePatch(
|
|||||||
return-void
|
return-void
|
||||||
"""
|
"""
|
||||||
|
|
||||||
videoUtilsMutableClass.addFieldAndInstructions(
|
context.addStaticFieldToIntegration(
|
||||||
context,
|
INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR,
|
||||||
"showVideoQualityFlyoutMenu",
|
"showVideoQualityFlyoutMenu",
|
||||||
"videoQualityBottomSheetClass",
|
"videoQualityBottomSheetClass",
|
||||||
definingClass,
|
definingClass,
|
||||||
smaliInstructions,
|
smaliInstructions
|
||||||
true
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@ package app.revanced.patches.youtube.utils.lottie
|
|||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH
|
import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH
|
||||||
import app.revanced.patches.youtube.utils.lottie.fingerprints.SetAnimationFingerprint
|
import app.revanced.patches.youtube.utils.lottie.fingerprints.SetAnimationFingerprint
|
||||||
import app.revanced.patches.youtube.utils.lottie.fingerprints.SetAnimationFingerprint.LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.lottie.fingerprints.SetAnimationFingerprint.LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
@ -20,21 +20,15 @@ object LottieAnimationViewHookPatch : BytecodePatch(
|
|||||||
"$UTILS_PATH/LottieAnimationViewPatch;"
|
"$UTILS_PATH/LottieAnimationViewPatch;"
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
|
context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) {
|
||||||
val setAnimationMethodName = SetAnimationFingerprint.resultOrThrow().mutableMethod.name
|
name == "setAnimation"
|
||||||
val setAnimationCall = "invoke-virtual {p0, p1}, " +
|
}.addInstruction(
|
||||||
LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR +
|
0,
|
||||||
"->" +
|
"invoke-virtual {p0, p1}, " +
|
||||||
setAnimationMethodName +
|
LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR +
|
||||||
"(I)V"
|
"->" +
|
||||||
|
SetAnimationFingerprint.resultOrThrow().mutableMethod.name +
|
||||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)
|
"(I)V"
|
||||||
?.mutableClass
|
)
|
||||||
?.methods
|
|
||||||
?.first { method -> method.name == "setAnimation" }
|
|
||||||
?.addInstruction(
|
|
||||||
0,
|
|
||||||
setAnimationCall
|
|
||||||
) ?: throw PatchException("Could not find setAnimation method")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,6 +18,7 @@ import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarButton
|
|||||||
import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarConstructorFingerprint
|
import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarConstructorFingerprint
|
||||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
@ -115,9 +116,9 @@ object NavigationBarHookPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
navigationTabCreatedCallback =
|
navigationTabCreatedCallback =
|
||||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
|
context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) {
|
||||||
method.name == "navigationTabCreatedCallback"
|
name == "navigationTabCreatedCallback"
|
||||||
} ?: throw PatchException("Could not find navigationTabCreatedCallback method")
|
}
|
||||||
|
|
||||||
MainActivityResolvePatch.injectOnBackPressedMethodCall(
|
MainActivityResolvePatch.injectOnBackPressedMethodCall(
|
||||||
INTEGRATIONS_CLASS_DESCRIPTOR,
|
INTEGRATIONS_CLASS_DESCRIPTOR,
|
||||||
|
@ -17,6 +17,7 @@ import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerCont
|
|||||||
import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint
|
import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.util.alsoResolve
|
import app.revanced.util.alsoResolve
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
@ -115,28 +116,25 @@ object PlayerControlsPatch : BytecodePatch(
|
|||||||
|
|
||||||
// region set methods to inject into integration
|
// region set methods to inject into integration
|
||||||
|
|
||||||
val playerControlsMutableClass =
|
|
||||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
|
||||||
|
|
||||||
changeVisibilityMethod =
|
changeVisibilityMethod =
|
||||||
playerControlsMutableClass.methods.single { method ->
|
context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) {
|
||||||
method.name == "changeVisibility"
|
name == "changeVisibility"
|
||||||
&& method.parameters == listOf("Z", "Z")
|
&& parameters == listOf("Z", "Z")
|
||||||
}
|
}
|
||||||
|
|
||||||
changeVisibilityNegatedImmediatelyMethod =
|
changeVisibilityNegatedImmediatelyMethod =
|
||||||
playerControlsMutableClass.methods.single { method ->
|
context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) {
|
||||||
method.name == "changeVisibilityNegatedImmediately"
|
name == "changeVisibilityNegatedImmediately"
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeBottomControlButtonMethod =
|
initializeBottomControlButtonMethod =
|
||||||
playerControlsMutableClass.methods.single { method ->
|
context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) {
|
||||||
method.name == "initializeBottomControlButton"
|
name == "initializeBottomControlButton"
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeTopControlButtonMethod =
|
initializeTopControlButtonMethod =
|
||||||
playerControlsMutableClass.methods.single { method ->
|
context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) {
|
||||||
method.name == "initializeTopControlButton"
|
name == "initializeTopControlButton"
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
@ -15,7 +15,10 @@ import app.revanced.patches.youtube.utils.playertype.fingerprint.BrowseIdClassFi
|
|||||||
import app.revanced.patches.youtube.utils.playertype.fingerprint.PlayerTypeFingerprint
|
import app.revanced.patches.youtube.utils.playertype.fingerprint.PlayerTypeFingerprint
|
||||||
import app.revanced.patches.youtube.utils.playertype.fingerprint.VideoStateFingerprint
|
import app.revanced.patches.youtube.utils.playertype.fingerprint.VideoStateFingerprint
|
||||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
|
||||||
import app.revanced.util.addFieldAndInstructions
|
import app.revanced.util.addStaticFieldToIntegration
|
||||||
|
import app.revanced.util.alsoResolve
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
import app.revanced.util.indexOfFirstStringInstructionOrThrow
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
@ -57,22 +60,20 @@ object PlayerTypeHookPatch : BytecodePatch(
|
|||||||
|
|
||||||
// region patch for set video state
|
// region patch for set video state
|
||||||
|
|
||||||
YouTubeControlsOverlayFingerprint.resultOrThrow().let { parentResult ->
|
VideoStateFingerprint.alsoResolve(
|
||||||
VideoStateFingerprint.also {
|
context, YouTubeControlsOverlayFingerprint
|
||||||
it.resolve(context, parentResult.classDef)
|
).let {
|
||||||
}.resultOrThrow().let {
|
it.mutableMethod.apply {
|
||||||
it.mutableMethod.apply {
|
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
val videoStateFieldName =
|
||||||
val videoStateFieldName =
|
getInstruction<ReferenceInstruction>(endIndex).reference
|
||||||
getInstruction<ReferenceInstruction>(endIndex).reference
|
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
0, """
|
0, """
|
||||||
iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field
|
iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field
|
||||||
invoke-static {v0}, $INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V
|
invoke-static {v0}, $INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,39 +84,36 @@ object PlayerTypeHookPatch : BytecodePatch(
|
|||||||
BrowseIdClassFingerprint.resultOrThrow().let {
|
BrowseIdClassFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val targetIndex = indexOfFirstStringInstructionOrThrow("VL") - 1
|
val targetIndex = indexOfFirstStringInstructionOrThrow("VL") - 1
|
||||||
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference
|
val targetClass = getInstruction(targetIndex)
|
||||||
val targetClass =
|
.getReference<FieldReference>()
|
||||||
context.findClass((targetReference as FieldReference).definingClass)!!.mutableClass
|
?.definingClass
|
||||||
|
?: throw PatchException("Could not find browseId class")
|
||||||
|
|
||||||
targetClass.methods.find { method -> method.name == "<init>" }
|
context.findMethodOrThrow(targetClass).apply {
|
||||||
?.apply {
|
val browseIdFieldReference = getInstruction<ReferenceInstruction>(
|
||||||
val browseIdFieldIndex = indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT)
|
indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT)
|
||||||
val browseIdFieldName =
|
).reference
|
||||||
(getInstruction<ReferenceInstruction>(browseIdFieldIndex).reference as FieldReference).name
|
val browseIdFieldName = (browseIdFieldReference as FieldReference).name
|
||||||
|
|
||||||
val smaliInstructions =
|
val smaliInstructions =
|
||||||
|
"""
|
||||||
|
if-eqz v0, :ignore
|
||||||
|
iget-object v0, v0, $definingClass->$browseIdFieldName:Ljava/lang/String;
|
||||||
|
if-eqz v0, :ignore
|
||||||
|
return-object v0
|
||||||
|
:ignore
|
||||||
|
const-string v0, ""
|
||||||
|
return-object v0
|
||||||
"""
|
"""
|
||||||
if-eqz v0, :ignore
|
|
||||||
iget-object v0, v0, $definingClass->$browseIdFieldName:Ljava/lang/String;
|
|
||||||
if-eqz v0, :ignore
|
|
||||||
return-object v0
|
|
||||||
:ignore
|
|
||||||
const-string v0, ""
|
|
||||||
return-object v0
|
|
||||||
"""
|
|
||||||
|
|
||||||
val rootViewMutableClass =
|
context.addStaticFieldToIntegration(
|
||||||
context.findClass(INTEGRATIONS_ROOT_VIEW_HOOK_CLASS_DESCRIPTOR)!!.mutableClass
|
INTEGRATIONS_ROOT_VIEW_HOOK_CLASS_DESCRIPTOR,
|
||||||
|
"getBrowseId",
|
||||||
rootViewMutableClass.addFieldAndInstructions(
|
"browseIdClass",
|
||||||
context,
|
definingClass,
|
||||||
"getBrowseId",
|
smaliInstructions
|
||||||
"browseIdClass",
|
)
|
||||||
definingClass,
|
}
|
||||||
smaliInstructions,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
} ?: throw PatchException("BrowseIdClass not found!")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
|
|||||||
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.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint
|
import app.revanced.patches.youtube.utils.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint
|
||||||
@ -17,6 +16,8 @@ import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fin
|
|||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberMeasureTextParentFingerprint
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberMeasureTextParentFingerprint
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberSetterFingerprint
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberSetterFingerprint
|
||||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||||
|
import app.revanced.util.alsoResolve
|
||||||
|
import app.revanced.util.findMethodOrThrow
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
@ -26,7 +27,6 @@ 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.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.Reference
|
|
||||||
|
|
||||||
@Patch(dependencies = [SettingsPatch::class])
|
@Patch(dependencies = [SettingsPatch::class])
|
||||||
object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch(
|
object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch(
|
||||||
@ -47,130 +47,115 @@ object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch(
|
|||||||
* In order to maintain compatibility with YouTube v18.48.39 or previous versions,
|
* In order to maintain compatibility with YouTube v18.48.39 or previous versions,
|
||||||
* This patch is applied only to the version after YouTube v18.49.37
|
* This patch is applied only to the version after YouTube v18.49.37
|
||||||
*/
|
*/
|
||||||
if (SettingsPatch.upward1849) {
|
if (!SettingsPatch.upward1849) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
RollingNumberSetterFingerprint.resultOrThrow().let {
|
RollingNumberSetterFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val rollingNumberClassIndex = it.scanResult.patternScanResult!!.startIndex
|
val rollingNumberClassIndex = it.scanResult.patternScanResult!!.startIndex
|
||||||
val rollingNumberClassReference =
|
val rollingNumberClassReference =
|
||||||
getInstruction<ReferenceInstruction>(rollingNumberClassIndex).reference
|
getInstruction<ReferenceInstruction>(rollingNumberClassIndex).reference.toString()
|
||||||
val rollingNumberClass =
|
val rollingNumberConstructorMethod =
|
||||||
context.findClass(rollingNumberClassReference.toString())!!.mutableClass
|
context.findMethodOrThrow(rollingNumberClassReference)
|
||||||
|
val charSequenceFieldReference = with(rollingNumberConstructorMethod) {
|
||||||
|
getInstruction<ReferenceInstruction>(
|
||||||
|
indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT)
|
||||||
|
).reference
|
||||||
|
}
|
||||||
|
|
||||||
lateinit var charSequenceFieldReference: Reference
|
val insertIndex = rollingNumberClassIndex + 1
|
||||||
|
val charSequenceInstanceRegister =
|
||||||
|
getInstruction<OneRegisterInstruction>(rollingNumberClassIndex).registerA
|
||||||
|
val registerCount = implementation!!.registerCount
|
||||||
|
|
||||||
rollingNumberClass.methods.find { method -> method.name == "<init>" }
|
// This register is being overwritten, so it is free to use.
|
||||||
?.apply {
|
val freeRegister = registerCount - 1
|
||||||
val rollingNumberFieldIndex =
|
val conversionContextRegister = registerCount - parameters.size + 1
|
||||||
indexOfFirstInstructionOrThrow(opcode = Opcode.IPUT_OBJECT)
|
|
||||||
charSequenceFieldReference =
|
|
||||||
getInstruction<ReferenceInstruction>(rollingNumberFieldIndex).reference
|
|
||||||
} ?: throw PatchException("RollingNumberClass not found!")
|
|
||||||
|
|
||||||
val insertIndex = rollingNumberClassIndex + 1
|
addInstructions(
|
||||||
|
insertIndex, """
|
||||||
val charSequenceInstanceRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(rollingNumberClassIndex).registerA
|
|
||||||
|
|
||||||
val registerCount = implementation!!.registerCount
|
|
||||||
|
|
||||||
// This register is being overwritten, so it is free to use.
|
|
||||||
val freeRegister = registerCount - 1
|
|
||||||
val conversionContextRegister = registerCount - parameters.size + 1
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
insertIndex, """
|
|
||||||
iget-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
|
iget-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
|
||||||
invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
|
invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;
|
||||||
move-result-object v$freeRegister
|
move-result-object v$freeRegister
|
||||||
iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
|
iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Rolling Number text views use the measured width of the raw string for layout.
|
// Rolling Number text views use the measured width of the raw string for layout.
|
||||||
// Modify the measure text calculation to include the left drawable separator if needed.
|
// Modify the measure text calculation to include the left drawable separator if needed.
|
||||||
RollingNumberMeasureAnimatedTextFingerprint.resultOrThrow().let {
|
RollingNumberMeasureAnimatedTextFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
val measuredTextWidthIndex = endIndex - 2
|
val measuredTextWidthIndex = endIndex - 2
|
||||||
val measuredTextWidthRegister =
|
val measuredTextWidthRegister =
|
||||||
getInstruction<TwoRegisterInstruction>(measuredTextWidthIndex).registerA
|
getInstruction<TwoRegisterInstruction>(measuredTextWidthIndex).registerA
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
endIndex + 1, """
|
endIndex + 1, """
|
||||||
invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
||||||
move-result v$measuredTextWidthRegister
|
move-result v$measuredTextWidthRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
val ifGeIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.IF_GE)
|
val ifGeIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.IF_GE)
|
||||||
val ifGeInstruction = getInstruction<TwoRegisterInstruction>(ifGeIndex)
|
val ifGeInstruction = getInstruction<TwoRegisterInstruction>(ifGeIndex)
|
||||||
|
|
||||||
removeInstruction(ifGeIndex)
|
removeInstruction(ifGeIndex)
|
||||||
addInstructionsWithLabels(
|
addInstructionsWithLabels(
|
||||||
ifGeIndex, """
|
ifGeIndex, """
|
||||||
if-ge v${ifGeInstruction.registerA}, v${ifGeInstruction.registerB}, :jump
|
if-ge v${ifGeInstruction.registerA}, v${ifGeInstruction.registerB}, :jump
|
||||||
""", ExternalLabel("jump", getInstruction(endIndex))
|
""", ExternalLabel("jump", getInstruction(endIndex))
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RollingNumberMeasureTextParentFingerprint.resultOrThrow().classDef.let { parentClassDef ->
|
RollingNumberMeasureStaticLabelFingerprint.alsoResolve(
|
||||||
RollingNumberMeasureStaticLabelFingerprint.resolve(context, parentClassDef)
|
context,
|
||||||
|
RollingNumberMeasureTextParentFingerprint
|
||||||
|
).let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||||
|
val freeRegister = getInstruction<TwoRegisterInstruction>(0).registerA
|
||||||
|
|
||||||
// Additional text measurement method. Used if YouTube decides not to animate the likes count
|
addInstructions(
|
||||||
// and sometimes used for initial video load.
|
measureTextIndex + 1, """
|
||||||
RollingNumberMeasureStaticLabelFingerprint.resultOrThrow().let {
|
move-result v$freeRegister
|
||||||
it.mutableMethod.apply {
|
invoke-static {p1, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
||||||
val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
"""
|
||||||
val freeRegister = getInstruction<TwoRegisterInstruction>(0).registerA
|
)
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
measureTextIndex + 1, """
|
|
||||||
move-result v$freeRegister
|
|
||||||
invoke-static {p1, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The rolling number Span is missing styling since it's initially set as a String.
|
// The rolling number Span is missing styling since it's initially set as a String.
|
||||||
// Modify the UI text view and use the styled like/dislike Span.
|
// Modify the UI text view and use the styled like/dislike Span.
|
||||||
RollingNumberTextViewFingerprint.resultOrThrow().let { parentResult ->
|
arrayOf(
|
||||||
// Initial TextView is set in this method.
|
// Initial TextView is set in this method.
|
||||||
val initiallyCreatedTextViewMethod = parentResult.mutableMethod
|
RollingNumberTextViewFingerprint
|
||||||
|
.resultOrThrow(),
|
||||||
|
|
||||||
// Video less than 24 hours after uploaded, like counts will be updated in real time.
|
// Video less than 24 hours after uploaded, like counts will be updated in real time.
|
||||||
// Whenever like counts are updated, TextView is set in this method.
|
// Whenever like counts are updated, TextView is set in this method.
|
||||||
val realTimeUpdateTextViewMethod =
|
RollingNumberTextViewAnimationUpdateFingerprint
|
||||||
RollingNumberTextViewAnimationUpdateFingerprint.also {
|
.alsoResolve(context, RollingNumberTextViewFingerprint)
|
||||||
it.resolve(context, parentResult.classDef)
|
).forEach { fingerprintResult ->
|
||||||
}.resultOrThrow().mutableMethod
|
fingerprintResult.mutableMethod.apply {
|
||||||
|
val setTextIndex = indexOfFirstInstructionOrThrow {
|
||||||
arrayOf(
|
getReference<MethodReference>()?.name == "setText"
|
||||||
initiallyCreatedTextViewMethod,
|
|
||||||
realTimeUpdateTextViewMethod
|
|
||||||
).forEach { insertMethod ->
|
|
||||||
insertMethod.apply {
|
|
||||||
val setTextIndex = indexOfFirstInstructionOrThrow {
|
|
||||||
getReference<MethodReference>()?.name == "setText"
|
|
||||||
}
|
|
||||||
val textViewRegister =
|
|
||||||
getInstruction<FiveRegisterInstruction>(setTextIndex).registerC
|
|
||||||
val textSpanRegister =
|
|
||||||
getInstruction<FiveRegisterInstruction>(setTextIndex).registerD
|
|
||||||
|
|
||||||
addInstructions(
|
|
||||||
setTextIndex, """
|
|
||||||
invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
|
||||||
move-result-object v$textSpanRegister
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
val textViewRegister =
|
||||||
|
getInstruction<FiveRegisterInstruction>(setTextIndex).registerC
|
||||||
|
val textSpanRegister =
|
||||||
|
getInstruction<FiveRegisterInstruction>(setTextIndex).registerD
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
setTextIndex, """
|
||||||
|
invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||||
|
move-result-object v$textSpanRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,28 +71,30 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SettingsPatch.upward1834) {
|
if (!SettingsPatch.upward1834) {
|
||||||
TextComponentSpecFingerprint.resultOrThrow().let {
|
return
|
||||||
it.mutableMethod.apply {
|
}
|
||||||
val insertIndex = indexOfFirstInstructionOrThrow {
|
|
||||||
getReference<MethodReference>()?.toString() == "Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;"
|
|
||||||
}
|
|
||||||
val charSequenceRegister =
|
|
||||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
|
||||||
val conversionContextRegister =
|
|
||||||
getInstruction<TwoRegisterInstruction>(0).registerA
|
|
||||||
val replaceReference =
|
|
||||||
getInstruction<ReferenceInstruction>(insertIndex).reference
|
|
||||||
|
|
||||||
addInstructions(
|
TextComponentSpecFingerprint.resultOrThrow().let {
|
||||||
insertIndex + 1, """
|
it.mutableMethod.apply {
|
||||||
invoke-static {v$conversionContextRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onCharSequenceLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
val insertIndex = indexOfFirstInstructionOrThrow {
|
||||||
move-result-object v$charSequenceRegister
|
getReference<MethodReference>()?.toString() == "Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;"
|
||||||
invoke-static {v$charSequenceRegister}, $replaceReference
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
removeInstruction(insertIndex)
|
|
||||||
}
|
}
|
||||||
|
val charSequenceRegister =
|
||||||
|
getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||||
|
val conversionContextRegister =
|
||||||
|
getInstruction<TwoRegisterInstruction>(0).registerA
|
||||||
|
val replaceReference =
|
||||||
|
getInstruction<ReferenceInstruction>(insertIndex).reference
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
insertIndex + 1, """
|
||||||
|
invoke-static {v$conversionContextRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onCharSequenceLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||||
|
move-result-object v$charSequenceRegister
|
||||||
|
invoke-static {v$charSequenceRegister}, $replaceReference
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
removeInstruction(insertIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,11 @@ import app.revanced.patcher.fingerprint.MethodFingerprintResult
|
|||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||||
import app.revanced.patcher.util.smali.toInstructions
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint
|
import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint
|
||||||
|
import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint
|
||||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.indexOfPlayerResponseModelInstruction
|
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.indexOfPlayerResponseModelInstruction
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.VideoEndFingerprint
|
import app.revanced.patches.youtube.utils.fingerprints.VideoEndFingerprint
|
||||||
@ -31,13 +31,12 @@ import app.revanced.patches.youtube.video.information.fingerprints.SeekRelativeF
|
|||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintBackgroundPlay
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintBackgroundPlay
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintShorts
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintShorts
|
||||||
import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint
|
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityListFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityListFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityTextFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityTextFingerprint
|
||||||
import app.revanced.patches.youtube.video.information.fingerprints.VideoTitleFingerprint
|
import app.revanced.patches.youtube.video.information.fingerprints.VideoTitleFingerprint
|
||||||
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
||||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
||||||
import app.revanced.util.addFieldAndInstructions
|
import app.revanced.util.addStaticFieldToIntegration
|
||||||
import app.revanced.util.alsoResolve
|
import app.revanced.util.alsoResolve
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
@ -121,7 +120,6 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
private var seekSourceMethodName = ""
|
private var seekSourceMethodName = ""
|
||||||
private var seekRelativeSourceMethodName = ""
|
private var seekRelativeSourceMethodName = ""
|
||||||
|
|
||||||
private lateinit var videoInformationMutableClass: MutableClass
|
|
||||||
private lateinit var context: BytecodeContext
|
private lateinit var context: BytecodeContext
|
||||||
|
|
||||||
private lateinit var playerConstructorMethod: MutableMethod
|
private lateinit var playerConstructorMethod: MutableMethod
|
||||||
@ -179,21 +177,18 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
return v0
|
return v0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
videoInformationMutableClass.addFieldAndInstructions(
|
context.addStaticFieldToIntegration(
|
||||||
context,
|
INTEGRATIONS_CLASS_DESCRIPTOR,
|
||||||
methodName,
|
methodName,
|
||||||
fieldName,
|
fieldName,
|
||||||
definingClass,
|
definingClass,
|
||||||
smaliInstructions,
|
smaliInstructions
|
||||||
true
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
this.context = context
|
this.context = context
|
||||||
videoInformationMutableClass =
|
|
||||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
|
||||||
|
|
||||||
VideoEndFingerprint.resultOrThrow().let {
|
VideoEndFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
@ -449,8 +444,8 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
return-void
|
return-void
|
||||||
"""
|
"""
|
||||||
|
|
||||||
videoInformationMutableClass.addFieldAndInstructions(
|
context.addStaticFieldToIntegration(
|
||||||
context,
|
INTEGRATIONS_CLASS_DESCRIPTOR,
|
||||||
"overridePlaybackSpeed",
|
"overridePlaybackSpeed",
|
||||||
"playbackSpeedClass",
|
"playbackSpeedClass",
|
||||||
playbackSpeedClass,
|
playbackSpeedClass,
|
||||||
@ -490,13 +485,12 @@ object VideoInformationPatch : BytecodePatch(
|
|||||||
return-void
|
return-void
|
||||||
"""
|
"""
|
||||||
|
|
||||||
videoInformationMutableClass.addFieldAndInstructions(
|
context.addStaticFieldToIntegration(
|
||||||
context,
|
INTEGRATIONS_CLASS_DESCRIPTOR,
|
||||||
"overrideVideoQuality",
|
"overrideVideoQuality",
|
||||||
"videoQualityClass",
|
"videoQualityClass",
|
||||||
videoQualityClass,
|
videoQualityClass,
|
||||||
smaliInstructions,
|
smaliInstructions
|
||||||
true
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,87 +470,102 @@ fun MethodFingerprintResult.getWalkerMethod(context: BytecodeContext, offset: In
|
|||||||
*/
|
*/
|
||||||
fun MutableMethod.getWalkerMethod(context: BytecodeContext, offset: Int): MutableMethod {
|
fun MutableMethod.getWalkerMethod(context: BytecodeContext, offset: Int): MutableMethod {
|
||||||
val newMethod = getInstruction<ReferenceInstruction>(offset).reference as MethodReference
|
val newMethod = getInstruction<ReferenceInstruction>(offset).reference as MethodReference
|
||||||
return context.findClass { classDef -> classDef.type == newMethod.definingClass }
|
return context.findMethodOrThrow(newMethod.definingClass) {
|
||||||
?.mutableClass
|
MethodUtil.methodSignaturesMatch(this, newMethod)
|
||||||
?.methods
|
}
|
||||||
?.first { method -> MethodUtil.methodSignaturesMatch(method, newMethod) }
|
|
||||||
?: throw PatchException("This method can not be walked at offset $offset inside the method $name")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MutableClass.addFieldAndInstructions(
|
fun BytecodeContext.addStaticFieldToIntegration(
|
||||||
context: BytecodeContext,
|
className: String,
|
||||||
methodName: String,
|
methodName: String,
|
||||||
fieldName: String,
|
fieldName: String,
|
||||||
objectClass: String,
|
objectClass: String,
|
||||||
smaliInstructions: String,
|
smaliInstructions: String,
|
||||||
shouldAddConstructor: Boolean
|
shouldAddConstructor: Boolean = true
|
||||||
) {
|
) {
|
||||||
val objectCall = "$this->$fieldName:$objectClass"
|
val mutableClass = findClass { classDef -> classDef.type == className }
|
||||||
|
?.mutableClass
|
||||||
|
?: throw PatchException("No matching classes found: $className")
|
||||||
|
|
||||||
methods.single { method -> method.name == methodName }.apply {
|
val objectCall = "$mutableClass->$fieldName:$objectClass"
|
||||||
staticFields.add(
|
|
||||||
ImmutableField(
|
|
||||||
definingClass,
|
|
||||||
fieldName,
|
|
||||||
objectClass,
|
|
||||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
|
||||||
null,
|
|
||||||
annotations,
|
|
||||||
null
|
|
||||||
).toMutable()
|
|
||||||
)
|
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
mutableClass.apply {
|
||||||
0,
|
methods.first { method -> method.name == methodName }.apply {
|
||||||
"""
|
staticFields.add(
|
||||||
|
ImmutableField(
|
||||||
|
definingClass,
|
||||||
|
fieldName,
|
||||||
|
objectClass,
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
null,
|
||||||
|
annotations,
|
||||||
|
null
|
||||||
|
).toMutable()
|
||||||
|
)
|
||||||
|
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
sget-object v0, $objectCall
|
sget-object v0, $objectCall
|
||||||
""" + smaliInstructions
|
""" + smaliInstructions
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldAddConstructor) {
|
if (!shouldAddConstructor) return
|
||||||
context.findClass(objectClass)!!.mutableClass.methods
|
|
||||||
.filter { method -> method.name == "<init>" }
|
|
||||||
.forEach { mutableMethod ->
|
|
||||||
mutableMethod.apply {
|
|
||||||
val initializeIndex = indexOfFirstInstructionOrThrow {
|
|
||||||
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
|
|
||||||
}
|
|
||||||
val insertIndex = if (initializeIndex == -1)
|
|
||||||
1
|
|
||||||
else
|
|
||||||
initializeIndex + 1
|
|
||||||
|
|
||||||
val initializeRegister = if (initializeIndex == -1)
|
findMethodsOrThrow(objectClass)
|
||||||
"p0"
|
.filter { method -> MethodUtil.isConstructor(method) }
|
||||||
else
|
.forEach { mutableMethod ->
|
||||||
"v${getInstruction<FiveRegisterInstruction>(initializeIndex).registerC}"
|
mutableMethod.apply {
|
||||||
|
val initializeIndex = indexOfFirstInstructionOrThrow {
|
||||||
addInstruction(
|
opcode == Opcode.INVOKE_DIRECT &&
|
||||||
insertIndex,
|
getReference<MethodReference>()?.name == "<init>"
|
||||||
"sput-object $initializeRegister, $objectCall"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
val insertIndex = if (initializeIndex == -1)
|
||||||
|
1
|
||||||
|
else
|
||||||
|
initializeIndex + 1
|
||||||
|
|
||||||
|
val initializeRegister = if (initializeIndex == -1)
|
||||||
|
"p0"
|
||||||
|
else
|
||||||
|
"v${getInstruction<FiveRegisterInstruction>(initializeIndex).registerC}"
|
||||||
|
|
||||||
|
addInstruction(
|
||||||
|
insertIndex,
|
||||||
|
"sput-object $initializeRegister, $objectCall"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun BytecodeContext.findMethodOrThrow(
|
||||||
|
reference: String,
|
||||||
|
methodPredicate: Method.() -> Boolean = { MethodUtil.isConstructor(this) }
|
||||||
|
) = findMethodsOrThrow(reference).first(methodPredicate)
|
||||||
|
|
||||||
|
fun BytecodeContext.findMethodsOrThrow(reference: String): MutableSet<MutableMethod> {
|
||||||
|
val methods =
|
||||||
|
findClass { classDef -> classDef.type == reference }
|
||||||
|
?.mutableClass
|
||||||
|
?.methods
|
||||||
|
|
||||||
|
if (methods != null) {
|
||||||
|
return methods
|
||||||
|
} else {
|
||||||
|
throw PatchException("No matching methods found in: $reference")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BytecodeContext.updatePatchStatus(
|
fun BytecodeContext.updatePatchStatus(
|
||||||
className: String,
|
className: String,
|
||||||
methodName: String
|
methodName: String
|
||||||
) {
|
) = findMethodOrThrow(className) { name == methodName }
|
||||||
this.classes.forEach { classDef ->
|
.replaceInstruction(
|
||||||
if (classDef.type.endsWith(className)) {
|
0,
|
||||||
val patchStatusMethod =
|
"const/4 v0, 0x1"
|
||||||
this.proxy(classDef).mutableClass.methods.first { it.name == methodName }
|
)
|
||||||
|
|
||||||
patchStatusMethod.replaceInstruction(
|
|
||||||
0,
|
|
||||||
"const/4 v0, 0x1"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the resolved methods of [MethodFingerprint]s early.
|
* Return the resolved methods of [MethodFingerprint]s early.
|
||||||
@ -571,7 +586,7 @@ fun List<MethodFingerprint>.returnEarly(bool: Boolean = false) {
|
|||||||
return v0
|
return v0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
else -> throw Exception("This case should never happen.")
|
else -> throw PatchException("This case should never happen: ${fingerprint.javaClass.simpleName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
result.mutableMethod.addInstructions(0, stringInstructions)
|
result.mutableMethod.addInstructions(0, stringInstructions)
|
||||||
|
Reference in New Issue
Block a user