From 56eff2a625e9f0c7e277d24c1a8460f1bf15730d Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 25 Jan 2026 01:10:30 +0100 Subject: [PATCH] some more migrations & fixing = to by for creating patches --- .../CustomCertificatesPatch.kt | 2 +- ...xportInternalDataDocumentsProviderPatch.kt | 2 +- .../revanced/patches/all/misc/hex/HexPatch.kt | 10 ++-- .../packagename/ChangePackageNamePatch.kt | 2 +- .../sharetargets/RemoveShareTargetsPatch.kt | 2 +- .../misc/spoof/EnableRomSignatureSpoofing.kt | 2 +- .../misc/targetSdk/SetTargetSdkVersion34.kt | 2 +- .../versioncode/ChangeVersionCodePatch.kt | 2 +- .../customclients/sync/ads/DisableAdsPatch.kt | 6 +- .../sync/syncforlemmy/ads/DisableAdsPatch.kt | 4 +- .../sync/syncforreddit/ads/DisableAdsPatch.kt | 4 +- .../fix/user/UseUserEndpointPatch.kt | 2 +- .../shared/layout/theme/Fingerprints.kt | 59 ++++++++----------- .../layout/theme/LithoColorHookPatch.kt | 4 +- .../misc/privacy/DisableSentryTelemetry.kt | 2 +- .../patches/songpal/badge/Fingerprints.kt | 48 ++++----------- .../patches/viber/ads/Fingerprints.kt | 12 +++- .../patches/viber/ads/HideAdsPatch.kt | 31 ++++------ .../ReturnYouTubeDislikePatch.kt | 4 +- .../youtube/layout/seekbar/Fingerprints.kt | 16 +++-- .../fix/backtoexitgesture/Fingerprints.kt | 9 +-- .../FixBackToExitGesturePatch.kt | 30 +++++----- .../misc/litho/filter/LithoFilterPatch.kt | 8 +-- .../youtube/misc/navigation/Fingerprints.kt | 14 ++--- .../misc/navigation/NavigationBarHookPatch.kt | 32 +++++----- .../patches/youtube/shared/Fingerprints.kt | 42 +++++++------ 26 files changed, 156 insertions(+), 195 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/customcertificates/CustomCertificatesPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/customcertificates/CustomCertificatesPatch.kt index b368b4001..d7230cb70 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/customcertificates/CustomCertificatesPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/customcertificates/CustomCertificatesPatch.kt @@ -10,7 +10,7 @@ import org.w3c.dom.Element import java.io.File @Suppress("unused", "ObjectPropertyName") -val `Custom network security` = creatingResourcePatch( +val `Custom network security` by creatingResourcePatch( description = "Allows trusting custom certificate authorities for a specific domain.", use = false, ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/directory/documentsprovider/ExportInternalDataDocumentsProviderPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/directory/documentsprovider/ExportInternalDataDocumentsProviderPatch.kt index 2be947ac2..d669539b6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/directory/documentsprovider/ExportInternalDataDocumentsProviderPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/directory/documentsprovider/ExportInternalDataDocumentsProviderPatch.kt @@ -6,7 +6,7 @@ import app.revanced.util.asSequence import app.revanced.util.getNode @Suppress("unused", "ObjectPropertyName") -val `Export internal data documents provider` = creatingResourcePatch( +val `Export internal data documents provider` by creatingResourcePatch( description = "Exports a documents provider that grants access to the internal data directory of this app " + "to file managers and other apps that support the Storage Access Framework.", use = false, diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/hex/HexPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/hex/HexPatch.kt index bf8a088ff..581685d10 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/hex/HexPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/hex/HexPatch.kt @@ -8,7 +8,7 @@ import app.revanced.patches.shared.misc.hex.hexPatch import app.revanced.util.Utils.trimIndentMultiline @Suppress("unused") -val Hex = creatingRawResourcePatch( +val Hex by creatingRawResourcePatch( description = "Replaces a hexadecimal patterns of bytes of files in an APK.", use = false, ) { @@ -40,13 +40,13 @@ val Hex = creatingRawResourcePatch( } catch (e: Exception) { throw PatchException( "Invalid replacement: $replacement.\n" + - "Every pattern must be followed by a pipe ('|'), " + - "the replacement pattern, another pipe ('|'), " + - "and the path to the file to make the changes in relative to the APK root. ", + "Every pattern must be followed by a pipe ('|'), " + + "the replacement pattern, another pipe ('|'), " + + "and the path to the file to make the changes in relative to the APK root. ", ) } } }, - ) + ), ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/packagename/ChangePackageNamePatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/packagename/ChangePackageNamePatch.kt index e3f50eade..14d51c56e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/packagename/ChangePackageNamePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/packagename/ChangePackageNamePatch.kt @@ -27,7 +27,7 @@ fun setOrGetFallbackPackageName(fallbackPackageName: String): String { } @Suppress("ObjectPropertyName") -val `Change package name` = creatingResourcePatch( +val `Change package name` by creatingResourcePatch( description = "Appends \".revanced\" to the package name by default. " + "Changing the package name of the app can lead to unexpected issues.", use = false, diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/shortcut/sharetargets/RemoveShareTargetsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/shortcut/sharetargets/RemoveShareTargetsPatch.kt index b7991dcd9..14ba0293e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/shortcut/sharetargets/RemoveShareTargetsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/shortcut/sharetargets/RemoveShareTargetsPatch.kt @@ -8,7 +8,7 @@ import java.io.FileNotFoundException import java.util.logging.Logger @Suppress("unused", "ObjectPropertyName") -val `Remove share targets` = creatingResourcePatch( +val `Remove share targets` by creatingResourcePatch( description = "Removes share targets like directly sharing to a frequent contact.", use = false, ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/EnableRomSignatureSpoofing.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/EnableRomSignatureSpoofing.kt index d29081968..af5999dfc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/EnableRomSignatureSpoofing.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/spoof/EnableRomSignatureSpoofing.kt @@ -14,7 +14,7 @@ import java.security.cert.CertificateFactory import java.util.* @Suppress("unused", "ObjectPropertyName") -val `Enable ROM signature spoofing` = creatingResourcePatch( +val `Enable ROM signature spoofing` by creatingResourcePatch( description = "Spoofs the signature via the manifest meta-data \"fake-signature\". " + "This patch only works with ROMs that support signature spoofing.", use = false, diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/targetSdk/SetTargetSdkVersion34.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/targetSdk/SetTargetSdkVersion34.kt index e3ca2f81f..0b9121e45 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/targetSdk/SetTargetSdkVersion34.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/targetSdk/SetTargetSdkVersion34.kt @@ -6,7 +6,7 @@ import org.w3c.dom.Element import java.util.logging.Logger @Suppress("unused", "ObjectPropertyName") -val `Set target SDK version 34` = creatingResourcePatch( +val `Set target SDK version 34` by creatingResourcePatch( description = "Changes the target SDK to version 34 (Android 14). " + "For devices running Android 15+, this will disable edge-to-edge display.", use = false, diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/versioncode/ChangeVersionCodePatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/versioncode/ChangeVersionCodePatch.kt index b61dbd882..5dff94834 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/versioncode/ChangeVersionCodePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/versioncode/ChangeVersionCodePatch.kt @@ -6,7 +6,7 @@ import app.revanced.util.getNode import org.w3c.dom.Element @Suppress("unused", "ObjectPropertyName") -val `Change version code` = creatingResourcePatch( +val `Change version code` by creatingResourcePatch( description = "Changes the version code of the app. This will turn off app store updates " + "and allows downgrading an existing app install to an older app version.", use = false, diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/DisableAdsPatch.kt index 165a3432f..8db9d168c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/DisableAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/ads/DisableAdsPatch.kt @@ -1,10 +1,12 @@ package app.revanced.patches.reddit.customclients.sync.ads import app.revanced.patcher.patch.BytecodePatchBuilder -import app.revanced.patcher.patch.creatingBytecodePatch +import app.revanced.patcher.patch.bytecodePatch import app.revanced.util.returnEarly -fun `Disable ads`(block: BytecodePatchBuilder.() -> Unit = {}) = creatingBytecodePatch { +fun disableAdsPatch(block: BytecodePatchBuilder.() -> Unit = {}) = bytecodePatch( + name = "Disable ads", +) { apply { isAdsEnabledMethod.returnEarly(false) } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforlemmy/ads/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforlemmy/ads/DisableAdsPatch.kt index 4587bdec1..ca74997aa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforlemmy/ads/DisableAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforlemmy/ads/DisableAdsPatch.kt @@ -1,10 +1,10 @@ package app.revanced.patches.reddit.customclients.sync.syncforlemmy.ads -import app.revanced.patches.reddit.customclients.sync.ads.`Disable ads` +import app.revanced.patches.reddit.customclients.sync.ads.disableAdsPatch import app.revanced.patches.reddit.customclients.sync.detection.piracy.disablePiracyDetectionPatch @Suppress("unused") -val disableAdsPatch = `Disable ads` { +val disableAdsPatch = disableAdsPatch { dependsOn(disablePiracyDetectionPatch) compatibleWith("com.laurencedawson.reddit_sync") diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/ads/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/ads/DisableAdsPatch.kt index dc25002c9..e50158cdd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/ads/DisableAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/ads/DisableAdsPatch.kt @@ -1,8 +1,8 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.ads -import app.revanced.patches.reddit.customclients.sync.ads.`Disable ads` +import app.revanced.patches.reddit.customclients.sync.ads.disableAdsPatch @Suppress("unused") -val disableAdsPatch = `Disable ads` { +val disableAdsPatch = disableAdsPatch { compatibleWith("io.syncapps.lemmy_sync") } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatch.kt index cd93db2dc..15504ee06 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatch.kt @@ -27,7 +27,7 @@ val `Use /user/ endpoint` by creatingBytecodePatch( oAuthUserIdRequestMethodMatch, oAuthUserInfoRequestMethodMatch, ).map { match -> - match.stringIndices.values.first() to match.method + match.indices.first() to match.method }.forEach { (userPathStringIndex, method) -> val userPathStringInstruction = method.getInstruction(userPathStringIndex) diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/Fingerprints.kt index 38ff79c69..c0ea184c6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/Fingerprints.kt @@ -1,50 +1,39 @@ package app.revanced.patches.shared.layout.theme -import app.revanced.patcher.accessFlags -import app.revanced.patcher.allOf -import app.revanced.patcher.field -import app.revanced.patcher.fieldAccess -import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.instructions -import app.revanced.patcher.invoke -import app.revanced.patcher.methodCall -import app.revanced.patcher.parameterTypes -import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.returnType +import app.revanced.patcher.* import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val BytecodePatchContext.lithoOnBoundsChangeMethod by gettingFirstMethodDeclaratively { +internal val lithoOnBoundsChangeMethodMatch = firstMethodComposite { + name("onBoundsChange") accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/graphics/Rect;") + + lateinit var methodDefiningClass: String + custom { + methodDefiningClass = definingClass + true + } + instructions( - allOf(Opcode.IPUT_OBJECT(), field { definingClass type == "Landroid/graphics/Path;" }), - fieldAccess( - opcode = Opcode.IPUT_OBJECT, - definingClass = "this", - type = "Landroid/graphics/Path;", + allOf( + Opcode.IPUT_OBJECT(), + field { type == "Landroid/graphics/Path;" && definingClass == methodDefiningClass }, ), - - methodCall( - definingClass = "this", - name = "isStateful", - returnType = "Z", - afterAtMost(5), + afterAtMost( + 5, + method { returnType == "Z" && name == "isStateful" && definingClass == methodDefiningClass }, ), - - fieldAccess( - opcode = Opcode.IGET_OBJECT, - definingClass = "this", - type = "Landroid/graphics/Paint", - afterAtMost(5), + afterAtMost( + 5, + allOf( + Opcode.IGET_OBJECT(), + field { type == "Landroid/graphics/Path;" && definingClass == methodDefiningClass }, + ), ), - methodCall( - smali = "Landroid/graphics/Paint;->setColor(I)V", - after(), + after( + method { toString() == "Landroid/graphics/Paint;->setColor(I)V" }, ), ) - custom { method, _ -> - method.name == "onBoundsChange" - } } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/LithoColorHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/LithoColorHookPatch.kt index c0f085bde..f373d593c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/LithoColorHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/LithoColorHookPatch.kt @@ -11,10 +11,10 @@ val lithoColorHookPatch = bytecodePatch( ) { apply { - var insertionIndex = lithoOnBoundsChangeMethod.patternMatch.endIndex - 1 + var insertionIndex = lithoOnBoundsChangeMethodMatch.indices.last() - 1 lithoColorOverrideHook = { targetMethodClass, targetMethodName -> - lithoOnBoundsChangeMethod.addInstructions( + lithoOnBoundsChangeMethodMatch.method.addInstructions( insertionIndex, """ invoke-static { p1 }, $targetMethodClass->$targetMethodName(I)I diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/DisableSentryTelemetry.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/DisableSentryTelemetry.kt index 960074997..936bca758 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/DisableSentryTelemetry.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/DisableSentryTelemetry.kt @@ -6,7 +6,7 @@ import app.revanced.util.getNode import org.w3c.dom.Element @Suppress("unused", "ObjectPropertyName") -val `Disable Sentry telemetry` = creatingResourcePatch( +val `Disable Sentry telemetry` by creatingResourcePatch( description = "Disables Sentry telemetry. See https://sentry.io/for/android/ for more information.", use = false, ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/songpal/badge/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/songpal/badge/Fingerprints.kt index 82b5bb2c6..c1fa94636 100644 --- a/patches/src/main/kotlin/app/revanced/patches/songpal/badge/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/songpal/badge/Fingerprints.kt @@ -1,53 +1,29 @@ package app.revanced.patches.songpal.badge -import app.revanced.patcher.accessFlags -import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.instructions +import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.returnType import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference +import com.android.tools.smali.dexlib2.util.MethodUtil // Located @ ub.i0.h#p (9.5.0) -internal val BytecodePatchContext.createTabsMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.createTabsMethod by gettingFirstMutableMethodDeclaratively { accessFlags(AccessFlags.PRIVATE) returnType("Ljava/util/List;") - custom { method, _ -> - method.implementation?.instructions?.any { instruction -> - if (instruction.opcode != Opcode.INVOKE_STATIC) return@any false - - val reference = (instruction as ReferenceInstruction).reference as MethodReference - - if (reference.parameterTypes.isNotEmpty()) return@any false - if (reference.definingClass != ACTIVITY_TAB_DESCRIPTOR) return@any false - if (reference.returnType != "[${ACTIVITY_TAB_DESCRIPTOR}") return@any false - true - } == true - } + instructions( + method { + parameterTypes.isEmpty() && + definingClass == ACTIVITY_TAB_DESCRIPTOR && + returnType == "[${ACTIVITY_TAB_DESCRIPTOR}" + }, + ) } // Located @ com.sony.songpal.mdr.vim.activity.MdrRemoteBaseActivity.e#run (9.5.0) -internal val BytecodePatchContext.showNotificationMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.showNotificationMethod by gettingFirstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC) returnType("V") - custom { method, _ -> - method.implementation?.instructions?.any { instruction -> - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return@any false - - with(expectedReference) { - val currentReference = (instruction as ReferenceInstruction).reference as MethodReference - currentReference.let { - if (it.definingClass != definingClass) return@any false - if (it.parameterTypes != parameterTypes) return@any false - if (it.returnType != returnType) return@any false - } - } - true - } == true - } + instructions(method { MethodUtil.methodSignaturesMatch(this, expectedReference) }) } internal val expectedReference = ImmutableMethodReference( diff --git a/patches/src/main/kotlin/app/revanced/patches/viber/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/viber/ads/Fingerprints.kt index 58537345e..134279d9a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/viber/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/viber/ads/Fingerprints.kt @@ -1,5 +1,13 @@ package app.revanced.patches.viber.ads -internal val BytecodePatchContext.findAdStringMethod by gettingFirstMethodDeclaratively { - strings("viber_plus_debug_ads_free_flag") +import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.instructions +import app.revanced.patcher.invoke +import com.android.tools.smali.dexlib2.Opcode + +internal val findAdStringMethodMatch = firstMethodComposite { + instructions( + Opcode.NEW_INSTANCE(), + "viber_plus_debug_ads_free_flag"(), + ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/viber/ads/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/viber/ads/HideAdsPatch.kt index 016736473..92afbd780 100644 --- a/patches/src/main/kotlin/app/revanced/patches/viber/ads/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/viber/ads/HideAdsPatch.kt @@ -1,12 +1,14 @@ package app.revanced.patches.viber.ads +import app.revanced.patcher.definingClass import app.revanced.patcher.extensions.getInstruction +import app.revanced.patcher.extensions.typeReference +import app.revanced.patcher.firstMutableMethodDeclaratively +import app.revanced.patcher.parameterTypes import app.revanced.patcher.patch.creatingBytecodePatch -import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.patcher.returnType import app.revanced.util.returnEarly -import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.TypeReference @Suppress("unused", "ObjectPropertyName") val `Hide Ads` by creatingBytecodePatch( @@ -15,26 +17,15 @@ val `Hide Ads` by creatingBytecodePatch( compatibleWith("com.viber.voip"("25.9.2.0", "26.1.2.0")) apply { - val method = findAdStringMethod + val referenceIndex = findAdStringMethodMatch.indices.first() - // Find the ads free string index - val stringIndex = findAdStringMethod.stringMatches.first().index + val targetClass = + findAdStringMethodMatch.immutableMethod.getInstruction(referenceIndex).typeReference - // Search backwards from the string to find the `new-instance` (TypeReference) instruction - val typeRefIndex = - method.indexOfFirstInstructionReversedOrThrow(stringIndex) { this.opcode == Opcode.NEW_INSTANCE } - - // Get the class name from the TypeReference - val targetClass = method.getInstruction(typeRefIndex).reference as TypeReference - - // Patch the ads-free method to always return true - val adFreeFingerprint = fingerprint { + val adFreeFingerprint = firstMutableMethodDeclaratively { + definingClass(targetClass!!.type) returnType("I") parameterTypes() - custom { method, classDef -> - classDef == targetClass - } - } - adFreeFingerprint.method.returnEarly(1) + }.returnEarly(1) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index 48990d27a..435f55531 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -17,7 +17,7 @@ import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.misc.playservice.* import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.conversionContextFingerprintToString +import app.revanced.patches.youtube.shared.conversionContextToStringMethod import app.revanced.patches.youtube.shared.rollingNumberTextViewAnimationUpdateMethod import app.revanced.patches.youtube.video.videoid.hookPlayerResponseVideoId import app.revanced.patches.youtube.video.videoid.hookVideoId @@ -121,7 +121,7 @@ val `Return YouTube Dislike` by creatingBytecodePatch( // This hook handles all situations, as it's where the created Spans are stored and later reused. // Find the field name of the conversion context. - val conversionContextClass = conversionContextFingerprintToString.originalClassDef + val conversionContextClass = conversionContextToStringMethod.originalClassDef val textComponentConversionContextField = textComponentConstructorMethod.originalClassDef.fields.find { it.type == conversionContextClass.type || // 20.41+ uses superclass field type. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt index dd86dd144..2dcdc2807 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt @@ -4,10 +4,13 @@ import app.revanced.patcher.accessFlags import app.revanced.patcher.addString import app.revanced.patcher.afterAtMost import app.revanced.patcher.anyInstruction +import app.revanced.patcher.custom +import app.revanced.patcher.definingClass import app.revanced.patcher.gettingFirstMethodDeclaratively import app.revanced.patcher.instructions import app.revanced.patcher.invoke import app.revanced.patcher.literal +import app.revanced.patcher.method import app.revanced.patcher.methodCall import app.revanced.patcher.opcode import app.revanced.patcher.opcodes @@ -113,15 +116,18 @@ internal val BytecodePatchContext.playerLinearGradientLegacyMethod by gettingFir internal const val LOTTIE_ANIMATION_VIEW_CLASS_TYPE = "Lcom/airbnb/lottie/LottieAnimationView;" internal val BytecodePatchContext.lottieAnimationViewSetAnimationIntMethod by gettingFirstMethodDeclaratively { + definingClass(LOTTIE_ANIMATION_VIEW_CLASS_TYPE) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameterTypes("I") returnType("V") - instructions( - methodCall("this", "isInEditMode"), - ) - custom { _, classDef -> - classDef.type == LOTTIE_ANIMATION_VIEW_CLASS_TYPE + + lateinit var methodDefiningClass: String + custom { + methodDefiningClass = definingClass + true } + + instructions(method { name == "isInEditMode" && definingClass == methodDefiningClass }) } internal val BytecodePatchContext.lottieCompositionFactoryZipMethod by gettingFirstMethodDeclaratively { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt index e6332410e..2eae6d63f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt @@ -3,20 +3,18 @@ package app.revanced.patches.youtube.misc.fix.backtoexitgesture import app.revanced.patcher.accessFlags import app.revanced.patcher.after import app.revanced.patcher.checkCast -import app.revanced.patcher.gettingFirstMethodDeclaratively +import app.revanced.patcher.firstMethodComposite import app.revanced.patcher.instructions import app.revanced.patcher.invoke import app.revanced.patcher.literal import app.revanced.patcher.methodCall -import app.revanced.patcher.opcode import app.revanced.patcher.opcodes import app.revanced.patcher.parameterTypes -import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.returnType import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val BytecodePatchContext.scrollPositionMethod by gettingFirstMethodDeclaratively { +internal val scrollPositionMethodMatch = firstMethodComposite("scroll_position") { accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returnType("V") parameterTypes("L") @@ -25,10 +23,9 @@ internal val BytecodePatchContext.scrollPositionMethod by gettingFirstMethodDecl Opcode.INVOKE_DIRECT, Opcode.RETURN_VOID, ) - strings("scroll_position") } -internal val BytecodePatchContext.recyclerViewTopScrollingMethod by gettingFirstMethodDeclaratively { +internal val recyclerViewTopScrollingMethodMatch = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt index 8df94702d..1e91dc580 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt @@ -16,27 +16,25 @@ internal val fixBackToExitGesturePatch = bytecodePatch( ) { apply { - recyclerViewTopScrollingMethod.let { - it.method.addInstructionsAtControlFlowLabel( - it.indices.last() + 1, + with(recyclerViewTopScrollingMethodMatch) { + method.addInstructionsAtControlFlowLabel( + indices.last() + 1, "invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onTopView()V", ) } - scrollPositionMethod.let { - navigate(it.originalMethod) - .to(it.patternMatch.startIndex + 1) - .stop().apply { - val index = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_VIRTUAL && getReference()?.definingClass == - "Landroid/support/v7/widget/RecyclerView;" - } - - addInstruction( - index, - "invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onScrollingViews()V", - ) + with(scrollPositionMethodMatch) { + navigate(immutableMethod).to(indices.first() + 1).stop().apply { + val index = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && getReference()?.definingClass == + "Landroid/support/v7/widget/RecyclerView;" } + + addInstruction( + index, + "invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onScrollingViews()V", + ) + } } mainActivityOnBackPressedMethod.apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt index a698e6aa2..fd6820372 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt @@ -10,7 +10,7 @@ import app.revanced.patcher.firstClassDef import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.playservice.* -import app.revanced.patches.youtube.shared.conversionContextFingerprintToString +import app.revanced.patches.youtube.shared.conversionContextToStringMethod import app.revanced.util.* import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -112,10 +112,10 @@ val lithoFilterPatch = bytecodePatch( // Find the identifier/path fields of the conversion context. - val conversionContextIdentifierField = conversionContextFingerprintToString.method + val conversionContextIdentifierField = conversionContextToStringMethod.method .findFieldFromToString("identifierProperty=") - val conversionContextPathBuilderField = conversionContextFingerprintToString.originalClassDef + val conversionContextPathBuilderField = conversionContextToStringMethod.originalClassDef .fields.single { field -> field.type == "Ljava/lang/StringBuilder;" } // Find class and methods to create an empty component. @@ -146,7 +146,7 @@ val lithoFilterPatch = bytecodePatch( # 20.41 field is the abstract superclass. # Verify it's the expected subclass just in case. - instance-of v$identifierRegister, v$freeRegister, ${conversionContextFingerprintToString.classDef.type} + instance-of v$identifierRegister, v$freeRegister, ${conversionContextToStringMethod.classDef.type} if-eqz v$identifierRegister, :unfiltered iget-object v$identifierRegister, v$freeRegister, $conversionContextIdentifierField diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt index d0ff15f73..80394fb77 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt @@ -10,6 +10,7 @@ import app.revanced.patcher.returnType import app.revanced.patches.shared.misc.mapping.ResourceType import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef internal val BytecodePatchContext.actionBarSearchResultsMethod by gettingFirstMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) @@ -43,7 +44,8 @@ internal val BytecodePatchContext.appCompatToolbarBackButtonMethod by gettingFir /** * Matches to the class found in [pivotBarConstructorMethod]. */ -internal val BytecodePatchContext.initializeButtonsMethod by gettingFirstMethodDeclaratively { +context(_: BytecodePatchContext) +internal fun ClassDef.getInitializeButtonsMethod() = firstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") instructions( @@ -114,16 +116,12 @@ internal val BytecodePatchContext.pivotBarButtonsCreateResourceIntViewMethod by } } -internal val BytecodePatchContext.pivotBarButtonsViewSetSelectedMethod by gettingFirstMethodDeclaratively { +internal val pivotBarButtonsViewSetSelectedMethodMatch = firstMethodComposite { + definingClass("Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("I", "Z") - instructions( - methodCall(name = "setSelected"), - ) - custom { method, _ -> - method.definingClass == "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;" - } + instructions(method("setSelected")) } internal val BytecodePatchContext.pivotBarConstructorMethod by gettingFirstMethodDeclaratively { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt index b3f907882..c449140b8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -1,9 +1,11 @@ package app.revanced.patches.youtube.misc.navigation +import app.revanced.patcher.classDef import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.extensions.instructions +import app.revanced.patcher.immutableClassDef import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch @@ -75,7 +77,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig } } - initializeButtonsMethod.match(pivotBarConstructorMethod.originalClassDef).method.apply { + pivotBarConstructorMethod.immutableClassDef.getInitializeButtonsMethod().apply { // Hook the current navigation bar enum value. Note, the 'You' tab does not have an enum value. val navigationEnumClassName = navigationEnumMethod.classDef.type addHook(NavigationHook.SET_LAST_APP_NAVIGATION_ENUM) { @@ -93,37 +95,33 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig } if (is_20_21_or_greater && !is_20_28_or_greater) { - val imageResourceIntTabMethod = pivotBarButtonsCreateResourceIntViewMethod.originalMethod addHook(NavigationHook.NAVIGATION_TAB_LOADED) predicate@{ MethodUtil.methodSignaturesMatch( getReference() ?: return@predicate false, - imageResourceIntTabMethod, + pivotBarButtonsCreateResourceIntViewMethod, ) } } - val imageResourceTabMethod = pivotBarButtonsCreateResourceStyledViewMethod.originalMethod addHook(NavigationHook.NAVIGATION_IMAGE_RESOURCE_TAB_LOADED) predicate@{ MethodUtil.methodSignaturesMatch( getReference() ?: return@predicate false, - imageResourceTabMethod, + pivotBarButtonsCreateResourceStyledViewMethod, ) } } - pivotBarButtonsViewSetSelectedMethod.let { - it.method.apply { - val index = it.instructionMatches.first().index - val instruction = getInstruction(index) - val viewRegister = instruction.registerC - val isSelectedRegister = instruction.registerD + pivotBarButtonsViewSetSelectedMethodMatch.method.apply { + val index = pivotBarButtonsViewSetSelectedMethodMatch.indices.first() + val instruction = getInstruction(index) + val viewRegister = instruction.registerC + val isSelectedRegister = instruction.registerD - addInstruction( - index + 1, - "invoke-static { v$viewRegister, v$isSelectedRegister }, " + - "$EXTENSION_CLASS_DESCRIPTOR->navigationTabSelected(Landroid/view/View;Z)V", - ) - } + addInstruction( + index + 1, + "invoke-static { v$viewRegister, v$isSelectedRegister }, " + + "$EXTENSION_CLASS_DESCRIPTOR->navigationTabSelected(Landroid/view/View;Z)V", + ) } // Hook onto back button pressed. Needed to fix race problem with diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt index 00ebe58ca..96b647c07 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt @@ -3,11 +3,15 @@ package app.revanced.patches.youtube.shared import app.revanced.patcher.accessFlags import app.revanced.patcher.after import app.revanced.patcher.allOf +import app.revanced.patcher.custom import app.revanced.patcher.definingClass import app.revanced.patcher.field import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.firstMethodDeclaratively import app.revanced.patcher.gettingFirstMethodDeclaratively import app.revanced.patcher.gettingFirstMutableMethodDeclaratively +import app.revanced.patcher.immutableClassDef +import app.revanced.patcher.instruction import app.revanced.patcher.instructions import app.revanced.patcher.invoke import app.revanced.patcher.method @@ -23,19 +27,16 @@ import com.android.tools.smali.dexlib2.Opcode internal const val YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE = "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;" -internal val conversionContextFingerprintToString = fingerprint { +internal val BytecodePatchContext.conversionContextToStringMethod by gettingFirstMethodDeclaratively( + ", widthConstraint=", + ", heightConstraint=", + ", templateLoggerFactory=", + ", rootDisposableContainer=", + ", identifierProperty=", +) { + name("toString") parameterTypes() - strings( - "ConversionContext{", // Partial string match. - ", widthConstraint=", - ", heightConstraint=", - ", templateLoggerFactory=", - ", rootDisposableContainer=", - ", identifierProperty=", - ) - custom { method, _ -> - method.name == "toString" - } + instructions("ConversionContext{"(String::startsWith)) // Partial string match. } internal fun getLayoutConstructorMethodMatch() = firstMethodComposite { @@ -57,20 +58,17 @@ internal fun getLayoutConstructorMethodMatch() = firstMethodComposite { } internal val BytecodePatchContext.mainActivityConstructorMethod by gettingFirstMethodDeclaratively { + definingClass(YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE) accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameterTypes() - custom { _, classDef -> - classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE - } } -internal val BytecodePatchContext.mainActivityOnBackPressedMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.mainActivityOnBackPressedMethod by gettingFirstMutableMethodDeclaratively { + name("onBackPressed") + definingClass(YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() - custom { method, classDef -> - method.name == "onBackPressed" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE - } } internal val BytecodePatchContext.mainActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { @@ -99,9 +97,9 @@ internal val BytecodePatchContext.rollingNumberTextViewAnimationUpdateMethod by Opcode.INT_TO_FLOAT, Opcode.INVOKE_VIRTUAL, // set textview padding using bitmap width ) - custom { _, classDef -> - classDef.superclass == "Landroid/support/v7/widget/AppCompatTextView;" || - classDef.superclass == + custom { + immutableClassDef.superclass == "Landroid/support/v7/widget/AppCompatTextView;" || + immutableClassDef.superclass == "Lcom/google/android/libraries/youtube/rendering/ui/spec/typography/YouTubeAppCompatTextView;" } }