chore: lint code

This commit is contained in:
inotia00 2024-06-07 21:44:22 +09:00
parent e374fa306b
commit ecd6fbdf5b
95 changed files with 804 additions and 405 deletions

View File

@ -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) }
}

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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 }
)

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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)
}

View File

@ -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(

View File

@ -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(

View File

@ -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

View File

@ -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
)

View File

@ -13,6 +13,7 @@ object PlayerTypeHookPatch : BytecodePatch(
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"$UTILS_PATH/PlayerTypeHookPatch;"
override fun execute(context: BytecodeContext) {
PlayerTypeFingerprint.resultOrThrow().let {

View File

@ -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, """

View File

@ -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")

View File

@ -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"
)
}
}

View File

@ -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")

View File

@ -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 =

View File

@ -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
}
}
}

View File

@ -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 {

View File

@ -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",

View File

@ -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)
}

View File

@ -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

View File

@ -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)

View File

@ -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(

View File

@ -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"
}
}
}
}

View File

@ -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.

View File

@ -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())
}

View File

@ -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
)

View File

@ -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 }
)

View File

@ -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)
}

View File

@ -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")
)

View File

@ -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("@#&=*+-_.,:!?()/~'%;\$"),
)

View File

@ -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;"

View File

@ -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",

View File

@ -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"
}

View File

@ -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)

View File

@ -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"
)
}
}

View File

@ -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(

View File

@ -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"
)
}
/**

View File

@ -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

View File

@ -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 {

View File

@ -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))

View File

@ -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,

View File

@ -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(

View File

@ -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

View File

@ -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,

View File

@ -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
}

View File

@ -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,

View File

@ -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, """

View File

@ -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,

View File

@ -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,

View File

@ -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(

View File

@ -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

View File

@ -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(

View File

@ -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 =
"""

View File

@ -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)
)
}
}

View File

@ -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: ")
)

View File

@ -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

View File

@ -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, """

View File

@ -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

View File

@ -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,

View File

@ -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
"""
)
}
}
}
}
}
}

View File

@ -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,

View File

@ -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
}
) {

View File

@ -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)

View File

@ -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

View File

@ -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(

View File

@ -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
"""
)
}
)
}
}
}

View File

@ -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

View File

@ -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")
}
}
}

View File

@ -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,

View File

@ -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,

View File

@ -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(

View File

@ -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,

View File

@ -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
)

View File

@ -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;"

View File

@ -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;"),
}
}

View File

@ -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, """

View File

@ -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 {

View File

@ -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")

View File

@ -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, """

View File

@ -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

View File

@ -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

View File

@ -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("&quot;", "")
val versionName =
versionNameField.initialValue.toString().trim().replace("\"", "").replace("&quot;", "")
contexts.updatePatchStatusSettings(
"ReVanced Integrations",

View File

@ -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 {

View File

@ -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,

View File

@ -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,

View File

@ -9,5 +9,5 @@ internal object VideoTitleFingerprint : LiteralValueFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
literalSupplier = { NotificationBigPictureIconWidth }
literalSupplier = { NotificationBigPictureIconWidth }
)

View File

@ -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, """

View File

@ -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
}

View File

@ -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)

View File

@ -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.")
}