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 -> ).also { loader ->
if (loader.isEmpty()) throw IllegalStateException("No patches found") if (loader.isEmpty()) throw IllegalStateException("No patches found")
}.let { bundle -> }.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() val output = StringBuilder()
// create a temp file // 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 // copy the contents of 'README-template.md' to the temp file
StringBuilder(readMeTemplateFile.readText()) 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.reddit.utils.compatibility.Constants.COMPATIBLE_PACKAGE to "\"COMPATIBLE_PACKAGE_REDDIT\"",
app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE to "\"COMPATIBLE_PACKAGE_YOUTUBE\"" app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE to "\"COMPATIBLE_PACKAGE_YOUTUBE\""
).forEach { (compatiblePackage, replaceString) -> ).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 -> .forEach { compatiblePackages ->
val pkgName = compatiblePackages.name val pkgName = compatiblePackages.name
val supportedVersion = if (compatiblePackages.versions == null && exception.containsKey(pkgName)) { val supportedVersion =
exception[pkgName] + "+" if (compatiblePackages.versions == null && exception.containsKey(pkgName)) {
} else { exception[pkgName] + "+"
compatiblePackages.versions } else {
?.toString() compatiblePackages.versions
?.replace("[", "[\n \"") ?.toString()
?.replace("]", "\"\n ]") ?.replace("[", "[\n \"")
?.replace(", ", "\",\n \"") ?.replace("]", "\"\n ]")
?: "\"ALL\"" ?.replace(", ", "\",\n \"")
} ?: "\"ALL\""
}
StringBuilder(readMeTemplateTempFile.readText()) StringBuilder(readMeTemplateTempFile.readText())
.replace(Regex(replaceString), supportedVersion) .replace(Regex(replaceString), supportedVersion)

View File

@ -65,8 +65,10 @@ object AccountComponentsPatch : BaseBytecodePatch(
result.mutableMethod.apply { result.mutableMethod.apply {
val textColorIndex = getTargetIndexWithMethodReferenceName("setTextColor") val textColorIndex = getTargetIndexWithMethodReferenceName("setTextColor")
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(textColorIndex, "setVisibility") val setVisibilityIndex =
val textViewInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex) getTargetIndexWithMethodReferenceName(textColorIndex, "setVisibility")
val textViewInstruction =
getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
replaceInstruction( replaceInstruction(
setVisibilityIndex, setVisibilityIndex,
@ -96,7 +98,8 @@ object AccountComponentsPatch : BaseBytecodePatch(
TermsOfServiceFingerprint.resultOrThrow().let { TermsOfServiceFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = getTargetIndexWithReference("/PrivacyTosFooter;->setVisibility(I)V") val insertIndex =
getTargetIndexWithReference("/PrivacyTosFooter;->setVisibility(I)V")
val visibilityRegister = val visibilityRegister =
getInstruction<FiveRegisterInstruction>(insertIndex).registerD getInstruction<FiveRegisterInstruction>(insertIndex).registerD

View File

@ -49,7 +49,8 @@ object ActionBarComponentsPatch : BaseBytecodePatch(
// hook download button // hook download button
val addViewIndex = getTargetIndexWithMethodReferenceName("addView") val addViewIndex = getTargetIndexWithMethodReferenceName("addView")
val addViewRegister = getInstruction<FiveRegisterInstruction>(addViewIndex).registerD val addViewRegister =
getInstruction<FiveRegisterInstruction>(addViewIndex).registerD
addInstruction( addInstruction(
addViewIndex + 1, addViewIndex + 1,
@ -86,7 +87,8 @@ object ActionBarComponentsPatch : BaseBytecodePatch(
val freeRegister = min(implementation!!.registerCount - parameters.size - 2, 15) val freeRegister = min(implementation!!.registerCount - parameters.size - 2, 15)
val spannedIndex = getTargetIndexWithReference(")Landroid/text/Spanned;") val spannedIndex = getTargetIndexWithReference(")Landroid/text/Spanned;")
val spannedRegister = getInstruction<FiveRegisterInstruction>(spannedIndex).registerC val spannedRegister =
getInstruction<FiveRegisterInstruction>(spannedIndex).registerC
val spannedReference = getInstruction<ReferenceInstruction>(spannedIndex).reference val spannedReference = getInstruction<ReferenceInstruction>(spannedIndex).reference
addInstructionsWithLabels( addInstructionsWithLabels(
@ -101,10 +103,12 @@ object ActionBarComponentsPatch : BaseBytecodePatch(
// set action button identifier // set action button identifier
val buttonTypeDownloadIndex = it.scanResult.patternScanResult!!.startIndex + 1 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 buttonTypeIndex = it.scanResult.patternScanResult!!.endIndex - 1
val buttonTypeRegister = getInstruction<OneRegisterInstruction>(buttonTypeIndex).registerA val buttonTypeRegister =
getInstruction<OneRegisterInstruction>(buttonTypeIndex).registerA
addInstruction( addInstruction(
buttonTypeIndex + 2, buttonTypeIndex + 2,

View File

@ -191,16 +191,19 @@ object AdsPatch : BaseBytecodePatch(
// get premium button at the bottom of the account switching menu // get premium button at the bottom of the account switching menu
AccountMenuFooterFingerprint.resultOrThrow().let { AccountMenuFooterFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.PrivacyTosFooter) val constIndex =
getWideLiteralInstructionIndex(SharedResourceIdPatch.PrivacyTosFooter)
val walkerIndex = getTargetIndex(constIndex + 2, Opcode.INVOKE_VIRTUAL) val walkerIndex = getTargetIndex(constIndex + 2, Opcode.INVOKE_VIRTUAL)
val viewIndex = getTargetIndex(constIndex, Opcode.IGET_OBJECT) 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) val walkerMethod = getWalkerMethod(context, walkerIndex)
walkerMethod.apply { walkerMethod.apply {
val insertIndex = getTargetIndexWithReference(viewReference) val insertIndex = getTargetIndexWithReference(viewReference)
val nullCheckIndex = getTargetIndex(insertIndex - 1, Opcode.IF_NEZ) val nullCheckIndex = getTargetIndex(insertIndex - 1, Opcode.IF_NEZ)
val nullCheckRegister = getInstruction<OneRegisterInstruction>(nullCheckIndex).registerA val nullCheckRegister =
getInstruction<OneRegisterInstruction>(nullCheckIndex).registerA
addInstruction( addInstruction(
nullCheckIndex, nullCheckIndex,

View File

@ -5,6 +5,6 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object InterstitialsContainerFingerprint : LiteralValueFingerprint( internal object InterstitialsContainerFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
strings= listOf("overlay_controller_param"), strings = listOf("overlay_controller_param"),
literalSupplier = { InterstitialsContainer } literalSupplier = { InterstitialsContainer }
) )

View File

@ -73,7 +73,8 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
// region patch for enable compact dialog // region patch for enable compact dialog
DialogSolidFingerprint.resultOrThrow().let { DialogSolidFingerprint.resultOrThrow().let {
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex) val walkerMethod =
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
walkerMethod.addInstructions( walkerMethod.addInstructions(
2, """ 2, """
invoke-static {p0}, $FLYOUT_CLASS_DESCRIPTOR->enableCompactDialog(I)I invoke-static {p0}, $FLYOUT_CLASS_DESCRIPTOR->enableCompactDialog(I)I
@ -94,17 +95,22 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
TrimSilenceSwitchFingerprint.resultOrThrow().let { TrimSilenceSwitchFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.TrimSilenceSwitch) val constIndex =
val onCheckedChangedListenerIndex = getTargetIndex(constIndex, Opcode.INVOKE_DIRECT) getWideLiteralInstructionIndex(SharedResourceIdPatch.TrimSilenceSwitch)
val onCheckedChangedListenerReference = getInstruction<ReferenceInstruction>(onCheckedChangedListenerIndex).reference val onCheckedChangedListenerIndex =
val onCheckedChangedListenerDefiningClass = (onCheckedChangedListenerReference as MethodReference).definingClass getTargetIndex(constIndex, Opcode.INVOKE_DIRECT)
val onCheckedChangedListenerReference =
getInstruction<ReferenceInstruction>(onCheckedChangedListenerIndex).reference
val onCheckedChangedListenerDefiningClass =
(onCheckedChangedListenerReference as MethodReference).definingClass
val onCheckedChangedListenerClass = val onCheckedChangedListenerClass =
context.findClass(onCheckedChangedListenerDefiningClass)!!.mutableClass context.findClass(onCheckedChangedListenerDefiningClass)!!.mutableClass
onCheckedChangedListenerClass.methods.find { method -> method.name == "onCheckedChanged" } onCheckedChangedListenerClass.methods.find { method -> method.name == "onCheckedChanged" }
?.apply { ?.apply {
val walkerIndex = indexOfFirstInstruction { val walkerIndex = indexOfFirstInstruction {
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference) val reference =
((this as? ReferenceInstruction)?.reference as? MethodReference)
opcode == Opcode.INVOKE_VIRTUAL opcode == Opcode.INVOKE_VIRTUAL
&& reference?.returnType == "V" && reference?.returnType == "V"
@ -113,7 +119,8 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
} }
getWalkerMethod(context, walkerIndex).apply { getWalkerMethod(context, walkerIndex).apply {
val insertIndex = getTargetIndex(Opcode.MOVE_RESULT) val insertIndex = getTargetIndex(Opcode.MOVE_RESULT)
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(
insertIndex + 1, """ insertIndex + 1, """
@ -148,25 +155,30 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch(
val enumIndex = indexOfFirstInstruction { val enumIndex = indexOfFirstInstruction {
opcode == Opcode.INVOKE_STATIC opcode == Opcode.INVOKE_STATIC
&& (this as? ReferenceInstruction)?.reference.toString().contains("(I)L") && (this as? ReferenceInstruction)?.reference.toString()
.contains("(I)L")
} + 1 } + 1
val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA val enumRegister = getInstruction<OneRegisterInstruction>(enumIndex).registerA
addInstructionsWithLabels( 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, 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 invoke-static {v$enumRegister}, $FLYOUT_CLASS_DESCRIPTOR->hideComponents(Ljava/lang/Enum;)Z
move-result v$freeRegister move-result v$freeRegister
if-nez v$freeRegister, :hide if-nez v$freeRegister, :hide
""", ExternalLabel("hide", getInstruction(implementation!!.instructions.size - 1)) """,
ExternalLabel("hide", getInstruction(implementation!!.instructions.size - 1))
) )
} }
} }
TouchOutsideFingerprint.resultOrThrow().let { TouchOutsideFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName("setOnClickListener") val setOnClickListenerIndex =
val setOnClickListenerRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC getTargetIndexWithMethodReferenceName("setOnClickListener")
val setOnClickListenerRegister =
getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
addInstruction( addInstruction(
setOnClickListenerIndex + 1, setOnClickListenerIndex + 1,

View File

@ -106,7 +106,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
// hide floating cast banner // hide floating cast banner
PlayerOverlayChipFingerprint.resultOrThrow().let { PlayerOverlayChipFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val targetIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.PlayerOverlayChip) + 2 val targetIndex =
getWideLiteralInstructionIndex(SharedResourceIdPatch.PlayerOverlayChip) + 2
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction( addInstruction(
@ -164,7 +165,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
fingerprint.resultOrThrow().let { fingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.startIndex val insertIndex = it.scanResult.patternScanResult!!.startIndex
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerD val insertRegister =
getInstruction<FiveRegisterInstruction>(insertIndex).registerD
addInstructions( addInstructions(
insertIndex, """ insertIndex, """
@ -232,7 +234,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
TasteBuilderSyntheticFingerprint.resolve(context, parentResult.classDef) TasteBuilderSyntheticFingerprint.resolve(context, parentResult.classDef)
parentResult.mutableMethod.apply { parentResult.mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.MusicTasteBuilderShelf) val constIndex =
getWideLiteralInstructionIndex(SharedResourceIdPatch.MusicTasteBuilderShelf)
val targetIndex = getTargetIndex(constIndex, Opcode.MOVE_RESULT_OBJECT) val targetIndex = getTargetIndex(constIndex, Opcode.MOVE_RESULT_OBJECT)
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
@ -281,7 +284,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
SearchBarFingerprint.resultOrThrow().let { SearchBarFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val setVisibilityIndex = getTargetIndexWithMethodReferenceName("setVisibility") val setVisibilityIndex = getTargetIndexWithMethodReferenceName("setVisibility")
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex) val setVisibilityInstruction =
getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
replaceInstruction( replaceInstruction(
setVisibilityIndex, 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.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR
import app.revanced.patches.shared.dialog.BaseViewerDiscretionDialogPatch 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 { onClickMethod.apply {
val onClickIndex = indexOfFirstInstruction { val onClickIndex = indexOfFirstInstruction {
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference) val reference =
((this as? ReferenceInstruction)?.reference as? MethodReference)
opcode == Opcode.INVOKE_INTERFACE opcode == Opcode.INVOKE_INTERFACE
&& reference?.returnType == "V" && reference?.returnType == "V"
&& reference.parameterTypes.size == 1 && reference.parameterTypes.size == 1
} }
onClickReference = getInstruction<ReferenceInstruction>(onClickIndex).reference onClickReference =
getInstruction<ReferenceInstruction>(onClickIndex).reference
injectCall(onClickIndex) injectCall(onClickIndex)
} }

View File

@ -59,7 +59,7 @@ object CustomBrandingIconPatch : BaseResourcePatch(
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext) {
AppIcon?.let { appIcon -> AppIcon?.let { appIcon ->
val appIconValue = appIcon.lowercase().replace(" ","_") val appIconValue = appIcon.lowercase().replace(" ", "_")
if (!availableIcon.containsValue(appIconValue)) { if (!availableIcon.containsValue(appIconValue)) {
mipmapDirectories.map { directory -> mipmapDirectories.map { directory ->
ResourceGroup( ResourceGroup(

View File

@ -136,8 +136,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
val invokeVirtualIndex = getTargetIndex(relativeIndex, Opcode.INVOKE_VIRTUAL) val invokeVirtualIndex = getTargetIndex(relativeIndex, Opcode.INVOKE_VIRTUAL)
val iGetIndex = getTargetIndex(relativeIndex, Opcode.IGET) val iGetIndex = getTargetIndex(relativeIndex, Opcode.IGET)
colorMathPlayerInvokeVirtualReference = getInstruction<ReferenceInstruction>(invokeVirtualIndex).reference colorMathPlayerInvokeVirtualReference =
colorMathPlayerIGetReference = getInstruction<ReferenceInstruction>(iGetIndex).reference getInstruction<ReferenceInstruction>(invokeVirtualIndex).reference
colorMathPlayerIGetReference =
getInstruction<ReferenceInstruction>(iGetIndex).reference
// black player background // black player background
val invokeDirectIndex = getTargetIndex(Opcode.INVOKE_DIRECT) val invokeDirectIndex = getTargetIndex(Opcode.INVOKE_DIRECT)
@ -161,7 +163,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
val colorGreyIndex = getWideLiteralInstructionIndex(ColorGrey) val colorGreyIndex = getWideLiteralInstructionIndex(ColorGrey)
val iPutIndex = getTargetIndex(colorGreyIndex, Opcode.IPUT) val iPutIndex = getTargetIndex(colorGreyIndex, Opcode.IPUT)
colorMathPlayerIPutReference = getInstruction<ReferenceInstruction>(iPutIndex).reference colorMathPlayerIPutReference =
getInstruction<ReferenceInstruction>(iPutIndex).reference
} }
parentResult.mutableClass.methods.filter { method -> parentResult.mutableClass.methods.filter { method ->
@ -172,8 +175,12 @@ object PlayerComponentsPatch : BaseBytecodePatch(
mutableMethod.apply { mutableMethod.apply {
val freeRegister = implementation!!.registerCount - parameters.size - 3 val freeRegister = implementation!!.registerCount - parameters.size - 3
val invokeDirectIndex = getTargetIndexReversed(implementation!!.instructions.size - 1, Opcode.INVOKE_DIRECT) val invokeDirectIndex = getTargetIndexReversed(
val invokeDirectReference = getInstruction<ReferenceInstruction>(invokeDirectIndex).reference implementation!!.instructions.size - 1,
Opcode.INVOKE_DIRECT
)
val invokeDirectReference =
getInstruction<ReferenceInstruction>(invokeDirectIndex).reference
addInstructionsWithLabels( addInstructionsWithLabels(
invokeDirectIndex + 1, """ invokeDirectIndex + 1, """
@ -275,14 +282,30 @@ object PlayerComponentsPatch : BaseBytecodePatch(
} }
} }
} else { } else {
miniPlayerConstructorMutableMethod.setInstanceFieldValue(NEXT_BUTTON_METHOD_NAME, TopStart) miniPlayerConstructorMutableMethod.setInstanceFieldValue(
NEXT_BUTTON_METHOD_NAME,
TopStart
)
mppWatchWhileLayoutMutableMethod.setStaticFieldValue(NEXT_BUTTON_FIELD_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) 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() mppWatchWhileLayoutMutableMethod.setViewArray()
@ -327,7 +350,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
SwipeToCloseFingerprint.resultOrThrow().let { SwipeToCloseFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = implementation!!.instructions.size - 1 val insertIndex = implementation!!.instructions.size - 1
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val targetRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(
insertIndex, """ insertIndex, """
@ -343,10 +367,12 @@ object PlayerComponentsPatch : BaseBytecodePatch(
InteractionLoggingEnumFingerprint.resultOrThrow().let { InteractionLoggingEnumFingerprint.resultOrThrow().let {
it.mutableMethod.apply { 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) 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 { it.mutableMethod.apply {
swipeToDismissWidgetIndex = getWideLiteralInstructionIndex(79500) swipeToDismissWidgetIndex = getWideLiteralInstructionIndex(79500)
swipeToDismissIGetObjectReference = getSwipeToDismissReference(Opcode.IGET_OBJECT, true) swipeToDismissIGetObjectReference =
swipeToDismissInvokeInterfacePrimaryReference = getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, true) getSwipeToDismissReference(Opcode.IGET_OBJECT, true)
swipeToDismissCheckCastReference = getSwipeToDismissReference(Opcode.CHECK_CAST, true) swipeToDismissInvokeInterfacePrimaryReference =
swipeToDismissNewInstanceReference = getSwipeToDismissReference(Opcode.NEW_INSTANCE, true) getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, true)
swipeToDismissInvokeStaticReference = getSwipeToDismissReference(Opcode.INVOKE_STATIC, false) swipeToDismissCheckCastReference =
swipeToDismissInvokeDirectReference = getSwipeToDismissReference(Opcode.INVOKE_DIRECT, false) getSwipeToDismissReference(Opcode.CHECK_CAST, true)
swipeToDismissInvokeInterfaceSecondaryReference = getSwipeToDismissReference(Opcode.INVOKE_INTERFACE, false) 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.resolve(context, parentResult.classDef)
HandleSignInEventFingerprint.resultOrThrow().let { HandleSignInEventFingerprint.resultOrThrow().let {
val dismissBehaviorMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex) val dismissBehaviorMethod =
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex)
dismissBehaviorMethod.apply { dismissBehaviorMethod.apply {
val insertIndex = getTargetIndexWithFieldReferenceType("Ljava/util/concurrent/atomic/AtomicBoolean;") val insertIndex =
val primaryRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerB getTargetIndexWithFieldReferenceType("Ljava/util/concurrent/atomic/AtomicBoolean;")
val primaryRegister =
getInstruction<TwoRegisterInstruction>(insertIndex).registerB
val secondaryRegister = primaryRegister + 1 val secondaryRegister = primaryRegister + 1
val tertiaryRegister = secondaryRegister + 1 val tertiaryRegister = secondaryRegister + 1
@ -410,7 +446,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
MiniPlayerDefaultTextFingerprint.resultOrThrow().let { MiniPlayerDefaultTextFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.endIndex val insertIndex = it.scanResult.patternScanResult!!.endIndex
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerB val insertRegister =
getInstruction<TwoRegisterInstruction>(insertIndex).registerB
addInstructions( addInstructions(
insertIndex, """ insertIndex, """
@ -429,22 +466,26 @@ object PlayerComponentsPatch : BaseBytecodePatch(
it.mutableClass.methods.find { method -> it.mutableClass.methods.find { method ->
method.parameters == listOf("Landroid/view/View;", "I") method.parameters == listOf("Landroid/view/View;", "I")
}?.apply { }?.apply {
val bottomSheetBehaviorIndex = implementation!!.instructions.indexOfFirst { instruction -> val bottomSheetBehaviorIndex =
instruction.opcode == Opcode.INVOKE_VIRTUAL implementation!!.instructions.indexOfFirst { instruction ->
&& instruction.getReference<MethodReference>()?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;" instruction.opcode == Opcode.INVOKE_VIRTUAL
&& instruction.getReference<MethodReference>()?.parameterTypes?.first() == "Z" && instruction.getReference<MethodReference>()?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;"
} && instruction.getReference<MethodReference>()?.parameterTypes?.first() == "Z"
}
if (bottomSheetBehaviorIndex < 0) if (bottomSheetBehaviorIndex < 0)
throw PatchException("Could not find bottomSheetBehaviorIndex") throw PatchException("Could not find bottomSheetBehaviorIndex")
val freeRegister = getInstruction<FiveRegisterInstruction>(bottomSheetBehaviorIndex).registerD val freeRegister =
getInstruction<FiveRegisterInstruction>(bottomSheetBehaviorIndex).registerD
addInstructionsWithLabels( addInstructionsWithLabels(
bottomSheetBehaviorIndex - 2, """ bottomSheetBehaviorIndex - 2,
"""
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSwipeToDismissMiniPlayer()Z invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSwipeToDismissMiniPlayer()Z
move-result v$freeRegister move-result v$freeRegister
if-nez v$freeRegister, :dismiss if-nez v$freeRegister, :dismiss
""", ExternalLabel("dismiss", getInstruction(bottomSheetBehaviorIndex + 1)) """,
ExternalLabel("dismiss", getInstruction(bottomSheetBehaviorIndex + 1))
) )
} ?: throw PatchException("Could not find targetMethod") } ?: throw PatchException("Could not find targetMethod")
@ -473,7 +514,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
ZenModeFingerprint.result?.let { ZenModeFingerprint.result?.let {
it.mutableMethod.apply { it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex 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 val insertIndex = it.scanResult.patternScanResult!!.endIndex + 1
@ -616,13 +658,16 @@ object PlayerComponentsPatch : BaseBytecodePatch(
val startIndex = it.scanResult.patternScanResult!!.startIndex val startIndex = it.scanResult.patternScanResult!!.startIndex
val endIndex = it.scanResult.patternScanResult!!.endIndex 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 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 shuffleReference3 = getInstruction<ReferenceInstruction>(endIndex).reference
val shuffleFieldReference = shuffleReference3 as FieldReference val shuffleFieldReference = shuffleReference3 as FieldReference
rememberShuffleStateImageViewReference = getInstruction<ReferenceInstruction>(imageViewIndex).reference rememberShuffleStateImageViewReference =
getInstruction<ReferenceInstruction>(imageViewIndex).reference
rememberShuffleStateShuffleStateLabel = """ rememberShuffleStateShuffleStateLabel = """
iget-object v1, v0, $shuffleReference1 iget-object v1, v0, $shuffleReference1
@ -783,10 +828,14 @@ object PlayerComponentsPatch : BaseBytecodePatch(
methodName: String, methodName: String,
viewId: Long viewId: Long
) { ) {
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) val miniPlayerPlayPauseReplayButtonIndex =
val miniPlayerPlayPauseReplayButtonRegister = getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
val findViewByIdIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL) val miniPlayerPlayPauseReplayButtonRegister =
val parentViewRegister = getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA
val findViewByIdIndex =
getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL)
val parentViewRegister =
getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC
addInstructions( addInstructions(
miniPlayerPlayPauseReplayButtonIndex, """ miniPlayerPlayPauseReplayButtonIndex, """
@ -802,10 +851,14 @@ object PlayerComponentsPatch : BaseBytecodePatch(
fieldName: String, fieldName: String,
viewId: Long viewId: Long
) { ) {
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) val miniPlayerPlayPauseReplayButtonIndex =
val constRegister = getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
val findViewByIdIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL) val constRegister =
val findViewByIdRegister = getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC getInstruction<OneRegisterInstruction>(miniPlayerPlayPauseReplayButtonIndex).registerA
val findViewByIdIndex =
getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL)
val findViewByIdRegister =
getInstruction<FiveRegisterInstruction>(findViewByIdIndex).registerC
addInstructions( addInstructions(
miniPlayerPlayPauseReplayButtonIndex, """ miniPlayerPlayPauseReplayButtonIndex, """
@ -818,8 +871,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
} }
private fun MutableMethod.setViewArray() { private fun MutableMethod.setViewArray() {
val miniPlayerPlayPauseReplayButtonIndex = getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) val miniPlayerPlayPauseReplayButtonIndex =
val invokeStaticIndex = getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_STATIC) getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton)
val invokeStaticIndex =
getTargetIndex(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_STATIC)
val viewArrayRegister = getInstruction<FiveRegisterInstruction>(invokeStaticIndex).registerC val viewArrayRegister = getInstruction<FiveRegisterInstruction>(invokeStaticIndex).registerC
addInstructions( addInstructions(

View File

@ -22,17 +22,20 @@ object AccessibilityNodeInfoPatch : BytecodePatch(
it.mutableMethod.apply { it.mutableMethod.apply {
// Target instruction is invoke-static, but can also be invoke-virtual. // Target instruction is invoke-static, but can also be invoke-virtual.
// Therefore, the opcode is not checked. // Therefore, the opcode is not checked.
val touchExplorationHoverEventMethodIndex = implementation!!.instructions.indexOfFirst { instruction -> val touchExplorationHoverEventMethodIndex =
val reference = ((instruction as? ReferenceInstruction)?.reference as? MethodReference) implementation!!.instructions.indexOfFirst { instruction ->
((instruction as? ReferenceInstruction)?.reference as? MethodReference)?.definingClass == definingClass val reference =
&& reference?.returnType == "Z" ((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 // Doesn't raise an exception, even if the target instruction is not found in this method
val touchExplorationHoverEventMethodName = if (touchExplorationHoverEventMethodIndex > -1) val touchExplorationHoverEventMethodName =
(getInstruction<ReferenceInstruction>(touchExplorationHoverEventMethodIndex).reference as MethodReference).name if (touchExplorationHoverEventMethodIndex > -1)
else (getInstruction<ReferenceInstruction>(touchExplorationHoverEventMethodIndex).reference as MethodReference).name
"UNDEFINED" else
"UNDEFINED"
val methods = it.mutableClass.methods val methods = it.mutableClass.methods

View File

@ -14,7 +14,11 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE, fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE,
mainActivityOnCreateFingerprint = MainActivityFingerprint, mainActivityOnCreateFingerprint = MainActivityFingerprint,
integrationsPatchDependency = IntegrationsPatch::class, integrationsPatchDependency = IntegrationsPatch::class,
dependencies = setOf(SpoofUserAgentPatch::class, PackageNamePatch::class, FileProviderPatch::class), dependencies = setOf(
SpoofUserAgentPatch::class,
PackageNamePatch::class,
FileProviderPatch::class
),
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch, gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
compatiblePackages = COMPATIBLE_PACKAGE compatiblePackages = COMPATIBLE_PACKAGE
) )

View File

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

View File

@ -55,9 +55,11 @@ object ReturnYouTubeDislikeBytecodePatch : BytecodePatch(
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = indexOfFirstInstruction { val insertIndex = indexOfFirstInstruction {
opcode == Opcode.INVOKE_STATIC opcode == Opcode.INVOKE_STATIC
&& (this as ReferenceInstruction).reference.toString().endsWith("Ljava/lang/CharSequence;") && (this as ReferenceInstruction).reference.toString()
.endsWith("Ljava/lang/CharSequence;")
} + 2 } + 2
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
addInstructions( addInstructions(
insertIndex, """ insertIndex, """

View File

@ -39,7 +39,10 @@ object ResourceUtils {
private fun ResourceContext.replacePackageName() { private fun ResourceContext.replacePackageName() {
this[SETTINGS_HEADER_PATH].writeText( this[SETTINGS_HEADER_PATH].writeText(
this[SETTINGS_HEADER_PATH].readText() 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 { .forEach {
if (!isIncludedCategory(category)) { if (!isIncludedCategory(category)) {
it.adoptChild(PREFERENCE_SCREEN_TAG_NAME) { 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") setAttribute("android:key", "revanced_preference_screen_$category")
} }
setPreferenceCategory(category) setPreferenceCategory(category)
@ -117,7 +123,9 @@ object ResourceUtils {
this.xmlEditor[SETTINGS_HEADER_PATH].use { editor -> this.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME) val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
List(tags.length) { tags.item(it) as Element } 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 { .forEach {
it.adoptChild("Preference") { it.adoptChild("Preference") {
setAttribute("android:title", "@string/$key" + "_title") setAttribute("android:title", "@string/$key" + "_title")
@ -145,7 +153,9 @@ object ResourceUtils {
this.xmlEditor[SETTINGS_HEADER_PATH].use { editor -> this.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME) val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
List(tags.length) { tags.item(it) as Element } 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 { .forEach {
it.adoptChild(SWITCH_PREFERENCE_TAG_NAME) { it.adoptChild(SWITCH_PREFERENCE_TAG_NAME) {
setAttribute("android:title", "@string/$key" + "_title") setAttribute("android:title", "@string/$key" + "_title")
@ -170,7 +180,9 @@ object ResourceUtils {
this.xmlEditor[SETTINGS_HEADER_PATH].use { editor -> this.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME) val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
List(tags.length) { tags.item(it) as Element } 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 { .forEach {
it.adoptChild("Preference") { it.adoptChild("Preference") {
setAttribute("android:title", "@string/$key" + "_title") 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.GoogleApiActivityFingerprint
import app.revanced.patches.music.utils.settings.fingerprints.PreferenceFingerprint import app.revanced.patches.music.utils.settings.fingerprints.PreferenceFingerprint
import app.revanced.patches.music.utils.settings.fingerprints.SettingsHeadersFragmentFingerprint 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.fingerprints.SharedSettingFingerprint
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
import app.revanced.util.getTargetIndex import app.revanced.util.getTargetIndex
import app.revanced.util.resultOrThrow import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
@ -109,9 +109,18 @@ object SettingsBytecodePatch : BytecodePatch(
} }
} }
MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR, "setDeviceInformation") MainActivityResolvePatch.injectOnCreateMethodCall(
MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR, "onCreate") INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR,
MainActivityResolvePatch.injectConstructorMethodCall(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR, "setActivity") "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 -> context.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME) val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
List(tags.length) { tags.item(it) as Element } 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 { .forEach {
it.adoptChild(SWITCH_PREFERENCE_TAG_NAME) { it.adoptChild(SWITCH_PREFERENCE_TAG_NAME) {
setAttribute("android:title", "@string/revanced_$key") setAttribute("android:title", "@string/revanced_$key")
@ -166,7 +168,9 @@ object SponsorBlockPatch : BaseResourcePatch(
context.xmlEditor[SETTINGS_HEADER_PATH].use { editor -> context.xmlEditor[SETTINGS_HEADER_PATH].use { editor ->
val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME) val tags = editor.file.getElementsByTagName(PREFERENCE_SCREEN_TAG_NAME)
List(tags.length) { tags.item(it) as Element } 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 { .forEach {
it.adoptChild("Preference") { it.adoptChild("Preference") {
setAttribute("android:title", "@string/revanced_$key") setAttribute("android:title", "@string/revanced_$key")

View File

@ -65,7 +65,8 @@ object VideoInformationPatch : BytecodePatch(
internal lateinit var playbackSpeedResult: MethodFingerprintResult internal lateinit var playbackSpeedResult: MethodFingerprintResult
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val videoInformationMutableClass = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass val videoInformationMutableClass =
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
VideoEndFingerprint.resultOrThrow().let { VideoEndFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
@ -119,7 +120,8 @@ object VideoInformationPatch : BytecodePatch(
* Set the video time method * Set the video time method
*/ */
PlayerControllerSetTimeReferenceFingerprint.resultOrThrow().let { 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 { VideoLengthFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val invalidateIndex = getTargetIndexWithMethodReferenceNameReversed("invalidate") val invalidateIndex = getTargetIndexWithMethodReferenceNameReversed("invalidate")
val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(invalidateIndex + 1, "Landroid/graphics/Rect;") val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(
rectangleFieldName = (getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name invalidateIndex + 1,
"Landroid/graphics/Rect;"
)
rectangleFieldName =
(getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name
val videoLengthRegisterIndex = it.scanResult.patternScanResult!!.startIndex + 1 val videoLengthRegisterIndex = it.scanResult.patternScanResult!!.startIndex + 1
val videoLengthRegister = val videoLengthRegister =

View File

@ -22,7 +22,8 @@ object VideoIdPatch : BytecodePatch(
it.mutableMethod.apply { it.mutableMethod.apply {
videoIdMethod = this videoIdMethod = this
videoIdInsertIndex = it.scanResult.patternScanResult!!.startIndex + 2 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 { 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 { targetMethod.apply {
val targetIndex = indexOfFirstInstruction { val targetIndex = indexOfFirstInstruction {

View File

@ -52,7 +52,7 @@ abstract class BaseGmsCoreSupportPatch(
) : BytecodePatch( ) : BytecodePatch(
name = "GmsCore support", name = "GmsCore support",
description = "Allows patched Google apps to run without root and under a different package name " + 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( dependencies = setOf(
PackageNamePatch::class, PackageNamePatch::class,
gmsCoreSupportResourcePatch::class, gmsCoreSupportResourcePatch::class,
@ -116,36 +116,43 @@ abstract class BaseGmsCoreSupportPatch(
.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"") .replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"")
} }
private fun BytecodeContext.transformStringReferences(transform: (str: String) -> String?) = classes.forEach { private fun BytecodeContext.transformStringReferences(transform: (str: String) -> String?) =
val mutableClass by lazy { classes.forEach {
proxy(it).mutableClass 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) }
} }
implementation.instructions.forEachIndexed insnLoop@{ index, instruction -> it.methods.forEach classLoop@{ methodDef ->
val string = ((instruction as? Instruction21c)?.reference as? StringReference)?.string val implementation = methodDef.implementation ?: return@classLoop
?: return@insnLoop
// Apply transformation. val mutableMethod by lazy {
val transformedString = transform(string) ?: return@insnLoop mutableClass.methods.first { method ->
MethodUtil.methodSignaturesMatch(
method,
methodDef
)
}
}
mutableMethod.replaceInstruction( implementation.instructions.forEachIndexed insnLoop@{ index, instruction ->
index, val string =
BuilderInstruction21c( ((instruction as? Instruction21c)?.reference as? StringReference)?.string
Opcode.CONST_STRING, ?: return@insnLoop
instruction.registerA,
ImmutableStringReference(transformedString), // 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. // 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 // gms also has a 'subscribedfeeds' authority, check for that one too
val subFeedsUriPrefix = "content://subscribedfeeds" val subFeedsUriPrefix = "content://subscribedfeeds"
if (str.startsWith(subFeedsUriPrefix)) { if (str.startsWith(subFeedsUriPrefix)) {
return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendorGroupId.subscribedfeeds") return str.replace(
subFeedsUriPrefix,
"content://$gmsCoreVendorGroupId.subscribedfeeds"
)
} }
} }
return null return null
} }
private fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? = { string -> private fun packageNameTransform(
fromPackageName: String,
toPackageName: String
): (String) -> String? = { string ->
when (string) { when (string) {
"$fromPackageName.SuggestionsProvider", "$fromPackageName.SuggestionsProvider",
"$fromPackageName.fileprovider", "$fromPackageName.fileprovider",

View File

@ -53,12 +53,18 @@ abstract class BaseGmsCoreSupportResourcePatch(
// Spoof package name and signature. // Spoof package name and signature.
applicationNode.adoptChild("meta-data") { 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) setAttribute("android:value", fromPackageName)
} }
applicationNode.adoptChild("meta-data") { 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) setAttribute("android:value", spoofedPackageSignature)
} }

View File

@ -113,7 +113,8 @@ object LithoFilterPatch : BytecodePatch(
if ((instruction as? ReferenceInstruction)?.reference.toString() != pathBuilderMethodCall) if ((instruction as? ReferenceInstruction)?.reference.toString() != pathBuilderMethodCall)
continue continue
val insertRegister = getInstruction<OneRegisterInstruction>(index + 1).registerA val insertRegister =
getInstruction<OneRegisterInstruction>(index + 1).registerA
val insertIndex = index + 2 val insertIndex = index + 2
addInstructionsWithLabels( addInstructionsWithLabels(
@ -134,13 +135,16 @@ object LithoFilterPatch : BytecodePatch(
""" """
} }
val stringBuilderIndex = getTargetIndexWithFieldReferenceType("Ljava/lang/StringBuilder;") val stringBuilderIndex =
val stringBuilderRegister = getInstruction<TwoRegisterInstruction>(stringBuilderIndex).registerA getTargetIndexWithFieldReferenceType("Ljava/lang/StringBuilder;")
val stringBuilderRegister =
getInstruction<TwoRegisterInstruction>(stringBuilderIndex).registerA
val emptyStringIndex = getEmptyStringInstructionIndex() val emptyStringIndex = getEmptyStringInstructionIndex()
val identifierIndex = getTargetIndexReversed(emptyStringIndex, Opcode.IPUT_OBJECT) 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 objectIndex = getTargetIndex(emptyStringIndex, Opcode.INVOKE_VIRTUAL)
val objectRegister = getInstruction<BuilderInstruction35c>(objectIndex).registerC val objectRegister = getInstruction<BuilderInstruction35c>(objectIndex).registerC

View File

@ -14,7 +14,7 @@ import kotlin.properties.Delegates
abstract class BaseMainActivityResolvePatch( abstract class BaseMainActivityResolvePatch(
private val mainActivityOnCreateFingerprint: MethodFingerprint private val mainActivityOnCreateFingerprint: MethodFingerprint
): BytecodePatch( ) : BytecodePatch(
setOf(mainActivityOnCreateFingerprint) setOf(mainActivityOnCreateFingerprint)
) { ) {
lateinit var mainActivityMutableClass: MutableClass lateinit var mainActivityMutableClass: MutableClass
@ -41,10 +41,18 @@ abstract class BaseMainActivityResolvePatch(
} }
fun injectConstructorMethodCall(classDescriptor: String, methodDescriptor: String) = fun injectConstructorMethodCall(classDescriptor: String, methodDescriptor: String) =
constructorMethod.injectMethodCall(classDescriptor, methodDescriptor, constructorMethodIndex) constructorMethod.injectMethodCall(
classDescriptor,
methodDescriptor,
constructorMethodIndex
)
fun injectOnBackPressedMethodCall(classDescriptor: String, methodDescriptor: String) = fun injectOnBackPressedMethodCall(classDescriptor: String, methodDescriptor: String) =
onBackPressedMethod.injectMethodCall(classDescriptor, methodDescriptor, onBackPressedMethodIndex) onBackPressedMethod.injectMethodCall(
classDescriptor,
methodDescriptor,
onBackPressedMethodIndex
)
fun injectOnCreateMethodCall(classDescriptor: String, methodDescriptor: String) = fun injectOnCreateMethodCall(classDescriptor: String, methodDescriptor: String) =
onCreateMethod.injectMethodCall(classDescriptor, methodDescriptor) 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.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.Reference 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." + @Deprecated(
"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.") "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( abstract class BaseOpusCodecsPatch(
private val descriptor: String private val descriptor: String
) : BytecodePatch( ) : BytecodePatch(

View File

@ -20,10 +20,14 @@ object OverlayBackgroundUtils {
arrayOf("height", "width").forEach replacement@{ replacement -> arrayOf("height", "width").forEach replacement@{ replacement ->
if (it !is Element) return@replacement if (it !is Element) return@replacement
if (it.attributes.getNamedItem("android:id")?.nodeValue?.endsWith(identifier) == true) { if (it.attributes.getNamedItem("android:id")?.nodeValue?.endsWith(
it.getAttributeNode("android:layout_$replacement")?.let { attribute -> identifier
attribute.textContent = "0.0dip" ) == 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, // IndexOutOfBoundsException is not possible here,
// but no such occurrences are present in the app. // 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, // This can technically also match non-user agent string builder append methods,
// but no such occurrences are present in the app. // 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. // Returns the patch indices as a Sequence, which will execute lazily.
fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? { fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? {
return method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) -> return method.implementation?.instructions?.asSequence()?.withIndex()
filterMap(classDef, method, instruction, index) ?.mapNotNull { (index, instruction) ->
} filterMap(classDef, method, instruction, index)
}
} }
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
@ -48,8 +49,9 @@ abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
val mutableClass = context.proxy(classDef).mutableClass val mutableClass = context.proxy(classDef).mutableClass
methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod -> methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod ->
val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque()) val patchIndices =
?: return@methods findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())
?: return@methods
while (!patchIndices.isEmpty()) transform(mutableMethod, patchIndices.removeLast()) while (!patchIndices.isEmpty()) transform(mutableMethod, patchIndices.removeLast())
} }

View File

@ -16,7 +16,10 @@ object TranslationsUtils {
this["res/$directory"].mkdir() this["res/$directory"].mkdir()
Files.copy( Files.copy(
inputStreamFromBundledResource("$sourceDirectory/translations", "$language/strings.xml")!!, inputStreamFromBundledResource(
"$sourceDirectory/translations",
"$language/strings.xml"
)!!,
this["res"].resolve("$directory/strings.xml").toPath(), this["res"].resolve("$directory/strings.xml").toPath(),
StandardCopyOption.REPLACE_EXISTING StandardCopyOption.REPLACE_EXISTING
) )

View File

@ -5,6 +5,6 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint
internal object InterstitialsContainerFingerprint : LiteralValueFingerprint( internal object InterstitialsContainerFingerprint : LiteralValueFingerprint(
returnType = "V", returnType = "V",
strings= listOf("overlay_controller_param"), strings = listOf("overlay_controller_param"),
literalSupplier = { InterstitialsContainer } literalSupplier = { InterstitialsContainer }
) )

View File

@ -102,7 +102,9 @@ object AlternativeThumbnailsPatch : BaseBytecodePatch(
block: (MutableMethod) -> Unit block: (MutableMethod) -> Unit
) = alsoResolve(fingerprint).also { block(it.mutableMethod) } ) = alsoResolve(fingerprint).also { block(it.mutableMethod) }
MessageDigestImageUrlFingerprint.resolveAndLetMutableMethod(MessageDigestImageUrlParentFingerprint) { MessageDigestImageUrlFingerprint.resolveAndLetMutableMethod(
MessageDigestImageUrlParentFingerprint
) {
loadImageUrlMethod = it loadImageUrlMethod = it
addImageUrlHook(ALTERNATIVE_THUMBNAILS_CLASS_DESCRIPTOR, true) addImageUrlHook(ALTERNATIVE_THUMBNAILS_CLASS_DESCRIPTOR, true)
} }

View File

@ -6,5 +6,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object MessageDigestImageUrlFingerprint : MethodFingerprint( internal object MessageDigestImageUrlFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, 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( internal object MessageDigestImageUrlParentFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Ljava/lang/String;", returnType = "Ljava/lang/String;",
parameters = emptyList(), parameters = emptyList(),
strings = listOf("@#&=*+-_.,:!?()/~'%;\$"), strings = listOf("@#&=*+-_.,:!?()/~'%;\$"),
) )

View File

@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object OnFailureFingerprint : MethodFingerprint( internal object OnFailureFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf( parameters = listOf(
"Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlRequest;",
"Lorg/chromium/net/UrlResponseInfo;", "Lorg/chromium/net/UrlResponseInfo;",
"Lorg/chromium/net/CronetException;" "Lorg/chromium/net/CronetException;"

View File

@ -8,7 +8,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object OnResponseStartedFingerprint : MethodFingerprint( internal object OnResponseStartedFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, 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( strings = listOf(
"Content-Length", "Content-Length",
"Content-Type", "Content-Type",

View File

@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object OnSucceededFingerprint : MethodFingerprint( internal object OnSucceededFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, 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, _ -> customFingerprint = { methodDef, _ ->
methodDef.name == "onSucceeded" methodDef.name == "onSucceeded"
} }

View File

@ -97,7 +97,8 @@ object FeedComponentsPatch : BaseBytecodePatch(
fingerprint.resultOrThrow().let { fingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.endIndex val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA val targetRegister =
getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction( addInstruction(
targetIndex + 1, targetIndex + 1,
@ -131,7 +132,7 @@ object FeedComponentsPatch : BaseBytecodePatch(
addInstruction( addInstruction(
targetIndex + 1, 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 { ChannelTabRendererFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val iteratorIndex = getTargetIndexWithMethodReferenceName("hasNext") val iteratorIndex = getTargetIndexWithMethodReferenceName("hasNext")
val iteratorRegister = getInstruction<FiveRegisterInstruction>(iteratorIndex).registerC val iteratorRegister =
getInstruction<FiveRegisterInstruction>(iteratorIndex).registerC
val targetIndex = indexOfFirstInstruction { val targetIndex = indexOfFirstInstruction {
val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference) val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference)

View File

@ -32,11 +32,17 @@ object AudioTracksPatch : BaseBytecodePatch(
opcode == Opcode.CHECK_CAST opcode == Opcode.CHECK_CAST
&& (this as ReferenceInstruction).reference.toString() == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;" && (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 arrayListIndex = getTargetIndexWithReference(
val insertIndex = getTargetIndexWithReference(arrayListIndex, "Ljava/util/List;->isEmpty()Z") + 2 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 formatStreamModelRegister =
val arrayListRegister = getInstruction<FiveRegisterInstruction>(arrayListIndex).registerC getInstruction<OneRegisterInstruction>(formatStreamModelIndex).registerA
val arrayListRegister =
getInstruction<FiveRegisterInstruction>(arrayListIndex).registerC
addInstructions( addInstructions(
insertIndex, """ insertIndex, """
@ -47,7 +53,7 @@ object AudioTracksPatch : BaseBytecodePatch(
addInstructions( addInstructions(
formatStreamModelIndex + 1, 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 { it.mutableMethod.apply {
val constIndex = getWideLiteralInstructionIndex(AccountSwitcherAccessibility) val constIndex = getWideLiteralInstructionIndex(AccountSwitcherAccessibility)
val insertIndex = getTargetIndex(constIndex, Opcode.IF_EQZ) val insertIndex = getTargetIndex(constIndex, Opcode.IF_EQZ)
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(insertIndex, "setVisibility") val setVisibilityIndex =
val visibilityRegister = getInstruction<FiveRegisterInstruction>(setVisibilityIndex).registerD getTargetIndexWithMethodReferenceName(insertIndex, "setVisibility")
val visibilityRegister =
getInstruction<FiveRegisterInstruction>(setVisibilityIndex).registerD
addInstructions( addInstructions(
insertIndex, """ insertIndex, """
@ -192,7 +194,8 @@ object LayoutComponentsPatch : BaseBytecodePatch(
SettingsMenuFingerprint.resultOrThrow().let { SettingsMenuFingerprint.resultOrThrow().let {
it.mutableMethod.apply { 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 val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstruction( addInstruction(

View File

@ -29,7 +29,10 @@ object GradientLoadingScreenPatch : BaseBytecodePatch(
GradientLoadingScreenPrimaryFingerprint to 45412406, GradientLoadingScreenPrimaryFingerprint to 45412406,
GradientLoadingScreenSecondaryFingerprint to 45418917 GradientLoadingScreenSecondaryFingerprint to 45418917
).forEach { (fingerprint, literal) -> ).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( internal object PivotBarSetTextFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, 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( opcodes = listOf(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID Opcode.RETURN_VOID

View File

@ -32,10 +32,14 @@ object SplashAnimationPatch : BaseBytecodePatch(
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
StartUpResourceIdFingerprint.resolve(context, StartUpResourceIdParentFingerprint.resultOrThrow().classDef) StartUpResourceIdFingerprint.resolve(
context,
StartUpResourceIdParentFingerprint.resultOrThrow().classDef
)
val startUpResourceIdMethod = StartUpResourceIdFingerprint.resultOrThrow().mutableMethod val startUpResourceIdMethod = StartUpResourceIdFingerprint.resultOrThrow().mutableMethod
val startUpResourceIdMethodCall = startUpResourceIdMethod.definingClass + "->" + startUpResourceIdMethod.name + "(I)Z" val startUpResourceIdMethodCall =
startUpResourceIdMethod.definingClass + "->" + startUpResourceIdMethod.name + "(I)Z"
SplashAnimationFingerprint.resultOrThrow().let { SplashAnimationFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {

View File

@ -118,7 +118,8 @@ object TabletMiniPlayerPatch : BaseBytecodePatch(
} else { } else {
MiniPlayerOverrideFingerprint.resultOrThrow().let { MiniPlayerOverrideFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val walkerMethod = getWalkerMethod(context, getStringInstructionIndex("appName") + 2) val walkerMethod =
getWalkerMethod(context, getStringInstructionIndex("appName") + 2)
walkerMethod.apply { walkerMethod.apply {
hook(getTargetIndex(Opcode.RETURN)) hook(getTargetIndex(Opcode.RETURN))

View File

@ -45,7 +45,6 @@ import app.revanced.util.getTargetIndexWithReference
import app.revanced.util.getTargetIndexWithReferenceReversed import app.revanced.util.getTargetIndexWithReferenceReversed
import app.revanced.util.getWalkerMethod import app.revanced.util.getWalkerMethod
import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.getWideLiteralInstructionIndex
import app.revanced.util.literalInstructionBooleanHook
import app.revanced.util.literalInstructionHook import app.revanced.util.literalInstructionHook
import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.patch.BaseBytecodePatch
import app.revanced.util.resultOrThrow 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. // YouTube's headers have the form of AttributeSet, which is decoded from YouTube's built-in classes.
val attributeResolverMethod = AttributeResolverFingerprint.resultOrThrow().mutableMethod 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 -> context.findClass(GENERAL_CLASS_DESCRIPTOR)!!.mutableClass.methods.single { method ->
method.name == "getHeaderDrawable" method.name == "getHeaderDrawable"
@ -139,9 +139,10 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
} }
// Override the header in the search bar. // Override the header in the search bar.
val setActionBarRingoMutableClass = SetActionBarRingoFingerprint.resultOrThrow().mutableClass val setActionBarRingoMutableClass =
setActionBarRingoMutableClass.methods.first { SetActionBarRingoFingerprint.resultOrThrow().mutableClass
method -> MethodUtil.isConstructor(method) setActionBarRingoMutableClass.methods.first { method ->
MethodUtil.isConstructor(method)
}.apply { }.apply {
val insertIndex = getTargetIndex(Opcode.IPUT_BOOLEAN) val insertIndex = getTargetIndex(Opcode.IPUT_BOOLEAN)
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
@ -190,7 +191,8 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
.apply { .apply {
val staticCalls = implementation!!.instructions.withIndex() val staticCalls = implementation!!.instructions.withIndex()
.filter { instruction -> .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?.parameterTypes?.size == 1 &&
methodReference.returnType == "Z" methodReference.returnType == "Z"
} }
@ -321,13 +323,18 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
) )
) )
} else { } else {
SearchBarFingerprint.resolve(context, SearchBarParentFingerprint.resultOrThrow().classDef) SearchBarFingerprint.resolve(
context,
SearchBarParentFingerprint.resultOrThrow().classDef
)
SearchBarFingerprint.resultOrThrow().let { SearchBarFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex val startIndex = it.scanResult.patternScanResult!!.startIndex
val setVisibilityIndex = getTargetIndexWithMethodReferenceName(startIndex, "setVisibility") val setVisibilityIndex =
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(setVisibilityIndex) getTargetIndexWithMethodReferenceName(startIndex, "setVisibility")
val setVisibilityInstruction =
getInstruction<FiveRegisterInstruction>(setVisibilityIndex)
replaceInstruction( replaceInstruction(
setVisibilityIndex, setVisibilityIndex,
@ -340,8 +347,10 @@ object ToolBarComponentsPatch : BaseBytecodePatch(
SearchResultFingerprint.resultOrThrow().let { SearchResultFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val startIndex = getWideLiteralInstructionIndex(VoiceSearch) val startIndex = getWideLiteralInstructionIndex(VoiceSearch)
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName(startIndex, "setOnClickListener") val setOnClickListenerIndex =
val viewRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC getTargetIndexWithMethodReferenceName(startIndex, "setOnClickListener")
val viewRegister =
getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
addInstruction( addInstruction(
setOnClickListenerIndex + 1, setOnClickListenerIndex + 1,

View File

@ -78,7 +78,7 @@ object CustomBrandingIconPatch : BaseResourcePatch(
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext) {
AppIcon?.let { appIcon -> AppIcon?.let { appIcon ->
val appIconValue = appIcon.lowercase().replace(" ","_") val appIconValue = appIcon.lowercase().replace(" ", "_")
if (!availableIcon.containsValue(appIconValue)) { if (!availableIcon.containsValue(appIconValue)) {
mipmapDirectories.map { directory -> mipmapDirectories.map { directory ->
ResourceGroup( ResourceGroup(

View File

@ -80,7 +80,8 @@ object MinimizedPlaybackPatch : BaseBytecodePatch(
} }
PiPControllerFingerprint.resultOrThrow().let { PiPControllerFingerprint.resultOrThrow().let {
val targetMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex) val targetMethod =
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
targetMethod.apply { targetMethod.apply {
val targetRegister = getInstruction<TwoRegisterInstruction>(0).registerA val targetRegister = getInstruction<TwoRegisterInstruction>(0).registerA

View File

@ -33,7 +33,8 @@ object OpenLinksDirectlyPatch : BaseBytecodePatch(
fingerprint.resultOrThrow().let { fingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = getTargetIndexWithMethodReferenceName("parse") val insertIndex = getTargetIndexWithMethodReferenceName("parse")
val insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC val insertRegister =
getInstruction<FiveRegisterInstruction>(insertIndex).registerC
replaceInstruction( replaceInstruction(
insertIndex, insertIndex,

View File

@ -45,13 +45,15 @@ object AmbientModeSwitchPatch : BaseBytecodePatch(
PowerSaveModeSyntheticFingerprint to true PowerSaveModeSyntheticFingerprint to true
).forEach { (fingerprint, reversed) -> ).forEach { (fingerprint, reversed) ->
fingerprint.resultOrThrow().mutableMethod.apply { 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 = val targetIndex =
if (reversed) if (reversed)
getTargetIndexReversed(stringIndex, Opcode.INVOKE_DIRECT) getTargetIndexReversed(stringIndex, Opcode.INVOKE_DIRECT)
else else
getTargetIndex(stringIndex, Opcode.INVOKE_DIRECT) 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 syntheticClassList += targetClass
} }

View File

@ -126,16 +126,20 @@ object PlayerButtonsPatch : BaseBytecodePatch(
TitleAnchorFingerprint.resultOrThrow().mutableMethod.apply { TitleAnchorFingerprint.resultOrThrow().mutableMethod.apply {
val titleAnchorConstIndex = getWideLiteralInstructionIndex(TitleAnchor) val titleAnchorConstIndex = getWideLiteralInstructionIndex(TitleAnchor)
val titleAnchorIndex = getTargetIndex(titleAnchorConstIndex, Opcode.MOVE_RESULT_OBJECT) val titleAnchorIndex = getTargetIndex(titleAnchorConstIndex, Opcode.MOVE_RESULT_OBJECT)
val titleAnchorRegister = getInstruction<OneRegisterInstruction>(titleAnchorIndex).registerA val titleAnchorRegister =
getInstruction<OneRegisterInstruction>(titleAnchorIndex).registerA
addInstruction( addInstruction(
titleAnchorIndex + 1, titleAnchorIndex + 1,
"invoke-static {v$titleAnchorRegister}, $PLAYER_CLASS_DESCRIPTOR->setTitleAnchorStartMargin(Landroid/view/View;)V" "invoke-static {v$titleAnchorRegister}, $PLAYER_CLASS_DESCRIPTOR->setTitleAnchorStartMargin(Landroid/view/View;)V"
) )
val playerCollapseButtonConstIndex = getWideLiteralInstructionIndex(PlayerCollapseButton) val playerCollapseButtonConstIndex =
val playerCollapseButtonIndex = getTargetIndex(playerCollapseButtonConstIndex, Opcode.CHECK_CAST) getWideLiteralInstructionIndex(PlayerCollapseButton)
val playerCollapseButtonRegister = getInstruction<OneRegisterInstruction>(playerCollapseButtonIndex).registerA val playerCollapseButtonIndex =
getTargetIndex(playerCollapseButtonConstIndex, Opcode.CHECK_CAST)
val playerCollapseButtonRegister =
getInstruction<OneRegisterInstruction>(playerCollapseButtonIndex).registerA
addInstruction( addInstruction(
playerCollapseButtonIndex + 1, playerCollapseButtonIndex + 1,

View File

@ -37,6 +37,7 @@ object CommentsComponentPatch : BaseBytecodePatch(
) { ) {
private const val FILTER_CLASS_DESCRIPTOR = private const val FILTER_CLASS_DESCRIPTOR =
"$COMPONENTS_PATH/CommentsFilter;" "$COMPONENTS_PATH/CommentsFilter;"
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// region patch for emoji picker button in shorts // region patch for emoji picker button in shorts
@ -44,7 +45,7 @@ object CommentsComponentPatch : BaseBytecodePatch(
ShortsLiveStreamEmojiPickerOpacityFingerprint.resultOrThrow().let { ShortsLiveStreamEmojiPickerOpacityFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = implementation!!.instructions.size - 1 val insertIndex = implementation!!.instructions.size - 1
val insertRegister= getInstruction<OneRegisterInstruction>(insertIndex).registerA val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstruction( addInstruction(
insertIndex, insertIndex,
@ -56,12 +57,15 @@ object CommentsComponentPatch : BaseBytecodePatch(
ShortsLiveStreamEmojiPickerOnClickListenerFingerprint.resultOrThrow().let { ShortsLiveStreamEmojiPickerOnClickListenerFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val emojiPickerEndpointIndex = getWideLiteralInstructionIndex(126326492) val emojiPickerEndpointIndex = getWideLiteralInstructionIndex(126326492)
val emojiPickerOnClickListenerIndex = getTargetIndex(emojiPickerEndpointIndex, Opcode.INVOKE_DIRECT) val emojiPickerOnClickListenerIndex =
val emojiPickerOnClickListenerMethod = getWalkerMethod(context, emojiPickerOnClickListenerIndex) getTargetIndex(emojiPickerEndpointIndex, Opcode.INVOKE_DIRECT)
val emojiPickerOnClickListenerMethod =
getWalkerMethod(context, emojiPickerOnClickListenerIndex)
emojiPickerOnClickListenerMethod.apply { emojiPickerOnClickListenerMethod.apply {
val insertIndex = getTargetIndex(Opcode.IF_EQZ) val insertIndex = getTargetIndex(Opcode.IF_EQZ)
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(
insertIndex, """ insertIndex, """

View File

@ -170,7 +170,7 @@ object PlayerComponentsPatch : BaseBytecodePatch(
LayoutCircleFingerprint, LayoutCircleFingerprint,
LayoutIconFingerprint, LayoutIconFingerprint,
LayoutVideoFingerprint LayoutVideoFingerprint
).forEach{ fingerprint -> ).forEach { fingerprint ->
fingerprint.resultOrThrow().let { fingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.endIndex val insertIndex = it.scanResult.patternScanResult!!.endIndex
@ -205,9 +205,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
val constRegister = getInstruction<OneRegisterInstruction>(constIndex).registerA val constRegister = getInstruction<OneRegisterInstruction>(constIndex).registerA
val insertIndex = getTargetIndexReversed(constIndex, Opcode.INVOKE_VIRTUAL) + 1 val insertIndex = getTargetIndexReversed(constIndex, Opcode.INVOKE_VIRTUAL) + 1
val jumpIndex = implementation!!.instructions.let { instruction -> val jumpIndex = implementation!!.instructions.let { instruction ->
insertIndex + instruction.subList(insertIndex, instruction.size - 1).indexOfFirst { instructions -> insertIndex + instruction.subList(insertIndex, instruction.size - 1)
instructions.opcode == Opcode.GOTO || instructions.opcode == Opcode.GOTO_16 .indexOfFirst { instructions ->
} instructions.opcode == Opcode.GOTO || instructions.opcode == Opcode.GOTO_16
}
} }
val replaceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex) val replaceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
@ -270,7 +271,8 @@ object PlayerComponentsPatch : BaseBytecodePatch(
val insertIndex = getWideLiteralInstructionIndex(SeekUndoEduOverlayStub) val insertIndex = getWideLiteralInstructionIndex(SeekUndoEduOverlayStub)
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
val onClickListenerIndex = getTargetIndexWithMethodReferenceName(insertIndex, "setOnClickListener") val onClickListenerIndex =
getTargetIndexWithMethodReferenceName(insertIndex, "setOnClickListener")
val constComponent = getConstComponent(insertIndex, onClickListenerIndex - 1) val constComponent = getConstComponent(insertIndex, onClickListenerIndex - 1)
if (constComponent.isNotEmpty()) { if (constComponent.isNotEmpty()) {
@ -315,8 +317,10 @@ object PlayerComponentsPatch : BaseBytecodePatch(
it.mutableClass.methods.find { method -> it.mutableClass.methods.find { method ->
method.parameters == listOf("Landroid/view/View${'$'}OnClickListener;") method.parameters == listOf("Landroid/view/View${'$'}OnClickListener;")
}?.apply { }?.apply {
val setOnClickListenerIndex = getTargetIndexWithMethodReferenceName("setOnClickListener") val setOnClickListenerIndex =
val setOnClickListenerRegister = getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC getTargetIndexWithMethodReferenceName("setOnClickListener")
val setOnClickListenerRegister =
getInstruction<FiveRegisterInstruction>(setOnClickListenerIndex).registerC
addInstruction( addInstruction(
setOnClickListenerIndex + 1, setOnClickListenerIndex + 1,

View File

@ -110,8 +110,10 @@ object DescriptionComponentsPatch : BaseBytecodePatch(
EngagementPanelTitleParentFingerprint.resultOrThrow().classDef EngagementPanelTitleParentFingerprint.resultOrThrow().classDef
) )
EngagementPanelTitleFingerprint.resultOrThrow().mutableMethod.apply { EngagementPanelTitleFingerprint.resultOrThrow().mutableMethod.apply {
val contentDescriptionIndex = getTargetIndexWithMethodReferenceName("setContentDescription") val contentDescriptionIndex =
val contentDescriptionRegister = getInstruction<FiveRegisterInstruction>(contentDescriptionIndex).registerD getTargetIndexWithMethodReferenceName("setContentDescription")
val contentDescriptionRegister =
getInstruction<FiveRegisterInstruction>(contentDescriptionIndex).registerD
addInstruction( addInstruction(
contentDescriptionIndex, contentDescriptionIndex,

View File

@ -2,7 +2,7 @@ package app.revanced.patches.youtube.player.flyoutmenu.hide.fingerprints
import app.revanced.util.fingerprint.LiteralValueFingerprint import app.revanced.util.fingerprint.LiteralValueFingerprint
/** /**
* This fingerprint is compatible with YouTube v18.39.xx+ * This fingerprint is compatible with YouTube v18.39.xx+
*/ */
internal object PiPModeConfigFingerprint : LiteralValueFingerprint( internal object PiPModeConfigFingerprint : LiteralValueFingerprint(

View File

@ -46,11 +46,14 @@ object ChangeTogglePatch : BaseBytecodePatch(
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val additionalSettingsConfigMethod = AdditionalSettingsConfigFingerprint.resultOrThrow().mutableMethod val additionalSettingsConfigMethod =
val methodToCall = additionalSettingsConfigMethod.definingClass + "->" + additionalSettingsConfigMethod.name + "()Z" AdditionalSettingsConfigFingerprint.resultOrThrow().mutableMethod
val methodToCall =
additionalSettingsConfigMethod.definingClass + "->" + additionalSettingsConfigMethod.name + "()Z"
// Resolves fingerprints // Resolves fingerprints
val playbackLoopOnClickListenerResult = PlaybackLoopOnClickListenerFingerprint.resultOrThrow() val playbackLoopOnClickListenerResult =
PlaybackLoopOnClickListenerFingerprint.resultOrThrow()
PlaybackLoopInitFingerprint.resolve(context, playbackLoopOnClickListenerResult.classDef) PlaybackLoopInitFingerprint.resolve(context, playbackLoopOnClickListenerResult.classDef)
var fingerprintArray = arrayOf( var fingerprintArray = arrayOf(
@ -90,7 +93,8 @@ object ChangeTogglePatch : BaseBytecodePatch(
it.mutableMethod.apply { it.mutableMethod.apply {
val referenceIndex = indexOfFirstInstruction { val referenceIndex = indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL opcode == Opcode.INVOKE_VIRTUAL
&& (this as ReferenceInstruction).reference.toString().endsWith(methodToCall) && (this as ReferenceInstruction).reference.toString()
.endsWith(methodToCall)
} }
if (referenceIndex > 0) { if (referenceIndex > 0) {
val insertRegister = val insertRegister =
@ -117,12 +121,14 @@ object ChangeTogglePatch : BaseBytecodePatch(
val stringReferenceIndex = stableVolumeMethod.indexOfFirstInstruction { val stringReferenceIndex = stableVolumeMethod.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL 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) if (stringReferenceIndex < 0)
throw PatchException("Target reference was not found in ${StableVolumeFingerprint.javaClass.simpleName}.") 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 { CinematicLightingFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
@ -135,15 +141,20 @@ object ChangeTogglePatch : BaseBytecodePatch(
val stringIndex = getStringInstructionIndex("menu_item_cinematic_lighting") val stringIndex = getStringInstructionIndex("menu_item_cinematic_lighting")
val checkCastIndex = getTargetIndexReversed(stringIndex, Opcode.CHECK_CAST) 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 iGetObjectSecondaryIndex = getTargetIndex(checkCastIndex, Opcode.IGET_OBJECT)
val checkCastReference = getInstruction<ReferenceInstruction>(checkCastIndex).reference val checkCastReference =
val iGetObjectPrimaryReference = getInstruction<ReferenceInstruction>(iGetObjectPrimaryIndex).reference getInstruction<ReferenceInstruction>(checkCastIndex).reference
val iGetObjectSecondaryReference = getInstruction<ReferenceInstruction>(iGetObjectSecondaryIndex).reference val iGetObjectPrimaryReference =
getInstruction<ReferenceInstruction>(iGetObjectPrimaryIndex).reference
val iGetObjectSecondaryReference =
getInstruction<ReferenceInstruction>(iGetObjectSecondaryIndex).reference
val invokeVirtualIndex = getTargetIndex(stringIndex, Opcode.INVOKE_VIRTUAL) val invokeVirtualIndex = getTargetIndex(stringIndex, Opcode.INVOKE_VIRTUAL)
val invokeVirtualInstruction = getInstruction<FiveRegisterInstruction>(invokeVirtualIndex) val invokeVirtualInstruction =
getInstruction<FiveRegisterInstruction>(invokeVirtualIndex)
val freeRegisterC = invokeVirtualInstruction.registerC val freeRegisterC = invokeVirtualInstruction.registerC
val freeRegisterD = invokeVirtualInstruction.registerD val freeRegisterD = invokeVirtualInstruction.registerD
val freeRegisterE = invokeVirtualInstruction.registerE val freeRegisterE = invokeVirtualInstruction.registerE

View File

@ -182,7 +182,8 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
val walkerMethod = getWalkerMethod(context, walkerIndex) val walkerMethod = getWalkerMethod(context, walkerIndex)
walkerMethod.apply { walkerMethod.apply {
val insertIndex = implementation!!.instructions.size - 1 val insertIndex = implementation!!.instructions.size - 1
val targetRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val targetRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(
insertIndex, """ insertIndex, """
@ -288,7 +289,8 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
LandScapeModeConfigFingerprint.resultOrThrow().let { LandScapeModeConfigFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = implementation!!.instructions.size - 1 val insertIndex = implementation!!.instructions.size - 1
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(
insertIndex, """ insertIndex, """
@ -300,7 +302,8 @@ object FullscreenComponentsPatch : BaseBytecodePatch(
BroadcastReceiverFingerprint.resultOrThrow().let { result -> BroadcastReceiverFingerprint.resultOrThrow().let { result ->
result.mutableMethod.apply { 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 val insertIndex = getTargetIndex(stringIndex, Opcode.IF_EQZ) + 1
addInstruction( addInstruction(

View File

@ -89,22 +89,29 @@ object OverlayButtonsBytecodePatch : BytecodePatch(
&& getReference<FieldReference>()?.definingClass == definingClass && getReference<FieldReference>()?.definingClass == definingClass
&& (this as TwoRegisterInstruction).registerA == registerResolver && (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 onClickListenerReferenceIndex =
val onClickListenerReference = getInstruction<ReferenceInstruction>(onClickListenerReferenceIndex).reference getTargetIndexWithReference("<init>(Ljava/lang/Object;I[B)V")
val onClickListenerClass = context.findClass((onClickListenerReference as MethodReference).definingClass)!!.mutableClass val onClickListenerReference =
getInstruction<ReferenceInstruction>(onClickListenerReferenceIndex).reference
val onClickListenerClass =
context.findClass((onClickListenerReference as MethodReference).definingClass)!!.mutableClass
var invokeInterfaceReference = "" var invokeInterfaceReference = ""
onClickListenerClass.methods.find { method -> method.name == "onClick" } onClickListenerClass.methods.find { method -> method.name == "onClick" }
?.apply { ?.apply {
val invokeInterfaceIndex = getTargetIndexWithReference(invokerObjectReference.toString()) + 1 val invokeInterfaceIndex =
getTargetIndexWithReference(invokerObjectReference.toString()) + 1
if (getInstruction(invokeInterfaceIndex).opcode != Opcode.INVOKE_INTERFACE) if (getInstruction(invokeInterfaceIndex).opcode != Opcode.INVOKE_INTERFACE)
throw PatchException("Opcode does not match") 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") } ?: 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 = val smaliInstructions =
""" """

View File

@ -129,7 +129,10 @@ object OverlayButtonsPatch : BaseResourcePatch(
val resources = commonResources + specificResources val resources = commonResources + specificResources
resources.forEach { resource -> resources.forEach { resource ->
val folderName = if (resource.endsWith(".xml")) "drawable" else "drawable-xxhdpi" 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;", "Ljava/util/Map;",
"L", "L",
"Ljava/lang/String", // VideoId "Ljava/lang/String", // VideoId
"L"), "L"
),
strings = listOf("Object is not an offlineable video: ") strings = listOf("Object is not an offlineable video: ")
) )

View File

@ -133,7 +133,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
TotalTimeFingerprint.resultOrThrow().let { TotalTimeFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val charSequenceIndex = getTargetIndexWithMethodReferenceName("getString") + 1 val charSequenceIndex = getTargetIndexWithMethodReferenceName("getString") + 1
val charSequenceRegister = getInstruction<OneRegisterInstruction>(charSequenceIndex).registerA val charSequenceRegister =
getInstruction<OneRegisterInstruction>(charSequenceIndex).registerA
val textViewIndex = getTargetIndexWithMethodReferenceName("getText") val textViewIndex = getTargetIndexWithMethodReferenceName("getText")
val textViewRegister = val textViewRegister =
getInstruction<FiveRegisterInstruction>(textViewIndex).registerC getInstruction<FiveRegisterInstruction>(textViewIndex).registerC
@ -162,7 +163,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
} }
ControlsOverlayStyleFingerprint.resultOrThrow().let { 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 { walkerMethod.apply {
val colorRegister = getInstruction<TwoRegisterInstruction>(0).registerA val colorRegister = getInstruction<TwoRegisterInstruction>(0).registerA
@ -221,18 +223,19 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
// region patch for hide seekbar // region patch for hide seekbar
SeekbarFingerprint.resultOrThrow().mutableClass.let { mutableClass -> SeekbarFingerprint.resultOrThrow().mutableClass.let { mutableClass ->
SeekbarOnDrawFingerprint.also { it.resolve(context, mutableClass) }.resultOrThrow().let { SeekbarOnDrawFingerprint.also { it.resolve(context, mutableClass) }.resultOrThrow()
it.mutableMethod.apply { .let {
addInstructionsWithLabels( it.mutableMethod.apply {
0, """ addInstructionsWithLabels(
0, """
invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideSeekbar()Z invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideSeekbar()Z
move-result v0 move-result v0
if-eqz v0, :show if-eqz v0, :show
return-void return-void
""", ExternalLabel("show", getInstruction(0)) """, ExternalLabel("show", getInstruction(0))
) )
}
} }
}
} }
// endregion // endregion
@ -240,7 +243,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
// region patch for hide time stamp // region patch for hide time stamp
PlayerSeekbarColorFingerprint.resultOrThrow().let { parentResult -> 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 { it.mutableMethod.apply {
addInstructionsWithLabels( addInstructionsWithLabels(
0, """ 0, """
@ -274,7 +278,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch(
"SETTINGS: RESTORE_OLD_SEEKBAR_THUMBNAILS" "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 // endregion

View File

@ -49,7 +49,8 @@ object SpeedOverlayPatch : BytecodePatch(
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val restoreSlideToSeekBehaviorFingerprintResult = RestoreSlideToSeekBehaviorFingerprint.result val restoreSlideToSeekBehaviorFingerprintResult =
RestoreSlideToSeekBehaviorFingerprint.result
val speedOverlayFingerprintResult = SpeedOverlayFingerprint.result val speedOverlayFingerprintResult = SpeedOverlayFingerprint.result
val speedOverlayValueFingerprintResult = SpeedOverlayValueFingerprint.result val speedOverlayValueFingerprintResult = SpeedOverlayValueFingerprint.result
@ -130,7 +131,8 @@ object SpeedOverlayPatch : BytecodePatch(
val jumpIndex = scanResult.endIndex + 1 val jumpIndex = scanResult.endIndex + 1
val insertIndex = scanResult.endIndex - 1 val insertIndex = scanResult.endIndex - 1
val insertRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA val insertRegister =
getInstruction<TwoRegisterInstruction>(insertIndex).registerA
hook(insertIndex, insertRegister, jumpIndex) hook(insertIndex, insertRegister, jumpIndex)
} }
@ -150,7 +152,8 @@ object SpeedOverlayPatch : BytecodePatch(
constructorMethod.apply { constructorMethod.apply {
val syntheticIndex = getTargetIndexReversed(Opcode.NEW_INSTANCE) val syntheticIndex = getTargetIndexReversed(Opcode.NEW_INSTANCE)
val syntheticClass = getInstruction<ReferenceInstruction>(syntheticIndex).reference.toString() val syntheticClass =
getInstruction<ReferenceInstruction>(syntheticIndex).reference.toString()
val syntheticMethod = val syntheticMethod =
context.findClass(syntheticClass)?.mutableClass context.findClass(syntheticClass)?.mutableClass
@ -170,8 +173,12 @@ object SpeedOverlayPatch : BytecodePatch(
""" """
) )
insertIndex = getTargetIndexWithMethodReferenceNameReversed(speedOverlayValueIndex, "removeCallbacks") + 1 insertIndex = getTargetIndexWithMethodReferenceNameReversed(
insertRegister = getInstruction<FiveRegisterInstruction>(insertIndex - 1).registerC speedOverlayValueIndex,
"removeCallbacks"
) + 1
insertRegister =
getInstruction<FiveRegisterInstruction>(insertIndex - 1).registerC
jumpIndex = getTargetIndex(speedOverlayValueIndex, Opcode.RETURN_VOID) + 1 jumpIndex = getTargetIndex(speedOverlayValueIndex, Opcode.RETURN_VOID) + 1
hook(insertIndex, insertRegister, jumpIndex) hook(insertIndex, insertRegister, jumpIndex)
} }
@ -181,7 +188,8 @@ object SpeedOverlayPatch : BytecodePatch(
SpeedOverlayTextValueFingerprint.resultOrThrow().let { SpeedOverlayTextValueFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.startIndex val targetIndex = it.scanResult.patternScanResult!!.startIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA val targetRegister =
getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions( addInstructions(
targetIndex + 1, """ targetIndex + 1, """

View File

@ -161,7 +161,10 @@ object ShortsComponentPatch : BaseBytecodePatch(
if (insertIndex == 0) if (insertIndex == 0)
throw PatchException("insert index not found") 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) { when (returnType) {
"Landroid/widget/TextView;" -> { "Landroid/widget/TextView;" -> {
val insertIndex = implementation!!.instructions.size - 1 val insertIndex = implementation!!.instructions.size - 1
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(
insertIndex + 1, """ insertIndex + 1, """
@ -196,6 +200,7 @@ object ShortsComponentPatch : BaseBytecodePatch(
) )
removeInstruction(insertIndex) removeInstruction(insertIndex)
} }
"V" -> { "V" -> {
addInstructionsWithLabels( addInstructionsWithLabels(
0, """ 0, """
@ -206,6 +211,7 @@ object ShortsComponentPatch : BaseBytecodePatch(
""", ExternalLabel("show", getInstruction(0)) """, ExternalLabel("show", getInstruction(0))
) )
} }
else -> { else -> {
throw PatchException("Unknown returnType: $returnType") throw PatchException("Unknown returnType: $returnType")
} }
@ -260,7 +266,8 @@ object ShortsComponentPatch : BaseBytecodePatch(
TextComponentSpecFingerprint.resultOrThrow().let { TextComponentSpecFingerprint.resultOrThrow().let {
it.mutableMethod.apply { 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 = val charSequenceRegister =
getInstruction<FiveRegisterInstruction>(insertIndex).registerC getInstruction<FiveRegisterInstruction>(insertIndex).registerC

View File

@ -25,7 +25,8 @@ object ShortsNavigationBarPatch : BytecodePatch(
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
InitializeButtonsFingerprint.resultOrThrow().let { parentResult -> 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 { it.mutableMethod.apply {
val startIndex = it.scanResult.patternScanResult!!.startIndex val startIndex = it.scanResult.patternScanResult!!.startIndex
val register = getInstruction<OneRegisterInstruction>(startIndex).registerA val register = getInstruction<OneRegisterInstruction>(startIndex).registerA
@ -39,7 +40,8 @@ object ShortsNavigationBarPatch : BytecodePatch(
} }
RenderBottomNavigationBarFingerprint.resultOrThrow().let { RenderBottomNavigationBarFingerprint.resultOrThrow().let {
val walkerMethod = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex) val walkerMethod =
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
walkerMethod.addInstruction( walkerMethod.addInstruction(
0, 0,

View File

@ -42,9 +42,12 @@ object ShortsRepeatPatch : BaseBytecodePatch(
injectEnum(enumName, fieldName) injectEnum(enumName, fieldName)
} }
val endScreenStringIndex = getStringInstructionIndex("REEL_LOOP_BEHAVIOR_END_SCREEN") val endScreenStringIndex =
val endScreenReferenceIndex = getTargetIndex(endScreenStringIndex, Opcode.SPUT_OBJECT) getStringInstructionIndex("REEL_LOOP_BEHAVIOR_END_SCREEN")
val endScreenReference = getInstruction<ReferenceInstruction>(endScreenReferenceIndex).reference.toString() val endScreenReferenceIndex =
getTargetIndex(endScreenStringIndex, Opcode.SPUT_OBJECT)
val endScreenReference =
getInstruction<ReferenceInstruction>(endScreenReferenceIndex).reference.toString()
val enumMethodName = ReelEnumStaticFingerprint.resultOrThrow().mutableMethod.name val enumMethodName = ReelEnumStaticFingerprint.resultOrThrow().mutableMethod.name
val enumMethodCall = "$definingClass->$enumMethodName(I)$definingClass" val enumMethodCall = "$definingClass->$enumMethodName(I)$definingClass"
@ -101,7 +104,8 @@ object ShortsRepeatPatch : BaseBytecodePatch(
if ((instruction as ReferenceInstruction).reference.toString() != enumMethodCall) if ((instruction as ReferenceInstruction).reference.toString() != enumMethodCall)
continue continue
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA val register =
getInstruction<OneRegisterInstruction>(index + 1).registerA
addInstructions( addInstructions(
index + 2, """ index + 2, """
@ -109,8 +113,8 @@ object ShortsRepeatPatch : BaseBytecodePatch(
move-result-object v$register move-result-object v$register
""" """
) )
}
} }
}
} }
} }
} }

View File

@ -38,13 +38,14 @@ object ResumingShortsOnStartupPatch : BaseBytecodePatch(
UserWasInShortsABConfigFingerprint.resultOrThrow().mutableMethod.apply { UserWasInShortsABConfigFingerprint.resultOrThrow().mutableMethod.apply {
val startIndex = indexOfOptionalInstruction(this) val startIndex = indexOfOptionalInstruction(this)
val walkerIndex = implementation!!.instructions.let { val walkerIndex = implementation!!.instructions.let {
val subListIndex = it.subList(startIndex, startIndex + 20).indexOfFirst { instruction -> val subListIndex =
val reference = instruction.getReference<MethodReference>() it.subList(startIndex, startIndex + 20).indexOfFirst { instruction ->
instruction.opcode == Opcode.INVOKE_VIRTUAL val reference = instruction.getReference<MethodReference>()
&& reference?.returnType == "Z" instruction.opcode == Opcode.INVOKE_VIRTUAL
&& reference.definingClass != "Lj${'$'}/util/Optional;" && reference?.returnType == "Z"
&& reference.parameterTypes.size == 0 && reference.definingClass != "Lj${'$'}/util/Optional;"
} && reference.parameterTypes.size == 0
}
if (subListIndex < 0) if (subListIndex < 0)
throw PatchException("subListIndex not found") throw PatchException("subListIndex not found")
@ -75,8 +76,10 @@ object ResumingShortsOnStartupPatch : BaseBytecodePatch(
getReference<MethodReference>()?.name == "isDone" getReference<MethodReference>()?.name == "isDone"
} }
if (listenableInstructionIndex < 0) throw PatchException("Could not find instruction index") if (listenableInstructionIndex < 0) throw PatchException("Could not find instruction index")
val originalInstructionRegister = getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC val originalInstructionRegister =
val freeRegister = getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA getInstruction<FiveRegisterInstruction>(listenableInstructionIndex).registerC
val freeRegister =
getInstruction<OneRegisterInstruction>(listenableInstructionIndex + 1).registerA
addInstructionsWithLabels( addInstructionsWithLabels(
listenableInstructionIndex + 1, listenableInstructionIndex + 1,

View File

@ -14,7 +14,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal object UserWasInShortsABConfigFingerprint : MethodFingerprint( internal object UserWasInShortsABConfigFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
strings = listOf("Failed to get offline response: "), strings = listOf("Failed to get offline response: "),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
indexOfOptionalInstruction(methodDef) >= 0 indexOfOptionalInstruction(methodDef) >= 0
} }
) { ) {

View File

@ -62,7 +62,8 @@ object SwipeControlsPatch : BaseBytecodePatch(
// region patch for swipe controls patch // 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 val mainActivityClass = mainActivityMutableClass
// inject the wrapper class from integrations into the class hierarchy of MainActivity (WatchWhileActivity) // 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) MenuItemVisibilityFingerprint.resolve(context, toolbarMenuItemInitializeResult.classDef)
toolbarMenuItemInitializeMethod = toolbarMenuItemInitializeResult.mutableMethod toolbarMenuItemInitializeMethod = toolbarMenuItemInitializeResult.mutableMethod
toolbarMenuItemVisibilityMethod = MenuItemVisibilityFingerprint.resultOrThrow().mutableMethod toolbarMenuItemVisibilityMethod =
MenuItemVisibilityFingerprint.resultOrThrow().mutableMethod
playerButtonMethod = PlayerButtonFingerprint.resultOrThrow().mutableMethod playerButtonMethod = PlayerButtonFingerprint.resultOrThrow().mutableMethod

View File

@ -32,7 +32,8 @@ object CairoSettingsPatch : BytecodePatch(
*/ */
CarioFragmentConfigFingerprint.result?.let { CarioFragmentConfigFingerprint.result?.let {
it.mutableMethod.apply { 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 val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction( addInstruction(

View File

@ -76,10 +76,12 @@ object SpoofClientPatch : BaseBytecodePatch(
BuildInitPlaybackRequestFingerprint.resultOrThrow().let { BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA val targetRegister =
getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
addInstructions( addInstructions(
moveUriStringIndex + 1, """ moveUriStringIndex + 1,
"""
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String; invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister move-result-object v$targetRegister
""", """,
@ -94,10 +96,12 @@ object SpoofClientPatch : BaseBytecodePatch(
BuildPlayerRequestURIFingerprint.resultOrThrow().let { BuildPlayerRequestURIFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val invokeToStringIndex = it.scanResult.patternScanResult!!.startIndex val invokeToStringIndex = it.scanResult.patternScanResult!!.startIndex
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC val uriRegister =
getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
addInstructions( addInstructions(
invokeToStringIndex, """ invokeToStringIndex,
"""
invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri; invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
move-result-object v$uriRegister move-result-object v$uriRegister
""", """,
@ -111,50 +115,59 @@ object SpoofClientPatch : BaseBytecodePatch(
val (clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField) = val (clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField) =
SetPlayerRequestClientTypeFingerprint.resultOrThrow().let { result -> SetPlayerRequestClientTypeFingerprint.resultOrThrow().let { result ->
with (result.mutableMethod) { with(result.mutableMethod) {
// Field in the player request object that holds the client info object. // Field in the player request object that holds the client info object.
val clientInfoField = getInstructions().find { instruction -> val clientInfoField = getInstructions().find { instruction ->
// requestMessage.clientInfo = clientInfoBuilder.build(); // requestMessage.clientInfo = clientInfoBuilder.build();
instruction.opcode == Opcode.IPUT_OBJECT && instruction.opcode == Opcode.IPUT_OBJECT &&
instruction.getReference<FieldReference>()?.type == CLIENT_INFO_CLASS_DESCRIPTOR 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. // Client info object's client type field.
val clientInfoClientTypeField = getInstruction(result.scanResult.patternScanResult!!.endIndex) val clientInfoClientTypeField =
.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientTypeField") getInstruction(result.scanResult.patternScanResult!!.endIndex)
.getReference<FieldReference>()
?: throw PatchException("Could not find clientInfoClientTypeField")
val clientInfoVersionIndex = getStringInstructionIndex("10.29") val clientInfoVersionIndex = getStringInstructionIndex("10.29")
val clientInfoVersionRegister = getInstruction<OneRegisterInstruction>(clientInfoVersionIndex).registerA val clientInfoVersionRegister =
getInstruction<OneRegisterInstruction>(clientInfoVersionIndex).registerA
val clientInfoClientVersionFieldIndex = implementation!!.instructions.let { val clientInfoClientVersionFieldIndex = implementation!!.instructions.let {
clientInfoVersionIndex + it.subList(clientInfoVersionIndex, it.size - 1).indexOfFirst { instruction -> clientInfoVersionIndex + it.subList(clientInfoVersionIndex, it.size - 1)
instruction.opcode == Opcode.IPUT_OBJECT .indexOfFirst { instruction ->
&& (instruction as TwoRegisterInstruction).registerA == clientInfoVersionRegister instruction.opcode == Opcode.IPUT_OBJECT
} && (instruction as TwoRegisterInstruction).registerA == clientInfoVersionRegister
}
} }
// Client info object's client version field. // Client info object's client version field.
val clientInfoClientVersionField = getInstruction(clientInfoClientVersionFieldIndex) val clientInfoClientVersionField =
.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientVersionField") getInstruction(clientInfoClientVersionFieldIndex)
.getReference<FieldReference>()
?: throw PatchException("Could not find clientInfoClientVersionField")
Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField) Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField)
} }
} }
val clientInfoClientModelField = CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.let { val clientInfoClientModelField =
val instructions = it.getInstructions() CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.let {
val getClientModelIndex = indexOfModelInstruction(it) val instructions = it.getInstructions()
val getClientModelIndex = indexOfModelInstruction(it)
// The next IPUT_OBJECT instruction after getting the client model is setting the client model field. // The next IPUT_OBJECT instruction after getting the client model is setting the client model field.
instructions.subList( instructions.subList(
getClientModelIndex, getClientModelIndex,
instructions.size, instructions.size,
).find { instruction -> ).find { instruction ->
val reference = instruction.getReference<FieldReference>() val reference = instruction.getReference<FieldReference>()
instruction.opcode == Opcode.IPUT_OBJECT instruction.opcode == Opcode.IPUT_OBJECT
&& reference?.definingClass == CLIENT_INFO_CLASS_DESCRIPTOR && reference?.definingClass == CLIENT_INFO_CLASS_DESCRIPTOR
&& reference.type == "Ljava/lang/String;" && reference.type == "Ljava/lang/String;"
}?.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientModelField") }?.getReference<FieldReference>()
} ?: throw PatchException("Could not find clientInfoClientModelField")
}
// endregion // endregion
@ -167,12 +180,13 @@ object SpoofClientPatch : BaseBytecodePatch(
val checkCastInstruction = getInstruction<OneRegisterInstruction>(checkCastIndex) val checkCastInstruction = getInstruction<OneRegisterInstruction>(checkCastIndex)
val requestMessageInstanceRegister = checkCastInstruction.registerA val requestMessageInstanceRegister = checkCastInstruction.registerA
val clientInfoContainerClassName = checkCastInstruction.getReference<TypeReference>()!!.type val clientInfoContainerClassName =
checkCastInstruction.getReference<TypeReference>()!!.type
addInstruction( addInstruction(
checkCastIndex + 1, checkCastIndex + 1,
"invoke-static { v$requestMessageInstanceRegister }," + "invoke-static { v$requestMessageInstanceRegister }," +
" $definingClass->$setClientInfoMethodName($clientInfoContainerClassName)V", " $definingClass->$setClientInfoMethodName($clientInfoContainerClassName)V",
) )
// Change client info to use the spoofed values. // Change client info to use the spoofed values.
@ -181,7 +195,13 @@ object SpoofClientPatch : BaseBytecodePatch(
ImmutableMethod( ImmutableMethod(
definingClass, definingClass,
setClientInfoMethodName, setClientInfoMethodName,
listOf(ImmutableMethodParameter(clientInfoContainerClassName, annotations, "clientInfoContainer")), listOf(
ImmutableMethodParameter(
clientInfoContainerClassName,
annotations,
"clientInfoContainer"
)
),
"V", "V",
AccessFlags.PRIVATE or AccessFlags.STATIC, AccessFlags.PRIVATE or AccessFlags.STATIC,
annotations, annotations,
@ -229,7 +249,7 @@ object SpoofClientPatch : BaseBytecodePatch(
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameter( PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameter(
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(" + "$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 // endregion
@ -238,18 +258,19 @@ object SpoofClientPatch : BaseBytecodePatch(
PlayerGestureConfigSyntheticFingerprint.resultOrThrow().let { PlayerGestureConfigSyntheticFingerprint.resultOrThrow().let {
arrayOf(3, 9).forEach { offSet -> arrayOf(3, 9).forEach { offSet ->
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex - offSet).apply { it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex - offSet)
val index = implementation!!.instructions.size - 1 .apply {
val register = getInstruction<OneRegisterInstruction>(index).registerA val index = implementation!!.instructions.size - 1
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions( addInstructions(
index, index,
""" """
invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->enablePlayerGesture(Z)Z invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->enablePlayerGesture(Z)Z
move-result v$register move-result v$register
""" """
) )
} }
} }
} }

View File

@ -1,8 +1,8 @@
package app.revanced.patches.youtube.utils.fix.client.fingerprints package app.revanced.patches.youtube.utils.fix.client.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.MethodFingerprint 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.patches.youtube.utils.fix.client.fingerprints.PlayerGestureConfigSyntheticFingerprint.indexOfDownAndOutAllowedInstruction
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction

View File

@ -28,14 +28,18 @@ object DoubleBackToClosePatch : BytecodePatch(
/** /**
* Hook onBackPressed method inside MainActivity (WatchWhileActivity) * 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 * Inject the methods which start of ScrollView
*/ */
ScrollPositionFingerprint.resultOrThrow().let { 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 val insertIndex = walkerMethod.implementation!!.instructions.size - 1 - 1
walkerMethod.injectScrollView(insertIndex, "onStartScrollView") walkerMethod.injectScrollView(insertIndex, "onStartScrollView")
@ -46,11 +50,12 @@ object DoubleBackToClosePatch : BytecodePatch(
* Inject the methods which stop of ScrollView * Inject the methods which stop of ScrollView
*/ */
ScrollTopParentFingerprint.resultOrThrow().let { parentResult -> ScrollTopParentFingerprint.resultOrThrow().let { parentResult ->
ScrollTopFingerprint.also { it.resolve(context, parentResult.classDef) }.resultOrThrow().let { ScrollTopFingerprint.also { it.resolve(context, parentResult.classDef) }.resultOrThrow()
val insertIndex = it.scanResult.patternScanResult!!.endIndex .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) -> ).forEach { (fingerprint, literalValue) ->
fingerprint.result?.let { fingerprint.result?.let {
it.mutableMethod.apply { it.mutableMethod.apply {
val targetIndex = getTargetIndex(getWideLiteralInstructionIndex(literalValue.toLong()), Opcode.MOVE_RESULT) val targetIndex = getTargetIndex(
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA getWideLiteralInstructionIndex(literalValue.toLong()),
Opcode.MOVE_RESULT
)
val targetRegister =
getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction( addInstruction(
targetIndex + 1, targetIndex + 1,

View File

@ -6,8 +6,8 @@ import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode 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( internal object StoryboardRendererDecoderSpecFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,

View File

@ -27,7 +27,8 @@ object ShortsPlaybackPatch : BytecodePatch(
*/ */
ShortsPlaybackFingerprint.result?.let { ShortsPlaybackFingerprint.result?.let {
it.mutableMethod.apply { 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 val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstruction( 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. * Automatically closing the suggested video end screen is not appropriate as it will disable the autoplay behavior.
*/ */
RemoveOnLayoutChangeListenerFingerprint.resultOrThrow().let { RemoveOnLayoutChangeListenerFingerprint.resultOrThrow().let {
val walkerIndex = it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex) val walkerIndex =
it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex)
walkerIndex.apply { walkerIndex.apply {
val invokeInterfaceIndex = getTargetIndex(Opcode.INVOKE_INTERFACE) 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 invokeInterfaceReference =
val iGetObjectReference = getInstruction<ReferenceInstruction>(iGetObjectIndex).reference getInstruction<ReferenceInstruction>(invokeInterfaceIndex).reference
val iGetObjectReference =
getInstruction<ReferenceInstruction>(iGetObjectIndex).reference
addInstructionsWithLabels( addInstructionsWithLabels(
0, 0,

View File

@ -15,7 +15,12 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE, fromPackageName = ORIGINAL_PACKAGE_NAME_YOUTUBE,
mainActivityOnCreateFingerprint = MainActivityFingerprint, mainActivityOnCreateFingerprint = MainActivityFingerprint,
integrationsPatchDependency = IntegrationsPatch::class, 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, gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
compatiblePackages = COMPATIBLE_PACKAGE compatiblePackages = COMPATIBLE_PACKAGE
) )

View File

@ -20,7 +20,8 @@ object Constants {
const val VIDEO_PATH = "$PATCHES_PATH/video" const val VIDEO_PATH = "$PATCHES_PATH/video"
const val ADS_CLASS_DESCRIPTOR = "$ADS_PATH/AdsPatch;" 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 FEED_CLASS_DESCRIPTOR = "$FEED_PATH/FeedPatch;"
const val GENERAL_CLASS_DESCRIPTOR = "$GENERAL_PATH/GeneralPatch;" const val GENERAL_CLASS_DESCRIPTOR = "$GENERAL_PATH/GeneralPatch;"
const val PLAYER_CLASS_DESCRIPTOR = "$PLAYER_PATH/PlayerPatch;" const val PLAYER_CLASS_DESCRIPTOR = "$PLAYER_PATH/PlayerPatch;"

View File

@ -72,14 +72,16 @@ object NavigationBarHookPatch : BytecodePatch(
resolve(context, PivotBarConstructorFingerprint.resultOrThrow().classDef) resolve(context, PivotBarConstructorFingerprint.resultOrThrow().classDef)
}.resultOrThrow().mutableMethod.apply { }.resultOrThrow().mutableMethod.apply {
// Hook the current navigation bar enum value. Note, the 'You' tab does not have an enum value. // 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) { addHook(Hook.SET_LAST_APP_NAVIGATION_ENUM) {
opcode == Opcode.INVOKE_STATIC && opcode == Opcode.INVOKE_STATIC &&
getReference<MethodReference>()?.definingClass == navigationEnumClassName getReference<MethodReference>()?.definingClass == navigationEnumClassName
} }
// Hook the creation of navigation tab views. // Hook the creation of navigation tab views.
val drawableTabMethod = PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow().mutableMethod val drawableTabMethod =
PivotBarButtonsCreateDrawableViewFingerprint.resultOrThrow().mutableMethod
addHook(Hook.NAVIGATION_TAB_LOADED) predicate@{ addHook(Hook.NAVIGATION_TAB_LOADED) predicate@{
MethodUtil.methodSignaturesMatch( MethodUtil.methodSignaturesMatch(
getReference<MethodReference>() ?: return@predicate false, 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@{ addHook(Hook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) predicate@{
MethodUtil.methodSignaturesMatch( MethodUtil.methodSignaturesMatch(
getReference<MethodReference>() ?: return@predicate false, getReference<MethodReference>() ?: return@predicate false,
@ -111,11 +114,15 @@ object NavigationBarHookPatch : BytecodePatch(
} }
} }
navigationTabCreatedCallback = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method -> navigationTabCreatedCallback =
method.name == "navigationTabCreatedCallback" context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
} ?: throw PatchException("Could not find navigationTabCreatedCallback 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 { val hookNavigationButtonCreated: (String) -> Unit by lazy {
@ -133,7 +140,10 @@ object NavigationBarHookPatch : BytecodePatch(
private enum class Hook(val methodName: String, val parameters: String) { private enum class Hook(val methodName: String, val parameters: String) {
SET_LAST_APP_NAVIGATION_ENUM("setLastAppNavigationEnum", "Ljava/lang/Enum;"), SET_LAST_APP_NAVIGATION_ENUM("setLastAppNavigationEnum", "Ljava/lang/Enum;"),
NAVIGATION_TAB_LOADED("navigationTabLoaded", "Landroid/view/View;"), 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;"), 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 { it.mutableClass.methods.find { method -> method.name == "<init>" }?.apply {
val targetIndex = getTargetIndex(Opcode.IPUT_OBJECT) val targetIndex = getTargetIndex(Opcode.IPUT_OBJECT)
val targetRegister = getInstruction<TwoRegisterInstruction>(targetIndex).registerA val targetRegister =
getInstruction<TwoRegisterInstruction>(targetIndex).registerA
addInstructions( addInstructions(
targetIndex + 1, """ targetIndex + 1, """

View File

@ -59,7 +59,8 @@ object PlayerTypeHookPatch : BytecodePatch(
// region patch for set video state // region patch for set video state
YouTubeControlsOverlayFingerprint.resultOrThrow().let { parentResult -> YouTubeControlsOverlayFingerprint.resultOrThrow().let { parentResult ->
VideoStateFingerprint.also { it.resolve(context, parentResult.classDef) VideoStateFingerprint.also {
it.resolve(context, parentResult.classDef)
}.resultOrThrow().let { }.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val endIndex = it.scanResult.patternScanResult!!.endIndex val endIndex = it.scanResult.patternScanResult!!.endIndex
@ -84,7 +85,8 @@ object PlayerTypeHookPatch : BytecodePatch(
it.mutableMethod.apply { it.mutableMethod.apply {
val targetIndex = getStringInstructionIndex("VL") - 1 val targetIndex = getStringInstructionIndex("VL") - 1
val targetReference = getInstruction<ReferenceInstruction>(targetIndex).reference 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>" } targetClass.methods.find { method -> method.name == "<init>" }
?.apply { ?.apply {

View File

@ -175,7 +175,8 @@ object SharedResourceIdPatch : ResourcePatch() {
RightComment = getId(DRAWABLE, "ic_right_comment_32c") RightComment = getId(DRAWABLE, "ic_right_comment_32c")
ScrimOverlay = getId(ID, "scrim_overlay") ScrimOverlay = getId(ID, "scrim_overlay")
Scrubbing = getId(DIMEN, "vertical_touch_offset_to_enter_fine_scrubbing") 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") SeekUndoEduOverlayStub = getId(ID, "seek_undo_edu_overlay_stub")
SingleLoopEduSnackBarText = getId(STRING, "single_loop_edu_snackbar_text") SingleLoopEduSnackBarText = getId(STRING, "single_loop_edu_snackbar_text")
SlidingDialogAnimation = getId(STYLE, "SlidingDialogAnimation") SlidingDialogAnimation = getId(STYLE, "SlidingDialogAnimation")
@ -186,9 +187,11 @@ object SharedResourceIdPatch : ResourcePatch() {
TotalTime = getId(STRING, "total_time") TotalTime = getId(STRING, "total_time")
TouchArea = getId(ID, "touch_area") TouchArea = getId(ID, "touch_area")
VideoQualityBottomSheet = getId(LAYOUT, "video_quality_bottom_sheet_list_fragment_title") 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") 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") YtOutlinePiPWhite = getId(DRAWABLE, "yt_outline_picture_in_picture_white_24")
YtOutlineVideoCamera = getId(DRAWABLE, "yt_outline_video_camera_black_24") YtOutlineVideoCamera = getId(DRAWABLE, "yt_outline_video_camera_black_24")
YtOutlineXWhite = getId(DRAWABLE, "yt_outline_x_white_24") YtOutlineXWhite = getId(DRAWABLE, "yt_outline_x_white_24")

View File

@ -70,13 +70,17 @@ object ReturnYouTubeDislikePatch : BaseBytecodePatch(
TextComponentContextFingerprint.resultOrThrow().let { TextComponentContextFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val conversionContextFieldIndex = getTargetIndexWithFieldReferenceType("Ljava/util/Map;") - 1 val conversionContextFieldIndex =
getTargetIndexWithFieldReferenceType("Ljava/util/Map;") - 1
val conversionContextFieldReference = val conversionContextFieldReference =
getInstruction<ReferenceInstruction>(conversionContextFieldIndex).reference getInstruction<ReferenceInstruction>(conversionContextFieldIndex).reference
val charSequenceIndex = getTargetIndexWithFieldReferenceType("Ljava/util/BitSet;") - 1 val charSequenceIndex =
val charSequenceRegister = getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerA getTargetIndexWithFieldReferenceType("Ljava/util/BitSet;") - 1
val freeRegister = getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerB val charSequenceRegister =
getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerA
val freeRegister =
getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerB
addInstructions( addInstructions(
charSequenceIndex - 1, """ charSequenceIndex - 1, """

View File

@ -71,7 +71,8 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch(
if (SettingsPatch.upward1834) { if (SettingsPatch.upward1834) {
TextComponentSpecFingerprint.resultOrThrow().let { TextComponentSpecFingerprint.resultOrThrow().let {
it.mutableMethod.apply { 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 = val charSequenceRegister =
getInstruction<FiveRegisterInstruction>(insertIndex).registerC getInstruction<FiveRegisterInstruction>(insertIndex).registerC

View File

@ -46,11 +46,21 @@ object SettingsBytecodePatch : BytecodePatch(
} }
} }
MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR, "setExtendedUtils") MainActivityResolvePatch.injectOnCreateMethodCall(
MainActivityResolvePatch.injectOnCreateMethodCall(INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR, "onCreate") INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR,
MainActivityResolvePatch.injectConstructorMethodCall(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR, "setActivity") "setExtendedUtils"
)
MainActivityResolvePatch.injectOnCreateMethodCall(
INTEGRATIONS_INITIALIZATION_CLASS_DESCRIPTOR,
"onCreate"
)
MainActivityResolvePatch.injectConstructorMethodCall(
INTEGRATIONS_UTILS_CLASS_DESCRIPTOR,
"setActivity"
)
} }
private fun MutableMethod.injectCall(index: Int) { private fun MutableMethod.injectCall(index: Int) {
val register = getInstruction<OneRegisterInstruction>(index).registerA val register = getInstruction<OneRegisterInstruction>(index).registerA

View File

@ -199,9 +199,11 @@ object SettingsPatch : BaseResourcePatch(
// region set ReVanced Integrations Version // 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 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( contexts.updatePatchStatusSettings(
"ReVanced Integrations", "ReVanced Integrations",

View File

@ -133,7 +133,8 @@ object SponsorBlockBytecodePatch : BytecodePatch(
it.mutableMethod.apply { it.mutableMethod.apply {
val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout) val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout)
val checkCastIndex = getTargetIndex(targetIndex, Opcode.CHECK_CAST) val checkCastIndex = getTargetIndex(targetIndex, Opcode.CHECK_CAST)
val targetRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA val targetRegister =
getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
addInstruction( addInstruction(
checkCastIndex + 1, checkCastIndex + 1,
@ -146,8 +147,12 @@ object SponsorBlockBytecodePatch : BytecodePatch(
RectangleFieldInvalidatorFingerprint.resultOrThrow().let { result -> RectangleFieldInvalidatorFingerprint.resultOrThrow().let { result ->
result.mutableMethod.apply { result.mutableMethod.apply {
val invalidateIndex = getTargetIndexWithMethodReferenceNameReversed("invalidate") val invalidateIndex = getTargetIndexWithMethodReferenceNameReversed("invalidate")
val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(invalidateIndex + 1, "Landroid/graphics/Rect;") val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(
val rectangleFieldName = (getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name invalidateIndex + 1,
"Landroid/graphics/Rect;"
)
val rectangleFieldName =
(getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name
SegmentPlaybackControllerFingerprint.resultOrThrow().let { SegmentPlaybackControllerFingerprint.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {

View File

@ -25,9 +25,10 @@ object ViewGroupMarginLayoutParamsHookPatch : BytecodePatch(
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val method = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method -> val method =
method.name == "hideViewGroupByMarginLayoutParams" context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method ->
} ?: throw PatchException("Could not find hideViewGroupByMarginLayoutParams method") method.name == "hideViewGroupByMarginLayoutParams"
} ?: throw PatchException("Could not find hideViewGroupByMarginLayoutParams method")
SetViewGroupMarginFingerprint.resolve( SetViewGroupMarginFingerprint.resolve(
context, context,

View File

@ -92,6 +92,7 @@ object VideoInformationPatch : BytecodePatch(
private const val REGISTER_VIDEO_ID = 2 private const val REGISTER_VIDEO_ID = 2
private const val REGISTER_VIDEO_TITLE = 3 private const val REGISTER_VIDEO_TITLE = 3
private const val REGISTER_VIDEO_LENGTH = 4 private const val REGISTER_VIDEO_LENGTH = 4
@Suppress("unused") @Suppress("unused")
private const val REGISTER_VIDEO_LENGTH_DUMMY = 5 private const val REGISTER_VIDEO_LENGTH_DUMMY = 5
private const val REGISTER_VIDEO_IS_LIVE = 6 private const val REGISTER_VIDEO_IS_LIVE = 6
@ -118,7 +119,8 @@ object VideoInformationPatch : BytecodePatch(
internal lateinit var videoEndMethod: MutableMethod internal lateinit var videoEndMethod: MutableMethod
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val videoInformationMutableClass = context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass val videoInformationMutableClass =
context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass
VideoEndFingerprint.resultOrThrow().let { VideoEndFingerprint.resultOrThrow().let {
@ -173,7 +175,8 @@ object VideoInformationPatch : BytecodePatch(
true 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.hookVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V")
VideoIdPatch.hookPlayerResponseVideoId( 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, // Call before any other video id hooks,
// so they can use VideoInformation and check if the video id is for a Short. // so they can use VideoInformation and check if the video id is for a Short.
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.PlayerParameterBeforeVideoId( 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 * Hook current playback speed
@ -278,7 +283,8 @@ object VideoInformationPatch : BytecodePatch(
speedSelectionInsertMethod = this speedSelectionInsertMethod = this
val speedSelectionValueInstructionIndex = getTargetIndex(Opcode.IGET) val speedSelectionValueInstructionIndex = getTargetIndex(Opcode.IGET)
val setPlaybackSpeedContainerClassFieldIndex = getTargetIndexReversed(speedSelectionValueInstructionIndex, Opcode.IGET_OBJECT) val setPlaybackSpeedContainerClassFieldIndex =
getTargetIndexReversed(speedSelectionValueInstructionIndex, Opcode.IGET_OBJECT)
val setPlaybackSpeedContainerClassFieldReference = val setPlaybackSpeedContainerClassFieldReference =
getInstruction<ReferenceInstruction>(setPlaybackSpeedContainerClassFieldIndex).reference.toString() getInstruction<ReferenceInstruction>(setPlaybackSpeedContainerClassFieldIndex).reference.toString()
@ -447,7 +453,7 @@ object VideoInformationPatch : BytecodePatch(
"invoke-static { p1, p2 }, $targetMethodClass->$targetMethodName(J)V" "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 { resultOrThrow().mutableMethod.apply {
val targetIndex = indexOfFirstInstruction { val targetIndex = indexOfFirstInstruction {
opcode == Opcode.INVOKE_INTERFACE opcode == Opcode.INVOKE_INTERFACE
@ -465,7 +471,13 @@ object VideoInformationPatch : BytecodePatch(
ImmutableMethod( ImmutableMethod(
definingClass, definingClass,
"setVideoInformation", "setVideoInformation",
listOf(ImmutableMethodParameter(PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR, annotations, null)), listOf(
ImmutableMethodParameter(
PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR,
annotations,
null
)
),
"V", "V",
AccessFlags.PRIVATE or AccessFlags.FINAL, AccessFlags.PRIVATE or AccessFlags.FINAL,
annotations, annotations,

View File

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

View File

@ -125,7 +125,8 @@ object VideoPlaybackPatch : BaseBytecodePatch(
QualityChangedFromRecyclerViewFingerprint.resultOrThrow().classDef QualityChangedFromRecyclerViewFingerprint.resultOrThrow().classDef
) )
val newMethod = PlaybackSpeedChangedFromRecyclerViewFingerprint.resultOrThrow().mutableMethod val newMethod =
PlaybackSpeedChangedFromRecyclerViewFingerprint.resultOrThrow().mutableMethod
arrayOf( arrayOf(
newMethod, newMethod,
@ -293,7 +294,8 @@ object VideoPlaybackPatch : BaseBytecodePatch(
ByteBufferArrayFingerprint.also { it.resolve(context, classDef) }.resultOrThrow().let { ByteBufferArrayFingerprint.also { it.resolve(context, classDef) }.resultOrThrow().let {
it.mutableMethod.apply { it.mutableMethod.apply {
val insertIndex = it.scanResult.patternScanResult!!.endIndex val insertIndex = it.scanResult.patternScanResult!!.endIndex
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA val insertRegister =
getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(
insertIndex, """ insertIndex, """

View File

@ -95,7 +95,8 @@ object PlayerResponseMethodHookPatch :
internal class VideoId(methodDescriptor: String) : Hook(methodDescriptor) internal class VideoId(methodDescriptor: String) : Hook(methodDescriptor)
internal class PlayerParameter(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 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. * @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 -> fun MethodFingerprint.setFields(consumer: (MutableMethod, Int, Int) -> Unit) =
val videoIdRegisterIndex = result.scanResult.patternScanResult!!.endIndex resultOrThrow().let { result ->
val videoIdRegisterIndex = result.scanResult.patternScanResult!!.endIndex
result.mutableMethod.let { result.mutableMethod.let {
val videoIdRegister = it.getInstruction<OneRegisterInstruction>(videoIdRegisterIndex).registerA val videoIdRegister =
val insertIndex = videoIdRegisterIndex + 1 it.getInstruction<OneRegisterInstruction>(videoIdRegisterIndex).registerA
consumer(it, insertIndex, videoIdRegister) val insertIndex = videoIdRegisterIndex + 1
consumer(it, insertIndex, videoIdRegister)
}
} }
}
VideoIdFingerprint.resolve(context, VideoIdParentFingerprint.resultOrThrow().classDef) VideoIdFingerprint.resolve(context, VideoIdParentFingerprint.resultOrThrow().classDef)

View File

@ -181,7 +181,8 @@ fun BytecodeContext.literalInstructionHook(
.mutableClass .mutableClass
.findMutableMethodOf(method).apply { .findMutableMethodOf(method).apply {
val index = getWideLiteralInstructionIndex(literal) val index = getWideLiteralInstructionIndex(literal)
val register = (instruction as OneRegisterInstruction).registerA.toString() val register =
(instruction as OneRegisterInstruction).registerA.toString()
addInstructions( addInstructions(
index + 1, index + 1,
@ -205,8 +206,7 @@ fun Method.getWideLiteralInstructionIndex(literal: Long) = implementation?.let {
} }
} ?: -1 } ?: -1
fun Method.getEmptyStringInstructionIndex() fun Method.getEmptyStringInstructionIndex() = getStringInstructionIndex("")
= getStringInstructionIndex("")
fun Method.getStringInstructionIndex(value: String) = implementation?.let { fun Method.getStringInstructionIndex(value: String) = implementation?.let {
it.instructions.indexOfFirst { instruction -> it.instructions.indexOfFirst { instruction ->
@ -300,8 +300,8 @@ fun Method.getTargetIndexWithFieldReferenceName(filedName: String) = implementat
} }
} ?: -1 } ?: -1
fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed(returnType: String) fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed(returnType: String) =
= getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType) getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType)
fun MutableMethod.getTargetIndexWithFieldReferenceName(startIndex: Int, filedName: String) = fun MutableMethod.getTargetIndexWithFieldReferenceName(startIndex: Int, filedName: String) =
implementation!!.instructions.let { 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) { for (index in startIndex downTo 0) {
val instruction = getInstruction(index) val instruction = getInstruction(index)
if (instruction.getReference<FieldReference>()?.name != filedName) if (instruction.getReference<FieldReference>()?.name != filedName)
@ -327,8 +330,8 @@ fun Method.getTargetIndexWithFieldReferenceType(returnType: String) = implementa
} }
} ?: -1 } ?: -1
fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed(returnType: String) fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed(returnType: String) =
= getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType) getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType)
fun MutableMethod.getTargetIndexWithFieldReferenceType(startIndex: Int, returnType: String) = fun MutableMethod.getTargetIndexWithFieldReferenceType(startIndex: Int, returnType: String) =
implementation!!.instructions.let { 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) { for (index in startIndex downTo 0) {
val instruction = getInstruction(index) val instruction = getInstruction(index)
if (instruction.getReference<FieldReference>()?.type != returnType) if (instruction.getReference<FieldReference>()?.type != returnType)
@ -354,8 +360,11 @@ fun Method.getTargetIndexWithMethodReferenceName(methodName: String) = implement
} }
} ?: -1 } ?: -1
fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(methodName: String) fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(methodName: String) =
= getTargetIndexWithMethodReferenceNameReversed(implementation!!.instructions.size - 1, methodName) getTargetIndexWithMethodReferenceNameReversed(
implementation!!.instructions.size - 1,
methodName
)
fun MutableMethod.getTargetIndexWithMethodReferenceName(startIndex: Int, methodName: String) = 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) { for (index in startIndex downTo 0) {
val instruction = getInstruction(index) val instruction = getInstruction(index)
if (instruction.getReference<MethodReference>()?.name != methodName) if (instruction.getReference<MethodReference>()?.name != methodName)
@ -494,11 +506,13 @@ fun List<MethodFingerprint>.returnEarly(bool: Boolean = false) {
const/4 v0, $const const/4 v0, $const
return-object v0 return-object v0
""" """
'V' -> "return-void" 'V' -> "return-void"
'I', 'Z' -> """ 'I', 'Z' -> """
const/4 v0, $const const/4 v0, $const
return v0 return v0
""" """
else -> throw Exception("This case should never happen.") else -> throw Exception("This case should never happen.")
} }