From a103eb5b7a4134b5bb583e4673eb1cfa927e6b2c Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Fri, 9 Jan 2026 20:00:49 +0100 Subject: [PATCH] migrate batch --- .../misc/gms/GmsCoreSupportPatch.kt | 2 +- .../misc/gms/GmsCoreSupportPatch.kt | 2 +- .../layout/branding/CustomBrandingPatch.kt | 4 +- ...ckWatchHistoryDomainNameResolutionPatch.kt | 4 +- .../patches/music/misc/gms/Fingerprints.kt | 18 +- .../music/misc/gms/GmsCoreSupportPatch.kt | 16 +- .../misc/spoof/SpoofVideoStreamsPatch.kt | 10 +- .../misc/tracks/ForceOriginalAudioPatch.kt | 4 +- .../patches/music/shared/Fingerprints.kt | 21 ++- .../misc/extension/hooks/InitHook.kt | 4 +- .../revanced/patches/shared/Fingerprints.kt | 22 +-- .../branding/BaseCustomBrandingPatch.kt | 27 +-- .../patches/shared/misc/audio/Fingerprints.kt | 24 +-- .../misc/audio/ForceOriginalAudioPatch.kt | 157 +++++++++--------- .../misc/extension/SharedExtensionPatch.kt | 12 +- .../shared/misc/gms/GmsCoreSupportPatch.kt | 44 ++--- .../shared/misc/privacy/Fingerprints.kt | 78 +++------ .../misc/privacy/SanitizeSharingLinksPatch.kt | 16 +- .../patches/shared/misc/spoof/Fingerprints.kt | 146 ++++++++-------- .../misc/spoof/SpoofVideoStreamsPatch.kt | 130 ++++++--------- .../extension/hooks/ApplicationInitHook.kt | 12 +- .../layout/branding/CustomBrandingPatch.kt | 2 +- .../layout/hide/infocards/Fingerprints.kt | 6 - .../youtube/misc/gms/GmsCoreSupportPatch.kt | 7 +- .../misc/spoof/SpoofVideoStreamsPatch.kt | 2 +- .../video/audio/ForceOriginalAudioPatch.kt | 2 +- 26 files changed, 334 insertions(+), 438 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch.kt index 630e737cc..7a3982974 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch.kt @@ -11,7 +11,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportResourcePatch val gmsCoreSupportPatch = gmsCoreSupportPatch( fromPackageName = MAGAZINES_PACKAGE_NAME, toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME, - mainActivityOnCreateFingerprint = magazinesActivityOnCreateFingerprint, + getMainActivityOnCreate = magazinesActivityOnCreateFingerprint, extensionPatch = extensionPatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch.kt index 75d265be3..f98bc0f01 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch.kt @@ -10,7 +10,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch val gmsCoreSupportPatch = gmsCoreSupportPatch( fromPackageName = PHOTOS_PACKAGE_NAME, toPackageName = REVANCED_PHOTOS_PACKAGE_NAME, - mainActivityOnCreateFingerprint = homeActivityOnCreateFingerprint, + getMainActivityOnCreate = homeActivityOnCreateFingerprint, extensionPatch = extensionPatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/branding/CustomBrandingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/branding/CustomBrandingPatch.kt index 2dbf06008..4f3b963fa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/branding/CustomBrandingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/branding/CustomBrandingPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.music.misc.extension.sharedExtensionPatch import app.revanced.patches.music.misc.gms.Constants.MUSIC_MAIN_ACTIVITY_NAME import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME -import app.revanced.patches.music.misc.gms.musicActivityOnCreateFingerprint +import app.revanced.patches.music.misc.gms.musicActivityOnCreateMethod import app.revanced.patches.music.misc.settings.PreferenceScreen import app.revanced.patches.shared.layout.branding.EXTENSION_CLASS_DESCRIPTOR import app.revanced.patches.shared.layout.branding.baseCustomBrandingPatch @@ -62,7 +62,7 @@ val customBrandingPatch = baseCustomBrandingPatch( originalAppPackageName = MUSIC_PACKAGE_NAME, isYouTubeMusic = true, numberOfPresetAppNames = 5, - mainActivityOnCreateFingerprint = musicActivityOnCreateFingerprint, + getMainActivityOnCreate = { musicActivityOnCreateMethod }, mainActivityName = MUSIC_MAIN_ACTIVITY_NAME, activityAliasNameWithIntents = MUSIC_MAIN_ACTIVITY_NAME, preferenceScreen = PreferenceScreen.GENERAL, diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt index d6ac3ef78..cdf873624 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt @@ -1,7 +1,7 @@ package app.revanced.patches.music.misc.dns import app.revanced.patches.music.misc.extension.sharedExtensionPatch -import app.revanced.patches.music.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.music.shared.mainActivityOnCreateMethod import app.revanced.patches.shared.misc.dns.checkWatchHistoryDomainNameResolutionPatch val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameResolutionPatch( @@ -18,5 +18,5 @@ val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameReso ) }, - mainActivityFingerprint = mainActivityOnCreateFingerprint + mainActivityFingerprint = mainActivityOnCreateMethod ) diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/Fingerprints.kt index 7131e143d..345f9a58f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/gms/Fingerprints.kt @@ -1,11 +1,13 @@ package app.revanced.patches.music.misc.gms -import app.revanced.patcher.fingerprint +import app.revanced.patcher.* +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext -internal val musicActivityOnCreateFingerprint = fingerprint { - returns("V") - parameters("Landroid/os/Bundle;") - custom { method, classDef -> - method.name == "onCreate" && classDef.endsWith("/MusicActivity;") - } -} + +internal val BytecodePatchContext.musicActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { + name("onCreate") + definingClass("/MusicActivity;"::endsWith) + returnType("V") + parameterTypes("Landroid/os/Bundle;") +} \ No newline at end of file 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 0d6b319d8..dbf518026 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 @@ -4,30 +4,26 @@ import app.revanced.patcher.patch.Option import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.music.misc.extension.sharedExtensionPatch +import app.revanced.patches.music.misc.fileprovider.fileProviderPatch import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME import app.revanced.patches.music.misc.settings.PreferenceScreen import app.revanced.patches.music.misc.settings.settingsPatch -import app.revanced.patches.music.misc.spoof.spoofVideoStreamsPatch -import app.revanced.patches.music.misc.fileprovider.fileProviderPatch -import app.revanced.patches.shared.castContextFetchFingerprint +import app.revanced.patches.shared.castContextFetchMethod import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch import app.revanced.patches.shared.misc.settings.preference.IntentPreference -import app.revanced.patches.shared.primeMethodFingerprint +import app.revanced.patches.shared.primeMethod @Suppress("unused") val gmsCoreSupportPatch = gmsCoreSupportPatch( fromPackageName = MUSIC_PACKAGE_NAME, toPackageName = REVANCED_MUSIC_PACKAGE_NAME, - primeMethodFingerprint = primeMethodFingerprint, - earlyReturnFingerprints = setOf( - castContextFetchFingerprint, - ), - mainActivityOnCreateFingerprint = musicActivityOnCreateFingerprint, + getPrimeMethod = { primeMethod }, + getEarlyReturnMethods = { setOf(castContextFetchMethod) }, + getMainActivityOnCreateMethod = { musicActivityOnCreateMethod }, extensionPatch = sharedExtensionPatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, ) { - dependsOn(spoofVideoStreamsPatch) compatibleWith( MUSIC_PACKAGE_NAME( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/SpoofVideoStreamsPatch.kt index e4268330d..f019fca84 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/SpoofVideoStreamsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/spoof/SpoofVideoStreamsPatch.kt @@ -3,14 +3,10 @@ package app.revanced.patches.music.misc.spoof import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.music.misc.extension.sharedExtensionPatch -import app.revanced.patches.music.misc.gms.musicActivityOnCreateFingerprint +import app.revanced.patches.music.misc.gms.musicActivityOnCreateMethod import app.revanced.patches.music.misc.settings.PreferenceScreen import app.revanced.patches.music.misc.settings.settingsPatch -import app.revanced.patches.music.playservice.is_7_16_or_greater -import app.revanced.patches.music.playservice.is_7_33_or_greater -import app.revanced.patches.music.playservice.is_8_11_or_greater -import app.revanced.patches.music.playservice.is_8_15_or_greater -import app.revanced.patches.music.playservice.versionCheckPatch +import app.revanced.patches.music.playservice.* import app.revanced.patches.shared.misc.settings.preference.ListPreference import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference @@ -18,7 +14,7 @@ import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch val spoofVideoStreamsPatch = spoofVideoStreamsPatch( extensionClassDescriptor = "Lapp/revanced/extension/music/patches/spoof/SpoofVideoStreamsPatch;", - mainActivityOnCreateFingerprint = musicActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = { musicActivityOnCreateMethod }, fixMediaFetchHotConfig = { is_7_16_or_greater }, fixMediaFetchHotConfigAlternative = { is_8_11_or_greater && !is_8_15_or_greater }, fixParsePlaybackResponseFeatureFlag = { is_7_33_or_greater }, diff --git a/patches/src/main/kotlin/app/revanced/patches/music/misc/tracks/ForceOriginalAudioPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/misc/tracks/ForceOriginalAudioPatch.kt index 09be85c56..cbdc7ab80 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/misc/tracks/ForceOriginalAudioPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/misc/tracks/ForceOriginalAudioPatch.kt @@ -5,7 +5,7 @@ import app.revanced.patches.music.misc.settings.PreferenceScreen import app.revanced.patches.music.misc.settings.settingsPatch import app.revanced.patches.music.playservice.is_8_05_or_greater import app.revanced.patches.music.playservice.versionCheckPatch -import app.revanced.patches.music.shared.mainActivityOnCreateFingerprint +import app.revanced.patches.music.shared.mainActivityOnCreateMethod import app.revanced.patches.shared.misc.audio.forceOriginalAudioPatch @Suppress("unused") @@ -25,7 +25,7 @@ val forceOriginalAudioPatch = forceOriginalAudioPatch( ) }, fixUseLocalizedAudioTrackFlag = { is_8_05_or_greater }, - mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = { mainActivityOnCreateMethod }, subclassExtensionClassDescriptor = "Lapp/revanced/extension/music/patches/ForceOriginalAudioPatch;", preferenceScreen = PreferenceScreen.MISC, ) diff --git a/patches/src/main/kotlin/app/revanced/patches/music/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/shared/Fingerprints.kt index d6c79197d..f5473788c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/shared/Fingerprints.kt @@ -1,13 +1,18 @@ package app.revanced.patches.music.shared -import app.revanced.patcher.fingerprint +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively +import app.revanced.patcher.definingClass +import app.revanced.patcher.name +import app.revanced.patcher.parameterTypes +import app.revanced.patcher.patch.BytecodePatchContext +import app.revanced.patcher.returnType -internal const val YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE = "Lcom/google/android/apps/youtube/music/activities/MusicActivity;" +internal const val YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE = + "Lcom/google/android/apps/youtube/music/activities/MusicActivity;" -internal val mainActivityOnCreateFingerprint = fingerprint { - returns("V") - parameters("Landroid/os/Bundle;") - custom { method, classDef -> - method.name == "onCreate" && classDef.type == YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE - } +internal val BytecodePatchContext.mainActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { + name("onCreate") + definingClass(YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE) + returnType("V") + parameterTypes("Landroid/os/Bundle;") } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/misc/extension/hooks/InitHook.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/misc/extension/hooks/InitHook.kt index d3d4523cb..0256df0a7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/misc/extension/hooks/InitHook.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/misc/extension/hooks/InitHook.kt @@ -2,6 +2,4 @@ package app.revanced.patches.reddit.customclients.baconreader.misc.extension.hoo import app.revanced.patches.shared.misc.extension.activityOnCreateExtensionHook -internal val initHook = activityOnCreateExtensionHook( - "Lcom/onelouder/baconreader/BaconReader;" -) +internal val initHook = activityOnCreateExtensionHook("Lcom/onelouder/baconreader/BaconReader;") diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/Fingerprints.kt index 8426f3870..fe55dcb07 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/Fingerprints.kt @@ -1,17 +1,13 @@ package app.revanced.patches.shared -import app.revanced.patcher.fingerprint -import app.revanced.patcher.addString +import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively +import app.revanced.patcher.patch.BytecodePatchContext -internal val castContextFetchFingerprint = fingerprint { - instructions( - addString("Error fetching CastContext.") - ) -} +internal val BytecodePatchContext.castContextFetchMethod by gettingFirstMutableMethodDeclaratively( + "Error fetching CastContext." +) -internal val primeMethodFingerprint = fingerprint { - instructions( - addString("com.android.vending"), - addString("com.google.android.GoogleCamera") - ) -} +internal val BytecodePatchContext.primeMethod by gettingFirstMutableMethodDeclaratively( + "com.android.vending", + "com.google.android.GoogleCamera" +) 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 7ba3b74d9..43892dd11 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 @@ -1,36 +1,21 @@ package app.revanced.patches.shared.layout.branding -import app.revanced.patcher.Fingerprint import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.getInstruction -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.ResourcePatchBuilder -import app.revanced.patcher.patch.ResourcePatchContext -import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch -import app.revanced.patcher.patch.stringOption +import app.revanced.patcher.patch.* import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.mapping.resourceMappingPatch import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen import app.revanced.patches.shared.misc.settings.preference.ListPreference -import app.revanced.util.ResourceGroup +import app.revanced.util.* import app.revanced.util.Utils.trimIndentMultiline -import app.revanced.util.addInstructionsAtControlFlowLabel -import app.revanced.util.copyResources -import app.revanced.util.findElementByAttributeValueOrThrow -import app.revanced.util.findInstructionIndicesReversedOrThrow -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfFirstInstructionReversedOrThrow -import app.revanced.util.removeFromParent -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.FieldReference import com.android.tools.smali.dexlib2.iface.reference.TypeReference +import com.android.tools.smali.dexlib2.mutable.MutableMethod import org.w3c.dom.Element import org.w3c.dom.NodeList import java.io.File @@ -81,13 +66,13 @@ internal fun baseCustomBrandingPatch( originalAppPackageName: String, isYouTubeMusic: Boolean, numberOfPresetAppNames: Int, - mainActivityOnCreateFingerprint: Fingerprint, + getMainActivityOnCreate: BytecodePatchContext.() -> MutableMethod, mainActivityName: String, activityAliasNameWithIntents: String, preferenceScreen: BasePreferenceScreen.Screen, block: ResourcePatchBuilder.() -> Unit, executeBlock: ResourcePatchContext.() -> Unit = {} -): ResourcePatch = resourcePatch( +) = resourcePatch( name = "Custom branding", description = "Adds options to change the app icon and app name. " + "Branding cannot be changed for mounted (root) installations." @@ -125,7 +110,7 @@ internal fun baseCustomBrandingPatch( addBrandLicensePatch, bytecodePatch { apply { - mainActivityOnCreateFingerprint.method.addInstruction( + getMainActivityOnCreate().addInstruction( 0, "invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setBranding()V" ) diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/Fingerprints.kt index 45b34aea9..5e9d1f2ac 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/Fingerprints.kt @@ -1,24 +1,18 @@ package app.revanced.patches.shared.misc.audio -import app.revanced.patcher.fingerprint -import app.revanced.patcher.literal +import app.revanced.patcher.* import com.android.tools.smali.dexlib2.AccessFlags -internal val formatStreamModelToStringFingerprint = fingerprint { +internal val formatStreamModelToStringMethodMatch = firstMethodComposite { + name("toString") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returns("Ljava/lang/String;") - custom { method, _ -> - method.name == "toString" - } - strings( - // Strings are partial matches. - "isDefaultAudioTrack=", - "audioTrackId=" + returnType("Ljava/lang/String;") + instructions( + "isDefaultAudioTrack="(String::contains), + "audioTrackId="(String::contains) ) } -internal val selectAudioStreamFingerprint = fingerprint { - instructions( - literal(45666189L) - ) +internal val selectAudioStreamMethodMatch = firstMethodComposite { + instructions(45666189L()) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/ForceOriginalAudioPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/ForceOriginalAudioPatch.kt index 8c3e4c127..8f62dd523 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/ForceOriginalAudioPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/ForceOriginalAudioPatch.kt @@ -1,6 +1,5 @@ package app.revanced.patches.shared.misc.audio -import app.revanced.patcher.Fingerprint import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructionsWithLabels @@ -8,8 +7,6 @@ import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.bytecodePatch -import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable -import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen @@ -24,6 +21,9 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter +import com.android.tools.smali.dexlib2.mutable.MutableField.Companion.toMutable +import com.android.tools.smali.dexlib2.mutable.MutableMethod +import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/patches/ForceOriginalAudioPatch;" @@ -35,7 +35,7 @@ internal fun forceOriginalAudioPatch( block: BytecodePatchBuilder.() -> Unit = {}, executeBlock: BytecodePatchContext.() -> Unit = {}, fixUseLocalizedAudioTrackFlag: BytecodePatchContext.() -> Boolean, - mainActivityOnCreateFingerprint: Fingerprint, + getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod, subclassExtensionClassDescriptor: String, preferenceScreen: BasePreferenceScreen.Screen ) = bytecodePatch( @@ -57,7 +57,7 @@ internal fun forceOriginalAudioPatch( ) ) - mainActivityOnCreateFingerprint.method.addInstruction( + getMainActivityOnCreateMethod().addInstruction( 0, "invoke-static { }, $subclassExtensionClassDescriptor->setEnabled()V" ) @@ -65,90 +65,91 @@ internal fun forceOriginalAudioPatch( // Disable feature flag that ignores the default track flag // and instead overrides to the user region language. if (fixUseLocalizedAudioTrackFlag()) { - selectAudioStreamFingerprint.method.insertLiteralOverride( - selectAudioStreamFingerprint.instructionMatches.first().index, + selectAudioStreamMethodMatch.method.insertLiteralOverride( + selectAudioStreamMethodMatch.indices.first(), "$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z" ) } - formatStreamModelToStringFingerprint.let { - val isDefaultAudioTrackMethod = it.originalMethod.findMethodFromToString("isDefaultAudioTrack=") - val audioTrackDisplayNameMethod = it.originalMethod.findMethodFromToString("audioTrackDisplayName=") - val audioTrackIdMethod = it.originalMethod.findMethodFromToString("audioTrackId=") + val isDefaultAudioTrackMethod = + formatStreamModelToStringMethodMatch.immutableMethod.findMethodFromToString("isDefaultAudioTrack=") + val audioTrackDisplayNameMethod = + formatStreamModelToStringMethodMatch.immutableMethod.findMethodFromToString("audioTrackDisplayName=") + val audioTrackIdMethod = + formatStreamModelToStringMethodMatch.immutableMethod.findMethodFromToString("audioTrackId=") - it.classDef.apply { - // Add a new field to store the override. - val helperFieldName = "patch_isDefaultAudioTrackOverride" - fields.add( - ImmutableField( - type, - helperFieldName, - "Ljava/lang/Boolean;", - // Boolean is a 100% immutable class (all fields are final) - // and safe to write to a shared field without volatile/synchronization, - // but without volatile the field can show stale data - // and the same field is calculated more than once by different threads. - AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value, - null, - null, - null - ).toMutable() + formatStreamModelToStringMethodMatch.classDef.apply { + // Add a new field to store the override. + val helperFieldName = "patch_isDefaultAudioTrackOverride" + fields.add( + ImmutableField( + type, + helperFieldName, + "Ljava/lang/Boolean;", + // Boolean is a 100% immutable class (all fields are final) + // and safe to write to a shared field without volatile/synchronization, + // but without volatile the field can show stale data + // and the same field is calculated more than once by different threads. + AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value, + null, + null, + null + ).toMutable() + ) + + // Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed. + val helperMethodClass = type + val helperMethodName = "patch_isDefaultAudioTrack" + val helperMethod = ImmutableMethod( + helperMethodClass, + helperMethodName, + listOf(ImmutableMethodParameter("Z", null, null)), + "Z", + AccessFlags.PRIVATE.value, + null, + null, + MutableMethodImplementation(6), + ).toMutable().apply { + addInstructionsWithLabels( + 0, + """ + iget-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean; + if-eqz v0, :call_extension + invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z + move-result v3 + return v3 + + :call_extension + invoke-virtual { p0 }, $audioTrackIdMethod + move-result-object v1 + + invoke-virtual { p0 }, $audioTrackDisplayNameMethod + move-result-object v2 + + invoke-static { p1, v1, v2 }, $EXTENSION_CLASS_DESCRIPTOR->isDefaultAudioStream(ZLjava/lang/String;Ljava/lang/String;)Z + move-result v3 + + invoke-static { v3 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean; + move-result-object v0 + iput-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean; + return v3 + """ ) + } + methods.add(helperMethod) - // Add a helper method because the isDefaultAudioTrack() has only 2 registers and 3 are needed. - val helperMethodClass = type - val helperMethodName = "patch_isDefaultAudioTrack" - val helperMethod = ImmutableMethod( - helperMethodClass, - helperMethodName, - listOf(ImmutableMethodParameter("Z", null, null)), - "Z", - AccessFlags.PRIVATE.value, - null, - null, - MutableMethodImplementation(6), - ).toMutable().apply { - addInstructionsWithLabels( - 0, - """ - iget-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean; - if-eqz v0, :call_extension - invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z - move-result v3 - return v3 - - :call_extension - invoke-virtual { p0 }, $audioTrackIdMethod - move-result-object v1 - - invoke-virtual { p0 }, $audioTrackDisplayNameMethod - move-result-object v2 - - invoke-static { p1, v1, v2 }, $EXTENSION_CLASS_DESCRIPTOR->isDefaultAudioStream(ZLjava/lang/String;Ljava/lang/String;)Z - move-result v3 - - invoke-static { v3 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean; - move-result-object v0 - iput-object v0, p0, $helperMethodClass->$helperFieldName:Ljava/lang/Boolean; - return v3 - """ - ) - } - methods.add(helperMethod) + // Modify isDefaultAudioTrack() to call extension helper method. + isDefaultAudioTrackMethod.apply { + val index = indexOfFirstInstructionOrThrow(Opcode.RETURN) + val register = getInstruction(index).registerA - // Modify isDefaultAudioTrack() to call extension helper method. - isDefaultAudioTrackMethod.apply { - val index = indexOfFirstInstructionOrThrow(Opcode.RETURN) - val register = getInstruction(index).registerA - - addInstructions( - index, - """ + addInstructions( + index, + """ invoke-direct { p0, v$register }, $helperMethodClass->$helperMethodName(Z)Z move-result v$register """ - ) - } + ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt index 26f860d84..5b0bfb1f2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt @@ -20,9 +20,9 @@ internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/ */ fun sharedExtensionPatch( extensionName: String, - vararg hooks: () -> ExtensionHook, + vararg hooks: ExtensionHook, ) = bytecodePatch { - dependsOn(sharedExtensionPatch(*hooks)) + dependsOn(sharedExtensionPatch(hooks = hooks)) extendWith("extensions/$extensionName.rve") } @@ -34,7 +34,7 @@ fun sharedExtensionPatch( * commonly for the onCreate method of exported activities. */ fun sharedExtensionPatch( - vararg hooks: () -> ExtensionHook, + vararg hooks: ExtensionHook, ) = bytecodePatch { extendWith("extensions/shared.rve") @@ -45,7 +45,7 @@ fun sharedExtensionPatch( afterDependents { // The hooks are made in afterDependents to ensure that the context is hooked before any other patches. - hooks.forEach { hook -> hook()(EXTENSION_CLASS_DESCRIPTOR) } + hooks.forEach { hook -> hook(EXTENSION_CLASS_DESCRIPTOR) } // Modify Utils method to include the patches release version. /** @@ -87,9 +87,9 @@ class ExtensionHook internal constructor( private val getContextRegister: Method.() -> String, private val predicate: DeclarativePredicate, ) { - context(context: BytecodePatchContext) + context(_: BytecodePatchContext) operator fun invoke(extensionClassDescriptor: String) { - val method = context.firstMutableMethodDeclaratively(predicate = predicate) + val method = firstMutableMethodDeclaratively(predicate = predicate) val insertIndex = method.getInsertIndex() val contextRegister = method.getContextRegister() 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 9976df196..626b2cf46 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 @@ -1,6 +1,5 @@ package app.revanced.patches.shared.misc.gms -import app.revanced.patcher.Fingerprint import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.instructions import app.revanced.patcher.extensions.replaceInstruction @@ -20,6 +19,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference +import com.android.tools.smali.dexlib2.mutable.MutableMethod import com.android.tools.smali.dexlib2.util.MethodUtil import org.w3c.dom.Element import org.w3c.dom.Node @@ -34,9 +34,9 @@ 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 primeMethodFingerprint The fingerprint of the "prime" method that needs to be patched. - * @param earlyReturnFingerprints The fingerprints of methods that need to be returned early. - * @param mainActivityOnCreateFingerprint The fingerprint of the main activity onCreate method. + * @param getPrimeMethod The "prime" method that needs to be patched. + * @param getEarlyReturnMethods 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 * that is used to patch the resources. @@ -46,9 +46,9 @@ private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$" fun gmsCoreSupportPatch( fromPackageName: String, toPackageName: String, - primeMethodFingerprint: Fingerprint? = null, - earlyReturnFingerprints: Set = setOf(), - mainActivityOnCreateFingerprint: Fingerprint, + getPrimeMethod: (BytecodePatchContext.() -> MutableMethod)? = null, + getEarlyReturnMethods: BytecodePatchContext.() -> Set = { setOf() }, + getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod, extensionPatch: Patch, gmsCoreSupportResourcePatchFactory: (gmsCoreVendorGroupIdOption: Option) -> Patch, executeBlock: BytecodePatchContext.() -> Unit = {}, @@ -165,18 +165,18 @@ fun gmsCoreSupportPatch( } fun transformPrimeMethod(packageName: String) { - primeMethodFingerprint!!.method.apply { - var register = 2 + val primeMethod = getPrimeMethod!!() - val index = instructions.indexOfFirst { - if (it.getReference()?.string != fromPackageName) return@indexOfFirst false + var register = 2 - register = (it as OneRegisterInstruction).registerA - return@indexOfFirst true - } + val index = primeMethod.instructions.indexOfFirst { + if (it.getReference()?.string != fromPackageName) return@indexOfFirst false - replaceInstruction(index, "const-string v$register, \"$packageName\"") + register = (it as OneRegisterInstruction).registerA + return@indexOfFirst true } + + primeMethod.replaceInstruction(index, "const-string v$register, \"$packageName\"") } // endregion @@ -198,18 +198,10 @@ fun gmsCoreSupportPatch( } // Specific method that needs to be patched. - primeMethodFingerprint?.let { transformPrimeMethod(packageName) } + getPrimeMethod?.let { transformPrimeMethod(packageName) } // Return these methods early to prevent the app from crashing. - earlyReturnFingerprints.forEach { - it.method.apply { - if (returnType == "Z") { - returnEarly(false) - } else { - returnEarly() - } - } - } + getEarlyReturnMethods().forEach { it.returnEarly() } serviceCheckFingerprint.method.returnEarly() // Google Play Utility is not present in all apps, so we need to check if it's present. @@ -221,7 +213,7 @@ fun gmsCoreSupportPatch( originalPackageNameExtensionFingerprint.method.returnEarly(fromPackageName) // Verify GmsCore is installed and whitelisted for power optimizations and background usage. - mainActivityOnCreateFingerprint.method.addInstruction( + getMainActivityOnCreateMethod().addInstruction( 0, "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" + "checkGmsCore(Landroid/app/Activity;)V" diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/Fingerprints.kt index 8fdd1d832..3f0a6c5f1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/Fingerprints.kt @@ -1,69 +1,39 @@ package app.revanced.patches.shared.misc.privacy -import app.revanced.patcher.InstructionLocation.MatchAfterImmediately -import app.revanced.patcher.InstructionLocation.MatchAfterWithin -import app.revanced.patcher.checkCast -import app.revanced.patcher.fieldAccess -import app.revanced.patcher.fingerprint -import app.revanced.patcher.methodCall -import app.revanced.patcher.opcode -import app.revanced.patcher.addString +import app.revanced.patcher.* import com.android.tools.smali.dexlib2.Opcode -internal val youTubeCopyTextFingerprint = fingerprint { - returns("V") - parameters("L", "Ljava/util/Map;") +internal val youTubeCopyTextFingerprintMethodMatch = firstMethodComposite { + returnType("V") + parameterTypes("L", "Ljava/util/Map;") instructions( - opcode(Opcode.IGET_OBJECT), - addString("text/plain", location = MatchAfterWithin(2)), - methodCall( - smali = "Landroid/content/ClipData;->newPlainText(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Landroid/content/ClipData;", - location = MatchAfterWithin(2) - ), - opcode(Opcode.MOVE_RESULT_OBJECT, location = MatchAfterWithin(2)), - methodCall( - smali = "Landroid/content/ClipboardManager;->setPrimaryClip(Landroid/content/ClipData;)V", - location = MatchAfterWithin(2) - ) + Opcode.IGET_OBJECT(), + after(0..2, "text/plain"()), + after(0..2, method("newPlainText")), + after(0..2, Opcode.MOVE_RESULT_OBJECT()), + after(0..2, method("setPrimaryClip")) ) } -internal val youTubeSystemShareSheetFingerprint = fingerprint { - returns("V") - parameters("L", "Ljava/util/Map;") +internal val youTubeSystemShareSheetMethodMatch = firstMethodComposite { + returnType("V") + parameterTypes("L", "Ljava/util/Map;") instructions( - methodCall( - smali = "Landroid/content/Intent;->setClassName(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;" - ), - - methodCall( - smali = "Ljava/util/List;->iterator()Ljava/util/Iterator;", - location = MatchAfterWithin(4) - ), - - fieldAccess( - opcode = Opcode.IGET_OBJECT, - type = "Ljava/lang/String;", - location = MatchAfterWithin(15) - ), - - methodCall( - smali = "Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;", - location = MatchAfterWithin(15) - ) + method("setClassName"), + after(0..4, method("iterator")), + after(0..15, allOf(Opcode.IGET_OBJECT(), type("Ljava/lang/String;"))), + after(0..15, method("putExtra")) ) } -internal val youTubeShareSheetFingerprint = fingerprint { - returns("V") - parameters("L", "Ljava/util/Map;") +internal val youTubeShareSheetMethodMatch = firstMethodComposite { + returnType("V") + parameterTypes("L", "Ljava/util/Map;") instructions( - opcode(Opcode.IGET_OBJECT), - checkCast("Ljava/lang/String;", location = MatchAfterImmediately()), - opcode(Opcode.GOTO, location = MatchAfterImmediately()), - - methodCall(smali = "Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;"), - - addString("YTShare_Logging_Share_Intent_Endpoint_Byte_Array") + Opcode.IGET_OBJECT(), + after(allOf(Opcode.CHECK_CAST(), type("Ljava/lang/String;"))), + after(Opcode.GOTO()), + method("putExtra"), + "YTShare_Logging_Share_Intent_Endpoint_Byte_Array"() ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/SanitizeSharingLinksPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/SanitizeSharingLinksPatch.kt index cfb29c603..df32f9e37 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/SanitizeSharingLinksPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/SanitizeSharingLinksPatch.kt @@ -1,6 +1,6 @@ package app.revanced.patches.shared.misc.privacy -import app.revanced.patcher.Fingerprint +import app.revanced.patcher.MatchBuilder import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.patch.BytecodePatchBuilder @@ -60,8 +60,8 @@ internal fun sanitizeSharingLinksPatch( } ) - fun Fingerprint.hookUrlString(matchIndex: Int) { - val index = instructionMatches[matchIndex].index + fun MatchBuilder.hookUrlString(matchIndex: Int) { + val index = indices[matchIndex] val urlRegister = method.getInstruction(index).registerA method.addInstructions( @@ -73,8 +73,8 @@ internal fun sanitizeSharingLinksPatch( ) } - fun Fingerprint.hookIntentPutExtra(matchIndex: Int) { - val index = instructionMatches[matchIndex].index + fun MatchBuilder.hookIntentPutExtra(matchIndex: Int) { + val index = indices[matchIndex] val urlRegister = method.getInstruction(index).registerE method.addInstructionsAtControlFlowLabel( @@ -87,12 +87,12 @@ internal fun sanitizeSharingLinksPatch( } // YouTube share sheet copy link. - youTubeCopyTextFingerprint.hookUrlString(0) + youTubeCopyTextFingerprintMethodMatch.hookUrlString(0) // YouTube share sheet other apps. - youTubeShareSheetFingerprint.hookIntentPutExtra(3) + youTubeShareSheetMethodMatch.hookIntentPutExtra(3) // Native system share sheet. - youTubeSystemShareSheetFingerprint.hookIntentPutExtra(3) + youTubeSystemShareSheetMethodMatch.hookIntentPutExtra(3) } } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt index 15e48efcb..9e74fff5f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt @@ -1,51 +1,48 @@ package app.revanced.patches.shared.misc.spoof +import app.revanced.patcher.accessFlags import app.revanced.patcher.fingerprint -import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction -import app.revanced.patcher.literal -import app.revanced.patcher.methodCall -import app.revanced.patcher.addString +import app.revanced.patcher.custom +import app.revanced.patcher.extensions.methodReference +import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.immutableClassDef +import app.revanced.patcher.instructions +import app.revanced.patcher.invoke +import app.revanced.patcher.method +import app.revanced.patcher.parameterTypes +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.Method -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val buildInitPlaybackRequestFingerprint = fingerprint { - returns("Lorg/chromium/net/UrlRequest\$Builder;") - opcodes( - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, // Moves the request URI string to a register to build the request with. - ) - strings( - "Content-Type", - "Range", - ) -} - -internal val buildPlayerRequestURIFingerprint = fingerprint { - returns("Ljava/lang/String;") - opcodes( - Opcode.INVOKE_VIRTUAL, // Register holds player request URI. - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.MONITOR_EXIT, - Opcode.RETURN_OBJECT, - ) - strings( - "key", - "asig", - ) -} - -internal val buildRequestFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) - returns("Lorg/chromium/net/UrlRequest") // UrlRequest; or UrlRequest$Builder; +internal val buildInitPlaybackRequestMatch = firstMethodComposite("Content-Type", "Range") { + returnType("Lorg/chromium/net/UrlRequest\$Builder;") instructions( - methodCall(name = "newUrlRequestBuilder") + Opcode.MOVE_RESULT_OBJECT(), + Opcode.IGET_OBJECT(), // Moves the request URI string to a register to build the request with. + ) +} + +internal val buildPlayerRequestURIMethodMatch = firstMethodComposite("key", "asig") { + returnType("Ljava/lang/String;") + instructions( + Opcode.INVOKE_VIRTUAL(), // Register holds player request URI. + Opcode.MOVE_RESULT_OBJECT(), + Opcode.IPUT_OBJECT(), + Opcode.IGET_OBJECT(), + Opcode.MONITOR_EXIT(), + Opcode.RETURN_OBJECT(), + ) +} + +internal val buildRequestMethodMatch = firstMethodComposite() { + accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) + returnType("Lorg/chromium/net/UrlRequest") // UrlRequest; or UrlRequest$Builder; + instructions( + method("newUrlRequestBuilder"), ) // UrlRequest; or UrlRequest$Builder; - custom { methodDef, _ -> + custom { // Different targets have slightly different parameters // Earlier targets have parameters: @@ -75,11 +72,11 @@ internal val buildRequestFingerprint = fingerprint { // Lorg/chromium/net/UrlRequest$Callback; // L - val parameterTypes = methodDef.parameterTypes + val parameterTypes = parameterTypes val parameterTypesSize = parameterTypes.size (parameterTypesSize == 6 || parameterTypesSize == 7 || parameterTypesSize == 8) && parameterTypes[1] == "Ljava/util/Map;" // URL headers. - && indexOfNewUrlRequestBuilderInstruction(methodDef) >= 0 + && indexOfNewUrlRequestBuilderInstruction(this) >= 0 } } @@ -96,19 +93,19 @@ internal val protobufClassParseByteBufferFingerprint = fingerprint { custom { method, _ -> method.name == "parseFrom" } } -internal val createStreamingDataFingerprint = fingerprint { +internal val createStreamingDataMethodMatch = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - parameters("L") - opcodes( - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IPUT_OBJECT, + parameterTypes("L") + instructions( + Opcode.IPUT_OBJECT(), + Opcode.IGET_OBJECT(), + Opcode.IF_NEZ(), + Opcode.SGET_OBJECT(), + Opcode.IPUT_OBJECT(), ) - custom { method, classDef -> - classDef.fields.any { field -> - field.name == "a" && field.type.endsWith("/StreamingDataOuterClass\$StreamingData;") + custom { + immutableClassDef.fields.any { field -> + field.name == "a" && field.type.endsWith($$"/StreamingDataOuterClass$StreamingData;") } } } @@ -129,22 +126,22 @@ internal val buildMediaDataSourceFingerprint = fingerprint { ) } -internal val hlsCurrentTimeFingerprint = fingerprint { +internal val hlsCurrentTimeMethodMatch = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - parameters("Z", "L") + parameterTypes("Z", "L") instructions( - literal(45355374L) // HLS current time feature flag. + 45355374L() // HLS current time feature flag. ) } internal const val DISABLED_BY_SABR_STREAMING_URI_STRING = "DISABLED_BY_SABR_STREAMING_URI" -internal val mediaFetchEnumConstructorFingerprint = fingerprint { - returns("V") - strings( - "ENABLED", - "DISABLED_FOR_PLAYBACK", - DISABLED_BY_SABR_STREAMING_URI_STRING +internal val mediaFetchEnumConstructorMethodMatch = firstMethodComposite { + returnType("V") + instructions( + "ENABLED"(), + "DISABLED_FOR_PLAYBACK"(), + DISABLED_BY_SABR_STREAMING_URI_STRING() ) } @@ -169,35 +166,30 @@ internal val patchIncludedExtensionMethodFingerprint = fingerprint { // This code appears to replace the player config after the streams are loaded. // Flag is present in YouTube 19.34, but is missing Platypus stream replacement code until 19.43. // Flag and Platypus code is also present in newer versions of YouTube Music. -internal val mediaFetchHotConfigFingerprint = fingerprint { - instructions( - literal(45645570L) - ) +internal val mediaFetchHotConfigMethodMatch = firstMethodComposite { + instructions(45645570L()) } // YT 20.10+, YT Music 8.11 - 8.14. // Flag is missing in YT Music 8.15+, and it is not known if a replacement flag/feature exists. -internal val mediaFetchHotConfigAlternativeFingerprint = fingerprint { - instructions( - literal(45683169L) - ) +internal val mediaFetchHotConfigAlternativeMethodMatch = firstMethodComposite { + instructions(45683169L()) } // Feature flag that enables different code for parsing and starting video playback, -// but it's exact purpose is not known. If this flag is enabled while stream spoofing +// but its exact purpose is not known. If this flag is enabled while stream spoofing // then videos will never start playback and load forever. // Flag does not seem to affect playback if spoofing is off. -internal val playbackStartDescriptorFeatureFlagFingerprint = fingerprint { - parameters() - returns("Z") - instructions( - literal(45665455L) - ) +internal val playbackStartDescriptorFeatureFlagMethodMatch = firstMethodComposite() { + parameterTypes() + returnType("Z") + instructions(45665455L()) } internal fun indexOfNewUrlRequestBuilderInstruction(method: Method) = method.indexOfFirstInstruction { - val reference = getReference() - opcode == Opcode.INVOKE_VIRTUAL && reference?.definingClass == "Lorg/chromium/net/CronetEngine;" + val reference = methodReference ?: return@indexOfFirstInstruction false + + opcode == Opcode.INVOKE_VIRTUAL && reference.definingClass == "Lorg/chromium/net/CronetEngine;" && reference.name == "newUrlRequestBuilder" && reference.parameterTypes.size == 3 && reference.parameterTypes[0] == "Ljava/lang/String;" diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt index 98c5da9d9..ea274c5f7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt @@ -1,25 +1,13 @@ package app.revanced.patches.shared.misc.spoof -import app.revanced.patcher.Fingerprint -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.addInstructionsWithLabels -import app.revanced.patcher.extensions.getInstruction -import app.revanced.patcher.extensions.instructions +import app.revanced.patcher.extensions.* import app.revanced.patcher.fingerprint import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.bytecodePatch -import com.android.tools.smali.dexlib2.mutable.MutableMethod -import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.util.findFreeRegister -import app.revanced.util.findInstructionIndicesReversedOrThrow -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.insertLiteralOverride -import app.revanced.util.returnEarly +import app.revanced.util.* import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation @@ -30,6 +18,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter +import com.android.tools.smali.dexlib2.mutable.MutableMethod +import com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/spoof/SpoofVideoStreamsPatch;" @@ -39,7 +29,7 @@ private var buildRequestMethodUrlRegister = -1 internal fun spoofVideoStreamsPatch( extensionClassDescriptor: String, - mainActivityOnCreateFingerprint: Fingerprint, + getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod, fixMediaFetchHotConfig: BytecodePatchBuilder.() -> Boolean = { false }, fixMediaFetchHotConfigAlternative: BytecodePatchBuilder.() -> Boolean = { false }, fixParsePlaybackResponseFeatureFlag: BytecodePatchBuilder.() -> Boolean = { false }, @@ -56,7 +46,7 @@ internal fun spoofVideoStreamsPatch( apply { addResources("shared", "misc.fix.playback.spoofVideoStreamsPatch") - mainActivityOnCreateFingerprint.method.addInstruction( + getMainActivityOnCreateMethod().addInstruction( 0, "invoke-static { }, $extensionClassDescriptor->setClientOrderToUse()V" ) @@ -72,48 +62,44 @@ internal fun spoofVideoStreamsPatch( // region Block /initplayback requests to fall back to /get_watch requests. - buildInitPlaybackRequestFingerprint.let { - it.method.apply { - val moveUriStringIndex = it.instructionMatches.first().index - val targetRegister = getInstruction(moveUriStringIndex).registerA + buildInitPlaybackRequestMatch.method.apply { + val moveUriStringIndex = buildInitPlaybackRequestMatch.indices.first() + val targetRegister = getInstruction(moveUriStringIndex).registerA - addInstructions( - moveUriStringIndex + 1, - """ - invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$targetRegister - """ - ) - } + addInstructions( + moveUriStringIndex + 1, + """ + invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$targetRegister + """ + ) } // endregion // region Block /get_watch requests to fall back to /player requests. - buildPlayerRequestURIFingerprint.let { - it.method.apply { - val invokeToStringIndex = it.instructionMatches.first().index - val uriRegister = getInstruction(invokeToStringIndex).registerC + buildPlayerRequestURIMethodMatch.method.apply { + val invokeToStringIndex = buildPlayerRequestURIMethodMatch.indices.first() + val uriRegister = getInstruction(invokeToStringIndex).registerC - addInstructions( - invokeToStringIndex, - """ - invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri; - move-result-object v$uriRegister - """ - ) - } + addInstructions( + invokeToStringIndex, + """ + invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri; + move-result-object v$uriRegister + """ + ) } // endregion // region Get replacement streams at player requests. - buildRequestFingerprint.method.apply { + buildRequestMethodMatch.method.apply { buildRequestMethod = this - val newRequestBuilderIndex = buildRequestFingerprint.instructionMatches.first().index + val newRequestBuilderIndex = buildRequestMethodMatch.indices.first() buildRequestMethodUrlRegister = getInstruction(newRequestBuilderIndex).registerD val freeRegister = findFreeRegister(newRequestBuilderIndex, buildRequestMethodUrlRegister) @@ -130,21 +116,21 @@ internal fun spoofVideoStreamsPatch( // region Replace the streaming data with the replacement streams. - createStreamingDataFingerprint.method.apply { + createStreamingDataMethodMatch.method.apply { val setStreamDataMethodName = "patch_setStreamingData" - val resultMethodType = createStreamingDataFingerprint.classDef.type - val videoDetailsIndex = createStreamingDataFingerprint.instructionMatches.last().index + val resultMethodType = createStreamingDataMethodMatch.classDef.type + val videoDetailsIndex = createStreamingDataMethodMatch.indices.last() val videoDetailsRegister = getInstruction(videoDetailsIndex).registerA val videoDetailsClass = getInstruction(videoDetailsIndex).getReference()!!.type addInstruction( videoDetailsIndex + 1, "invoke-direct { p0, v$videoDetailsRegister }, " + - "$resultMethodType->$setStreamDataMethodName($videoDetailsClass)V", + "$resultMethodType->$setStreamDataMethodName($videoDetailsClass)V", ) val protobufClass = protobufClassParseByteBufferFingerprint.method.definingClass - val setStreamingDataIndex = createStreamingDataFingerprint.instructionMatches.first().index + val setStreamingDataIndex = createStreamingDataMethodMatch.indices.first() val playerProtoClass = getInstruction(setStreamingDataIndex + 1) .getReference()!!.definingClass @@ -158,7 +144,7 @@ internal fun spoofVideoStreamsPatch( ).getReference() // Use a helper method to avoid the need of picking out multiple free registers from the hooked code. - createStreamingDataFingerprint.classDef.methods.add( + createStreamingDataMethodMatch.classDef.methods.add( ImmutableMethod( resultMethodType, setStreamDataMethodName, @@ -270,25 +256,21 @@ internal fun spoofVideoStreamsPatch( // region Fix iOS livestream current time. - hlsCurrentTimeFingerprint.let { - it.method.insertLiteralOverride( - it.instructionMatches.first().index, - "$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z" - ) - } + hlsCurrentTimeMethodMatch.method.insertLiteralOverride( + hlsCurrentTimeMethodMatch.indices.first(), + "$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z" + ) // endregion // region Disable SABR playback. // If SABR is disabled, it seems 'MediaFetchHotConfig' may no longer need an override (not confirmed). - val (mediaFetchEnumClass, sabrFieldReference) = with(mediaFetchEnumConstructorFingerprint.method) { - val stringIndex = mediaFetchEnumConstructorFingerprint.stringMatches.first { - it.string == DISABLED_BY_SABR_STREAMING_URI_STRING - }.index + val (mediaFetchEnumClass, sabrFieldReference) = with(mediaFetchEnumConstructorMethodMatch.method) { + val disabledBySABRStreamingUrlString = mediaFetchEnumConstructorMethodMatch.indices.last() val mediaFetchEnumClass = definingClass - val sabrFieldIndex = indexOfFirstInstructionOrThrow(stringIndex) { + val sabrFieldIndex = indexOfFirstInstructionOrThrow(disabledBySABRStreamingUrlString) { opcode == Opcode.SPUT_OBJECT && getReference()?.type == mediaFetchEnumClass } @@ -327,30 +309,24 @@ internal fun spoofVideoStreamsPatch( // region turn off stream config replacement feature flag. if (fixMediaFetchHotConfig()) { - mediaFetchHotConfigFingerprint.let { - it.method.insertLiteralOverride( - it.instructionMatches.first().index, - "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" - ) - } + mediaFetchHotConfigMethodMatch.method.insertLiteralOverride( + mediaFetchHotConfigMethodMatch.indices.first(), + "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" + ) } if (fixMediaFetchHotConfigAlternative()) { - mediaFetchHotConfigAlternativeFingerprint.let { - it.method.insertLiteralOverride( - it.instructionMatches.first().index, - "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" - ) - } + mediaFetchHotConfigAlternativeMethodMatch.method.insertLiteralOverride( + mediaFetchHotConfigAlternativeMethodMatch.indices.first(), + "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" + ) } if (fixParsePlaybackResponseFeatureFlag()) { - playbackStartDescriptorFeatureFlagFingerprint.let { - it.method.insertLiteralOverride( - it.instructionMatches.first().index, - "$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z" - ) - } + playbackStartDescriptorFeatureFlagMethodMatch.method.insertLiteralOverride( + playbackStartDescriptorFeatureFlagMethodMatch.indices.first(), + "$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z" + ) } // endregion diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/extension/hooks/ApplicationInitHook.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/extension/hooks/ApplicationInitHook.kt index 13a1590a7..aa037d7f2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/extension/hooks/ApplicationInitHook.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/extension/hooks/ApplicationInitHook.kt @@ -1,10 +1,10 @@ package app.revanced.patches.twitter.misc.extension.hooks +import app.revanced.patcher.definingClass +import app.revanced.patcher.name import app.revanced.patches.shared.misc.extension.extensionHook -internal val applicationInitHook = - extensionHook { - custom { method, classDef -> - classDef.type == "Lcom/twitter/app/TwitterApplication;" && method.name == "onCreate" - } - } \ No newline at end of file +internal val applicationInitHook = extensionHook { + name("onCreate") + definingClass("Lcom/twitter/app/TwitterApplication;") +} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt index bc1a9c781..cf21471fa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/branding/CustomBrandingPatch.kt @@ -15,7 +15,7 @@ val customBrandingPatch = baseCustomBrandingPatch( originalAppPackageName = YOUTUBE_PACKAGE_NAME, isYouTubeMusic = false, numberOfPresetAppNames = 5, - mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, + getMainActivityOnCreate = mainActivityOnCreateFingerprint, mainActivityName = YOUTUBE_MAIN_ACTIVITY_NAME, activityAliasNameWithIntents = "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity", preferenceScreen = PreferenceScreen.GENERAL_LAYOUT, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt index 77669971b..f432796a4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt @@ -12,12 +12,6 @@ import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val infocardsIncognitoMatch = firstMethodBuilder { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - returnType("V") - parameterTypes("L", "J") - instructions(string("vibrator")) -} internal val infocardsIncognitoFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("Ljava/lang/Boolean;") 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 9dab9c0df..6807f51cd 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 @@ -3,7 +3,6 @@ package app.revanced.patches.youtube.misc.gms import app.revanced.patcher.patch.Option import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResourcesPatch -import app.revanced.patches.shared.castContextFetchFingerprint import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch import app.revanced.patches.shared.misc.settings.preference.IntentPreference import app.revanced.patches.shared.primeMethodFingerprint @@ -20,11 +19,11 @@ import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint val gmsCoreSupportPatch = gmsCoreSupportPatch( fromPackageName = YOUTUBE_PACKAGE_NAME, toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME, - primeMethodFingerprint = primeMethodFingerprint, - earlyReturnFingerprints = setOf( + getPrimeMethod = primeMethodFingerprint, + getEarlyReturnMethods = setOf( castContextFetchFingerprint, ), - mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = mainActivityOnCreateFingerprint, extensionPatch = sharedExtensionPatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt index 592843406..32824fcb8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt @@ -17,7 +17,7 @@ import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint val spoofVideoStreamsPatch = spoofVideoStreamsPatch( extensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;", - mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = mainActivityOnCreateFingerprint, fixMediaFetchHotConfig = { is_19_34_or_greater }, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt index cbccffe1c..37fe186ac 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt @@ -27,7 +27,7 @@ val forceOriginalAudioPatch = forceOriginalAudioPatch( ) }, fixUseLocalizedAudioTrackFlag = { is_20_07_or_greater }, - mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, + getMainActivityOnCreateMethod = mainActivityOnCreateFingerprint, subclassExtensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/ForceOriginalAudioPatch;", preferenceScreen = PreferenceScreen.VIDEO, )