From 3a3fe5ed9bbea5ed68daca36817e3392fa819c98 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 25 Jan 2026 01:49:03 +0100 Subject: [PATCH] some more migrations --- .../music/misc/gms/GmsCoreSupportPatch.kt | 17 ++-- .../branding/BaseCustomBrandingPatch.kt | 2 +- .../shared/layout/branding/Fingerprints.kt | 17 ++-- .../patches/shared/misc/gms/Fingerprints.kt | 23 ++--- .../shared/misc/gms/GmsCoreSupportPatch.kt | 11 +-- .../youtube/misc/gms/GmsCoreSupportPatch.kt | 12 +-- .../misc/playercontrols/Fingerprints.kt | 85 +++++++------------ .../playercontrols/PlayerControlsPatch.kt | 68 ++++++--------- .../youtube/misc/playertype/Fingerprints.kt | 55 +++++------- .../misc/playertype/PlayerTypeHookPatch.kt | 50 +++++------ .../youtube/misc/settings/Fingerprints.kt | 28 ++---- .../youtube/misc/settings/SettingsPatch.kt | 7 +- .../quality/AdvancedVideoQualityMenuPatch.kt | 23 ++--- .../youtube/video/quality/Fingerprints.kt | 26 +++--- .../quality/RememberVideoQualityPatch.kt | 5 +- 15 files changed, 168 insertions(+), 261 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt index dbf518026..1adde0983 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.music.misc.gms +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.Option import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch @@ -19,7 +20,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch( fromPackageName = MUSIC_PACKAGE_NAME, toPackageName = REVANCED_MUSIC_PACKAGE_NAME, getPrimeMethod = { primeMethod }, - getEarlyReturnMethods = { setOf(castContextFetchMethod) }, + earlyReturnMethods = setOf(BytecodePatchContext::castContextFetchMethod::get), getMainActivityOnCreateMethod = { musicActivityOnCreateMethod }, extensionPatch = sharedExtensionPatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, @@ -28,8 +29,8 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch( compatibleWith( MUSIC_PACKAGE_NAME( "7.29.52", - "8.10.52" - ) + "8.10.52", + ), ) } @@ -50,17 +51,17 @@ private fun gmsCoreSupportResourcePatch( "microg_settings", intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") { "$gmsCoreVendorGroupId.android.gms" - } - ) + }, + ), ) - } + }, ) { dependsOn( addResourcesPatch, settingsPatch, fileProviderPatch( MUSIC_PACKAGE_NAME, - REVANCED_MUSIC_PACKAGE_NAME - ) + REVANCED_MUSIC_PACKAGE_NAME, + ), ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/BaseCustomBrandingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/BaseCustomBrandingPatch.kt index 3721cb998..854957efc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/BaseCustomBrandingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/BaseCustomBrandingPatch.kt @@ -334,7 +334,7 @@ internal fun baseCustomBrandingPatch( ) // Bundled icons. - iconStyleNames.forEachIndexed { index, style -> + iconStyleNames.forEach { style -> application.appendChild( createAlias( aliasName = aliasName(style), diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/Fingerprints.kt index 16963e60e..add3716a6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/Fingerprints.kt @@ -1,25 +1,22 @@ package app.revanced.patches.shared.layout.branding -import app.revanced.patcher.accessFlags -import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.parameterTypes +import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.returnType import com.android.tools.smali.dexlib2.AccessFlags -internal val BytecodePatchContext.numberOfPresetAppNamesExtensionMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.numberOfPresetAppNamesExtensionMethod by gettingFirstMutableMethodDeclaratively { + name("numberOfPresetAppNames") + definingClass(EXTENSION_CLASS_DESCRIPTOR) accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returnType("I") parameterTypes() - custom { method, classDef -> - method.name == "numberOfPresetAppNames" && classDef.type == EXTENSION_CLASS_DESCRIPTOR - } } // A much simpler fingerprint exists that can set the small icon (contains string "414843287017"), // but that has limited usage and this fingerprint allows changing any part of the notification. -internal val BytecodePatchContext.notificationMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.notificationMethod by gettingFirstMutableMethodDeclaratively( + "key_action_priority", +) { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameterTypes("L") - strings("key_action_priority") } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/Fingerprints.kt index e47d0d490..34a7b2d68 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/Fingerprints.kt @@ -1,13 +1,10 @@ package app.revanced.patches.shared.misc.gms -import app.revanced.patcher.accessFlags -import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.parameterTypes +import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patcher.returnType import com.android.tools.smali.dexlib2.AccessFlags -internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMethodDeclaratively( +internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMutableMethodDeclarativelyOrNull( "This should never happen.", "MetadataValueReader", "com.google.android.gms", @@ -17,7 +14,7 @@ internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMethodD parameterTypes("L", "I") } -internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMethodDeclaratively( +internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMutableMethodDeclaratively( "Google Play Services not available", ) { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) @@ -25,20 +22,18 @@ internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMethodDeclar parameterTypes("L", "I") } -internal val BytecodePatchContext.gmsCoreSupportMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.gmsCoreSupportMethod by gettingFirstMutableMethodDeclaratively { + name("getGmsCoreVendorGroupId") + definingClass(EXTENSION_CLASS_DESCRIPTOR) accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returnType("Ljava/lang/String;") parameterTypes() - custom { method, classDef -> - method.name == "getGmsCoreVendorGroupId" && classDef.type == EXTENSION_CLASS_DESCRIPTOR - } } -internal val BytecodePatchContext.originalPackageNameExtensionMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.originalPackageNameExtensionMethod by gettingFirstMutableMethodDeclaratively { + name("getOriginalPackageName") + definingClass(EXTENSION_CLASS_DESCRIPTOR) accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returnType("Ljava/lang/String;") parameterTypes() - custom { methodDef, classDef -> - methodDef.name == "getOriginalPackageName" && classDef.type == EXTENSION_CLASS_DESCRIPTOR - } } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt index 642920146..bb573cc50 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt @@ -4,7 +4,6 @@ import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.instructions import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patches.all.misc.packagename.`Change package name` import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName import app.revanced.patches.all.misc.resources.addResources @@ -36,7 +35,7 @@ private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$" * @param fromPackageName The package name of the original app. * @param toPackageName The package name to fall back to if no custom package name is specified in patch options. * @param getPrimeMethod The "prime" method that needs to be patched. - * @param getEarlyReturnMethods The methods that need to be returned early. + * @param earlyReturnMethods The methods that need to be returned early. * @param getMainActivityOnCreateMethod The main activity onCreate method. * @param extensionPatch The patch responsible for the extension. * @param gmsCoreSupportResourcePatchFactory The factory for the corresponding resource patch @@ -48,7 +47,7 @@ fun gmsCoreSupportPatch( fromPackageName: String, toPackageName: String, getPrimeMethod: (BytecodePatchContext.() -> MutableMethod)? = null, - getEarlyReturnMethods: Set MutableMethod> = emptySet(), + earlyReturnMethods: Set MutableMethod> = emptySet(), getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod, extensionPatch: Patch, gmsCoreSupportResourcePatchFactory: (gmsCoreVendorGroupIdOption: Option) -> Patch, @@ -203,13 +202,11 @@ fun gmsCoreSupportPatch( getPrimeMethod?.let { transformPrimeMethod(packageName) } // Return these methods early to prevent the app from crashing. - getEarlyReturnMethods().forEach { it.returnEarly() } + earlyReturnMethods.forEach { it().returnEarly() } serviceCheckMethod.returnEarly() // Google Play Utility is not present in all apps, so we need to check if it's present. - if (googlePlayUtilityMethodOrNull != null) { - googlePlayUtilityMethod.returnEarly(0) - } + googlePlayUtilityMethod?.returnEarly(0) // Set original and patched package names for extension to use. originalPackageNameExtensionMethod.returnEarly(fromPackageName) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt index e740689b2..7ddf45c9f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt @@ -22,7 +22,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch( fromPackageName = YOUTUBE_PACKAGE_NAME, toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME, getPrimeMethod = BytecodePatchContext::primeMethod::get, - getEarlyReturnMethods = setOf(BytecodePatchContext::castContextFetchMethod::get), + earlyReturnMethods = setOf(BytecodePatchContext::castContextFetchMethod::get), getMainActivityOnCreateMethod = BytecodePatchContext::mainActivityOnCreateMethod::get, extensionPatch = sharedExtensionPatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, @@ -38,7 +38,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch( "20.14.43", "20.21.37", "20.31.40", - ) + ), ) } @@ -59,14 +59,14 @@ private fun gmsCoreSupportResourcePatch( "microg_settings", intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") { "$gmsCoreVendorGroupId.android.gms" - } - ) + }, + ), ) - } + }, ) { dependsOn( addResourcesPatch, settingsPatch, - accountCredentialsInvalidTextPatch + accountCredentialsInvalidTextPatch, ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt index 2e9d7779b..6e568cd70 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt @@ -1,21 +1,14 @@ package app.revanced.patches.youtube.misc.playercontrols -import app.revanced.patcher.accessFlags -import app.revanced.patcher.checkCast -import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.instructions -import app.revanced.patcher.invoke -import app.revanced.patcher.methodCall -import app.revanced.patcher.opcode -import app.revanced.patcher.opcodes -import app.revanced.patcher.parameterTypes +import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext -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.playerControlsVisibilityEntityModelMethod by gettingFirstMethodDeclaratively { + name("getPlayerControlsVisibility") accessFlags(AccessFlags.PUBLIC) returnType("L") parameterTypes() @@ -23,131 +16,113 @@ internal val BytecodePatchContext.playerControlsVisibilityEntityModelMethod by g Opcode.IGET, Opcode.INVOKE_STATIC, ) - custom { method, _ -> - method.name == "getPlayerControlsVisibility" - } } internal val BytecodePatchContext.youtubeControlsOverlayMethod by gettingFirstMethodDeclaratively { returnType("V") parameterTypes() instructions( - methodCall(name = "setFocusableInTouchMode"), + method("setFocusableInTouchMode"), ResourceType.ID("inset_overlay_view_layout"), ResourceType.ID("scrim_overlay"), ) } -internal val BytecodePatchContext.motionEventMethod by gettingFirstMethodDeclaratively { +internal val motionEventMethodMatch = firstMethodComposite { returnType("V") parameterTypes("Landroid/view/MotionEvent;") - instructions( - methodCall(name = "setTranslationY"), - ) + instructions(method("setTranslationY")) } -internal val BytecodePatchContext.playerControlsExtensionHookListenersExistMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.playerControlsExtensionHookListenersExistMethod by gettingFirstMutableMethodDeclaratively { + name("fullscreenButtonVisibilityCallbacksExist") + definingClass(EXTENSION_CLASS_DESCRIPTOR) accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returnType("Z") parameterTypes() - custom { methodDef, classDef -> - methodDef.name == "fullscreenButtonVisibilityCallbacksExist" && - classDef.type == EXTENSION_CLASS_DESCRIPTOR - } } -internal val BytecodePatchContext.playerControlsExtensionHookMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.playerControlsExtensionHookMethod by gettingFirstMutableMethodDeclaratively { + name("fullscreenButtonVisibilityChanged") + definingClass(EXTENSION_CLASS_DESCRIPTOR) accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returnType("V") parameterTypes("Z") - custom { methodDef, classDef -> - methodDef.name == "fullscreenButtonVisibilityChanged" && - classDef.type == EXTENSION_CLASS_DESCRIPTOR - } } -internal val BytecodePatchContext.playerTopControlsInflateMethod by gettingFirstMethodDeclaratively { +internal val playerTopControlsInflateMethod = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() instructions( ResourceType.ID("controls_layout_stub"), - methodCall("Landroid/view/ViewStub;", "inflate"), + method { name == "inflate" && definingClass == "Landroid/view/ViewStub;" }, after(Opcode.MOVE_RESULT_OBJECT()), ) } -internal val BytecodePatchContext.playerBottomControlsInflateMethod by gettingFirstMethodDeclaratively { +internal val playerBottomControlsInflateMethodMatch = firstMethodComposite { returnType("Ljava/lang/Object;") parameterTypes() instructions( ResourceType.ID("bottom_ui_container_stub"), - methodCall("Landroid/view/ViewStub;", "inflate"), + method { name == "inflate" && definingClass == "Landroid/view/ViewStub;" }, after(Opcode.MOVE_RESULT_OBJECT()), ) } -internal val BytecodePatchContext.overlayViewInflateMethod by gettingFirstMethodDeclaratively { +internal val overlayViewInflateMethodMatch = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/view/View;") instructions( ResourceType.ID("heatseeker_viewstub"), ResourceType.ID("fullscreen_button"), - checkCast("Landroid/widget/ImageView;"), + allOf(Opcode.CHECK_CAST(), type("Landroid/widget/ImageView;")), ) } /** * Resolves to the class found in [playerTopControlsInflateMethod]. */ -internal val BytecodePatchContext.controlsOverlayVisibilityMethod by gettingFirstMethodDeclaratively { +context(_: BytecodePatchContext) +internal fun ClassDef.getControlsOverlayVisibilityMethod() = firstMutableMethodDeclaratively { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returnType("V") parameterTypes("Z", "Z") } -internal val BytecodePatchContext.playerBottomControlsExploderFeatureFlagMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.playerBottomControlsExploderFeatureFlagMethod by gettingFirstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") parameterTypes() - instructions( - 45643739L(), - ) + instructions(45643739L()) } -internal val BytecodePatchContext.playerTopControlsExperimentalLayoutFeatureFlagMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.playerTopControlsExperimentalLayoutFeatureFlagMethod by gettingFirstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("I") parameterTypes() - instructions( - 45629424L(), - ) + instructions(45629424L()) } -internal val BytecodePatchContext.playerControlsLargeOverlayButtonsFeatureFlagMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.playerControlsLargeOverlayButtonsFeatureFlagMethod by gettingFirstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") parameterTypes() - instructions( - 45709810L(), - ) + instructions(45709810L()) } -internal val BytecodePatchContext.playerControlsFullscreenLargeButtonsFeatureFlagMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.playerControlsFullscreenLargeButtonsFeatureFlagMethod by gettingFirstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") parameterTypes() - instructions( - 45686474L(), - ) + instructions(45686474L()) } -internal val BytecodePatchContext.playerControlsButtonStrokeFeatureFlagMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.playerControlsButtonStrokeFeatureFlagMethod by gettingFirstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") parameterTypes() - instructions( - 45713296L(), - ) + instructions(45713296L()) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt index c54e80a50..68538e434 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt @@ -2,26 +2,15 @@ package app.revanced.patches.youtube.misc.playercontrols import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.getInstruction +import app.revanced.patcher.immutableClassDef import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.Document import app.revanced.patches.shared.misc.mapping.resourceMappingPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch -import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater -import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater -import app.revanced.patches.youtube.misc.playservice.is_20_19_or_greater -import app.revanced.patches.youtube.misc.playservice.is_20_20_or_greater -import app.revanced.patches.youtube.misc.playservice.is_20_28_or_greater -import app.revanced.patches.youtube.misc.playservice.is_20_30_or_greater -import app.revanced.patches.youtube.misc.playservice.versionCheckPatch -import app.revanced.util.copyXmlNode -import app.revanced.util.findElementByAttributeValue -import app.revanced.util.findElementByAttributeValueOrThrow -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.inputStreamFromBundledResource -import app.revanced.util.returnEarly -import app.revanced.util.returnLate +import app.revanced.patches.youtube.misc.playservice.* +import app.revanced.util.* import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.mutable.MutableMethod @@ -244,51 +233,44 @@ val playerControlsPatch = bytecodePatch( ) apply { - playerBottomControlsInflateMethod.let { - it.method.apply { - inflateBottomControlMethod = this + playerBottomControlsInflateMethodMatch.method.apply { + inflateBottomControlMethod = this - val inflateReturnObjectIndex = it.indices.last() - inflateBottomControlRegister = getInstruction(inflateReturnObjectIndex).registerA - inflateBottomControlInsertIndex = inflateReturnObjectIndex + 1 - } + val inflateReturnObjectIndex = playerBottomControlsInflateMethodMatch.indices.last() + inflateBottomControlRegister = getInstruction(inflateReturnObjectIndex).registerA + inflateBottomControlInsertIndex = inflateReturnObjectIndex + 1 } - playerTopControlsInflateMethod.let { - it.method.apply { - inflateTopControlMethod = this + playerTopControlsInflateMethod.method.apply { + inflateTopControlMethod = this - val inflateReturnObjectIndex = it.indices.last() - inflateTopControlRegister = getInstruction(inflateReturnObjectIndex).registerA - inflateTopControlInsertIndex = inflateReturnObjectIndex + 1 - } + val inflateReturnObjectIndex = playerTopControlsInflateMethod.indices.last() + inflateTopControlRegister = getInstruction(inflateReturnObjectIndex).registerA + inflateTopControlInsertIndex = inflateReturnObjectIndex + 1 } - visibilityMethod = controlsOverlayVisibilityMethod.match( - playerTopControlsInflateMethod.originalClassDef, - ).method + visibilityMethod = + playerTopControlsInflateMethod.immutableClassDef.getControlsOverlayVisibilityMethod() // Hook the fullscreen close button. Used to fix visibility // when seeking and other situations. - overlayViewInflateMethod.let { - it.method.apply { - val index = it.indices.last() - val register = getInstruction(index).registerA + overlayViewInflateMethodMatch.method.apply { + val index = overlayViewInflateMethodMatch.indices.last() + val register = getInstruction(index).registerA - addInstruction( - index + 1, - "invoke-static { v$register }, " + - "$EXTENSION_CLASS_DESCRIPTOR->setFullscreenCloseButton(Landroid/widget/ImageView;)V", - ) - } + addInstruction( + index + 1, + "invoke-static { v$register }, " + + "$EXTENSION_CLASS_DESCRIPTOR->setFullscreenCloseButton(Landroid/widget/ImageView;)V", + ) } visibilityImmediateCallbacksExistMethod = playerControlsExtensionHookListenersExistMethod visibilityImmediateMethod = playerControlsExtensionHookMethod - motionEventMethod.match(youtubeControlsOverlayMethod.originalClassDef).let { + motionEventMethodMatch.match(youtubeControlsOverlayMethod.immutableClassDef).let { visibilityNegatedImmediateMethod = it.method - visibilityNegatedImmediateInsertIndex = it.instructionMatches.first().index + 1 + visibilityNegatedImmediateInsertIndex = it.indices.first() + 1 } // A/B test for a slightly different bottom overlay controls, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt index 4580598c3..5b4ba07c1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt @@ -1,36 +1,28 @@ package app.revanced.patches.youtube.misc.playertype -import app.revanced.patcher.accessFlags -import app.revanced.patcher.after -import app.revanced.patcher.afterAtMost -import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.instructions -import app.revanced.patcher.invoke -import app.revanced.patcher.parameterTypes +import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext -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 -internal val BytecodePatchContext.playerTypeEnumMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.playerTypeEnumMethod by gettingFirstMethodDeclaratively( + "NONE", + "HIDDEN", + "WATCH_WHILE_MINIMIZED", + "WATCH_WHILE_MAXIMIZED", + "WATCH_WHILE_FULLSCREEN", + "WATCH_WHILE_SLIDING_MAXIMIZED_FULLSCREEN", + "WATCH_WHILE_SLIDING_MINIMIZED_MAXIMIZED", + "WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED", + "INLINE_MINIMAL", + "VIRTUAL_REALITY_FULLSCREEN", + "WATCH_WHILE_PICTURE_IN_PICTURE", +) { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) - strings( - "NONE", - "HIDDEN", - "WATCH_WHILE_MINIMIZED", - "WATCH_WHILE_MAXIMIZED", - "WATCH_WHILE_FULLSCREEN", - "WATCH_WHILE_SLIDING_MAXIMIZED_FULLSCREEN", - "WATCH_WHILE_SLIDING_MINIMIZED_MAXIMIZED", - "WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED", - "INLINE_MINIMAL", - "VIRTUAL_REALITY_FULLSCREEN", - "WATCH_WHILE_PICTURE_IN_PICTURE", - ) } -internal val BytecodePatchContext.reelWatchPagerMethod by gettingFirstMethodDeclaratively { +internal val reelWatchPagerMethodMatch = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Landroid/view/View;") instructions( @@ -39,17 +31,16 @@ internal val BytecodePatchContext.reelWatchPagerMethod by gettingFirstMethodDecl ) } -internal val BytecodePatchContext.videoStateEnumMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.videoStateEnumMethod by gettingFirstMethodDeclaratively( + "NEW", + "PLAYING", + "PAUSED", + "RECOVERABLE_ERROR", + "UNRECOVERABLE_ERROR", + "ENDED", +) { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) parameterTypes() - strings( - "NEW", - "PLAYING", - "PAUSED", - "RECOVERABLE_ERROR", - "UNRECOVERABLE_ERROR", - "ENDED", - ) } // 20.33 and lower class name ControlsState. 20.34+ class name is obfuscated. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt index 50696f282..e99afc754 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt @@ -1,9 +1,9 @@ package app.revanced.patches.youtube.misc.playertype +import app.revanced.patcher.* import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction -import app.revanced.patcher.fieldAccess import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.shared.misc.mapping.ResourceType import app.revanced.patches.shared.misc.mapping.resourceMappingPatch @@ -20,54 +20,44 @@ val playerTypeHookPatch = bytecodePatch( dependsOn(sharedExtensionPatch, resourceMappingPatch) apply { - val playerOverlaysSetPlayerTypeFingerprint = fingerprint { + firstMutableMethodDeclaratively { + definingClass { endsWith("/YouTubePlayerOverlaysLayout;") } accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") - parameterTypes(playerTypeEnumMethod.originalClassDef.type) - custom { _, classDef -> - classDef.endsWith("/YouTubePlayerOverlaysLayout;") - } - } - - playerOverlaysSetPlayerTypeFingerprint.method.addInstruction( + parameterTypes(playerTypeEnumMethod.immutableClassDef.type) + }.addInstruction( 0, "invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->setPlayerType(Ljava/lang/Enum;)V", ) - reelWatchPagerMethod.let { - it.method.apply { - val index = it.indices.last() - val register = getInstruction(index).registerA + reelWatchPagerMethodMatch.method.apply { + val index = reelWatchPagerMethodMatch.indices.last() + val register = getInstruction(index).registerA - addInstruction( - index + 1, - "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->onShortsCreate(Landroid/view/View;)V", - ) - } + addInstruction( + index + 1, + "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->onShortsCreate(Landroid/view/View;)V", + ) } - val controlStateType = controlsStateToStringMethod.originalClassDef.type + val controlStateType = controlsStateToStringMethod.immutableClassDef.type - val videoStateFingerprint = fingerprint { + val videoStateEnumMethod = videoStateEnumMethod + firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes(controlStateType) instructions( + field { + definingClass == controlStateType && type == videoStateEnumMethod.immutableClassDef.type + }, // Obfuscated parameter field name. - fieldAccess( - definingClass = controlStateType, - type = videoStateEnumMethod.originalClassDef.type, - ), ResourceType.STRING("accessibility_play"), ResourceType.STRING("accessibility_pause"), ) - } - - videoStateFingerprint.let { + }.let { it.method.apply { - val videoStateFieldName = getInstruction( - it.instructionMatches.first().index, - ).reference + val videoStateFieldName = getInstruction(it.indices.first()).reference addInstructions( 0, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt index 6dbe4f0e7..7dfbacb7f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt @@ -1,50 +1,38 @@ package app.revanced.patches.youtube.misc.settings -import app.revanced.patcher.accessFlags -import app.revanced.patcher.after -import app.revanced.patcher.afterAtMost -import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.instructions -import app.revanced.patcher.invoke -import app.revanced.patcher.opcode -import app.revanced.patcher.parameterTypes +import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext -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 -internal val BytecodePatchContext.licenseActivityOnCreateMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.licenseActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { + name("onCreate") + definingClass("/LicenseActivity;") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/os/Bundle;") - custom { method, classDef -> - method.name == "onCreate" && classDef.endsWith("/LicenseActivity;") - } } -internal val BytecodePatchContext.setThemeMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.setThemeMethod by gettingFirstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes() - instructions( - ResourceType.STRING("app_theme_appearance_dark"), - ) + instructions(ResourceType.STRING("app_theme_appearance_dark")) } -internal val BytecodePatchContext.cairoFragmentConfigMethod by gettingFirstMethodDeclaratively { +internal val cairoFragmentConfigMethodMatch = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") instructions( 45532100L(), - afterAtMost(10, Opcode.MOVE_RESULT()), ) } // Flag is present in 20.23, but bold icons are missing and forcing them crashes the app. // 20.31 is the first target with all the bold icons present. -internal val BytecodePatchContext.boldIconsFeatureFlagMethod by gettingFirstMethodDeclaratively { +internal val boldIconsFeatureFlagMethod = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") parameterTypes() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt index cc37bb340..c7e321b6e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.misc.settings +import app.revanced.patcher.classDef import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.patch.bytecodePatch @@ -239,8 +240,8 @@ val settingsPatch = bytecodePatch( } // Add setting to force Cairo settings fragment on/off. - cairoFragmentConfigMethod.insertLiteralOverride( - cairoFragmentConfigMethod.instructionMatches.first().index, + cairoFragmentConfigMethodMatch.method.insertLiteralOverride( + cairoFragmentConfigMethodMatch.indices.first(), "$YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z", ) @@ -249,7 +250,7 @@ val settingsPatch = bytecodePatch( if (is_20_31_or_greater) { boldIconsFeatureFlagMethod.let { it.method.insertLiteralOverride( - it.instructionMatches.first().index, + it.indices.first(), "$YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useBoldIcons(Z)Z", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt index 365f7bdc0..cd3c46108 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt @@ -47,20 +47,15 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch { ) // Used for the old type of the video quality menu. - videoQualityBottomSheetListFragmentname = getResourceId( - ResourceType.LAYOUT, - "video_quality_bottom_sheet_list_fragment_title", - ) - - videoQualityQuickMenuAdvancedMenuDescription = getResourceId( - ResourceType.STRING, - "video_quality_quick_menu_advanced_menu_description", - ) + videoQualityBottomSheetListFragmentname = + ResourceType.LAYOUT["video_quality_bottom_sheet_list_fragment_title"] + videoQualityQuickMenuAdvancedMenuDescription = + ResourceType.STRING["video_quality_quick_menu_advanced_menu_description"] // region Patch for the old type of the video quality menu. // Used for regular videos when spoofing to old app version, // and for the Shorts quality flyout on newer app versions. - videoQualityMenuViewInflateMethod.let { + videoQualityMenuViewInflateMethodMatch.let { it.method.apply { val checkCastIndex = it.indices.last() val listViewRegister = getInstruction(checkCastIndex).registerA @@ -74,10 +69,10 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch { } // Force YT to add the 'advanced' quality menu for Shorts. - videoQualityMenuOptionsMethod.let { - val patternMatch = it.instructionMatches - val startIndex = patternMatch.first().index - val insertIndex = patternMatch.last().index + videoQualityMenuOptionsMethodMatch.let { + val startIndex = it.indices.first() + val insertIndex = it.indices.last() + if (startIndex != 0) throw PatchException("Unexpected opcode start index: $startIndex") it.method.apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt index ecd9d5dd5..3f0009908 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.youtube.video.quality import app.revanced.patcher.accessFlags -import app.revanced.patcher.addString +import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.firstMutableMethodDeclaratively import app.revanced.patcher.gettingFirstMethodDeclaratively -import app.revanced.patcher.instructions +import app.revanced.patcher.name import app.revanced.patcher.opcodes import app.revanced.patcher.parameterTypes import app.revanced.patcher.patch.BytecodePatchContext @@ -12,17 +13,15 @@ import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val BytecodePatchContext.videoQualityItemOnClickParentMethod by gettingFirstMethodDeclaratively { +internal val BytecodePatchContext.videoQualityItemOnClickParentMethod by gettingFirstMethodDeclaratively( + "VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT", +) { returnType("V") - instructions( - "VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT"(), - ) } -/** - * Resolves to class found in [videoQualityItemOnClickMethod]. - */ -internal val BytecodePatchContext.videoQualityItemOnClickMethod by gettingFirstMethodDeclaratively { +context(_: BytecodePatchContext) +internal fun com.android.tools.smali.dexlib2.iface.ClassDef.getVideoQualityItemOnClickMethod() = firstMutableMethodDeclaratively { + name("onItemClick") returnType("V") parameterTypes( "Landroid/widget/AdapterView;", @@ -30,12 +29,9 @@ internal val BytecodePatchContext.videoQualityItemOnClickMethod by gettingFirstM "I", "J", ) - custom { method, _ -> - method.name == "onItemClick" - } } -internal val BytecodePatchContext.videoQualityMenuOptionsMethod by gettingFirstMethodDeclaratively { +internal val videoQualityMenuOptionsMethodMatch = firstMethodComposite { accessFlags(AccessFlags.STATIC) returnType("[L") parameterTypes("Landroid/content/Context", "L", "L") @@ -49,7 +45,7 @@ internal val BytecodePatchContext.videoQualityMenuOptionsMethod by gettingFirstM literal { videoQualityQuickMenuAdvancedMenuDescription } } -internal val BytecodePatchContext.videoQualityMenuViewInflateMethod by gettingFirstMethodDeclaratively { +internal val videoQualityMenuViewInflateMethodMatch = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes("L", "L", "L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt index 963ad0b22..f7893c686 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt @@ -2,6 +2,7 @@ package app.revanced.patches.youtube.video.quality import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.getInstruction +import app.revanced.patcher.immutableClassDef import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch @@ -64,9 +65,7 @@ val rememberVideoQualityPatch = bytecodePatch { onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted") // Inject a call to remember the selected quality for Shorts. - videoQualityItemOnClickMethod.match( - videoQualityItemOnClickParentMethod.classDef, - ).method.addInstruction( + videoQualityItemOnClickParentMethod.immutableClassDef.getVideoQualityItemOnClickMethod().addInstruction( 0, "invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedShortsQuality(I)V", )