mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-22 19:09:12 +02:00
chore(YouTube): replace with a fingerprint that supports a wider range of versions
This commit is contained in:
parent
088f0ebf6b
commit
67d365e509
@ -102,8 +102,8 @@ abstract class BaseCronetImageUrlHookPatch(
|
||||
// Add a helper get method that returns the URL field.
|
||||
RequestFingerprint.resultOrThrow().apply {
|
||||
// The url is the only string field that is set inside the constructor.
|
||||
val urlFieldInstruction = mutableMethod.getInstructions().single {
|
||||
if (it.opcode != Opcode.IPUT_OBJECT) return@single false
|
||||
val urlFieldInstruction = mutableMethod.getInstructions().first {
|
||||
if (it.opcode != Opcode.IPUT_OBJECT) return@first false
|
||||
|
||||
val reference = (it as ReferenceInstruction).reference as FieldReference
|
||||
reference.type == "Ljava/lang/String;"
|
||||
|
@ -2,11 +2,12 @@ package app.revanced.patches.youtube.general.autocaptions.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object StoryboardRendererDecoderRecommendedLevelFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
||||
parameters = listOf(PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR),
|
||||
strings = listOf("#-1#")
|
||||
)
|
||||
|
@ -11,6 +11,7 @@ import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.general.toolbar.fingerprints.ActionBarRingoBackgroundFingerprint
|
||||
import app.revanced.patches.youtube.general.toolbar.fingerprints.ActionBarRingoConstructorFingerprint
|
||||
import app.revanced.patches.youtube.general.toolbar.fingerprints.ActionBarRingoTextFingerprint
|
||||
import app.revanced.patches.youtube.general.toolbar.fingerprints.AttributeResolverFingerprint
|
||||
import app.revanced.patches.youtube.general.toolbar.fingerprints.CreateButtonDrawableFingerprint
|
||||
@ -72,6 +73,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
compatiblePackages = COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
ActionBarRingoBackgroundFingerprint,
|
||||
ActionBarRingoConstructorFingerprint,
|
||||
AttributeResolverFingerprint,
|
||||
CreateButtonDrawableFingerprint,
|
||||
CreateSearchSuggestionsFingerprint,
|
||||
@ -178,7 +180,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
"invoke-static {v$viewRegister}, $GENERAL_CLASS_DESCRIPTOR->setWideSearchBarLayout(Landroid/view/View;)V"
|
||||
)
|
||||
|
||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex + 1
|
||||
val targetIndex = ActionBarRingoBackgroundFingerprint.indexOfStaticInstruction(this) + 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
injectSearchBarHook(
|
||||
@ -187,39 +189,11 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
"enableWideSearchBarWithHeaderInverse"
|
||||
)
|
||||
}
|
||||
|
||||
it.mutableClass.methods.first { method -> MethodUtil.isConstructor(method) }
|
||||
.apply {
|
||||
val staticCalls = implementation!!.instructions.withIndex()
|
||||
.filter { instruction ->
|
||||
val methodReference =
|
||||
((instruction.value as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
methodReference?.parameterTypes?.size == 1 &&
|
||||
methodReference.returnType == "Z"
|
||||
}
|
||||
|
||||
if (staticCalls.size != 2)
|
||||
throw PatchException("Size of staticCalls does not match: ${staticCalls.size}")
|
||||
|
||||
mapOf(
|
||||
staticCalls.elementAt(0).index to "enableWideSearchBar",
|
||||
staticCalls.elementAt(1).index to "enableWideSearchBarWithHeader"
|
||||
).forEach { (index, descriptor) ->
|
||||
val walkerMethod = getWalkerMethod(context, index)
|
||||
|
||||
walkerMethod.apply {
|
||||
injectSearchBarHook(
|
||||
implementation!!.instructions.size - 1,
|
||||
descriptor
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ActionBarRingoTextFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex + 1
|
||||
val targetIndex = ActionBarRingoTextFingerprint.indexOfStaticInstruction(this) + 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
injectSearchBarHook(
|
||||
@ -230,6 +204,35 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
ActionBarRingoConstructorFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val staticCalls = implementation!!.instructions
|
||||
.withIndex()
|
||||
.filter { (_, instruction) ->
|
||||
val methodReference = (instruction as? ReferenceInstruction)?.reference
|
||||
instruction.opcode == Opcode.INVOKE_STATIC &&
|
||||
methodReference is MethodReference &&
|
||||
methodReference.parameterTypes.size == 1 &&
|
||||
methodReference.returnType == "Z"
|
||||
}
|
||||
|
||||
if (staticCalls.size != 2)
|
||||
throw PatchException("Size of staticCalls does not match: ${staticCalls.size}")
|
||||
|
||||
mapOf(
|
||||
staticCalls.elementAt(0).index to "enableWideSearchBar",
|
||||
staticCalls.elementAt(1).index to "enableWideSearchBarWithHeader"
|
||||
).forEach { (index, descriptor) ->
|
||||
val walkerMethod = getWalkerMethod(context, index)
|
||||
|
||||
walkerMethod.apply {
|
||||
injectSearchBarHook(
|
||||
implementation!!.instructions.lastIndex,
|
||||
descriptor
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
YouActionBarFingerprint.resolve(context, setActionBarRingoMutableClass)
|
||||
YouActionBarFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
|
@ -1,15 +1,28 @@
|
||||
package app.revanced.patches.youtube.general.toolbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.general.toolbar.fingerprints.ActionBarRingoBackgroundFingerprint.indexOfStaticInstruction
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ActionBarRingoBackground
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object ActionBarRingoBackgroundFingerprint : LiteralValueFingerprint(
|
||||
internal object ActionBarRingoBackgroundFingerprint : MethodFingerprint(
|
||||
returnType = "Landroid/view/View;",
|
||||
parameters = listOf("Landroid/view/LayoutInflater;"),
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_STATIC
|
||||
),
|
||||
literalSupplier = { ActionBarRingoBackground }
|
||||
)
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.containsWideLiteralInstructionIndex(ActionBarRingoBackground) &&
|
||||
indexOfStaticInstruction(methodDef) >= 0
|
||||
}
|
||||
) {
|
||||
fun indexOfStaticInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_STATIC &&
|
||||
reference?.parameterTypes?.size == 1 &&
|
||||
reference.parameterTypes.firstOrNull() == "Landroid/content/Context;" &&
|
||||
reference.returnType == "Z"
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package app.revanced.patches.youtube.general.toolbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
internal object ActionBarRingoConstructorFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
strings = listOf("default"),
|
||||
customFingerprint = custom@{ methodDef, _ ->
|
||||
if (!MethodUtil.isConstructor(methodDef)) {
|
||||
return@custom false
|
||||
}
|
||||
|
||||
val parameterTypes = methodDef.parameterTypes
|
||||
parameterTypes.size >= 5 && parameterTypes[0] == "Landroid/content/Context;"
|
||||
}
|
||||
)
|
@ -1,16 +1,36 @@
|
||||
package app.revanced.patches.youtube.general.toolbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.util.fingerprint.MethodReferenceNameFingerprint
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.general.toolbar.fingerprints.ActionBarRingoTextFingerprint.indexOfStaticInstruction
|
||||
import app.revanced.patches.youtube.general.toolbar.fingerprints.ActionBarRingoTextFingerprint.indexOfStartDelayInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object ActionBarRingoTextFingerprint : MethodReferenceNameFingerprint(
|
||||
returnType = "V",
|
||||
internal object ActionBarRingoTextFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_STATIC
|
||||
),
|
||||
reference = { "setStartDelay" }
|
||||
)
|
||||
customFingerprint = { methodDef, _ ->
|
||||
indexOfStartDelayInstruction(methodDef) >= 0 &&
|
||||
indexOfStaticInstruction(methodDef) >= 0
|
||||
}
|
||||
) {
|
||||
fun indexOfStartDelayInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "setStartDelay"
|
||||
}
|
||||
|
||||
fun indexOfStaticInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstructionReversed (indexOfStartDelayInstruction(methodDef)) {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_STATIC &&
|
||||
reference?.parameterTypes?.size == 1 &&
|
||||
reference.parameterTypes.firstOrNull() == "Landroid/content/Context;" &&
|
||||
reference.returnType == "Z"
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.BackgroundPlaybackManagerFingerprint
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.BackgroundPlaybackSettingsFingerprint
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.KidsBackgroundPlaybackPolicyControllerFingerprint
|
||||
@ -14,9 +15,12 @@ import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||
import app.revanced.util.findOpcodeIndicesReversed
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
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.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
@ -40,13 +44,24 @@ object BackgroundPlaybackPatch : BaseBytecodePatch(
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
BackgroundPlaybackManagerFingerprint.resultOrThrow().mutableMethod.addInstructions(
|
||||
0, """
|
||||
invoke-static {}, $MISC_PATH/BackgroundPlaybackPatch;->playbackIsNotShort()Z
|
||||
move-result v0
|
||||
return v0
|
||||
"""
|
||||
)
|
||||
BackgroundPlaybackManagerFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
findOpcodeIndicesReversed(Opcode.RETURN).forEach{ index ->
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
// Replace to preserve control flow label.
|
||||
replaceInstruction(
|
||||
index,
|
||||
"invoke-static { v$register }, $MISC_PATH/BackgroundPlaybackPatch;->allowBackgroundPlayback(Z)Z"
|
||||
)
|
||||
|
||||
addInstructions(index + 1,
|
||||
"""
|
||||
move-result v$register
|
||||
return v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Enable background playback option in YouTube settings
|
||||
BackgroundPlaybackSettingsFingerprint.resultOrThrow().let {
|
||||
|
@ -2,6 +2,7 @@ package app.revanced.patches.youtube.misc.backgroundplayback.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
@ -11,7 +12,7 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
internal object KidsBackgroundPlaybackPolicyControllerParentFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
||||
parameters = listOf(PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.SGET_OBJECT
|
||||
|
@ -10,6 +10,7 @@ import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.player.descriptions.fingerprints.EngagementPanelTitleFingerprint
|
||||
import app.revanced.patches.youtube.player.descriptions.fingerprints.EngagementPanelTitleParentFingerprint
|
||||
import app.revanced.patches.youtube.player.descriptions.fingerprints.TextViewComponentFingerprint
|
||||
import app.revanced.patches.youtube.player.descriptions.fingerprints.TextViewComponentFingerprint.indexOfTextIsSelectableInstruction
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint
|
||||
import app.revanced.patches.youtube.utils.fingerprints.RollingNumberTextViewFingerprint
|
||||
@ -94,8 +95,7 @@ object DescriptionComponentsPatch : BaseBytecodePatch(
|
||||
if (SettingsPatch.upward1902) {
|
||||
TextViewComponentFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex =
|
||||
getTargetIndexWithMethodReferenceNameOrThrow("setTextIsSelectable")
|
||||
val insertIndex = indexOfTextIsSelectableInstruction(this)
|
||||
val insertInstruction = getInstruction<FiveRegisterInstruction>(insertIndex)
|
||||
|
||||
replaceInstruction(
|
||||
|
@ -1,14 +1,30 @@
|
||||
package app.revanced.patches.youtube.player.descriptions.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.MethodReferenceNameFingerprint
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.player.descriptions.fingerprints.TextViewComponentFingerprint.indexOfTextIsSelectableInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
/**
|
||||
* This fingerprint is compatible with YouTube v18.35.xx~
|
||||
* Nonetheless, the patch works in YouTube v19.02.xx~
|
||||
*/
|
||||
internal object TextViewComponentFingerprint : MethodReferenceNameFingerprint(
|
||||
internal object TextViewComponentFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
opcodes = listOf(Opcode.CMPL_FLOAT),
|
||||
reference = { "setBreakStrategy" }
|
||||
)
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.implementation != null &&
|
||||
indexOfTextIsSelectableInstruction(methodDef) >= 0
|
||||
},
|
||||
) {
|
||||
fun indexOfTextIsSelectableInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
reference?.name == "setTextIsSelectable" &&
|
||||
reference.definingClass != "Landroid/widget/TextView;"
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
"invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->setQuickActionMargin(Landroid/widget/FrameLayout;)V"
|
||||
"invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->setQuickActionMargin(Landroid/view/View;)V"
|
||||
)
|
||||
|
||||
addInstruction(
|
||||
|
@ -38,7 +38,6 @@ import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT
|
||||
import app.revanced.util.getTargetIndexOrThrow
|
||||
import app.revanced.util.getTargetIndexReversedOrThrow
|
||||
import app.revanced.util.getTargetIndexWithReferenceOrThrow
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.literalInstructionHook
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
@ -93,7 +92,7 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
"SETTINGS: SHORTS_COMPONENTS"
|
||||
)
|
||||
|
||||
if (SettingsPatch.upward1925) {
|
||||
if (SettingsPatch.upward1925 && !SettingsPatch.upward1928) {
|
||||
settingArray += "SETTINGS: SHORTS_TIME_STAMP"
|
||||
}
|
||||
|
||||
@ -279,18 +278,15 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
// region patch for hide paused header
|
||||
|
||||
ShortsPausedHeaderFingerprint.resultOrThrow().let {
|
||||
val targetMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
targetMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->hideShortsPausedHeader()Z
|
||||
move-result v0
|
||||
if-nez v0, :hide
|
||||
""",
|
||||
ExternalLabel("hide", getInstruction(implementation!!.instructions.lastIndex))
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
invoke-static {v$insertRegister}, $SHORTS_CLASS_DESCRIPTOR->hideShortsPausedHeader(Z)Z
|
||||
move-result v$insertRegister
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ object ShortsNavigationBarPatch : BytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
BottomNavigationBarFingerprint.resultOrThrow().let {
|
||||
BottomNavigationBarFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("findViewById") + 1
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
@ -29,7 +29,7 @@ object ShortsTimeStampPatch : BytecodePatch(
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
if (!SettingsPatch.upward1925) return
|
||||
if (!SettingsPatch.upward1925 || SettingsPatch.upward1928) return
|
||||
|
||||
// region patch for enable time stamp
|
||||
|
||||
|
@ -10,8 +10,7 @@ internal object ShortsPausedHeaderFingerprint : MethodFingerprint(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
),
|
||||
strings = listOf("r_pfcv")
|
||||
)
|
@ -0,0 +1,17 @@
|
||||
package app.revanced.patches.youtube.utils
|
||||
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object PlayerResponseModelUtils {
|
||||
const val PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR =
|
||||
"Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
||||
|
||||
fun indexOfPlayerResponseModelInstruction(methodDef: Method) = methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_INTERFACE &&
|
||||
getReference<MethodReference>()?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
package app.revanced.patches.youtube.utils.pip.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object PiPPlaybackFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
||||
parameters = listOf(PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
|
@ -129,7 +129,7 @@ object PlayerTypeHookPatch : BytecodePatch(
|
||||
// so this works regardless which layout is used.
|
||||
ActionBarSearchResultsFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val instructionIndex =
|
||||
getTargetIndexWithMethodReferenceNameOrThrow("setLayoutDirection")
|
||||
ActionBarSearchResultsFingerprint.indexOfLayoutDirectionInstruction(this)
|
||||
val viewRegister = getInstruction<FiveRegisterInstruction>(instructionIndex).registerC
|
||||
|
||||
addInstruction(
|
||||
|
@ -1,13 +1,28 @@
|
||||
package app.revanced.patches.youtube.utils.playertype.fingerprint
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.playertype.fingerprint.ActionBarSearchResultsFingerprint.indexOfLayoutDirectionInstruction
|
||||
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ActionBarSearchResultsViewMic
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object ActionBarSearchResultsFingerprint : LiteralValueFingerprint(
|
||||
internal object ActionBarSearchResultsFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "Landroid/view/View;",
|
||||
parameters = listOf("Landroid/view/LayoutInflater;"),
|
||||
literalSupplier = { ActionBarSearchResultsViewMic }
|
||||
)
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.containsWideLiteralInstructionIndex(ActionBarSearchResultsViewMic) &&
|
||||
indexOfLayoutDirectionInstruction(methodDef) >= 0
|
||||
}
|
||||
) {
|
||||
fun indexOfLayoutDirectionInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>().toString() == "Landroid/view/View;->setLayoutDirection(I)V"
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patches.shared.litho.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH
|
||||
@ -18,11 +19,18 @@ import app.revanced.patches.youtube.utils.returnyoutubedislike.shorts.ReturnYouT
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getTargetIndexOrThrow
|
||||
import app.revanced.util.getTargetIndexWithFieldReferenceType
|
||||
import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
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
|
||||
|
||||
@Suppress("unused")
|
||||
object ReturnYouTubeDislikePatch : BaseBytecodePatch(
|
||||
@ -75,15 +83,36 @@ object ReturnYouTubeDislikePatch : BaseBytecodePatch(
|
||||
val conversionContextFieldReference =
|
||||
getInstruction<ReferenceInstruction>(conversionContextFieldIndex).reference
|
||||
|
||||
val charSequenceIndex =
|
||||
getTargetIndexWithFieldReferenceTypeOrThrow("Ljava/util/BitSet;") - 1
|
||||
val charSequenceRegister =
|
||||
getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerA
|
||||
val freeRegister =
|
||||
getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerB
|
||||
val charSequenceIndex1932 =
|
||||
getTargetIndexWithFieldReferenceType("Ljava/util/BitSet;") - 1
|
||||
val charSequenceIndex1933 = indexOfFirstInstruction {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
reference?.returnType == "V" &&
|
||||
reference.parameterTypes.firstOrNull() == "Ljava/lang/CharSequence;"
|
||||
}
|
||||
|
||||
val insertIndex: Int
|
||||
val charSequenceRegister: Int
|
||||
|
||||
if (charSequenceIndex1932 > -2) {
|
||||
charSequenceRegister =
|
||||
getInstruction<TwoRegisterInstruction>(charSequenceIndex1932).registerA
|
||||
insertIndex = charSequenceIndex1932 - 1
|
||||
} else if (charSequenceIndex1933 > -1) {
|
||||
charSequenceRegister =
|
||||
getInstruction<FiveRegisterInstruction>(charSequenceIndex1933).registerD
|
||||
insertIndex = charSequenceIndex1933
|
||||
} else {
|
||||
throw PatchException("Could not find insert index")
|
||||
}
|
||||
|
||||
val freeRegister = getInstruction<TwoRegisterInstruction>(
|
||||
getTargetIndexOrThrow(insertIndex, Opcode.IGET_OBJECT)
|
||||
).registerA
|
||||
|
||||
addInstructions(
|
||||
charSequenceIndex - 1, """
|
||||
insertIndex, """
|
||||
move-object/from16 v$freeRegister, p0
|
||||
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
|
||||
invoke-static {v$freeRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||
|
@ -15,6 +15,8 @@ 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.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.indexOfPlayerResponseModelInstruction
|
||||
import app.revanced.patches.youtube.utils.fingerprints.VideoEndFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.SHARED_PATH
|
||||
import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
|
||||
@ -88,9 +90,6 @@ object VideoInformationPatch : BytecodePatch(
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"$SHARED_PATH/VideoInformation;"
|
||||
|
||||
private const val PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR =
|
||||
"Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
||||
|
||||
private const val REGISTER_PLAYER_RESPONSE_MODEL = 8
|
||||
|
||||
private const val REGISTER_CHANNEL_ID = 0
|
||||
@ -275,19 +274,17 @@ object VideoInformationPatch : BytecodePatch(
|
||||
/**
|
||||
* Set current video information
|
||||
*/
|
||||
channelIdMethodCall = ChannelIdFingerprint.getMethodName("Ljava/lang/String;")
|
||||
channelNameMethodCall = ChannelNameFingerprint.getMethodName("Ljava/lang/String;")
|
||||
videoIdMethodCall = VideoIdFingerprint.getMethodName("Ljava/lang/String;")
|
||||
videoTitleMethodCall = VideoTitleFingerprint.getMethodName("Ljava/lang/String;")
|
||||
videoLengthMethodCall = VideoLengthFingerprint.getMethodName("J")
|
||||
videoIsLiveMethodCall = ChannelIdFingerprint.getMethodName("Z")
|
||||
channelIdMethodCall = ChannelIdFingerprint.getPlayerResponseInstruction("Ljava/lang/String;")
|
||||
channelNameMethodCall = ChannelNameFingerprint.getPlayerResponseInstruction("Ljava/lang/String;")
|
||||
videoIdMethodCall = VideoIdFingerprint.getPlayerResponseInstruction("Ljava/lang/String;")
|
||||
videoTitleMethodCall = VideoTitleFingerprint.getPlayerResponseInstruction("Ljava/lang/String;")
|
||||
videoLengthMethodCall = VideoLengthFingerprint.getPlayerResponseInstruction("J")
|
||||
videoIsLiveMethodCall = ChannelIdFingerprint.getPlayerResponseInstruction("Z")
|
||||
|
||||
PlaybackInitializationFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_DIRECT
|
||||
&& getReference<MethodReference>()?.returnType == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
} + 1
|
||||
val targetIndex =
|
||||
PlaybackInitializationFingerprint.indexOfPlayerResponseModelInstruction(this) + 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
@ -304,10 +301,7 @@ object VideoInformationPatch : BytecodePatch(
|
||||
|
||||
VideoIdFingerprintBackgroundPlay.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_INTERFACE
|
||||
&& getReference<MethodReference>()?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
}
|
||||
val targetIndex = indexOfPlayerResponseModelInstruction(this)
|
||||
val targetRegister = getInstruction<FiveRegisterInstruction>(targetIndex).registerC
|
||||
|
||||
addInstruction(
|
||||
@ -322,10 +316,7 @@ object VideoInformationPatch : BytecodePatch(
|
||||
|
||||
VideoIdFingerprintShorts.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_INTERFACE
|
||||
&& getReference<MethodReference>()?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
}
|
||||
val targetIndex = indexOfPlayerResponseModelInstruction(this)
|
||||
val targetRegister = getInstruction<FiveRegisterInstruction>(targetIndex).registerC
|
||||
|
||||
addInstruction(
|
||||
@ -557,14 +548,16 @@ object VideoInformationPatch : BytecodePatch(
|
||||
"invoke-static { p1, p2 }, $targetMethodClass->$targetMethodName(J)V"
|
||||
)
|
||||
|
||||
private fun MethodFingerprint.getMethodName(returnType: String): String {
|
||||
private fun MethodFingerprint.getPlayerResponseInstruction(returnType: String): String {
|
||||
resultOrThrow().mutableMethod.apply {
|
||||
val targetIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_INTERFACE
|
||||
&& getReference<MethodReference>()?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
&& getReference<MethodReference>()?.returnType == returnType
|
||||
}
|
||||
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference
|
||||
val targetReference = getInstruction<ReferenceInstruction>(
|
||||
indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_INTERFACE &&
|
||||
reference?.definingClass == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR &&
|
||||
reference.returnType == returnType
|
||||
}
|
||||
).reference
|
||||
|
||||
return "invoke-interface {v${REGISTER_PLAYER_RESPONSE_MODEL}}, $targetReference"
|
||||
}
|
||||
|
@ -2,7 +2,9 @@ package app.revanced.patches.youtube.video.information.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
@ -12,9 +14,10 @@ internal object OnPlaybackSpeedItemClickFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
parameters = listOf("Landroid/widget/AdapterView;", "Landroid/view/View;", "I", "J"),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.name == "onItemClick" && methodDef.implementation?.instructions?.find {
|
||||
it.opcode == Opcode.IGET_OBJECT &&
|
||||
it.getReference<FieldReference>()!!.type == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
||||
} != null
|
||||
methodDef.name == "onItemClick" &&
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.IGET_OBJECT &&
|
||||
getReference<FieldReference>()?.type == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
} >= 0
|
||||
}
|
||||
)
|
@ -2,11 +2,26 @@ package app.revanced.patches.youtube.video.information.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.video.information.fingerprints.PlaybackInitializationFingerprint.indexOfPlayerResponseModelInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object PlaybackInitializationFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = emptyList(),
|
||||
strings = listOf("play() called when the player wasn\'t loaded.")
|
||||
)
|
||||
strings = listOf("play() called when the player wasn\'t loaded."),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
indexOfPlayerResponseModelInstruction(methodDef) >= 0
|
||||
}
|
||||
) {
|
||||
fun indexOfPlayerResponseModelInstruction(methodDef: Method) = methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_DIRECT &&
|
||||
getReference<MethodReference>()?.returnType == PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
package app.revanced.patches.youtube.video.information.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.indexOfPlayerResponseModelInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
@ -10,7 +9,6 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
*/
|
||||
internal object VideoIdFingerprintBackgroundPlay : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.DECLARED_SYNCHRONIZED,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IF_EQZ,
|
||||
@ -23,6 +21,8 @@ internal object VideoIdFingerprintBackgroundPlay : MethodFingerprint(
|
||||
Opcode.RETURN_VOID
|
||||
),
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
methodDef.name == "l" && classDef.methods.count() == 17
|
||||
methodDef.name == "l" &&
|
||||
classDef.methods.count() == 17 &&
|
||||
indexOfPlayerResponseModelInstruction(methodDef) >= 0
|
||||
}
|
||||
)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.youtube.video.information.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR
|
||||
import app.revanced.util.containsWideLiteralInstructionIndex
|
||||
import app.revanced.util.getTargetIndexWithFieldReferenceName
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@ -12,7 +13,7 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
*/
|
||||
internal object VideoIdFingerprintShorts : MethodFingerprint(
|
||||
returnType = "V",
|
||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
||||
parameters = listOf(PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
|
@ -292,7 +292,7 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
||||
|
||||
addInstructions(
|
||||
insertIndex + 1, """
|
||||
invoke-static {v$insertRegister}, $INTEGRATIONS_AV1_CODEC_CLASS_DESCRIPTOR->replaceCodec(Ljava/lang/String;)Ljava/lang/String;
|
||||
invoke-static/range {v$insertRegister .. v$insertRegister}, $INTEGRATIONS_AV1_CODEC_CLASS_DESCRIPTOR->replaceCodec(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$insertRegister
|
||||
"""
|
||||
)
|
||||
|
@ -227,7 +227,11 @@ fun Method.indexOfWideLiteralInstructionOrThrow(literal: Long): Int {
|
||||
* @see indexOfFirstInstructionOrThrow
|
||||
*/
|
||||
fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.() -> Boolean): Int {
|
||||
val index = this.implementation!!.instructions.drop(startIndex).indexOfFirst(predicate)
|
||||
var instructions = this.implementation!!.instructions
|
||||
if (startIndex != 0) {
|
||||
instructions = instructions.drop(startIndex)
|
||||
}
|
||||
val index = instructions.indexOfFirst(predicate)
|
||||
|
||||
return if (index >= 0) {
|
||||
startIndex + index
|
||||
@ -236,6 +240,18 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
|
||||
*
|
||||
* @return the index of the instruction
|
||||
* @throws PatchException
|
||||
* @see indexOfFirstInstruction
|
||||
*/
|
||||
fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int =
|
||||
indexOfFirstInstructionOrThrow(startIndex) {
|
||||
opcode == targetOpcode
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
|
||||
*
|
||||
@ -254,17 +270,84 @@ fun Method.indexOfFirstInstructionOrThrow(
|
||||
return index
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of matching instruction,
|
||||
* starting from and [startIndex] and searching down.
|
||||
*
|
||||
* @param startIndex Optional starting index to search down from. Searching includes the start index.
|
||||
* @return -1 if the instruction is not found.
|
||||
* @see indexOfFirstInstructionReversedOrThrow
|
||||
*/
|
||||
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int =
|
||||
indexOfFirstInstructionReversed(startIndex) {
|
||||
opcode == targetOpcode
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of matching instruction,
|
||||
* starting from and [startIndex] and searching down.
|
||||
*
|
||||
* @param startIndex Optional starting index to search down from. Searching includes the start index.
|
||||
* @return -1 if the instruction is not found.
|
||||
* @see indexOfFirstInstructionReversedOrThrow
|
||||
*/
|
||||
fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, predicate: Instruction.() -> Boolean): Int {
|
||||
var instructions = this.implementation!!.instructions
|
||||
if (startIndex != null) {
|
||||
instructions = instructions.take(startIndex + 1)
|
||||
}
|
||||
|
||||
return instructions.indexOfLast(predicate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of matching instruction,
|
||||
* starting from and [startIndex] and searching down.
|
||||
*
|
||||
* @param startIndex Optional starting index to search down from. Searching includes the start index.
|
||||
* @return -1 if the instruction is not found.
|
||||
* @see indexOfFirstInstructionReversed
|
||||
*/
|
||||
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, targetOpcode: Opcode): Int =
|
||||
indexOfFirstInstructionReversedOrThrow(startIndex) {
|
||||
opcode == targetOpcode
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of matching instruction,
|
||||
* starting from and [startIndex] and searching down.
|
||||
*
|
||||
* @param startIndex Optional starting index to search down from. Searching includes the start index.
|
||||
* @return -1 if the instruction is not found.
|
||||
* @see indexOfFirstInstructionReversed
|
||||
*/
|
||||
fun Method.indexOfFirstInstructionReversedOrThrow(startIndex: Int? = null, predicate: Instruction.() -> Boolean): Int {
|
||||
val index = indexOfFirstInstructionReversed(startIndex, predicate)
|
||||
|
||||
if (index < 0) {
|
||||
throw PatchException("Could not find instruction index")
|
||||
}
|
||||
|
||||
return index
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The list of indices of the opcode in reverse order.
|
||||
*/
|
||||
fun Method.findOpcodeIndicesReversed(opcode: Opcode): List<Int> {
|
||||
fun Method.findOpcodeIndicesReversed(opcode: Opcode): List<Int> =
|
||||
findOpcodeIndicesReversed { this.opcode == opcode }
|
||||
|
||||
/**
|
||||
* @return The list of indices of the opcode in reverse order.
|
||||
*/
|
||||
fun Method.findOpcodeIndicesReversed(filter: Instruction.() -> Boolean): List<Int> {
|
||||
val indexes = implementation!!.instructions
|
||||
.withIndex()
|
||||
.filter { (_, instruction) -> instruction.opcode == opcode }
|
||||
.filter { (_, instruction) -> filter.invoke(instruction) }
|
||||
.map { (index, _) -> index }
|
||||
.reversed()
|
||||
|
||||
if (indexes.isEmpty()) throw PatchException("No ${opcode.name} instructions found in: $this")
|
||||
if (indexes.isEmpty()) throw PatchException("No matching instructions found in: $this")
|
||||
|
||||
return indexes
|
||||
}
|
||||
@ -341,8 +424,19 @@ inline fun <reified T : Reference> Instruction.getReference() =
|
||||
* @param predicate The predicate to match.
|
||||
* @return The index of the first [Instruction] that matches the predicate.
|
||||
*/
|
||||
fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) =
|
||||
this.implementation!!.instructions.indexOfFirst(predicate)
|
||||
fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) = indexOfFirstInstruction(0, predicate)
|
||||
|
||||
/**
|
||||
* Get the index of the first [Instruction] that matches the predicate, starting from [startIndex].
|
||||
*
|
||||
* @param startIndex Optional starting index to start searching from.
|
||||
* @return -1 if the instruction is not found.
|
||||
* @see indexOfFirstInstructionOrThrow
|
||||
*/
|
||||
fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int =
|
||||
indexOfFirstInstruction(startIndex) {
|
||||
opcode == targetOpcode
|
||||
}
|
||||
|
||||
fun MutableMethod.getTargetIndexOrThrow(opcode: Opcode) =
|
||||
getTargetIndexOrThrow(0, opcode)
|
||||
|
Loading…
x
Reference in New Issue
Block a user