mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-02 23:54:33 +02:00
chore: lint code
This commit is contained in:
parent
e374fa306b
commit
ecd6fbdf5b
@ -8,5 +8,8 @@ internal fun main() = PatchBundleLoader.Jar(
|
||||
).also { loader ->
|
||||
if (loader.isEmpty()) throw IllegalStateException("No patches found")
|
||||
}.let { bundle ->
|
||||
arrayOf(JsonPatchesFileGenerator(), ReadMeFileGenerator()).forEach { generator -> generator.generate(bundle) }
|
||||
arrayOf(
|
||||
JsonPatchesFileGenerator(),
|
||||
ReadMeFileGenerator()
|
||||
).forEach { generator -> generator.generate(bundle) }
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ internal class ReadMeFileGenerator : PatchesFileGenerator {
|
||||
val output = StringBuilder()
|
||||
|
||||
// create a temp file
|
||||
val readMeTemplateTempFile = File.createTempFile("README", ".md", File(Paths.get("").toAbsolutePath().toString()))
|
||||
val readMeTemplateTempFile =
|
||||
File.createTempFile("README", ".md", File(Paths.get("").toAbsolutePath().toString()))
|
||||
|
||||
// copy the contents of 'README-template.md' to the temp file
|
||||
StringBuilder(readMeTemplateFile.readText())
|
||||
@ -37,19 +38,24 @@ internal class ReadMeFileGenerator : PatchesFileGenerator {
|
||||
app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE to "\"COMPATIBLE_PACKAGE_REDDIT\"",
|
||||
app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE to "\"COMPATIBLE_PACKAGE_YOUTUBE\""
|
||||
).forEach { (compatiblePackage, replaceString) ->
|
||||
compatiblePackage.map { CompatiblePackage(it.name, it.versions?.toSet()?.ifEmpty { null }) }
|
||||
compatiblePackage.map {
|
||||
CompatiblePackage(
|
||||
it.name,
|
||||
it.versions?.toSet()?.ifEmpty { null })
|
||||
}
|
||||
.forEach { compatiblePackages ->
|
||||
val pkgName = compatiblePackages.name
|
||||
val supportedVersion = if (compatiblePackages.versions == null && exception.containsKey(pkgName)) {
|
||||
exception[pkgName] + "+"
|
||||
} else {
|
||||
compatiblePackages.versions
|
||||
?.toString()
|
||||
?.replace("[", "[\n \"")
|
||||
?.replace("]", "\"\n ]")
|
||||
?.replace(", ", "\",\n \"")
|
||||
?: "\"ALL\""
|
||||
}
|
||||
val supportedVersion =
|
||||
if (compatiblePackages.versions == null && exception.containsKey(pkgName)) {
|
||||
exception[pkgName] + "+"
|
||||
} else {
|
||||
compatiblePackages.versions
|
||||
?.toString()
|
||||
?.replace("[", "[\n \"")
|
||||
?.replace("]", "\"\n ]")
|
||||
?.replace(", ", "\",\n \"")
|
||||
?: "\"ALL\""
|
||||
}
|
||||
|
||||
StringBuilder(readMeTemplateTempFile.readText())
|
||||
.replace(Regex(replaceString), supportedVersion)
|
||||
|
@ -65,8 +65,10 @@ object AccountComponentsPatch : BaseBytecodePatch(
|
||||
result.mutableMethod.apply {
|
||||
|
||||
val textColorIndex = getTargetIndexWithMethodReferenceName("setTextColor")
|
||||
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(textColorIndex, "setVisibility")
|
||||
val textViewInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
|
||||
val setVisibilityIndex =
|
||||
getTargetIndexWithMethodReferenceName(textColorIndex, "setVisibility")
|
||||
val textViewInstruction =
|
||||
getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
|
||||
|
||||
replaceInstruction(
|
||||
setVisibilityIndex,
|
||||
@ -96,7 +98,8 @@ object AccountComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
TermsOfServiceFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = getTargetIndexWithReference("/PrivacyTosFooter;->setVisibility(I)V")
|
||||
val insertIndex =
|
||||
getTargetIndexWithReference("/PrivacyTosFooter;->setVisibility(I)V")
|
||||
val visibilityRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
|
||||
|
@ -49,7 +49,8 @@ object ActionBarComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
// hook download button
|
||||
val addViewIndex = getTargetIndexWithMethodReferenceName("addView")
|
||||
val addViewRegister = getInstruction<FiveRegisterInstruction>(addViewIndex).registerD
|
||||
val addViewRegister =
|
||||
getInstruction<FiveRegisterInstruction>(addViewIndex).registerD
|
||||
|
||||
addInstruction(
|
||||
addViewIndex + 1,
|
||||
@ -86,7 +87,8 @@ object ActionBarComponentsPatch : BaseBytecodePatch(
|
||||
val freeRegister = min(implementation!!.registerCount - parameters.size - 2, 15)
|
||||
|
||||
val spannedIndex = getTargetIndexWithReference(")Landroid/text/Spanned;")
|
||||
val spannedRegister = getInstruction<FiveRegisterInstruction>(spannedIndex).registerC
|
||||
val spannedRegister =
|
||||
getInstruction<FiveRegisterInstruction>(spannedIndex).registerC
|
||||
val spannedReference = getInstruction<ReferenceInstruction>(spannedIndex).reference
|
||||
|
||||
addInstructionsWithLabels(
|
||||
@ -101,10 +103,12 @@ object ActionBarComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
// set action button identifier
|
||||
val buttonTypeDownloadIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||
val buttonTypeDownloadRegister = getInstruction<OneRegisterInstruction>(buttonTypeDownloadIndex).registerA
|
||||
val buttonTypeDownloadRegister =
|
||||
getInstruction<OneRegisterInstruction>(buttonTypeDownloadIndex).registerA
|
||||
|
||||
val buttonTypeIndex = it.scanResult.patternScanResult!!.endIndex - 1
|
||||
val buttonTypeRegister = getInstruction<OneRegisterInstruction>(buttonTypeIndex).registerA
|
||||
val buttonTypeRegister =
|
||||
getInstruction<OneRegisterInstruction>(buttonTypeIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
buttonTypeIndex + 2,
|
||||
|
@ -191,16 +191,19 @@ object AdsPatch : BaseBytecodePatch(
|
||||
// get premium button at the bottom of the account switching menu
|
||||
AccountMenuFooterFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.PrivacyTosFooter)
|
||||
val constIndex =
|
||||
getWideLiteralInstructionIndex(SharedResourceIdPatch.PrivacyTosFooter)
|
||||
val walkerIndex = getTargetIndex(constIndex + 2, Opcode.INVOKE_VIRTUAL)
|
||||
val viewIndex = getTargetIndex(constIndex, Opcode.IGET_OBJECT)
|
||||
val viewReference = getInstruction<ReferenceInstruction>(viewIndex).reference.toString()
|
||||
val viewReference =
|
||||
getInstruction<ReferenceInstruction>(viewIndex).reference.toString()
|
||||
|
||||
val walkerMethod = getWalkerMethod(context, walkerIndex)
|
||||
walkerMethod.apply {
|
||||
val insertIndex = getTargetIndexWithReference(viewReference)
|
||||
val nullCheckIndex = getTargetIndex(insertIndex - 1, Opcode.IF_NEZ)
|
||||
val nullCheckRegister = getInstruction<OneRegisterInstruction>(nullCheckIndex).registerA
|
||||
val nullCheckRegister =
|
||||
getInstruction<OneRegisterInstruction>(nullCheckIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
nullCheckIndex,
|
||||
|
@ -5,6 +5,6 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
|
||||
internal object InterstitialsContainerFingerprint : LiteralValueFingerprint(
|
||||
returnType = "V",
|
||||
strings= listOf("overlay_controller_param"),
|
||||
strings = listOf("overlay_controller_param"),
|
||||
literalSupplier = { InterstitialsContainer }
|
||||
)
|
@ -73,7 +73,8 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
|
||||
// region patch for enable compact dialog
|
||||
|
||||
DialogSolidFingerprint.resultOrThrow().let {
|
||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
val walkerMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
walkerMethod.addInstructions(
|
||||
2, """
|
||||
invoke-static {p0}, $FLYOUT_CLASS_DESCRIPTOR->enableCompactDialog(I)I
|
||||
@ -94,17 +95,22 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
TrimSilenceSwitchFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.TrimSilenceSwitch)
|
||||
val onCheckedChangedListenerIndex = getTargetIndex(constIndex, Opcode.INVOKE_DIRECT)
|
||||
val onCheckedChangedListenerReference = getInstruction<ReferenceInstruction>(onCheckedChangedListenerIndex).reference
|
||||
val onCheckedChangedListenerDefiningClass = (onCheckedChangedListenerReference as MethodReference).definingClass
|
||||
val constIndex =
|
||||
getWideLiteralInstructionIndex(SharedResourceIdPatch.TrimSilenceSwitch)
|
||||
val onCheckedChangedListenerIndex =
|
||||
getTargetIndex(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 = indexOfFirstInstruction {
|
||||
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
val reference =
|
||||
((this as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
|
||||
opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& reference?.returnType == "V"
|
||||
@ -113,7 +119,8 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
|
||||
}
|
||||
getWalkerMethod(context, walkerIndex).apply {
|
||||
val insertIndex = getTargetIndex(Opcode.MOVE_RESULT)
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
val insertRegister =
|
||||
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex + 1, """
|
||||
@ -148,25 +155,30 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
val enumIndex = indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_STATIC
|
||||
&& (this as? ReferenceInstruction)?.reference.toString().contains("(I)L")
|
||||
&& (this as? ReferenceInstruction)?.reference.toString()
|
||||
.contains("(I)L")
|
||||
} + 1
|
||||
val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA
|
||||
|
||||
addInstructionsWithLabels(
|
||||
enumIndex + 1, """
|
||||
enumIndex + 1,
|
||||
"""
|
||||
invoke-static {v$enumRegister, v$textViewRegister, v$imageViewRegister}, $FLYOUT_CLASS_DESCRIPTOR->replaceComponents(Ljava/lang/Enum;Landroid/widget/TextView;Landroid/widget/ImageView;)V
|
||||
invoke-static {v$enumRegister}, $FLYOUT_CLASS_DESCRIPTOR->hideComponents(Ljava/lang/Enum;)Z
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :hide
|
||||
""", ExternalLabel("hide", getInstruction(implementation!!.instructions.size - 1))
|
||||
""",
|
||||
ExternalLabel("hide", getInstruction(implementation!!.instructions.size - 1))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TouchOutsideFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName("setOnClickListener")
|
||||
val setOnClickListenerRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
|
||||
val setOnClickListenerIndex =
|
||||
getTargetIndexWithMethodReferenceName("setOnClickListener")
|
||||
val setOnClickListenerRegister =
|
||||
getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
|
||||
|
||||
addInstruction(
|
||||
setOnClickListenerIndex + 1,
|
||||
|
@ -106,7 +106,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
|
||||
// hide floating cast banner
|
||||
PlayerOverlayChipFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.PlayerOverlayChip) + 2
|
||||
val targetIndex =
|
||||
getWideLiteralInstructionIndex(SharedResourceIdPatch.PlayerOverlayChip) + 2
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
@ -164,7 +165,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
|
||||
fingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
val insertRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
@ -232,7 +234,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
|
||||
TasteBuilderSyntheticFingerprint.resolve(context, parentResult.classDef)
|
||||
|
||||
parentResult.mutableMethod.apply {
|
||||
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.MusicTasteBuilderShelf)
|
||||
val constIndex =
|
||||
getWideLiteralInstructionIndex(SharedResourceIdPatch.MusicTasteBuilderShelf)
|
||||
val targetIndex = getTargetIndex(constIndex, Opcode.MOVE_RESULT_OBJECT)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
@ -281,7 +284,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
|
||||
SearchBarFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val setVisibilityIndex = getTargetIndexWithMethodReferenceName("setVisibility")
|
||||
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
|
||||
val setVisibilityInstruction =
|
||||
getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
|
||||
|
||||
replaceInstruction(
|
||||
setVisibilityIndex,
|
||||
|
@ -3,4 +3,5 @@ package app.revanced.patches.music.general.dialog
|
||||
import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.shared.dialog.BaseViewerDiscretionDialogPatch
|
||||
|
||||
object ViewerDiscretionDialogBytecodePatch : BaseViewerDiscretionDialogPatch(GENERAL_CLASS_DESCRIPTOR)
|
||||
object ViewerDiscretionDialogBytecodePatch :
|
||||
BaseViewerDiscretionDialogPatch(GENERAL_CLASS_DESCRIPTOR)
|
||||
|
@ -51,13 +51,15 @@ object DislikeRedirectionPatch : BaseBytecodePatch(
|
||||
|
||||
onClickMethod.apply {
|
||||
val onClickIndex = indexOfFirstInstruction {
|
||||
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
val reference =
|
||||
((this as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
|
||||
opcode == Opcode.INVOKE_INTERFACE
|
||||
&& reference?.returnType == "V"
|
||||
&& reference.parameterTypes.size == 1
|
||||
}
|
||||
onClickReference = getInstruction<ReferenceInstruction>(onClickIndex).reference
|
||||
onClickReference =
|
||||
getInstruction<ReferenceInstruction>(onClickIndex).reference
|
||||
|
||||
injectCall(onClickIndex)
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
AppIcon?.let { appIcon ->
|
||||
val appIconValue = appIcon.lowercase().replace(" ","_")
|
||||
val appIconValue = appIcon.lowercase().replace(" ", "_")
|
||||
if (!availableIcon.containsValue(appIconValue)) {
|
||||
mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
|
@ -136,8 +136,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
val invokeVirtualIndex = getTargetIndex(relativeIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val iGetIndex = getTargetIndex(relativeIndex, Opcode.IGET)
|
||||
|
||||
colorMathPlayerInvokeVirtualReference = getInstruction<ReferenceInstruction>(invokeVirtualIndex).reference
|
||||
colorMathPlayerIGetReference = getInstruction<ReferenceInstruction>(iGetIndex).reference
|
||||
colorMathPlayerInvokeVirtualReference =
|
||||
getInstruction<ReferenceInstruction>(invokeVirtualIndex).reference
|
||||
colorMathPlayerIGetReference =
|
||||
getInstruction<ReferenceInstruction>(iGetIndex).reference
|
||||
|
||||
// black player background
|
||||
val invokeDirectIndex = getTargetIndex(Opcode.INVOKE_DIRECT)
|
||||
@ -161,7 +163,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
val colorGreyIndex = getWideLiteralInstructionIndex(ColorGrey)
|
||||
val iPutIndex = getTargetIndex(colorGreyIndex, Opcode.IPUT)
|
||||
|
||||
colorMathPlayerIPutReference = getInstruction<ReferenceInstruction>(iPutIndex).reference
|
||||
colorMathPlayerIPutReference =
|
||||
getInstruction<ReferenceInstruction>(iPutIndex).reference
|
||||
}
|
||||
|
||||
parentResult.mutableClass.methods.filter { method ->
|
||||
@ -172,8 +175,12 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
mutableMethod.apply {
|
||||
val freeRegister = implementation!!.registerCount - parameters.size - 3
|
||||
|
||||
val invokeDirectIndex = getTargetIndexReversed(implementation!!.instructions.size - 1, Opcode.INVOKE_DIRECT)
|
||||
val invokeDirectReference = getInstruction<ReferenceInstruction>(invokeDirectIndex).reference
|
||||
val invokeDirectIndex = getTargetIndexReversed(
|
||||
implementation!!.instructions.size - 1,
|
||||
Opcode.INVOKE_DIRECT
|
||||
)
|
||||
val invokeDirectReference =
|
||||
getInstruction<ReferenceInstruction>(invokeDirectIndex).reference
|
||||
|
||||
addInstructionsWithLabels(
|
||||
invokeDirectIndex + 1, """
|
||||
@ -275,14 +282,30 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
miniPlayerConstructorMutableMethod.setInstanceFieldValue(NEXT_BUTTON_METHOD_NAME, TopStart)
|
||||
miniPlayerConstructorMutableMethod.setInstanceFieldValue(
|
||||
NEXT_BUTTON_METHOD_NAME,
|
||||
TopStart
|
||||
)
|
||||
mppWatchWhileLayoutMutableMethod.setStaticFieldValue(NEXT_BUTTON_FIELD_NAME, TopStart)
|
||||
pendingIntentReceiverMutableMethod.setOnClickListener(context, NEXT_BUTTON_INTENT_STRING, NEXT_BUTTON_ONCLICK_METHOD_NAME, NEXT_BUTTON_CLASS_FIELD_NAME)
|
||||
pendingIntentReceiverMutableMethod.setOnClickListener(
|
||||
context,
|
||||
NEXT_BUTTON_INTENT_STRING,
|
||||
NEXT_BUTTON_ONCLICK_METHOD_NAME,
|
||||
NEXT_BUTTON_CLASS_FIELD_NAME
|
||||
)
|
||||
}
|
||||
|
||||
miniPlayerConstructorMutableMethod.setInstanceFieldValue(PREVIOUS_BUTTON_METHOD_NAME, TopEnd)
|
||||
miniPlayerConstructorMutableMethod.setInstanceFieldValue(
|
||||
PREVIOUS_BUTTON_METHOD_NAME,
|
||||
TopEnd
|
||||
)
|
||||
mppWatchWhileLayoutMutableMethod.setStaticFieldValue(PREVIOUS_BUTTON_FIELD_NAME, TopEnd)
|
||||
pendingIntentReceiverMutableMethod.setOnClickListener(context, PREVIOUS_BUTTON_INTENT_STRING, PREVIOUS_BUTTON_ONCLICK_METHOD_NAME, PREVIOUS_BUTTON_CLASS_FIELD_NAME)
|
||||
pendingIntentReceiverMutableMethod.setOnClickListener(
|
||||
context,
|
||||
PREVIOUS_BUTTON_INTENT_STRING,
|
||||
PREVIOUS_BUTTON_ONCLICK_METHOD_NAME,
|
||||
PREVIOUS_BUTTON_CLASS_FIELD_NAME
|
||||
)
|
||||
|
||||
mppWatchWhileLayoutMutableMethod.setViewArray()
|
||||
|
||||
@ -327,7 +350,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
SwipeToCloseFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = implementation!!.instructions.size - 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
@ -343,10 +367,12 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
InteractionLoggingEnumFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val stringIndex = getStringInstructionIndex("INTERACTION_LOGGING_GESTURE_TYPE_SWIPE")
|
||||
val stringIndex =
|
||||
getStringInstructionIndex("INTERACTION_LOGGING_GESTURE_TYPE_SWIPE")
|
||||
val sPutObjectIndex = getTargetIndex(stringIndex, Opcode.SPUT_OBJECT)
|
||||
|
||||
swipeToDismissSGetObjectReference = getInstruction<ReferenceInstruction>(sPutObjectIndex).reference
|
||||
swipeToDismissSGetObjectReference =
|
||||
getInstruction<ReferenceInstruction>(sPutObjectIndex).reference
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,13 +380,20 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
it.mutableMethod.apply {
|
||||
swipeToDismissWidgetIndex = getWideLiteralInstructionIndex(79500)
|
||||
|
||||
swipeToDismissIGetObjectReference = getSwipeToDismissReference(Opcode.IGET_OBJECT, true)
|
||||
swipeToDismissInvokeInterfacePrimaryReference = getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, true)
|
||||
swipeToDismissCheckCastReference = getSwipeToDismissReference(Opcode.CHECK_CAST, true)
|
||||
swipeToDismissNewInstanceReference = getSwipeToDismissReference(Opcode.NEW_INSTANCE, true)
|
||||
swipeToDismissInvokeStaticReference = getSwipeToDismissReference(Opcode.INVOKE_STATIC, false)
|
||||
swipeToDismissInvokeDirectReference = getSwipeToDismissReference(Opcode.INVOKE_DIRECT, false)
|
||||
swipeToDismissInvokeInterfaceSecondaryReference = getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, false)
|
||||
swipeToDismissIGetObjectReference =
|
||||
getSwipeToDismissReference(Opcode.IGET_OBJECT, true)
|
||||
swipeToDismissInvokeInterfacePrimaryReference =
|
||||
getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, true)
|
||||
swipeToDismissCheckCastReference =
|
||||
getSwipeToDismissReference(Opcode.CHECK_CAST, true)
|
||||
swipeToDismissNewInstanceReference =
|
||||
getSwipeToDismissReference(Opcode.NEW_INSTANCE, true)
|
||||
swipeToDismissInvokeStaticReference =
|
||||
getSwipeToDismissReference(Opcode.INVOKE_STATIC, false)
|
||||
swipeToDismissInvokeDirectReference =
|
||||
getSwipeToDismissReference(Opcode.INVOKE_DIRECT, false)
|
||||
swipeToDismissInvokeInterfaceSecondaryReference =
|
||||
getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,11 +402,14 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
HandleSignInEventFingerprint.resolve(context, parentResult.classDef)
|
||||
|
||||
HandleSignInEventFingerprint.resultOrThrow().let {
|
||||
val dismissBehaviorMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
||||
val dismissBehaviorMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
||||
|
||||
dismissBehaviorMethod.apply {
|
||||
val insertIndex = getTargetIndexWithFieldReferenceType("Ljava/util/concurrent/atomic/AtomicBoolean;")
|
||||
val primaryRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerB
|
||||
val insertIndex =
|
||||
getTargetIndexWithFieldReferenceType("Ljava/util/concurrent/atomic/AtomicBoolean;")
|
||||
val primaryRegister =
|
||||
getInstruction<TwoRegisterInstruction>(insertIndex).registerB
|
||||
val secondaryRegister = primaryRegister + 1
|
||||
val tertiaryRegister = secondaryRegister + 1
|
||||
|
||||
@ -410,7 +446,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
MiniPlayerDefaultTextFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerB
|
||||
val insertRegister =
|
||||
getInstruction<TwoRegisterInstruction>(insertIndex).registerB
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
@ -429,22 +466,26 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
it.mutableClass.methods.find { method ->
|
||||
method.parameters == listOf("Landroid/view/View;", "I")
|
||||
}?.apply {
|
||||
val bottomSheetBehaviorIndex = implementation!!.instructions.indexOfFirst { instruction ->
|
||||
instruction.opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& instruction.getReference<MethodReference>()?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;"
|
||||
&& instruction.getReference<MethodReference>()?.parameterTypes?.first() == "Z"
|
||||
}
|
||||
val bottomSheetBehaviorIndex =
|
||||
implementation!!.instructions.indexOfFirst { instruction ->
|
||||
instruction.opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& instruction.getReference<MethodReference>()?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;"
|
||||
&& instruction.getReference<MethodReference>()?.parameterTypes?.first() == "Z"
|
||||
}
|
||||
if (bottomSheetBehaviorIndex < 0)
|
||||
throw PatchException("Could not find bottomSheetBehaviorIndex")
|
||||
|
||||
val freeRegister = getInstruction<FiveRegisterInstruction>(bottomSheetBehaviorIndex).registerD
|
||||
val freeRegister =
|
||||
getInstruction<FiveRegisterInstruction>(bottomSheetBehaviorIndex).registerD
|
||||
|
||||
addInstructionsWithLabels(
|
||||
bottomSheetBehaviorIndex - 2, """
|
||||
bottomSheetBehaviorIndex - 2,
|
||||
"""
|
||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSwipeToDismissMiniPlayer()Z
|
||||
move-result v$freeRegister
|
||||
if-nez v$freeRegister, :dismiss
|
||||
""", ExternalLabel("dismiss", getInstruction(bottomSheetBehaviorIndex + 1))
|
||||
""",
|
||||
ExternalLabel("dismiss", getInstruction(bottomSheetBehaviorIndex + 1))
|
||||
)
|
||||
} ?: throw PatchException("Could not find targetMethod")
|
||||
|
||||
@ -473,7 +514,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
ZenModeFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(startIndex).registerA
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(startIndex).registerA
|
||||
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex + 1
|
||||
|
||||
@ -616,13 +658,16 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val imageViewIndex = getTargetIndexWithFieldReferenceType("Landroid/widget/ImageView;")
|
||||
val imageViewIndex =
|
||||
getTargetIndexWithFieldReferenceType("Landroid/widget/ImageView;")
|
||||
|
||||
val shuffleReference1 = getInstruction<ReferenceInstruction>(startIndex).reference
|
||||
val shuffleReference2 = getInstruction<ReferenceInstruction>(startIndex + 1).reference
|
||||
val shuffleReference2 =
|
||||
getInstruction<ReferenceInstruction>(startIndex + 1).reference
|
||||
val shuffleReference3 = getInstruction<ReferenceInstruction>(endIndex).reference
|
||||
val shuffleFieldReference = shuffleReference3 as FieldReference
|
||||
rememberShuffleStateImageViewReference = getInstruction<ReferenceInstruction>(imageViewIndex).reference
|
||||
rememberShuffleStateImageViewReference =
|
||||
getInstruction<ReferenceInstruction>(imageViewIndex).reference
|
||||
|
||||
rememberShuffleStateShuffleStateLabel = """
|
||||
iget-object v1, v0, $shuffleReference1
|
||||
@ -783,10 +828,14 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
methodName: String,
|
||||
viewId: Long
|
||||
) {
|
||||
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
|
||||
val miniPlayerPlayPauseReplayButtonRegister = getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA
|
||||
val findViewByIdIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val parentViewRegister = getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC
|
||||
val miniPlayerPlayPauseReplayButtonIndex =
|
||||
getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
|
||||
val miniPlayerPlayPauseReplayButtonRegister =
|
||||
getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA
|
||||
val findViewByIdIndex =
|
||||
getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val parentViewRegister =
|
||||
getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
miniPlayerPlayPauseReplayButtonIndex, """
|
||||
@ -802,10 +851,14 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
fieldName: String,
|
||||
viewId: Long
|
||||
) {
|
||||
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
|
||||
val constRegister = getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA
|
||||
val findViewByIdIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val findViewByIdRegister = getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC
|
||||
val miniPlayerPlayPauseReplayButtonIndex =
|
||||
getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
|
||||
val constRegister =
|
||||
getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA
|
||||
val findViewByIdIndex =
|
||||
getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val findViewByIdRegister =
|
||||
getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
miniPlayerPlayPauseReplayButtonIndex, """
|
||||
@ -818,8 +871,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
}
|
||||
|
||||
private fun MutableMethod.setViewArray() {
|
||||
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
|
||||
val invokeStaticIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_STATIC)
|
||||
val miniPlayerPlayPauseReplayButtonIndex =
|
||||
getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
|
||||
val invokeStaticIndex =
|
||||
getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_STATIC)
|
||||
val viewArrayRegister = getInstruction<FiveRegisterInstruction>(invokeStaticIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
|
@ -22,17 +22,20 @@ object AccessibilityNodeInfoPatch : BytecodePatch(
|
||||
it.mutableMethod.apply {
|
||||
// Target instruction is invoke-static, but can also be invoke-virtual.
|
||||
// Therefore, the opcode is not checked.
|
||||
val touchExplorationHoverEventMethodIndex = implementation!!.instructions.indexOfFirst { instruction ->
|
||||
val reference = ((instruction as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
((instruction as? ReferenceInstruction)?.reference as? MethodReference)?.definingClass == definingClass
|
||||
&& reference?.returnType == "Z"
|
||||
}
|
||||
val touchExplorationHoverEventMethodIndex =
|
||||
implementation!!.instructions.indexOfFirst { instruction ->
|
||||
val reference =
|
||||
((instruction as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
((instruction as? ReferenceInstruction)?.reference as? MethodReference)?.definingClass == definingClass
|
||||
&& reference?.returnType == "Z"
|
||||
}
|
||||
|
||||
// Doesn't raise an exception, even if the target instruction is not found in this method
|
||||
val touchExplorationHoverEventMethodName = if (touchExplorationHoverEventMethodIndex > -1)
|
||||
(getInstruction<ReferenceInstruction>(touchExplorationHoverEventMethodIndex).reference as MethodReference).name
|
||||
else
|
||||
"UNDEFINED"
|
||||
val touchExplorationHoverEventMethodName =
|
||||
if (touchExplorationHoverEventMethodIndex > -1)
|
||||
(getInstruction<ReferenceInstruction>(touchExplorationHoverEventMethodIndex).reference as MethodReference).name
|
||||
else
|
||||
"UNDEFINED"
|
||||
|
||||
val methods = it.mutableClass.methods
|
||||
|
||||
|
@ -14,7 +14,11 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE,
|
||||
mainActivityOnCreateFingerprint = MainActivityFingerprint,
|
||||
integrationsPatchDependency = IntegrationsPatch::class,
|
||||
dependencies = setOf(SpoofUserAgentPatch::class, PackageNamePatch::class, FileProviderPatch::class),
|
||||
dependencies = setOf(
|
||||
SpoofUserAgentPatch::class,
|
||||
PackageNamePatch::class,
|
||||
FileProviderPatch::class
|
||||
),
|
||||
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
)
|
||||
|
@ -13,6 +13,7 @@ object PlayerTypeHookPatch : BytecodePatch(
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"$UTILS_PATH/PlayerTypeHookPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
PlayerTypeFingerprint.resultOrThrow().let {
|
||||
|
@ -55,9 +55,11 @@ object ReturnYouTubeDislikeBytecodePatch : BytecodePatch(
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_STATIC
|
||||
&& (this as ReferenceInstruction).reference.toString().endsWith("Ljava/lang/CharSequence;")
|
||||
&& (this as ReferenceInstruction).reference.toString()
|
||||
.endsWith("Ljava/lang/CharSequence;")
|
||||
} + 2
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
|
||||
val insertRegister =
|
||||
getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
|
@ -39,7 +39,10 @@ object ResourceUtils {
|
||||
private fun ResourceContext.replacePackageName() {
|
||||
this[SETTINGS_HEADER_PATH].writeText(
|
||||
this[SETTINGS_HEADER_PATH].readText()
|
||||
.replace("\"com.google.android.apps.youtube.music\"", "\"" + musicPackageName + "\"")
|
||||
.replace(
|
||||
"\"com.google.android.apps.youtube.music\"",
|
||||
"\"" + musicPackageName + "\""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -65,7 +68,10 @@ object ResourceUtils {
|
||||
.forEach {
|
||||
if (!isIncludedCategory(category)) {
|
||||
it.adoptChild(PREFERENCE_SCREEN_TAG_NAME) {
|
||||
setAttribute("android:title", "@string/revanced_preference_screen_$category" + "_title")
|
||||
setAttribute(
|
||||
"android:title",
|
||||
"@string/revanced_preference_screen_$category" + "_title"
|
||||
)
|
||||
setAttribute("android:key", "revanced_preference_screen_$category")
|
||||
}
|
||||
setPreferenceCategory(category)
|
||||
@ -117,7 +123,9 @@ object ResourceUtils {
|
||||
this.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
|
||||
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
|
||||
List(tags.length) { tags.item(it) as Element }
|
||||
.filter { it.getAttribute("android:key").contains("revanced_preference_screen_$category") }
|
||||
.filter {
|
||||
it.getAttribute("android:key").contains("revanced_preference_screen_$category")
|
||||
}
|
||||
.forEach {
|
||||
it.adoptChild("Preference") {
|
||||
setAttribute("android:title", "@string/$key" + "_title")
|
||||
@ -145,7 +153,9 @@ object ResourceUtils {
|
||||
this.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
|
||||
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
|
||||
List(tags.length) { tags.item(it) as Element }
|
||||
.filter { it.getAttribute("android:key").contains("revanced_preference_screen_$category") }
|
||||
.filter {
|
||||
it.getAttribute("android:key").contains("revanced_preference_screen_$category")
|
||||
}
|
||||
.forEach {
|
||||
it.adoptChild(SWITCH_PREFERENCE_TAG_NAME) {
|
||||
setAttribute("android:title", "@string/$key" + "_title")
|
||||
@ -170,7 +180,9 @@ object ResourceUtils {
|
||||
this.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
|
||||
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
|
||||
List(tags.length) { tags.item(it) as Element }
|
||||
.filter { it.getAttribute("android:key").contains("revanced_preference_screen_$category") }
|
||||
.filter {
|
||||
it.getAttribute("android:key").contains("revanced_preference_screen_$category")
|
||||
}
|
||||
.forEach {
|
||||
it.adoptChild("Preference") {
|
||||
setAttribute("android:title", "@string/$key" + "_title")
|
||||
|
@ -15,8 +15,8 @@ import app.revanced.patches.music.utils.mainactivity.MainActivityResolvePatch
|
||||
import app.revanced.patches.music.utils.settings.fingerprints.GoogleApiActivityFingerprint
|
||||
import app.revanced.patches.music.utils.settings.fingerprints.PreferenceFingerprint
|
||||
import app.revanced.patches.music.utils.settings.fingerprints.SettingsHeadersFragmentFingerprint
|
||||
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.shared.fingerprints.SharedSettingFingerprint
|
||||
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@ -109,9 +109,18 @@ object SettingsBytecodePatch : BytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR, "setDeviceInformation")
|
||||
MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR, "onCreate")
|
||||
MainActivityResolvePatch.injectConstructorMethodCall(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR, "setActivity")
|
||||
MainActivityResolvePatch.injectOnCreateMethodCall(
|
||||
INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR,
|
||||
"setDeviceInformation"
|
||||
)
|
||||
MainActivityResolvePatch.injectOnCreateMethodCall(
|
||||
INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR,
|
||||
"onCreate"
|
||||
)
|
||||
MainActivityResolvePatch.injectConstructorMethodCall(
|
||||
INTEGRATIONS_UTILS_CLASS_DESCRIPTOR,
|
||||
"setActivity"
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +143,9 @@ object SponsorBlockPatch : BaseResourcePatch(
|
||||
context.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
|
||||
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
|
||||
List(tags.length) { tags.item(it) as Element }
|
||||
.filter { it.getAttribute("android:key").contains("revanced_preference_screen_$category") }
|
||||
.filter {
|
||||
it.getAttribute("android:key").contains("revanced_preference_screen_$category")
|
||||
}
|
||||
.forEach {
|
||||
it.adoptChild(SWITCH_PREFERENCE_TAG_NAME) {
|
||||
setAttribute("android:title", "@string/revanced_$key")
|
||||
@ -166,7 +168,9 @@ object SponsorBlockPatch : BaseResourcePatch(
|
||||
context.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
|
||||
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
|
||||
List(tags.length) { tags.item(it) as Element }
|
||||
.filter { it.getAttribute("android:key").contains("revanced_preference_screen_$category") }
|
||||
.filter {
|
||||
it.getAttribute("android:key").contains("revanced_preference_screen_$category")
|
||||
}
|
||||
.forEach {
|
||||
it.adoptChild("Preference") {
|
||||
setAttribute("android:title", "@string/revanced_$key")
|
||||
|
@ -65,7 +65,8 @@ object VideoInformationPatch : BytecodePatch(
|
||||
internal lateinit var playbackSpeedResult: MethodFingerprintResult
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
val videoInformationMutableClass = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
||||
val videoInformationMutableClass =
|
||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
||||
|
||||
VideoEndFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
@ -119,7 +120,8 @@ object VideoInformationPatch : BytecodePatch(
|
||||
* Set the video time method
|
||||
*/
|
||||
PlayerControllerSetTimeReferenceFingerprint.resultOrThrow().let {
|
||||
videoTimeConstructorMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
||||
videoTimeConstructorMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,8 +139,12 @@ object VideoInformationPatch : BytecodePatch(
|
||||
VideoLengthFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val invalidateIndex = getTargetIndexWithMethodReferenceNameReversed("invalidate")
|
||||
val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(invalidateIndex + 1, "Landroid/graphics/Rect;")
|
||||
rectangleFieldName = (getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name
|
||||
val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(
|
||||
invalidateIndex + 1,
|
||||
"Landroid/graphics/Rect;"
|
||||
)
|
||||
rectangleFieldName =
|
||||
(getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name
|
||||
|
||||
val videoLengthRegisterIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||
val videoLengthRegister =
|
||||
|
@ -22,7 +22,8 @@ object VideoIdPatch : BytecodePatch(
|
||||
it.mutableMethod.apply {
|
||||
videoIdMethod = this
|
||||
videoIdInsertIndex = it.scanResult.patternScanResult!!.startIndex + 2
|
||||
videoIdRegister = getInstruction<OneRegisterInstruction>(videoIdInsertIndex - 1).registerA
|
||||
videoIdRegister =
|
||||
getInstruction<OneRegisterInstruction>(videoIdInsertIndex - 1).registerA
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ abstract class BaseAutoCaptionsPatch(
|
||||
}
|
||||
|
||||
SubtitleTrackFingerprint.resultOrThrow().let {
|
||||
val targetMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
val targetMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
|
||||
targetMethod.apply {
|
||||
val targetIndex = indexOfFirstInstruction {
|
||||
|
@ -52,7 +52,7 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
) : BytecodePatch(
|
||||
name = "GmsCore support",
|
||||
description = "Allows patched Google apps to run without root and under a different package name " +
|
||||
"by using GmsCore instead of Google Play Services.",
|
||||
"by using GmsCore instead of Google Play Services.",
|
||||
dependencies = setOf(
|
||||
PackageNamePatch::class,
|
||||
gmsCoreSupportResourcePatch::class,
|
||||
@ -116,36 +116,43 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"")
|
||||
}
|
||||
|
||||
private fun BytecodeContext.transformStringReferences(transform: (str: String) -> String?) = classes.forEach {
|
||||
val mutableClass by lazy {
|
||||
proxy(it).mutableClass
|
||||
}
|
||||
|
||||
it.methods.forEach classLoop@{ methodDef ->
|
||||
val implementation = methodDef.implementation ?: return@classLoop
|
||||
|
||||
val mutableMethod by lazy {
|
||||
mutableClass.methods.first { method -> MethodUtil.methodSignaturesMatch(method, methodDef) }
|
||||
private fun BytecodeContext.transformStringReferences(transform: (str: String) -> String?) =
|
||||
classes.forEach {
|
||||
val mutableClass by lazy {
|
||||
proxy(it).mutableClass
|
||||
}
|
||||
|
||||
implementation.instructions.forEachIndexed insnLoop@{ index, instruction ->
|
||||
val string = ((instruction as? Instruction21c)?.reference as? StringReference)?.string
|
||||
?: return@insnLoop
|
||||
it.methods.forEach classLoop@{ methodDef ->
|
||||
val implementation = methodDef.implementation ?: return@classLoop
|
||||
|
||||
// Apply transformation.
|
||||
val transformedString = transform(string) ?: return@insnLoop
|
||||
val mutableMethod by lazy {
|
||||
mutableClass.methods.first { method ->
|
||||
MethodUtil.methodSignaturesMatch(
|
||||
method,
|
||||
methodDef
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
mutableMethod.replaceInstruction(
|
||||
index,
|
||||
BuilderInstruction21c(
|
||||
Opcode.CONST_STRING,
|
||||
instruction.registerA,
|
||||
ImmutableStringReference(transformedString),
|
||||
),
|
||||
)
|
||||
implementation.instructions.forEachIndexed insnLoop@{ index, instruction ->
|
||||
val string =
|
||||
((instruction as? Instruction21c)?.reference as? StringReference)?.string
|
||||
?: return@insnLoop
|
||||
|
||||
// Apply transformation.
|
||||
val transformedString = transform(string) ?: return@insnLoop
|
||||
|
||||
mutableMethod.replaceInstruction(
|
||||
index,
|
||||
BuilderInstruction21c(
|
||||
Opcode.CONST_STRING,
|
||||
instruction.registerA,
|
||||
ImmutableStringReference(transformedString),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Collection of transformations that are applied to all strings.
|
||||
|
||||
@ -180,14 +187,20 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
// gms also has a 'subscribedfeeds' authority, check for that one too
|
||||
val subFeedsUriPrefix = "content://subscribedfeeds"
|
||||
if (str.startsWith(subFeedsUriPrefix)) {
|
||||
return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendorGroupId.subscribedfeeds")
|
||||
return str.replace(
|
||||
subFeedsUriPrefix,
|
||||
"content://$gmsCoreVendorGroupId.subscribedfeeds"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? = { string ->
|
||||
private fun packageNameTransform(
|
||||
fromPackageName: String,
|
||||
toPackageName: String
|
||||
): (String) -> String? = { string ->
|
||||
when (string) {
|
||||
"$fromPackageName.SuggestionsProvider",
|
||||
"$fromPackageName.fileprovider",
|
||||
|
@ -53,12 +53,18 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||
|
||||
// Spoof package name and signature.
|
||||
applicationNode.adoptChild("meta-data") {
|
||||
setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_NAME")
|
||||
setAttribute(
|
||||
"android:name",
|
||||
"$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_NAME"
|
||||
)
|
||||
setAttribute("android:value", fromPackageName)
|
||||
}
|
||||
|
||||
applicationNode.adoptChild("meta-data") {
|
||||
setAttribute("android:name", "$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_SIGNATURE")
|
||||
setAttribute(
|
||||
"android:name",
|
||||
"$gmsCoreVendorGroupId.android.gms.SPOOFED_PACKAGE_SIGNATURE"
|
||||
)
|
||||
setAttribute("android:value", spoofedPackageSignature)
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,8 @@ object LithoFilterPatch : BytecodePatch(
|
||||
if ((instruction as? ReferenceInstruction)?.reference.toString() != pathBuilderMethodCall)
|
||||
continue
|
||||
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||
val insertRegister =
|
||||
getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||
val insertIndex = index + 2
|
||||
|
||||
addInstructionsWithLabels(
|
||||
@ -134,13 +135,16 @@ object LithoFilterPatch : BytecodePatch(
|
||||
"""
|
||||
}
|
||||
|
||||
val stringBuilderIndex = getTargetIndexWithFieldReferenceType("Ljava/lang/StringBuilder;")
|
||||
val stringBuilderRegister = getInstruction<TwoRegisterInstruction>(stringBuilderIndex).registerA
|
||||
val stringBuilderIndex =
|
||||
getTargetIndexWithFieldReferenceType("Ljava/lang/StringBuilder;")
|
||||
val stringBuilderRegister =
|
||||
getInstruction<TwoRegisterInstruction>(stringBuilderIndex).registerA
|
||||
|
||||
val emptyStringIndex = getEmptyStringInstructionIndex()
|
||||
|
||||
val identifierIndex = getTargetIndexReversed(emptyStringIndex, Opcode.IPUT_OBJECT)
|
||||
val identifierRegister = getInstruction<TwoRegisterInstruction>(identifierIndex).registerA
|
||||
val identifierRegister =
|
||||
getInstruction<TwoRegisterInstruction>(identifierIndex).registerA
|
||||
|
||||
val objectIndex = getTargetIndex(emptyStringIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val objectRegister = getInstruction<BuilderInstruction35c>(objectIndex).registerC
|
||||
|
@ -14,7 +14,7 @@ import kotlin.properties.Delegates
|
||||
|
||||
abstract class BaseMainActivityResolvePatch(
|
||||
private val mainActivityOnCreateFingerprint: MethodFingerprint
|
||||
): BytecodePatch(
|
||||
) : BytecodePatch(
|
||||
setOf(mainActivityOnCreateFingerprint)
|
||||
) {
|
||||
lateinit var mainActivityMutableClass: MutableClass
|
||||
@ -41,10 +41,18 @@ abstract class BaseMainActivityResolvePatch(
|
||||
}
|
||||
|
||||
fun injectConstructorMethodCall(classDescriptor: String, methodDescriptor: String) =
|
||||
constructorMethod.injectMethodCall(classDescriptor, methodDescriptor, constructorMethodIndex)
|
||||
constructorMethod.injectMethodCall(
|
||||
classDescriptor,
|
||||
methodDescriptor,
|
||||
constructorMethodIndex
|
||||
)
|
||||
|
||||
fun injectOnBackPressedMethodCall(classDescriptor: String, methodDescriptor: String) =
|
||||
onBackPressedMethod.injectMethodCall(classDescriptor, methodDescriptor, onBackPressedMethodIndex)
|
||||
onBackPressedMethod.injectMethodCall(
|
||||
classDescriptor,
|
||||
methodDescriptor,
|
||||
onBackPressedMethodIndex
|
||||
)
|
||||
|
||||
fun injectOnCreateMethodCall(classDescriptor: String, methodDescriptor: String) =
|
||||
onCreateMethod.injectMethodCall(classDescriptor, methodDescriptor)
|
||||
|
@ -13,8 +13,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.Reference
|
||||
|
||||
@Deprecated("This patch is generally not required for the latest versions of YouTube and YouTube Music." +
|
||||
"For YouTube Music, if user spoofs the app version to v4.27.53, mp4a codec is still used, this is the patch for some of these users.")
|
||||
@Deprecated(
|
||||
"This patch is generally not required for the latest versions of YouTube and YouTube Music." +
|
||||
"For YouTube Music, if user spoofs the app version to v4.27.53, mp4a codec is still used, this is the patch for some of these users."
|
||||
)
|
||||
abstract class BaseOpusCodecsPatch(
|
||||
private val descriptor: String
|
||||
) : BytecodePatch(
|
||||
|
@ -20,10 +20,14 @@ object OverlayBackgroundUtils {
|
||||
arrayOf("height", "width").forEach replacement@{ replacement ->
|
||||
if (it !is Element) return@replacement
|
||||
|
||||
if (it.attributes.getNamedItem("android:id")?.nodeValue?.endsWith(identifier) == true) {
|
||||
it.getAttributeNode("android:layout_$replacement")?.let { attribute ->
|
||||
attribute.textContent = "0.0dip"
|
||||
}
|
||||
if (it.attributes.getNamedItem("android:id")?.nodeValue?.endsWith(
|
||||
identifier
|
||||
) == true
|
||||
) {
|
||||
it.getAttributeNode("android:layout_$replacement")
|
||||
?.let { attribute ->
|
||||
attribute.textContent = "0.0dip"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ abstract class BaseSpoofUserAgentPatch(
|
||||
|
||||
// IndexOutOfBoundsException is not possible here,
|
||||
// but no such occurrences are present in the app.
|
||||
val referee = getInstruction(instructionIndex + 2).getReference<MethodReference>()?.toString()
|
||||
val referee =
|
||||
getInstruction(instructionIndex + 2).getReference<MethodReference>()?.toString()
|
||||
|
||||
// This can technically also match non-user agent string builder append methods,
|
||||
// but no such occurrences are present in the app.
|
||||
|
@ -21,9 +21,10 @@ abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
|
||||
|
||||
// Returns the patch indices as a Sequence, which will execute lazily.
|
||||
fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? {
|
||||
return method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) ->
|
||||
filterMap(classDef, method, instruction, index)
|
||||
}
|
||||
return method.implementation?.instructions?.asSequence()?.withIndex()
|
||||
?.mapNotNull { (index, instruction) ->
|
||||
filterMap(classDef, method, instruction, index)
|
||||
}
|
||||
}
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
@ -48,8 +49,9 @@ abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
|
||||
val mutableClass = context.proxy(classDef).mutableClass
|
||||
|
||||
methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod ->
|
||||
val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())
|
||||
?: return@methods
|
||||
val patchIndices =
|
||||
findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())
|
||||
?: return@methods
|
||||
|
||||
while (!patchIndices.isEmpty()) transform(mutableMethod, patchIndices.removeLast())
|
||||
}
|
||||
|
@ -16,7 +16,10 @@ object TranslationsUtils {
|
||||
this["res/$directory"].mkdir()
|
||||
|
||||
Files.copy(
|
||||
inputStreamFromBundledResource("$sourceDirectory/translations", "$language/strings.xml")!!,
|
||||
inputStreamFromBundledResource(
|
||||
"$sourceDirectory/translations",
|
||||
"$language/strings.xml"
|
||||
)!!,
|
||||
this["res"].resolve("$directory/strings.xml").toPath(),
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
|
@ -5,6 +5,6 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
|
||||
internal object InterstitialsContainerFingerprint : LiteralValueFingerprint(
|
||||
returnType = "V",
|
||||
strings= listOf("overlay_controller_param"),
|
||||
strings = listOf("overlay_controller_param"),
|
||||
literalSupplier = { InterstitialsContainer }
|
||||
)
|
@ -102,7 +102,9 @@ object AlternativeThumbnailsPatch : BaseBytecodePatch(
|
||||
block: (MutableMethod) -> Unit
|
||||
) = alsoResolve(fingerprint).also { block(it.mutableMethod) }
|
||||
|
||||
MessageDigestImageUrlFingerprint.resolveAndLetMutableMethod(MessageDigestImageUrlParentFingerprint) {
|
||||
MessageDigestImageUrlFingerprint.resolveAndLetMutableMethod(
|
||||
MessageDigestImageUrlParentFingerprint
|
||||
) {
|
||||
loadImageUrlMethod = it
|
||||
addImageUrlHook(ALTERNATIVE_THUMBNAILS_CLASS_DESCRIPTOR, true)
|
||||
}
|
||||
|
@ -6,5 +6,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object MessageDigestImageUrlFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf("Ljava/lang/String;", "L")
|
||||
parameters = listOf("Ljava/lang/String;", "L")
|
||||
)
|
@ -6,7 +6,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object MessageDigestImageUrlParentFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "Ljava/lang/String;",
|
||||
returnType = "Ljava/lang/String;",
|
||||
parameters = emptyList(),
|
||||
strings = listOf("@#&=*+-_.,:!?()/~'%;\$"),
|
||||
)
|
@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
internal object OnFailureFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf(
|
||||
parameters = listOf(
|
||||
"Lorg/chromium/net/UrlRequest;",
|
||||
"Lorg/chromium/net/UrlResponseInfo;",
|
||||
"Lorg/chromium/net/CronetException;"
|
||||
|
@ -8,7 +8,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
internal object OnResponseStartedFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;"),
|
||||
parameters = listOf("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;"),
|
||||
strings = listOf(
|
||||
"Content-Length",
|
||||
"Content-Type",
|
||||
|
@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
internal object OnSucceededFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;"),
|
||||
parameters = listOf("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;"),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.name == "onSucceeded"
|
||||
}
|
||||
|
@ -97,7 +97,8 @@ object FeedComponentsPatch : BaseBytecodePatch(
|
||||
fingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
@ -131,7 +132,7 @@ object FeedComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
"invoke-static {v$targetRegister}, $FEED_CLASS_DESCRIPTOR->hideCaptionsButtonContainer(Landroid/view/View;)V"
|
||||
"invoke-static {v$targetRegister}, $FEED_CLASS_DESCRIPTOR->hideCaptionsButtonContainer(Landroid/view/View;)V"
|
||||
)
|
||||
}
|
||||
|
||||
@ -253,7 +254,8 @@ object FeedComponentsPatch : BaseBytecodePatch(
|
||||
ChannelTabRendererFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val iteratorIndex = getTargetIndexWithMethodReferenceName("hasNext")
|
||||
val iteratorRegister = getInstruction<FiveRegisterInstruction>(iteratorIndex).registerC
|
||||
val iteratorRegister =
|
||||
getInstruction<FiveRegisterInstruction>(iteratorIndex).registerC
|
||||
|
||||
val targetIndex = indexOfFirstInstruction {
|
||||
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
|
@ -32,11 +32,17 @@ object AudioTracksPatch : BaseBytecodePatch(
|
||||
opcode == Opcode.CHECK_CAST
|
||||
&& (this as ReferenceInstruction).reference.toString() == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;"
|
||||
}
|
||||
val arrayListIndex = getTargetIndexWithReference(formatStreamModelIndex, "Ljava/util/List;->add(Ljava/lang/Object;)Z")
|
||||
val insertIndex = getTargetIndexWithReference(arrayListIndex, "Ljava/util/List;->isEmpty()Z") + 2
|
||||
val arrayListIndex = getTargetIndexWithReference(
|
||||
formatStreamModelIndex,
|
||||
"Ljava/util/List;->add(Ljava/lang/Object;)Z"
|
||||
)
|
||||
val insertIndex =
|
||||
getTargetIndexWithReference(arrayListIndex, "Ljava/util/List;->isEmpty()Z") + 2
|
||||
|
||||
val formatStreamModelRegister = getInstruction<OneRegisterInstruction>(formatStreamModelIndex).registerA
|
||||
val arrayListRegister = getInstruction<FiveRegisterInstruction>(arrayListIndex).registerC
|
||||
val formatStreamModelRegister =
|
||||
getInstruction<OneRegisterInstruction>(formatStreamModelIndex).registerA
|
||||
val arrayListRegister =
|
||||
getInstruction<FiveRegisterInstruction>(arrayListIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
@ -47,7 +53,7 @@ object AudioTracksPatch : BaseBytecodePatch(
|
||||
|
||||
addInstructions(
|
||||
formatStreamModelIndex + 1,
|
||||
"invoke-static {v$formatStreamModelRegister}, $GENERAL_CLASS_DESCRIPTOR->setFormatStreamModelArray(Ljava/lang/Object;)V"
|
||||
"invoke-static {v$formatStreamModelRegister}, $GENERAL_CLASS_DESCRIPTOR->setFormatStreamModelArray(Ljava/lang/Object;)V"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -174,8 +174,10 @@ object LayoutComponentsPatch : BaseBytecodePatch(
|
||||
it.mutableMethod.apply {
|
||||
val constIndex = getWideLiteralInstructionIndex(AccountSwitcherAccessibility)
|
||||
val insertIndex = getTargetIndex(constIndex, Opcode.IF_EQZ)
|
||||
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(insertIndex, "setVisibility")
|
||||
val visibilityRegister = getInstruction<FiveRegisterInstruction>(setVisibilityIndex).registerD
|
||||
val setVisibilityIndex =
|
||||
getTargetIndexWithMethodReferenceName(insertIndex, "setVisibility")
|
||||
val visibilityRegister =
|
||||
getInstruction<FiveRegisterInstruction>(setVisibilityIndex).registerD
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
@ -192,7 +194,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
SettingsMenuFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = getTargetIndexWithFieldReferenceType("Landroid/support/v7/widget/RecyclerView;")
|
||||
val insertIndex =
|
||||
getTargetIndexWithFieldReferenceType("Landroid/support/v7/widget/RecyclerView;")
|
||||
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
|
@ -29,7 +29,10 @@ object GradientLoadingScreenPatch : BaseBytecodePatch(
|
||||
GradientLoadingScreenPrimaryFingerprint to 45412406,
|
||||
GradientLoadingScreenSecondaryFingerprint to 45418917
|
||||
).forEach { (fingerprint, literal) ->
|
||||
fingerprint.literalInstructionBooleanHook(literal, "$GENERAL_CLASS_DESCRIPTOR->enableGradientLoadingScreen()Z")
|
||||
fingerprint.literalInstructionBooleanHook(
|
||||
literal,
|
||||
"$GENERAL_CLASS_DESCRIPTOR->enableGradientLoadingScreen()Z"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,7 +8,11 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
internal object PivotBarSetTextFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf("Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;", "Landroid/widget/TextView;", "Ljava/lang/CharSequence;"),
|
||||
parameters = listOf(
|
||||
"Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;",
|
||||
"Landroid/widget/TextView;",
|
||||
"Ljava/lang/CharSequence;"
|
||||
),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID
|
||||
|
@ -32,10 +32,14 @@ object SplashAnimationPatch : BaseBytecodePatch(
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
StartUpResourceIdFingerprint.resolve(context, StartUpResourceIdParentFingerprint.resultOrThrow().classDef)
|
||||
StartUpResourceIdFingerprint.resolve(
|
||||
context,
|
||||
StartUpResourceIdParentFingerprint.resultOrThrow().classDef
|
||||
)
|
||||
|
||||
val startUpResourceIdMethod = StartUpResourceIdFingerprint.resultOrThrow().mutableMethod
|
||||
val startUpResourceIdMethodCall = startUpResourceIdMethod.definingClass + "->" + startUpResourceIdMethod.name + "(I)Z"
|
||||
val startUpResourceIdMethodCall =
|
||||
startUpResourceIdMethod.definingClass + "->" + startUpResourceIdMethod.name + "(I)Z"
|
||||
|
||||
SplashAnimationFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
|
@ -118,7 +118,8 @@ object TabletMiniPlayerPatch : BaseBytecodePatch(
|
||||
} else {
|
||||
MiniPlayerOverrideFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val walkerMethod = getWalkerMethod(context, getStringInstructionIndex("appName") + 2)
|
||||
val walkerMethod =
|
||||
getWalkerMethod(context, getStringInstructionIndex("appName") + 2)
|
||||
|
||||
walkerMethod.apply {
|
||||
hook(getTargetIndex(Opcode.RETURN))
|
||||
|
@ -45,7 +45,6 @@ import app.revanced.util.getTargetIndexWithReference
|
||||
import app.revanced.util.getTargetIndexWithReferenceReversed
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.getWideLiteralInstructionIndex
|
||||
import app.revanced.util.literalInstructionBooleanHook
|
||||
import app.revanced.util.literalInstructionHook
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
@ -109,7 +108,8 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
// YouTube's headers have the form of AttributeSet, which is decoded from YouTube's built-in classes.
|
||||
val attributeResolverMethod = AttributeResolverFingerprint.resultOrThrow().mutableMethod
|
||||
val attributeResolverMethodCall = attributeResolverMethod.definingClass + "->" + attributeResolverMethod.name + "(Landroid/content/Context;I)Landroid/graphics/drawable/Drawable;"
|
||||
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"
|
||||
@ -139,9 +139,10 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
}
|
||||
|
||||
// Override the header in the search bar.
|
||||
val setActionBarRingoMutableClass = SetActionBarRingoFingerprint.resultOrThrow().mutableClass
|
||||
setActionBarRingoMutableClass.methods.first {
|
||||
method -> MethodUtil.isConstructor(method)
|
||||
val setActionBarRingoMutableClass =
|
||||
SetActionBarRingoFingerprint.resultOrThrow().mutableClass
|
||||
setActionBarRingoMutableClass.methods.first { method ->
|
||||
MethodUtil.isConstructor(method)
|
||||
}.apply {
|
||||
val insertIndex = getTargetIndex(Opcode.IPUT_BOOLEAN)
|
||||
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
@ -190,7 +191,8 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
.apply {
|
||||
val staticCalls = implementation!!.instructions.withIndex()
|
||||
.filter { instruction ->
|
||||
val methodReference = ((instruction.value as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
val methodReference =
|
||||
((instruction.value as? ReferenceInstruction)?.reference as? MethodReference)
|
||||
methodReference?.parameterTypes?.size == 1 &&
|
||||
methodReference.returnType == "Z"
|
||||
}
|
||||
@ -321,13 +323,18 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
)
|
||||
)
|
||||
} else {
|
||||
SearchBarFingerprint.resolve(context, SearchBarParentFingerprint.resultOrThrow().classDef)
|
||||
SearchBarFingerprint.resolve(
|
||||
context,
|
||||
SearchBarParentFingerprint.resultOrThrow().classDef
|
||||
)
|
||||
|
||||
SearchBarFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(startIndex, "setVisibility")
|
||||
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
|
||||
val setVisibilityIndex =
|
||||
getTargetIndexWithMethodReferenceName(startIndex, "setVisibility")
|
||||
val setVisibilityInstruction =
|
||||
getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
|
||||
|
||||
replaceInstruction(
|
||||
setVisibilityIndex,
|
||||
@ -340,8 +347,10 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
|
||||
SearchResultFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val startIndex = getWideLiteralInstructionIndex(VoiceSearch)
|
||||
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName(startIndex, "setOnClickListener")
|
||||
val viewRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
|
||||
val setOnClickListenerIndex =
|
||||
getTargetIndexWithMethodReferenceName(startIndex, "setOnClickListener")
|
||||
val viewRegister =
|
||||
getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
|
||||
|
||||
addInstruction(
|
||||
setOnClickListenerIndex + 1,
|
||||
|
@ -78,7 +78,7 @@ object CustomBrandingIconPatch : BaseResourcePatch(
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
AppIcon?.let { appIcon ->
|
||||
val appIconValue = appIcon.lowercase().replace(" ","_")
|
||||
val appIconValue = appIcon.lowercase().replace(" ", "_")
|
||||
if (!availableIcon.containsValue(appIconValue)) {
|
||||
mipmapDirectories.map { directory ->
|
||||
ResourceGroup(
|
||||
|
@ -80,7 +80,8 @@ object MinimizedPlaybackPatch : BaseBytecodePatch(
|
||||
}
|
||||
|
||||
PiPControllerFingerprint.resultOrThrow().let {
|
||||
val targetMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
val targetMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
|
||||
targetMethod.apply {
|
||||
val targetRegister = getInstruction<TwoRegisterInstruction>(0).registerA
|
||||
|
@ -33,7 +33,8 @@ object OpenLinksDirectlyPatch : BaseBytecodePatch(
|
||||
fingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = getTargetIndexWithMethodReferenceName("parse")
|
||||
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||
val insertRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||
|
||||
replaceInstruction(
|
||||
insertIndex,
|
||||
|
@ -45,13 +45,15 @@ object AmbientModeSwitchPatch : BaseBytecodePatch(
|
||||
PowerSaveModeSyntheticFingerprint to true
|
||||
).forEach { (fingerprint, reversed) ->
|
||||
fingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val stringIndex = getStringInstructionIndex("android.os.action.POWER_SAVE_MODE_CHANGED")
|
||||
val stringIndex =
|
||||
getStringInstructionIndex("android.os.action.POWER_SAVE_MODE_CHANGED")
|
||||
val targetIndex =
|
||||
if (reversed)
|
||||
getTargetIndexReversed(stringIndex, Opcode.INVOKE_DIRECT)
|
||||
else
|
||||
getTargetIndex(stringIndex, Opcode.INVOKE_DIRECT)
|
||||
val targetClass = (getInstruction<ReferenceInstruction>(targetIndex).reference as MethodReference).definingClass
|
||||
val targetClass =
|
||||
(getInstruction<ReferenceInstruction>(targetIndex).reference as MethodReference).definingClass
|
||||
|
||||
syntheticClassList += targetClass
|
||||
}
|
||||
|
@ -126,16 +126,20 @@ object PlayerButtonsPatch : BaseBytecodePatch(
|
||||
TitleAnchorFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val titleAnchorConstIndex = getWideLiteralInstructionIndex(TitleAnchor)
|
||||
val titleAnchorIndex = getTargetIndex(titleAnchorConstIndex, Opcode.MOVE_RESULT_OBJECT)
|
||||
val titleAnchorRegister = getInstruction<OneRegisterInstruction>(titleAnchorIndex).registerA
|
||||
val titleAnchorRegister =
|
||||
getInstruction<OneRegisterInstruction>(titleAnchorIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
titleAnchorIndex + 1,
|
||||
"invoke-static {v$titleAnchorRegister}, $PLAYER_CLASS_DESCRIPTOR->setTitleAnchorStartMargin(Landroid/view/View;)V"
|
||||
)
|
||||
|
||||
val playerCollapseButtonConstIndex = getWideLiteralInstructionIndex(PlayerCollapseButton)
|
||||
val playerCollapseButtonIndex = getTargetIndex(playerCollapseButtonConstIndex, Opcode.CHECK_CAST)
|
||||
val playerCollapseButtonRegister = getInstruction<OneRegisterInstruction>(playerCollapseButtonIndex).registerA
|
||||
val playerCollapseButtonConstIndex =
|
||||
getWideLiteralInstructionIndex(PlayerCollapseButton)
|
||||
val playerCollapseButtonIndex =
|
||||
getTargetIndex(playerCollapseButtonConstIndex, Opcode.CHECK_CAST)
|
||||
val playerCollapseButtonRegister =
|
||||
getInstruction<OneRegisterInstruction>(playerCollapseButtonIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
playerCollapseButtonIndex + 1,
|
||||
|
@ -37,6 +37,7 @@ object CommentsComponentPatch : BaseBytecodePatch(
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"$COMPONENTS_PATH/CommentsFilter;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
// region patch for emoji picker button in shorts
|
||||
@ -44,7 +45,7 @@ object CommentsComponentPatch : BaseBytecodePatch(
|
||||
ShortsLiveStreamEmojiPickerOpacityFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = implementation!!.instructions.size - 1
|
||||
val insertRegister= getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
@ -56,12 +57,15 @@ object CommentsComponentPatch : BaseBytecodePatch(
|
||||
ShortsLiveStreamEmojiPickerOnClickListenerFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val emojiPickerEndpointIndex = getWideLiteralInstructionIndex(126326492)
|
||||
val emojiPickerOnClickListenerIndex = getTargetIndex(emojiPickerEndpointIndex, Opcode.INVOKE_DIRECT)
|
||||
val emojiPickerOnClickListenerMethod = getWalkerMethod(context, emojiPickerOnClickListenerIndex)
|
||||
val emojiPickerOnClickListenerIndex =
|
||||
getTargetIndex(emojiPickerEndpointIndex, Opcode.INVOKE_DIRECT)
|
||||
val emojiPickerOnClickListenerMethod =
|
||||
getWalkerMethod(context, emojiPickerOnClickListenerIndex)
|
||||
|
||||
emojiPickerOnClickListenerMethod.apply {
|
||||
val insertIndex = getTargetIndex(Opcode.IF_EQZ)
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
val insertRegister =
|
||||
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
|
@ -170,7 +170,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
LayoutCircleFingerprint,
|
||||
LayoutIconFingerprint,
|
||||
LayoutVideoFingerprint
|
||||
).forEach{ fingerprint ->
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
@ -205,9 +205,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
val constRegister = getInstruction<OneRegisterInstruction>(constIndex).registerA
|
||||
val insertIndex = getTargetIndexReversed(constIndex, Opcode.INVOKE_VIRTUAL) + 1
|
||||
val jumpIndex = implementation!!.instructions.let { instruction ->
|
||||
insertIndex + instruction.subList(insertIndex, instruction.size - 1).indexOfFirst { instructions ->
|
||||
instructions.opcode == Opcode.GOTO || instructions.opcode == Opcode.GOTO_16
|
||||
}
|
||||
insertIndex + instruction.subList(insertIndex, instruction.size - 1)
|
||||
.indexOfFirst { instructions ->
|
||||
instructions.opcode == Opcode.GOTO || instructions.opcode == Opcode.GOTO_16
|
||||
}
|
||||
}
|
||||
|
||||
val replaceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
|
||||
@ -270,7 +271,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
val insertIndex = getWideLiteralInstructionIndex(SeekUndoEduOverlayStub)
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
val onClickListenerIndex = getTargetIndexWithMethodReferenceName(insertIndex, "setOnClickListener")
|
||||
val onClickListenerIndex =
|
||||
getTargetIndexWithMethodReferenceName(insertIndex, "setOnClickListener")
|
||||
val constComponent = getConstComponent(insertIndex, onClickListenerIndex - 1)
|
||||
|
||||
if (constComponent.isNotEmpty()) {
|
||||
@ -315,8 +317,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
|
||||
it.mutableClass.methods.find { method ->
|
||||
method.parameters == listOf("Landroid/view/View${'$'}OnClickListener;")
|
||||
}?.apply {
|
||||
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName("setOnClickListener")
|
||||
val setOnClickListenerRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
|
||||
val setOnClickListenerIndex =
|
||||
getTargetIndexWithMethodReferenceName("setOnClickListener")
|
||||
val setOnClickListenerRegister =
|
||||
getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
|
||||
|
||||
addInstruction(
|
||||
setOnClickListenerIndex + 1,
|
||||
|
@ -110,8 +110,10 @@ object DescriptionComponentsPatch : BaseBytecodePatch(
|
||||
EngagementPanelTitleParentFingerprint.resultOrThrow().classDef
|
||||
)
|
||||
EngagementPanelTitleFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val contentDescriptionIndex = getTargetIndexWithMethodReferenceName("setContentDescription")
|
||||
val contentDescriptionRegister = getInstruction<FiveRegisterInstruction>(contentDescriptionIndex).registerD
|
||||
val contentDescriptionIndex =
|
||||
getTargetIndexWithMethodReferenceName("setContentDescription")
|
||||
val contentDescriptionRegister =
|
||||
getInstruction<FiveRegisterInstruction>(contentDescriptionIndex).registerD
|
||||
|
||||
addInstruction(
|
||||
contentDescriptionIndex,
|
||||
|
@ -2,7 +2,7 @@ package app.revanced.patches.youtube.player.flyoutmenu.hide.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
|
||||
/**
|
||||
/**
|
||||
* This fingerprint is compatible with YouTube v18.39.xx+
|
||||
*/
|
||||
internal object PiPModeConfigFingerprint : LiteralValueFingerprint(
|
||||
|
@ -46,11 +46,14 @@ object ChangeTogglePatch : BaseBytecodePatch(
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
val additionalSettingsConfigMethod = AdditionalSettingsConfigFingerprint.resultOrThrow().mutableMethod
|
||||
val methodToCall = additionalSettingsConfigMethod.definingClass + "->" + additionalSettingsConfigMethod.name + "()Z"
|
||||
val additionalSettingsConfigMethod =
|
||||
AdditionalSettingsConfigFingerprint.resultOrThrow().mutableMethod
|
||||
val methodToCall =
|
||||
additionalSettingsConfigMethod.definingClass + "->" + additionalSettingsConfigMethod.name + "()Z"
|
||||
|
||||
// Resolves fingerprints
|
||||
val playbackLoopOnClickListenerResult = PlaybackLoopOnClickListenerFingerprint.resultOrThrow()
|
||||
val playbackLoopOnClickListenerResult =
|
||||
PlaybackLoopOnClickListenerFingerprint.resultOrThrow()
|
||||
PlaybackLoopInitFingerprint.resolve(context, playbackLoopOnClickListenerResult.classDef)
|
||||
|
||||
var fingerprintArray = arrayOf(
|
||||
@ -90,7 +93,8 @@ object ChangeTogglePatch : BaseBytecodePatch(
|
||||
it.mutableMethod.apply {
|
||||
val referenceIndex = indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& (this as ReferenceInstruction).reference.toString().endsWith(methodToCall)
|
||||
&& (this as ReferenceInstruction).reference.toString()
|
||||
.endsWith(methodToCall)
|
||||
}
|
||||
if (referenceIndex > 0) {
|
||||
val insertRegister =
|
||||
@ -117,12 +121,14 @@ object ChangeTogglePatch : BaseBytecodePatch(
|
||||
|
||||
val stringReferenceIndex = stableVolumeMethod.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& (this as ReferenceInstruction).reference.toString().endsWith("(Ljava/lang/String;Ljava/lang/String;)V")
|
||||
&& (this as ReferenceInstruction).reference.toString()
|
||||
.endsWith("(Ljava/lang/String;Ljava/lang/String;)V")
|
||||
}
|
||||
if (stringReferenceIndex < 0)
|
||||
throw PatchException("Target reference was not found in ${StableVolumeFingerprint.javaClass.simpleName}.")
|
||||
|
||||
val stringReference = stableVolumeMethod.getInstruction<ReferenceInstruction>(stringReferenceIndex).reference
|
||||
val stringReference =
|
||||
stableVolumeMethod.getInstruction<ReferenceInstruction>(stringReferenceIndex).reference
|
||||
|
||||
CinematicLightingFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
@ -135,15 +141,20 @@ object ChangeTogglePatch : BaseBytecodePatch(
|
||||
val stringIndex = getStringInstructionIndex("menu_item_cinematic_lighting")
|
||||
|
||||
val checkCastIndex = getTargetIndexReversed(stringIndex, Opcode.CHECK_CAST)
|
||||
val iGetObjectPrimaryIndex = getTargetIndexReversed(checkCastIndex, Opcode.IGET_OBJECT)
|
||||
val iGetObjectPrimaryIndex =
|
||||
getTargetIndexReversed(checkCastIndex, Opcode.IGET_OBJECT)
|
||||
val iGetObjectSecondaryIndex = getTargetIndex(checkCastIndex, Opcode.IGET_OBJECT)
|
||||
|
||||
val checkCastReference = getInstruction<ReferenceInstruction>(checkCastIndex).reference
|
||||
val iGetObjectPrimaryReference = getInstruction<ReferenceInstruction>(iGetObjectPrimaryIndex).reference
|
||||
val iGetObjectSecondaryReference = getInstruction<ReferenceInstruction>(iGetObjectSecondaryIndex).reference
|
||||
val checkCastReference =
|
||||
getInstruction<ReferenceInstruction>(checkCastIndex).reference
|
||||
val iGetObjectPrimaryReference =
|
||||
getInstruction<ReferenceInstruction>(iGetObjectPrimaryIndex).reference
|
||||
val iGetObjectSecondaryReference =
|
||||
getInstruction<ReferenceInstruction>(iGetObjectSecondaryIndex).reference
|
||||
|
||||
val invokeVirtualIndex = getTargetIndex(stringIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val invokeVirtualInstruction = getInstruction<FiveRegisterInstruction>(invokeVirtualIndex)
|
||||
val invokeVirtualInstruction =
|
||||
getInstruction<FiveRegisterInstruction>(invokeVirtualIndex)
|
||||
val freeRegisterC = invokeVirtualInstruction.registerC
|
||||
val freeRegisterD = invokeVirtualInstruction.registerD
|
||||
val freeRegisterE = invokeVirtualInstruction.registerE
|
||||
|
@ -182,7 +182,8 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
|
||||
val walkerMethod = getWalkerMethod(context, walkerIndex)
|
||||
walkerMethod.apply {
|
||||
val insertIndex = implementation!!.instructions.size - 1
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
@ -288,7 +289,8 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
|
||||
LandScapeModeConfigFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = implementation!!.instructions.size - 1
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
val insertRegister =
|
||||
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
@ -300,7 +302,8 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
|
||||
|
||||
BroadcastReceiverFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val stringIndex = getStringInstructionIndex("android.intent.action.SCREEN_ON")
|
||||
val stringIndex =
|
||||
getStringInstructionIndex("android.intent.action.SCREEN_ON")
|
||||
val insertIndex = getTargetIndex(stringIndex, Opcode.IF_EQZ) + 1
|
||||
|
||||
addInstruction(
|
||||
|
@ -89,22 +89,29 @@ object OverlayButtonsBytecodePatch : BytecodePatch(
|
||||
&& getReference<FieldReference>()?.definingClass == definingClass
|
||||
&& (this as TwoRegisterInstruction).registerA == registerResolver
|
||||
}
|
||||
val invokerObjectReference = getInstruction<ReferenceInstruction>(invokerObjectIndex).reference
|
||||
val invokerObjectReference =
|
||||
getInstruction<ReferenceInstruction>(invokerObjectIndex).reference
|
||||
|
||||
val onClickListenerReferenceIndex = getTargetIndexWithReference("<init>(Ljava/lang/Object;I[B)V")
|
||||
val onClickListenerReference = getInstruction<ReferenceInstruction>(onClickListenerReferenceIndex).reference
|
||||
val onClickListenerClass = context.findClass((onClickListenerReference as MethodReference).definingClass)!!.mutableClass
|
||||
val onClickListenerReferenceIndex =
|
||||
getTargetIndexWithReference("<init>(Ljava/lang/Object;I[B)V")
|
||||
val onClickListenerReference =
|
||||
getInstruction<ReferenceInstruction>(onClickListenerReferenceIndex).reference
|
||||
val onClickListenerClass =
|
||||
context.findClass((onClickListenerReference as MethodReference).definingClass)!!.mutableClass
|
||||
|
||||
var invokeInterfaceReference = ""
|
||||
onClickListenerClass.methods.find { method -> method.name == "onClick" }
|
||||
?.apply {
|
||||
val invokeInterfaceIndex = getTargetIndexWithReference(invokerObjectReference.toString()) + 1
|
||||
val invokeInterfaceIndex =
|
||||
getTargetIndexWithReference(invokerObjectReference.toString()) + 1
|
||||
if (getInstruction(invokeInterfaceIndex).opcode != Opcode.INVOKE_INTERFACE)
|
||||
throw PatchException("Opcode does not match")
|
||||
invokeInterfaceReference = getInstruction<ReferenceInstruction>(invokeInterfaceIndex).reference.toString()
|
||||
invokeInterfaceReference =
|
||||
getInstruction<ReferenceInstruction>(invokeInterfaceIndex).reference.toString()
|
||||
} ?: throw PatchException("Could not find onClick method")
|
||||
|
||||
val alwaysRepeatMutableClass = context.findClass(INTEGRATIONS_ALWAYS_REPEAT_CLASS_DESCRIPTOR)!!.mutableClass
|
||||
val alwaysRepeatMutableClass =
|
||||
context.findClass(INTEGRATIONS_ALWAYS_REPEAT_CLASS_DESCRIPTOR)!!.mutableClass
|
||||
|
||||
val smaliInstructions =
|
||||
"""
|
||||
|
@ -129,7 +129,10 @@ object OverlayButtonsPatch : BaseResourcePatch(
|
||||
val resources = commonResources + specificResources
|
||||
resources.forEach { resource ->
|
||||
val folderName = if (resource.endsWith(".xml")) "drawable" else "drawable-xxhdpi"
|
||||
context.copyResources("youtube/overlaybuttons/$iconValue", ResourceGroup(folderName, resource))
|
||||
context.copyResources(
|
||||
"youtube/overlaybuttons/$iconValue",
|
||||
ResourceGroup(folderName, resource)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ internal object OfflineVideoEndpointFingerprint : MethodFingerprint(
|
||||
"Ljava/util/Map;",
|
||||
"L",
|
||||
"Ljava/lang/String", // VideoId
|
||||
"L"),
|
||||
"L"
|
||||
),
|
||||
strings = listOf("Object is not an offlineable video: ")
|
||||
)
|
||||
|
@ -133,7 +133,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
|
||||
TotalTimeFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val charSequenceIndex = getTargetIndexWithMethodReferenceName("getString") + 1
|
||||
val charSequenceRegister = getInstruction<OneRegisterInstruction>(charSequenceIndex).registerA
|
||||
val charSequenceRegister =
|
||||
getInstruction<OneRegisterInstruction>(charSequenceIndex).registerA
|
||||
val textViewIndex = getTargetIndexWithMethodReferenceName("getText")
|
||||
val textViewRegister =
|
||||
getInstruction<FiveRegisterInstruction>(textViewIndex).registerC
|
||||
@ -162,7 +163,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
|
||||
}
|
||||
|
||||
ControlsOverlayStyleFingerprint.resultOrThrow().let {
|
||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
val walkerMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
walkerMethod.apply {
|
||||
val colorRegister = getInstruction<TwoRegisterInstruction>(0).registerA
|
||||
|
||||
@ -221,18 +223,19 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
|
||||
// region patch for hide seekbar
|
||||
|
||||
SeekbarFingerprint.resultOrThrow().mutableClass.let { mutableClass ->
|
||||
SeekbarOnDrawFingerprint.also { it.resolve(context, mutableClass) }.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
SeekbarOnDrawFingerprint.also { it.resolve(context, mutableClass) }.resultOrThrow()
|
||||
.let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideSeekbar()Z
|
||||
move-result v0
|
||||
if-eqz v0, :show
|
||||
return-void
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
@ -240,7 +243,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
|
||||
// region patch for hide time stamp
|
||||
|
||||
PlayerSeekbarColorFingerprint.resultOrThrow().let { parentResult ->
|
||||
TimeCounterFingerprint.also { it.resolve(context, parentResult.classDef) }.resultOrThrow().let {
|
||||
TimeCounterFingerprint.also { it.resolve(context, parentResult.classDef) }
|
||||
.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
@ -274,7 +278,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
|
||||
"SETTINGS: RESTORE_OLD_SEEKBAR_THUMBNAILS"
|
||||
)
|
||||
)
|
||||
} ?: println("WARNING: Restore old seekbar thumbnails setting is not supported in this version. Use YouTube 19.16.39 or earlier.")
|
||||
}
|
||||
?: println("WARNING: Restore old seekbar thumbnails setting is not supported in this version. Use YouTube 19.16.39 or earlier.")
|
||||
|
||||
// endregion
|
||||
|
||||
|
@ -49,7 +49,8 @@ object SpeedOverlayPatch : BytecodePatch(
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
val restoreSlideToSeekBehaviorFingerprintResult = RestoreSlideToSeekBehaviorFingerprint.result
|
||||
val restoreSlideToSeekBehaviorFingerprintResult =
|
||||
RestoreSlideToSeekBehaviorFingerprint.result
|
||||
val speedOverlayFingerprintResult = SpeedOverlayFingerprint.result
|
||||
val speedOverlayValueFingerprintResult = SpeedOverlayValueFingerprint.result
|
||||
|
||||
@ -130,7 +131,8 @@ object SpeedOverlayPatch : BytecodePatch(
|
||||
|
||||
val jumpIndex = scanResult.endIndex + 1
|
||||
val insertIndex = scanResult.endIndex - 1
|
||||
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
val insertRegister =
|
||||
getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
hook(insertIndex, insertRegister, jumpIndex)
|
||||
}
|
||||
@ -150,7 +152,8 @@ object SpeedOverlayPatch : BytecodePatch(
|
||||
|
||||
constructorMethod.apply {
|
||||
val syntheticIndex = getTargetIndexReversed(Opcode.NEW_INSTANCE)
|
||||
val syntheticClass = getInstruction<ReferenceInstruction>(syntheticIndex).reference.toString()
|
||||
val syntheticClass =
|
||||
getInstruction<ReferenceInstruction>(syntheticIndex).reference.toString()
|
||||
|
||||
val syntheticMethod =
|
||||
context.findClass(syntheticClass)?.mutableClass
|
||||
@ -170,8 +173,12 @@ object SpeedOverlayPatch : BytecodePatch(
|
||||
"""
|
||||
)
|
||||
|
||||
insertIndex = getTargetIndexWithMethodReferenceNameReversed(speedOverlayValueIndex, "removeCallbacks") + 1
|
||||
insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex - 1).registerC
|
||||
insertIndex = getTargetIndexWithMethodReferenceNameReversed(
|
||||
speedOverlayValueIndex,
|
||||
"removeCallbacks"
|
||||
) + 1
|
||||
insertRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex - 1).registerC
|
||||
jumpIndex = getTargetIndex(speedOverlayValueIndex, Opcode.RETURN_VOID) + 1
|
||||
hook(insertIndex, insertRegister, jumpIndex)
|
||||
}
|
||||
@ -181,7 +188,8 @@ object SpeedOverlayPatch : BytecodePatch(
|
||||
SpeedOverlayTextValueFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
targetIndex + 1, """
|
||||
|
@ -161,7 +161,10 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
if (insertIndex == 0)
|
||||
throw PatchException("insert index not found")
|
||||
|
||||
hideButtons(insertIndex, "hideShortsSoundButton(Ljava/lang/Object;)Ljava/lang/Object;")
|
||||
hideButtons(
|
||||
insertIndex,
|
||||
"hideShortsSoundButton(Ljava/lang/Object;)Ljava/lang/Object;"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,7 +189,8 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
when (returnType) {
|
||||
"Landroid/widget/TextView;" -> {
|
||||
val insertIndex = implementation!!.instructions.size - 1
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
val insertRegister =
|
||||
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex + 1, """
|
||||
@ -196,6 +200,7 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
)
|
||||
removeInstruction(insertIndex)
|
||||
}
|
||||
|
||||
"V" -> {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
@ -206,6 +211,7 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
""", ExternalLabel("show", getInstruction(0))
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw PatchException("Unknown returnType: $returnType")
|
||||
}
|
||||
@ -260,7 +266,8 @@ object ShortsComponentPatch : BaseBytecodePatch(
|
||||
|
||||
TextComponentSpecFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = getTargetIndexWithReference("Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;")
|
||||
val insertIndex =
|
||||
getTargetIndexWithReference("Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;")
|
||||
|
||||
val charSequenceRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||
|
@ -25,7 +25,8 @@ object ShortsNavigationBarPatch : BytecodePatch(
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
InitializeButtonsFingerprint.resultOrThrow().let { parentResult ->
|
||||
SetPivotBarFingerprint.also { it.resolve(context, parentResult.classDef) }.resultOrThrow().let {
|
||||
SetPivotBarFingerprint.also { it.resolve(context, parentResult.classDef) }
|
||||
.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val register = getInstruction<OneRegisterInstruction>(startIndex).registerA
|
||||
@ -39,7 +40,8 @@ object ShortsNavigationBarPatch : BytecodePatch(
|
||||
}
|
||||
|
||||
RenderBottomNavigationBarFingerprint.resultOrThrow().let {
|
||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
val walkerMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
|
||||
walkerMethod.addInstruction(
|
||||
0,
|
||||
|
@ -42,9 +42,12 @@ object ShortsRepeatPatch : BaseBytecodePatch(
|
||||
injectEnum(enumName, fieldName)
|
||||
}
|
||||
|
||||
val endScreenStringIndex = getStringInstructionIndex("REEL_LOOP_BEHAVIOR_END_SCREEN")
|
||||
val endScreenReferenceIndex = getTargetIndex(endScreenStringIndex, Opcode.SPUT_OBJECT)
|
||||
val endScreenReference = getInstruction<ReferenceInstruction>(endScreenReferenceIndex).reference.toString()
|
||||
val endScreenStringIndex =
|
||||
getStringInstructionIndex("REEL_LOOP_BEHAVIOR_END_SCREEN")
|
||||
val endScreenReferenceIndex =
|
||||
getTargetIndex(endScreenStringIndex, Opcode.SPUT_OBJECT)
|
||||
val endScreenReference =
|
||||
getInstruction<ReferenceInstruction>(endScreenReferenceIndex).reference.toString()
|
||||
|
||||
val enumMethodName = ReelEnumStaticFingerprint.resultOrThrow().mutableMethod.name
|
||||
val enumMethodCall = "$definingClass->$enumMethodName(I)$definingClass"
|
||||
@ -101,7 +104,8 @@ object ShortsRepeatPatch : BaseBytecodePatch(
|
||||
if ((instruction as ReferenceInstruction).reference.toString() != enumMethodCall)
|
||||
continue
|
||||
|
||||
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||
val register =
|
||||
getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||
|
||||
addInstructions(
|
||||
index + 2, """
|
||||
@ -109,8 +113,8 @@ object ShortsRepeatPatch : BaseBytecodePatch(
|
||||
move-result-object v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,13 +38,14 @@ object ResumingShortsOnStartupPatch : BaseBytecodePatch(
|
||||
UserWasInShortsABConfigFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val startIndex = indexOfOptionalInstruction(this)
|
||||
val walkerIndex = implementation!!.instructions.let {
|
||||
val subListIndex = it.subList(startIndex, startIndex + 20).indexOfFirst { instruction ->
|
||||
val reference = instruction.getReference<MethodReference>()
|
||||
instruction.opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& reference?.returnType == "Z"
|
||||
&& reference.definingClass != "Lj${'$'}/util/Optional;"
|
||||
&& reference.parameterTypes.size == 0
|
||||
}
|
||||
val subListIndex =
|
||||
it.subList(startIndex, startIndex + 20).indexOfFirst { instruction ->
|
||||
val reference = instruction.getReference<MethodReference>()
|
||||
instruction.opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& reference?.returnType == "Z"
|
||||
&& reference.definingClass != "Lj${'$'}/util/Optional;"
|
||||
&& reference.parameterTypes.size == 0
|
||||
}
|
||||
if (subListIndex < 0)
|
||||
throw PatchException("subListIndex not found")
|
||||
|
||||
@ -75,8 +76,10 @@ object ResumingShortsOnStartupPatch : BaseBytecodePatch(
|
||||
getReference<MethodReference>()?.name == "isDone"
|
||||
}
|
||||
if (listenableInstructionIndex < 0) throw PatchException("Could not find instruction index")
|
||||
val originalInstructionRegister = getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC
|
||||
val freeRegister = getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA
|
||||
val originalInstructionRegister =
|
||||
getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC
|
||||
val freeRegister =
|
||||
getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA
|
||||
|
||||
addInstructionsWithLabels(
|
||||
listenableInstructionIndex + 1,
|
||||
|
@ -14,7 +14,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
internal object UserWasInShortsABConfigFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
strings = listOf("Failed to get offline response: "),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
customFingerprint = { methodDef, _ ->
|
||||
indexOfOptionalInstruction(methodDef) >= 0
|
||||
}
|
||||
) {
|
||||
|
@ -62,7 +62,8 @@ object SwipeControlsPatch : BaseBytecodePatch(
|
||||
|
||||
// region patch for swipe controls patch
|
||||
|
||||
val hostActivityClass = context.findClass(INTEGRATIONS_SWIPE_CONTROLS_HOST_ACTIVITY_CLASS_DESCRIPTOR)!!.mutableClass
|
||||
val hostActivityClass =
|
||||
context.findClass(INTEGRATIONS_SWIPE_CONTROLS_HOST_ACTIVITY_CLASS_DESCRIPTOR)!!.mutableClass
|
||||
val mainActivityClass = mainActivityMutableClass
|
||||
|
||||
// inject the wrapper class from integrations into the class hierarchy of MainActivity (WatchWhileActivity)
|
||||
|
@ -43,7 +43,8 @@ object CastButtonPatch : BytecodePatch(
|
||||
MenuItemVisibilityFingerprint.resolve(context, toolbarMenuItemInitializeResult.classDef)
|
||||
|
||||
toolbarMenuItemInitializeMethod = toolbarMenuItemInitializeResult.mutableMethod
|
||||
toolbarMenuItemVisibilityMethod = MenuItemVisibilityFingerprint.resultOrThrow().mutableMethod
|
||||
toolbarMenuItemVisibilityMethod =
|
||||
MenuItemVisibilityFingerprint.resultOrThrow().mutableMethod
|
||||
|
||||
playerButtonMethod = PlayerButtonFingerprint.resultOrThrow().mutableMethod
|
||||
|
||||
|
@ -32,7 +32,8 @@ object CairoSettingsPatch : BytecodePatch(
|
||||
*/
|
||||
CarioFragmentConfigFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getTargetIndex(getWideLiteralInstructionIndex(45532100), Opcode.MOVE_RESULT)
|
||||
val targetIndex =
|
||||
getTargetIndex(getWideLiteralInstructionIndex(45532100), Opcode.MOVE_RESULT)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
|
@ -76,10 +76,12 @@ object SpoofClientPatch : BaseBytecodePatch(
|
||||
BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
moveUriStringIndex + 1, """
|
||||
moveUriStringIndex + 1,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$targetRegister
|
||||
""",
|
||||
@ -94,10 +96,12 @@ object SpoofClientPatch : BaseBytecodePatch(
|
||||
BuildPlayerRequestURIFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val invokeToStringIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
||||
val uriRegister =
|
||||
getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
invokeToStringIndex, """
|
||||
invokeToStringIndex,
|
||||
"""
|
||||
invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
|
||||
move-result-object v$uriRegister
|
||||
""",
|
||||
@ -111,50 +115,59 @@ object SpoofClientPatch : BaseBytecodePatch(
|
||||
|
||||
val (clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField) =
|
||||
SetPlayerRequestClientTypeFingerprint.resultOrThrow().let { result ->
|
||||
with (result.mutableMethod) {
|
||||
with(result.mutableMethod) {
|
||||
// Field in the player request object that holds the client info object.
|
||||
val clientInfoField = getInstructions().find { instruction ->
|
||||
// requestMessage.clientInfo = clientInfoBuilder.build();
|
||||
instruction.opcode == Opcode.IPUT_OBJECT &&
|
||||
instruction.getReference<FieldReference>()?.type == CLIENT_INFO_CLASS_DESCRIPTOR
|
||||
}?.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoField")
|
||||
}?.getReference<FieldReference>()
|
||||
?: throw PatchException("Could not find clientInfoField")
|
||||
|
||||
// Client info object's client type field.
|
||||
val clientInfoClientTypeField = getInstruction(result.scanResult.patternScanResult!!.endIndex)
|
||||
.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientTypeField")
|
||||
val clientInfoClientTypeField =
|
||||
getInstruction(result.scanResult.patternScanResult!!.endIndex)
|
||||
.getReference<FieldReference>()
|
||||
?: throw PatchException("Could not find clientInfoClientTypeField")
|
||||
|
||||
val clientInfoVersionIndex = getStringInstructionIndex("10.29")
|
||||
val clientInfoVersionRegister = getInstruction<OneRegisterInstruction>(clientInfoVersionIndex).registerA
|
||||
val clientInfoVersionRegister =
|
||||
getInstruction<OneRegisterInstruction>(clientInfoVersionIndex).registerA
|
||||
val clientInfoClientVersionFieldIndex = implementation!!.instructions.let {
|
||||
clientInfoVersionIndex + it.subList(clientInfoVersionIndex, it.size - 1).indexOfFirst { instruction ->
|
||||
instruction.opcode == Opcode.IPUT_OBJECT
|
||||
&& (instruction as TwoRegisterInstruction).registerA == clientInfoVersionRegister
|
||||
}
|
||||
clientInfoVersionIndex + it.subList(clientInfoVersionIndex, it.size - 1)
|
||||
.indexOfFirst { instruction ->
|
||||
instruction.opcode == Opcode.IPUT_OBJECT
|
||||
&& (instruction as TwoRegisterInstruction).registerA == clientInfoVersionRegister
|
||||
}
|
||||
}
|
||||
|
||||
// Client info object's client version field.
|
||||
val clientInfoClientVersionField = getInstruction(clientInfoClientVersionFieldIndex)
|
||||
.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientVersionField")
|
||||
val clientInfoClientVersionField =
|
||||
getInstruction(clientInfoClientVersionFieldIndex)
|
||||
.getReference<FieldReference>()
|
||||
?: throw PatchException("Could not find clientInfoClientVersionField")
|
||||
|
||||
Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField)
|
||||
}
|
||||
}
|
||||
|
||||
val clientInfoClientModelField = CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.let {
|
||||
val instructions = it.getInstructions()
|
||||
val getClientModelIndex = indexOfModelInstruction(it)
|
||||
val clientInfoClientModelField =
|
||||
CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.let {
|
||||
val instructions = it.getInstructions()
|
||||
val getClientModelIndex = indexOfModelInstruction(it)
|
||||
|
||||
// The next IPUT_OBJECT instruction after getting the client model is setting the client model field.
|
||||
instructions.subList(
|
||||
getClientModelIndex,
|
||||
instructions.size,
|
||||
).find { instruction ->
|
||||
val reference = instruction.getReference<FieldReference>()
|
||||
instruction.opcode == Opcode.IPUT_OBJECT
|
||||
&& reference?.definingClass == CLIENT_INFO_CLASS_DESCRIPTOR
|
||||
&& reference.type == "Ljava/lang/String;"
|
||||
}?.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientModelField")
|
||||
}
|
||||
// The next IPUT_OBJECT instruction after getting the client model is setting the client model field.
|
||||
instructions.subList(
|
||||
getClientModelIndex,
|
||||
instructions.size,
|
||||
).find { instruction ->
|
||||
val reference = instruction.getReference<FieldReference>()
|
||||
instruction.opcode == Opcode.IPUT_OBJECT
|
||||
&& reference?.definingClass == CLIENT_INFO_CLASS_DESCRIPTOR
|
||||
&& reference.type == "Ljava/lang/String;"
|
||||
}?.getReference<FieldReference>()
|
||||
?: throw PatchException("Could not find clientInfoClientModelField")
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
@ -167,12 +180,13 @@ object SpoofClientPatch : BaseBytecodePatch(
|
||||
|
||||
val checkCastInstruction = getInstruction<OneRegisterInstruction>(checkCastIndex)
|
||||
val requestMessageInstanceRegister = checkCastInstruction.registerA
|
||||
val clientInfoContainerClassName = checkCastInstruction.getReference<TypeReference>()!!.type
|
||||
val clientInfoContainerClassName =
|
||||
checkCastInstruction.getReference<TypeReference>()!!.type
|
||||
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
"invoke-static { v$requestMessageInstanceRegister }," +
|
||||
" $definingClass->$setClientInfoMethodName($clientInfoContainerClassName)V",
|
||||
" $definingClass->$setClientInfoMethodName($clientInfoContainerClassName)V",
|
||||
)
|
||||
|
||||
// Change client info to use the spoofed values.
|
||||
@ -181,7 +195,13 @@ object SpoofClientPatch : BaseBytecodePatch(
|
||||
ImmutableMethod(
|
||||
definingClass,
|
||||
setClientInfoMethodName,
|
||||
listOf(ImmutableMethodParameter(clientInfoContainerClassName, annotations, "clientInfoContainer")),
|
||||
listOf(
|
||||
ImmutableMethodParameter(
|
||||
clientInfoContainerClassName,
|
||||
annotations,
|
||||
"clientInfoContainer"
|
||||
)
|
||||
),
|
||||
"V",
|
||||
AccessFlags.PRIVATE or AccessFlags.STATIC,
|
||||
annotations,
|
||||
@ -229,7 +249,7 @@ object SpoofClientPatch : BaseBytecodePatch(
|
||||
|
||||
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameter(
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(" +
|
||||
"Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
|
||||
"Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
|
||||
)
|
||||
|
||||
// endregion
|
||||
@ -238,18 +258,19 @@ object SpoofClientPatch : BaseBytecodePatch(
|
||||
|
||||
PlayerGestureConfigSyntheticFingerprint.resultOrThrow().let {
|
||||
arrayOf(3, 9).forEach { offSet ->
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex - offSet).apply {
|
||||
val index = implementation!!.instructions.size - 1
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex - offSet)
|
||||
.apply {
|
||||
val index = implementation!!.instructions.size - 1
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
addInstructions(
|
||||
index,
|
||||
"""
|
||||
addInstructions(
|
||||
index,
|
||||
"""
|
||||
invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->enablePlayerGesture(Z)Z
|
||||
move-result v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package app.revanced.patches.youtube.utils.fix.client.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
|
||||
import app.revanced.patches.youtube.utils.fix.client.fingerprints.PlayerGestureConfigSyntheticFingerprint.indexOfDownAndOutAllowedInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
|
@ -28,14 +28,18 @@ object DoubleBackToClosePatch : BytecodePatch(
|
||||
/**
|
||||
* Hook onBackPressed method inside MainActivity (WatchWhileActivity)
|
||||
*/
|
||||
MainActivityResolvePatch.injectOnBackPressedMethodCall(INTEGRATIONS_CLASS_DESCRIPTOR, "closeActivityOnBackPressed")
|
||||
MainActivityResolvePatch.injectOnBackPressedMethodCall(
|
||||
INTEGRATIONS_CLASS_DESCRIPTOR,
|
||||
"closeActivityOnBackPressed"
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* Inject the methods which start of ScrollView
|
||||
*/
|
||||
ScrollPositionFingerprint.resultOrThrow().let {
|
||||
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
val walkerMethod =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
val insertIndex = walkerMethod.implementation!!.instructions.size - 1 - 1
|
||||
|
||||
walkerMethod.injectScrollView(insertIndex, "onStartScrollView")
|
||||
@ -46,11 +50,12 @@ object DoubleBackToClosePatch : BytecodePatch(
|
||||
* Inject the methods which stop of ScrollView
|
||||
*/
|
||||
ScrollTopParentFingerprint.resultOrThrow().let { parentResult ->
|
||||
ScrollTopFingerprint.also { it.resolve(context, parentResult.classDef) }.resultOrThrow().let {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
ScrollTopFingerprint.also { it.resolve(context, parentResult.classDef) }.resultOrThrow()
|
||||
.let {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
it.mutableMethod.injectScrollView(insertIndex, "onStopScrollView")
|
||||
}
|
||||
it.mutableMethod.injectScrollView(insertIndex, "onStopScrollView")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,8 +33,12 @@ object FullscreenButtonViewStubPatch : BytecodePatch(
|
||||
).forEach { (fingerprint, literalValue) ->
|
||||
fingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getTargetIndex(getWideLiteralInstructionIndex(literalValue.toLong()), Opcode.MOVE_RESULT)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
val targetIndex = getTargetIndex(
|
||||
getWideLiteralInstructionIndex(literalValue.toLong()),
|
||||
Opcode.MOVE_RESULT
|
||||
)
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
targetIndex + 1,
|
||||
|
@ -6,8 +6,8 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
* Resolves to the same method as [StoryboardRendererDecoderRecommendedLevelFingerprint].
|
||||
*/
|
||||
* Resolves to the same method as [StoryboardRendererDecoderRecommendedLevelFingerprint].
|
||||
*/
|
||||
internal object StoryboardRendererDecoderSpecFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
|
@ -27,7 +27,8 @@ object ShortsPlaybackPatch : BytecodePatch(
|
||||
*/
|
||||
ShortsPlaybackFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getTargetIndex(getWideLiteralInstructionIndex(45387052), Opcode.MOVE_RESULT)
|
||||
val targetIndex =
|
||||
getTargetIndex(getWideLiteralInstructionIndex(45387052), Opcode.MOVE_RESULT)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
|
@ -32,14 +32,18 @@ object SuggestedVideoEndScreenPatch : BytecodePatch(
|
||||
* Automatically closing the suggested video end screen is not appropriate as it will disable the autoplay behavior.
|
||||
*/
|
||||
RemoveOnLayoutChangeListenerFingerprint.resultOrThrow().let {
|
||||
val walkerIndex = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
val walkerIndex =
|
||||
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
|
||||
|
||||
walkerIndex.apply {
|
||||
val invokeInterfaceIndex = getTargetIndex(Opcode.INVOKE_INTERFACE)
|
||||
val iGetObjectIndex = getTargetIndexReversed(invokeInterfaceIndex, Opcode.IGET_OBJECT)
|
||||
val iGetObjectIndex =
|
||||
getTargetIndexReversed(invokeInterfaceIndex, Opcode.IGET_OBJECT)
|
||||
|
||||
val invokeInterfaceReference = getInstruction<ReferenceInstruction>(invokeInterfaceIndex).reference
|
||||
val iGetObjectReference = getInstruction<ReferenceInstruction>(iGetObjectIndex).reference
|
||||
val invokeInterfaceReference =
|
||||
getInstruction<ReferenceInstruction>(invokeInterfaceIndex).reference
|
||||
val iGetObjectReference =
|
||||
getInstruction<ReferenceInstruction>(iGetObjectIndex).reference
|
||||
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
|
@ -15,7 +15,12 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE,
|
||||
mainActivityOnCreateFingerprint = MainActivityFingerprint,
|
||||
integrationsPatchDependency = IntegrationsPatch::class,
|
||||
dependencies = setOf(SpoofClientPatch::class, SpoofUserAgentPatch::class, PackageNamePatch::class, SettingsPatch::class),
|
||||
dependencies = setOf(
|
||||
SpoofClientPatch::class,
|
||||
SpoofUserAgentPatch::class,
|
||||
PackageNamePatch::class,
|
||||
SettingsPatch::class
|
||||
),
|
||||
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
||||
compatiblePackages = COMPATIBLE_PACKAGE
|
||||
)
|
||||
|
@ -20,7 +20,8 @@ object Constants {
|
||||
const val VIDEO_PATH = "$PATCHES_PATH/video"
|
||||
|
||||
const val ADS_CLASS_DESCRIPTOR = "$ADS_PATH/AdsPatch;"
|
||||
const val ALTERNATIVE_THUMBNAILS_CLASS_DESCRIPTOR = "$ALTERNATIVE_THUMBNAILS_PATH/AlternativeThumbnailsPatch;"
|
||||
const val ALTERNATIVE_THUMBNAILS_CLASS_DESCRIPTOR =
|
||||
"$ALTERNATIVE_THUMBNAILS_PATH/AlternativeThumbnailsPatch;"
|
||||
const val FEED_CLASS_DESCRIPTOR = "$FEED_PATH/FeedPatch;"
|
||||
const val GENERAL_CLASS_DESCRIPTOR = "$GENERAL_PATH/GeneralPatch;"
|
||||
const val PLAYER_CLASS_DESCRIPTOR = "$PLAYER_PATH/PlayerPatch;"
|
||||
|
@ -72,14 +72,16 @@ object NavigationBarHookPatch : BytecodePatch(
|
||||
resolve(context, PivotBarConstructorFingerprint.resultOrThrow().classDef)
|
||||
}.resultOrThrow().mutableMethod.apply {
|
||||
// Hook the current navigation bar enum value. Note, the 'You' tab does not have an enum value.
|
||||
val navigationEnumClassName = NavigationEnumFingerprint.resultOrThrow().mutableClass.type
|
||||
val navigationEnumClassName =
|
||||
NavigationEnumFingerprint.resultOrThrow().mutableClass.type
|
||||
addHook(Hook.SET_LAST_APP_NAVIGATION_ENUM) {
|
||||
opcode == Opcode.INVOKE_STATIC &&
|
||||
getReference<MethodReference>()?.definingClass == navigationEnumClassName
|
||||
}
|
||||
|
||||
// Hook the creation of navigation tab views.
|
||||
val drawableTabMethod = PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow().mutableMethod
|
||||
val drawableTabMethod =
|
||||
PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow().mutableMethod
|
||||
addHook(Hook.NAVIGATION_TAB_LOADED) predicate@{
|
||||
MethodUtil.methodSignaturesMatch(
|
||||
getReference<MethodReference>() ?: return@predicate false,
|
||||
@ -87,7 +89,8 @@ object NavigationBarHookPatch : BytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
val imageResourceTabMethod = PivotBarButtonsCreateResourceViewFingerprint.resultOrThrow().method
|
||||
val imageResourceTabMethod =
|
||||
PivotBarButtonsCreateResourceViewFingerprint.resultOrThrow().method
|
||||
addHook(Hook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) predicate@{
|
||||
MethodUtil.methodSignaturesMatch(
|
||||
getReference<MethodReference>() ?: return@predicate false,
|
||||
@ -111,11 +114,15 @@ object NavigationBarHookPatch : BytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
navigationTabCreatedCallback = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
|
||||
method.name == "navigationTabCreatedCallback"
|
||||
} ?: throw PatchException("Could not find navigationTabCreatedCallback method")
|
||||
navigationTabCreatedCallback =
|
||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
|
||||
method.name == "navigationTabCreatedCallback"
|
||||
} ?: throw PatchException("Could not find navigationTabCreatedCallback method")
|
||||
|
||||
MainActivityResolvePatch.injectOnBackPressedMethodCall(INTEGRATIONS_CLASS_DESCRIPTOR, "onBackPressed")
|
||||
MainActivityResolvePatch.injectOnBackPressedMethodCall(
|
||||
INTEGRATIONS_CLASS_DESCRIPTOR,
|
||||
"onBackPressed"
|
||||
)
|
||||
}
|
||||
|
||||
val hookNavigationButtonCreated: (String) -> Unit by lazy {
|
||||
@ -133,7 +140,10 @@ object NavigationBarHookPatch : BytecodePatch(
|
||||
private enum class Hook(val methodName: String, val parameters: String) {
|
||||
SET_LAST_APP_NAVIGATION_ENUM("setLastAppNavigationEnum", "Ljava/lang/Enum;"),
|
||||
NAVIGATION_TAB_LOADED("navigationTabLoaded", "Landroid/view/View;"),
|
||||
NAVIGATION_IMAGE_RESOURCE_TAB_LOADED("navigationImageResourceTabLoaded", "Landroid/view/View;"),
|
||||
NAVIGATION_IMAGE_RESOURCE_TAB_LOADED(
|
||||
"navigationImageResourceTabLoaded",
|
||||
"Landroid/view/View;"
|
||||
),
|
||||
SEARCH_BAR_RESULTS_VIEW_LOADED("searchBarResultsViewLoaded", "Landroid/view/View;"),
|
||||
}
|
||||
}
|
@ -32,7 +32,8 @@ object PlayerControlsVisibilityHookPatch : BytecodePatch(
|
||||
|
||||
it.mutableClass.methods.find { method -> method.name == "<init>" }?.apply {
|
||||
val targetIndex = getTargetIndex(Opcode.IPUT_OBJECT)
|
||||
val targetRegister = getInstruction<TwoRegisterInstruction>(targetIndex).registerA
|
||||
val targetRegister =
|
||||
getInstruction<TwoRegisterInstruction>(targetIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
targetIndex + 1, """
|
||||
|
@ -59,7 +59,8 @@ object PlayerTypeHookPatch : BytecodePatch(
|
||||
// region patch for set video state
|
||||
|
||||
YouTubeControlsOverlayFingerprint.resultOrThrow().let { parentResult ->
|
||||
VideoStateFingerprint.also { it.resolve(context, parentResult.classDef)
|
||||
VideoStateFingerprint.also {
|
||||
it.resolve(context, parentResult.classDef)
|
||||
}.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
@ -84,7 +85,8 @@ object PlayerTypeHookPatch : BytecodePatch(
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getStringInstructionIndex("VL") - 1
|
||||
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference
|
||||
val targetClass = context.findClass((targetReference as FieldReference).definingClass)!!.mutableClass
|
||||
val targetClass =
|
||||
context.findClass((targetReference as FieldReference).definingClass)!!.mutableClass
|
||||
|
||||
targetClass.methods.find { method -> method.name == "<init>" }
|
||||
?.apply {
|
||||
|
@ -175,7 +175,8 @@ object SharedResourceIdPatch : ResourcePatch() {
|
||||
RightComment = getId(DRAWABLE, "ic_right_comment_32c")
|
||||
ScrimOverlay = getId(ID, "scrim_overlay")
|
||||
Scrubbing = getId(DIMEN, "vertical_touch_offset_to_enter_fine_scrubbing")
|
||||
SeekEasyHorizontalTouchOffsetToStartScrubbing = getId(DIMEN, "seek_easy_horizontal_touch_offset_to_start_scrubbing")
|
||||
SeekEasyHorizontalTouchOffsetToStartScrubbing =
|
||||
getId(DIMEN, "seek_easy_horizontal_touch_offset_to_start_scrubbing")
|
||||
SeekUndoEduOverlayStub = getId(ID, "seek_undo_edu_overlay_stub")
|
||||
SingleLoopEduSnackBarText = getId(STRING, "single_loop_edu_snackbar_text")
|
||||
SlidingDialogAnimation = getId(STYLE, "SlidingDialogAnimation")
|
||||
@ -186,9 +187,11 @@ object SharedResourceIdPatch : ResourcePatch() {
|
||||
TotalTime = getId(STRING, "total_time")
|
||||
TouchArea = getId(ID, "touch_area")
|
||||
VideoQualityBottomSheet = getId(LAYOUT, "video_quality_bottom_sheet_list_fragment_title")
|
||||
VideoQualityUnavailableAnnouncement = getId(STRING, "video_quality_unavailable_announcement")
|
||||
VideoQualityUnavailableAnnouncement =
|
||||
getId(STRING, "video_quality_unavailable_announcement")
|
||||
VoiceSearch = getId(ID, "voice_search")
|
||||
YouTubeControlsOverlaySubtitleButton = getId(LAYOUT, "youtube_controls_overlay_subtitle_button")
|
||||
YouTubeControlsOverlaySubtitleButton =
|
||||
getId(LAYOUT, "youtube_controls_overlay_subtitle_button")
|
||||
YtOutlinePiPWhite = getId(DRAWABLE, "yt_outline_picture_in_picture_white_24")
|
||||
YtOutlineVideoCamera = getId(DRAWABLE, "yt_outline_video_camera_black_24")
|
||||
YtOutlineXWhite = getId(DRAWABLE, "yt_outline_x_white_24")
|
||||
|
@ -70,13 +70,17 @@ object ReturnYouTubeDislikePatch : BaseBytecodePatch(
|
||||
|
||||
TextComponentContextFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val conversionContextFieldIndex = getTargetIndexWithFieldReferenceType("Ljava/util/Map;") - 1
|
||||
val conversionContextFieldIndex =
|
||||
getTargetIndexWithFieldReferenceType("Ljava/util/Map;") - 1
|
||||
val conversionContextFieldReference =
|
||||
getInstruction<ReferenceInstruction>(conversionContextFieldIndex).reference
|
||||
|
||||
val charSequenceIndex = getTargetIndexWithFieldReferenceType("Ljava/util/BitSet;") - 1
|
||||
val charSequenceRegister = getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerA
|
||||
val freeRegister = getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerB
|
||||
val charSequenceIndex =
|
||||
getTargetIndexWithFieldReferenceType("Ljava/util/BitSet;") - 1
|
||||
val charSequenceRegister =
|
||||
getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerA
|
||||
val freeRegister =
|
||||
getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerB
|
||||
|
||||
addInstructions(
|
||||
charSequenceIndex - 1, """
|
||||
|
@ -71,7 +71,8 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch(
|
||||
if (SettingsPatch.upward1834) {
|
||||
TextComponentSpecFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = getTargetIndexWithReference("Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;")
|
||||
val insertIndex =
|
||||
getTargetIndexWithReference("Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;")
|
||||
|
||||
val charSequenceRegister =
|
||||
getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||
|
@ -46,11 +46,21 @@ object SettingsBytecodePatch : BytecodePatch(
|
||||
}
|
||||
}
|
||||
|
||||
MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR, "setExtendedUtils")
|
||||
MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR, "onCreate")
|
||||
MainActivityResolvePatch.injectConstructorMethodCall(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR, "setActivity")
|
||||
MainActivityResolvePatch.injectOnCreateMethodCall(
|
||||
INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR,
|
||||
"setExtendedUtils"
|
||||
)
|
||||
MainActivityResolvePatch.injectOnCreateMethodCall(
|
||||
INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR,
|
||||
"onCreate"
|
||||
)
|
||||
MainActivityResolvePatch.injectConstructorMethodCall(
|
||||
INTEGRATIONS_UTILS_CLASS_DESCRIPTOR,
|
||||
"setActivity"
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private fun MutableMethod.injectCall(index: Int) {
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
|
@ -199,9 +199,11 @@ object SettingsPatch : BaseResourcePatch(
|
||||
|
||||
// region set ReVanced Integrations Version
|
||||
|
||||
val buildConfigMutableClass = SettingsBytecodePatch.contexts.findClass { it.sourceFile == "BuildConfig.java" }!!.mutableClass
|
||||
val buildConfigMutableClass =
|
||||
SettingsBytecodePatch.contexts.findClass { it.sourceFile == "BuildConfig.java" }!!.mutableClass
|
||||
val versionNameField = buildConfigMutableClass.fields.single { it.name == "VERSION_NAME" }
|
||||
val versionName = versionNameField.initialValue.toString().trim().replace("\"","").replace(""", "")
|
||||
val versionName =
|
||||
versionNameField.initialValue.toString().trim().replace("\"", "").replace(""", "")
|
||||
|
||||
contexts.updatePatchStatusSettings(
|
||||
"ReVanced Integrations",
|
||||
|
@ -133,7 +133,8 @@ object SponsorBlockBytecodePatch : BytecodePatch(
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout)
|
||||
val checkCastIndex = getTargetIndex(targetIndex, Opcode.CHECK_CAST)
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||
val targetRegister =
|
||||
getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
@ -146,8 +147,12 @@ object SponsorBlockBytecodePatch : BytecodePatch(
|
||||
RectangleFieldInvalidatorFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val invalidateIndex = getTargetIndexWithMethodReferenceNameReversed("invalidate")
|
||||
val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(invalidateIndex + 1, "Landroid/graphics/Rect;")
|
||||
val rectangleFieldName = (getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name
|
||||
val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(
|
||||
invalidateIndex + 1,
|
||||
"Landroid/graphics/Rect;"
|
||||
)
|
||||
val rectangleFieldName =
|
||||
(getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name
|
||||
|
||||
SegmentPlaybackControllerFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
|
@ -25,9 +25,10 @@ object ViewGroupMarginLayoutParamsHookPatch : BytecodePatch(
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
val method = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
|
||||
method.name == "hideViewGroupByMarginLayoutParams"
|
||||
} ?: throw PatchException("Could not find hideViewGroupByMarginLayoutParams method")
|
||||
val method =
|
||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
|
||||
method.name == "hideViewGroupByMarginLayoutParams"
|
||||
} ?: throw PatchException("Could not find hideViewGroupByMarginLayoutParams method")
|
||||
|
||||
SetViewGroupMarginFingerprint.resolve(
|
||||
context,
|
||||
|
@ -92,6 +92,7 @@ object VideoInformationPatch : BytecodePatch(
|
||||
private const val REGISTER_VIDEO_ID = 2
|
||||
private const val REGISTER_VIDEO_TITLE = 3
|
||||
private const val REGISTER_VIDEO_LENGTH = 4
|
||||
|
||||
@Suppress("unused")
|
||||
private const val REGISTER_VIDEO_LENGTH_DUMMY = 5
|
||||
private const val REGISTER_VIDEO_IS_LIVE = 6
|
||||
@ -118,7 +119,8 @@ object VideoInformationPatch : BytecodePatch(
|
||||
internal lateinit var videoEndMethod: MutableMethod
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
val videoInformationMutableClass = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
||||
val videoInformationMutableClass =
|
||||
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
|
||||
|
||||
VideoEndFingerprint.resultOrThrow().let {
|
||||
|
||||
@ -173,7 +175,8 @@ object VideoInformationPatch : BytecodePatch(
|
||||
true
|
||||
)
|
||||
|
||||
videoEndMethod = getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
videoEndMethod =
|
||||
getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex + 1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,11 +267,13 @@ object VideoInformationPatch : BytecodePatch(
|
||||
*/
|
||||
VideoIdPatch.hookVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V")
|
||||
VideoIdPatch.hookPlayerResponseVideoId(
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;Z)V")
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;Z)V"
|
||||
)
|
||||
// Call before any other video id hooks,
|
||||
// so they can use VideoInformation and check if the video id is for a Short.
|
||||
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameterBeforeVideoId(
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->newPlayerResponseParameter(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;")
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->newPlayerResponseParameter(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;"
|
||||
)
|
||||
|
||||
/**
|
||||
* Hook current playback speed
|
||||
@ -278,7 +283,8 @@ object VideoInformationPatch : BytecodePatch(
|
||||
speedSelectionInsertMethod = this
|
||||
val speedSelectionValueInstructionIndex = getTargetIndex(Opcode.IGET)
|
||||
|
||||
val setPlaybackSpeedContainerClassFieldIndex = getTargetIndexReversed(speedSelectionValueInstructionIndex, Opcode.IGET_OBJECT)
|
||||
val setPlaybackSpeedContainerClassFieldIndex =
|
||||
getTargetIndexReversed(speedSelectionValueInstructionIndex, Opcode.IGET_OBJECT)
|
||||
val setPlaybackSpeedContainerClassFieldReference =
|
||||
getInstruction<ReferenceInstruction>(setPlaybackSpeedContainerClassFieldIndex).reference.toString()
|
||||
|
||||
@ -447,7 +453,7 @@ object VideoInformationPatch : BytecodePatch(
|
||||
"invoke-static { p1, p2 }, $targetMethodClass->$targetMethodName(J)V"
|
||||
)
|
||||
|
||||
private fun MethodFingerprint.getMethodName(returnType : String) :String {
|
||||
private fun MethodFingerprint.getMethodName(returnType: String): String {
|
||||
resultOrThrow().mutableMethod.apply {
|
||||
val targetIndex = indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_INTERFACE
|
||||
@ -465,7 +471,13 @@ object VideoInformationPatch : BytecodePatch(
|
||||
ImmutableMethod(
|
||||
definingClass,
|
||||
"setVideoInformation",
|
||||
listOf(ImmutableMethodParameter(PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR, annotations, null)),
|
||||
listOf(
|
||||
ImmutableMethodParameter(
|
||||
PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR,
|
||||
annotations,
|
||||
null
|
||||
)
|
||||
),
|
||||
"V",
|
||||
AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||
annotations,
|
||||
|
@ -9,5 +9,5 @@ internal object VideoTitleFingerprint : LiteralValueFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = emptyList(),
|
||||
literalSupplier = { NotificationBigPictureIconWidth }
|
||||
literalSupplier = { NotificationBigPictureIconWidth }
|
||||
)
|
||||
|
@ -125,7 +125,8 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
||||
QualityChangedFromRecyclerViewFingerprint.resultOrThrow().classDef
|
||||
)
|
||||
|
||||
val newMethod = PlaybackSpeedChangedFromRecyclerViewFingerprint.resultOrThrow().mutableMethod
|
||||
val newMethod =
|
||||
PlaybackSpeedChangedFromRecyclerViewFingerprint.resultOrThrow().mutableMethod
|
||||
|
||||
arrayOf(
|
||||
newMethod,
|
||||
@ -293,7 +294,8 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
||||
ByteBufferArrayFingerprint.also { it.resolve(context, classDef) }.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
val insertRegister =
|
||||
getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex, """
|
||||
|
@ -95,7 +95,8 @@ object PlayerResponseMethodHookPatch :
|
||||
internal class VideoId(methodDescriptor: String) : Hook(methodDescriptor)
|
||||
|
||||
internal class PlayerParameter(methodDescriptor: String) : Hook(methodDescriptor)
|
||||
internal class PlayerParameterBeforeVideoId(methodDescriptor: String) : Hook(methodDescriptor)
|
||||
internal class PlayerParameterBeforeVideoId(methodDescriptor: String) :
|
||||
Hook(methodDescriptor)
|
||||
|
||||
override fun toString() = methodDescriptor
|
||||
}
|
||||
|
@ -32,15 +32,17 @@ object VideoIdPatch : BytecodePatch(
|
||||
*
|
||||
* @param consumer Consumer that receives the method, insert index and video id register index.
|
||||
*/
|
||||
fun MethodFingerprint.setFields(consumer: (MutableMethod, Int, Int) -> Unit) = resultOrThrow().let { result ->
|
||||
val videoIdRegisterIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
fun MethodFingerprint.setFields(consumer: (MutableMethod, Int, Int) -> Unit) =
|
||||
resultOrThrow().let { result ->
|
||||
val videoIdRegisterIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
result.mutableMethod.let {
|
||||
val videoIdRegister = it.getInstruction<OneRegisterInstruction>(videoIdRegisterIndex).registerA
|
||||
val insertIndex = videoIdRegisterIndex + 1
|
||||
consumer(it, insertIndex, videoIdRegister)
|
||||
result.mutableMethod.let {
|
||||
val videoIdRegister =
|
||||
it.getInstruction<OneRegisterInstruction>(videoIdRegisterIndex).registerA
|
||||
val insertIndex = videoIdRegisterIndex + 1
|
||||
consumer(it, insertIndex, videoIdRegister)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VideoIdFingerprint.resolve(context, VideoIdParentFingerprint.resultOrThrow().classDef)
|
||||
|
||||
|
@ -181,7 +181,8 @@ fun BytecodeContext.literalInstructionHook(
|
||||
.mutableClass
|
||||
.findMutableMethodOf(method).apply {
|
||||
val index = getWideLiteralInstructionIndex(literal)
|
||||
val register = (instruction as OneRegisterInstruction).registerA.toString()
|
||||
val register =
|
||||
(instruction as OneRegisterInstruction).registerA.toString()
|
||||
|
||||
addInstructions(
|
||||
index + 1,
|
||||
@ -205,8 +206,7 @@ fun Method.getWideLiteralInstructionIndex(literal: Long) = implementation?.let {
|
||||
}
|
||||
} ?: -1
|
||||
|
||||
fun Method.getEmptyStringInstructionIndex()
|
||||
= getStringInstructionIndex("")
|
||||
fun Method.getEmptyStringInstructionIndex() = getStringInstructionIndex("")
|
||||
|
||||
fun Method.getStringInstructionIndex(value: String) = implementation?.let {
|
||||
it.instructions.indexOfFirst { instruction ->
|
||||
@ -300,8 +300,8 @@ fun Method.getTargetIndexWithFieldReferenceName(filedName: String) = implementat
|
||||
}
|
||||
} ?: -1
|
||||
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed(returnType: String)
|
||||
= getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType)
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed(returnType: String) =
|
||||
getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType)
|
||||
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceName(startIndex: Int, filedName: String) =
|
||||
implementation!!.instructions.let {
|
||||
@ -310,7 +310,10 @@ fun MutableMethod.getTargetIndexWithFieldReferenceName(startIndex: Int, filedNam
|
||||
}
|
||||
}
|
||||
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed(startIndex: Int, filedName: String): Int {
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed(
|
||||
startIndex: Int,
|
||||
filedName: String
|
||||
): Int {
|
||||
for (index in startIndex downTo 0) {
|
||||
val instruction = getInstruction(index)
|
||||
if (instruction.getReference<FieldReference>()?.name != filedName)
|
||||
@ -327,8 +330,8 @@ fun Method.getTargetIndexWithFieldReferenceType(returnType: String) = implementa
|
||||
}
|
||||
} ?: -1
|
||||
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed(returnType: String)
|
||||
= getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType)
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed(returnType: String) =
|
||||
getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType)
|
||||
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceType(startIndex: Int, returnType: String) =
|
||||
implementation!!.instructions.let {
|
||||
@ -337,7 +340,10 @@ fun MutableMethod.getTargetIndexWithFieldReferenceType(startIndex: Int, returnTy
|
||||
}
|
||||
}
|
||||
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed(startIndex: Int, returnType: String): Int {
|
||||
fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed(
|
||||
startIndex: Int,
|
||||
returnType: String
|
||||
): Int {
|
||||
for (index in startIndex downTo 0) {
|
||||
val instruction = getInstruction(index)
|
||||
if (instruction.getReference<FieldReference>()?.type != returnType)
|
||||
@ -354,8 +360,11 @@ fun Method.getTargetIndexWithMethodReferenceName(methodName: String) = implement
|
||||
}
|
||||
} ?: -1
|
||||
|
||||
fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(methodName: String)
|
||||
= getTargetIndexWithMethodReferenceNameReversed(implementation!!.instructions.size - 1, methodName)
|
||||
fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(methodName: String) =
|
||||
getTargetIndexWithMethodReferenceNameReversed(
|
||||
implementation!!.instructions.size - 1,
|
||||
methodName
|
||||
)
|
||||
|
||||
|
||||
fun MutableMethod.getTargetIndexWithMethodReferenceName(startIndex: Int, methodName: String) =
|
||||
@ -365,7 +374,10 @@ fun MutableMethod.getTargetIndexWithMethodReferenceName(startIndex: Int, methodN
|
||||
}
|
||||
}
|
||||
|
||||
fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(startIndex: Int, methodName: String): Int {
|
||||
fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(
|
||||
startIndex: Int,
|
||||
methodName: String
|
||||
): Int {
|
||||
for (index in startIndex downTo 0) {
|
||||
val instruction = getInstruction(index)
|
||||
if (instruction.getReference<MethodReference>()?.name != methodName)
|
||||
@ -494,11 +506,13 @@ fun List<MethodFingerprint>.returnEarly(bool: Boolean = false) {
|
||||
const/4 v0, $const
|
||||
return-object v0
|
||||
"""
|
||||
|
||||
'V' -> "return-void"
|
||||
'I', 'Z' -> """
|
||||
const/4 v0, $const
|
||||
return v0
|
||||
"""
|
||||
|
||||
else -> throw Exception("This case should never happen.")
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user