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