migrate batch

This commit is contained in:
oSumAtrIX 2026-01-09 20:00:49 +01:00
parent 69a71fbd3a
commit a103eb5b7a
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
26 changed files with 334 additions and 438 deletions

View file

@ -11,7 +11,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportResourcePatch
val gmsCoreSupportPatch = gmsCoreSupportPatch( val gmsCoreSupportPatch = gmsCoreSupportPatch(
fromPackageName = MAGAZINES_PACKAGE_NAME, fromPackageName = MAGAZINES_PACKAGE_NAME,
toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME, toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME,
mainActivityOnCreateFingerprint = magazinesActivityOnCreateFingerprint, getMainActivityOnCreate = magazinesActivityOnCreateFingerprint,
extensionPatch = extensionPatch, extensionPatch = extensionPatch,
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
) { ) {

View file

@ -10,7 +10,7 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
val gmsCoreSupportPatch = gmsCoreSupportPatch( val gmsCoreSupportPatch = gmsCoreSupportPatch(
fromPackageName = PHOTOS_PACKAGE_NAME, fromPackageName = PHOTOS_PACKAGE_NAME,
toPackageName = REVANCED_PHOTOS_PACKAGE_NAME, toPackageName = REVANCED_PHOTOS_PACKAGE_NAME,
mainActivityOnCreateFingerprint = homeActivityOnCreateFingerprint, getMainActivityOnCreate = homeActivityOnCreateFingerprint,
extensionPatch = extensionPatch, extensionPatch = extensionPatch,
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
) { ) {

View file

@ -6,7 +6,7 @@ import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch 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_MAIN_ACTIVITY_NAME
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_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.music.misc.settings.PreferenceScreen
import app.revanced.patches.shared.layout.branding.EXTENSION_CLASS_DESCRIPTOR import app.revanced.patches.shared.layout.branding.EXTENSION_CLASS_DESCRIPTOR
import app.revanced.patches.shared.layout.branding.baseCustomBrandingPatch import app.revanced.patches.shared.layout.branding.baseCustomBrandingPatch
@ -62,7 +62,7 @@ val customBrandingPatch = baseCustomBrandingPatch(
originalAppPackageName = MUSIC_PACKAGE_NAME, originalAppPackageName = MUSIC_PACKAGE_NAME,
isYouTubeMusic = true, isYouTubeMusic = true,
numberOfPresetAppNames = 5, numberOfPresetAppNames = 5,
mainActivityOnCreateFingerprint = musicActivityOnCreateFingerprint, getMainActivityOnCreate = { musicActivityOnCreateMethod },
mainActivityName = MUSIC_MAIN_ACTIVITY_NAME, mainActivityName = MUSIC_MAIN_ACTIVITY_NAME,
activityAliasNameWithIntents = MUSIC_MAIN_ACTIVITY_NAME, activityAliasNameWithIntents = MUSIC_MAIN_ACTIVITY_NAME,
preferenceScreen = PreferenceScreen.GENERAL, preferenceScreen = PreferenceScreen.GENERAL,

View file

@ -1,7 +1,7 @@
package app.revanced.patches.music.misc.dns package app.revanced.patches.music.misc.dns
import app.revanced.patches.music.misc.extension.sharedExtensionPatch 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 import app.revanced.patches.shared.misc.dns.checkWatchHistoryDomainNameResolutionPatch
val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameResolutionPatch( val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameResolutionPatch(
@ -18,5 +18,5 @@ val checkWatchHistoryDomainNameResolutionPatch = checkWatchHistoryDomainNameReso
) )
}, },
mainActivityFingerprint = mainActivityOnCreateFingerprint mainActivityFingerprint = mainActivityOnCreateMethod
) )

View file

@ -1,11 +1,13 @@
package app.revanced.patches.music.misc.gms 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") internal val BytecodePatchContext.musicActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively {
parameters("Landroid/os/Bundle;") name("onCreate")
custom { method, classDef -> definingClass("/MusicActivity;"::endsWith)
method.name == "onCreate" && classDef.endsWith("/MusicActivity;") returnType("V")
} parameterTypes("Landroid/os/Bundle;")
} }

View file

@ -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.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch 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.MUSIC_PACKAGE_NAME
import app.revanced.patches.music.misc.gms.Constants.REVANCED_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.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch import app.revanced.patches.music.misc.settings.settingsPatch
import app.revanced.patches.music.misc.spoof.spoofVideoStreamsPatch import app.revanced.patches.shared.castContextFetchMethod
import app.revanced.patches.music.misc.fileprovider.fileProviderPatch
import app.revanced.patches.shared.castContextFetchFingerprint
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
import app.revanced.patches.shared.misc.settings.preference.IntentPreference import app.revanced.patches.shared.misc.settings.preference.IntentPreference
import app.revanced.patches.shared.primeMethodFingerprint import app.revanced.patches.shared.primeMethod
@Suppress("unused") @Suppress("unused")
val gmsCoreSupportPatch = gmsCoreSupportPatch( val gmsCoreSupportPatch = gmsCoreSupportPatch(
fromPackageName = MUSIC_PACKAGE_NAME, fromPackageName = MUSIC_PACKAGE_NAME,
toPackageName = REVANCED_MUSIC_PACKAGE_NAME, toPackageName = REVANCED_MUSIC_PACKAGE_NAME,
primeMethodFingerprint = primeMethodFingerprint, getPrimeMethod = { primeMethod },
earlyReturnFingerprints = setOf( getEarlyReturnMethods = { setOf(castContextFetchMethod) },
castContextFetchFingerprint, getMainActivityOnCreateMethod = { musicActivityOnCreateMethod },
),
mainActivityOnCreateFingerprint = musicActivityOnCreateFingerprint,
extensionPatch = sharedExtensionPatch, extensionPatch = sharedExtensionPatch,
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
) { ) {
dependsOn(spoofVideoStreamsPatch)
compatibleWith( compatibleWith(
MUSIC_PACKAGE_NAME( MUSIC_PACKAGE_NAME(

View file

@ -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.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.music.misc.extension.sharedExtensionPatch 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.PreferenceScreen
import app.revanced.patches.music.misc.settings.settingsPatch 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.*
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.shared.misc.settings.preference.ListPreference 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.PreferenceScreenPreference
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
@ -18,7 +14,7 @@ import app.revanced.patches.shared.misc.spoof.spoofVideoStreamsPatch
val spoofVideoStreamsPatch = spoofVideoStreamsPatch( val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
extensionClassDescriptor = "Lapp/revanced/extension/music/patches/spoof/SpoofVideoStreamsPatch;", extensionClassDescriptor = "Lapp/revanced/extension/music/patches/spoof/SpoofVideoStreamsPatch;",
mainActivityOnCreateFingerprint = musicActivityOnCreateFingerprint, getMainActivityOnCreateMethod = { musicActivityOnCreateMethod },
fixMediaFetchHotConfig = { is_7_16_or_greater }, fixMediaFetchHotConfig = { is_7_16_or_greater },
fixMediaFetchHotConfigAlternative = { is_8_11_or_greater && !is_8_15_or_greater }, fixMediaFetchHotConfigAlternative = { is_8_11_or_greater && !is_8_15_or_greater },
fixParsePlaybackResponseFeatureFlag = { is_7_33_or_greater }, fixParsePlaybackResponseFeatureFlag = { is_7_33_or_greater },

View file

@ -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.misc.settings.settingsPatch
import app.revanced.patches.music.playservice.is_8_05_or_greater import app.revanced.patches.music.playservice.is_8_05_or_greater
import app.revanced.patches.music.playservice.versionCheckPatch 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 import app.revanced.patches.shared.misc.audio.forceOriginalAudioPatch
@Suppress("unused") @Suppress("unused")
@ -25,7 +25,7 @@ val forceOriginalAudioPatch = forceOriginalAudioPatch(
) )
}, },
fixUseLocalizedAudioTrackFlag = { is_8_05_or_greater }, fixUseLocalizedAudioTrackFlag = { is_8_05_or_greater },
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, getMainActivityOnCreateMethod = { mainActivityOnCreateMethod },
subclassExtensionClassDescriptor = "Lapp/revanced/extension/music/patches/ForceOriginalAudioPatch;", subclassExtensionClassDescriptor = "Lapp/revanced/extension/music/patches/ForceOriginalAudioPatch;",
preferenceScreen = PreferenceScreen.MISC, preferenceScreen = PreferenceScreen.MISC,
) )

View file

@ -1,13 +1,18 @@
package app.revanced.patches.music.shared 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 { internal val BytecodePatchContext.mainActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively {
returns("V") name("onCreate")
parameters("Landroid/os/Bundle;") definingClass(YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE)
custom { method, classDef -> returnType("V")
method.name == "onCreate" && classDef.type == YOUTUBE_MUSIC_MAIN_ACTIVITY_CLASS_TYPE parameterTypes("Landroid/os/Bundle;")
}
} }

View file

@ -2,6 +2,4 @@ package app.revanced.patches.reddit.customclients.baconreader.misc.extension.hoo
import app.revanced.patches.shared.misc.extension.activityOnCreateExtensionHook import app.revanced.patches.shared.misc.extension.activityOnCreateExtensionHook
internal val initHook = activityOnCreateExtensionHook( internal val initHook = activityOnCreateExtensionHook("Lcom/onelouder/baconreader/BaconReader;")
"Lcom/onelouder/baconreader/BaconReader;"
)

View file

@ -1,17 +1,13 @@
package app.revanced.patches.shared package app.revanced.patches.shared
import app.revanced.patcher.fingerprint import app.revanced.patcher.BytecodePatchContextMethodMatching.gettingFirstMutableMethodDeclaratively
import app.revanced.patcher.addString import app.revanced.patcher.patch.BytecodePatchContext
internal val castContextFetchFingerprint = fingerprint { internal val BytecodePatchContext.castContextFetchMethod by gettingFirstMutableMethodDeclaratively(
instructions( "Error fetching CastContext."
addString("Error fetching CastContext.") )
)
}
internal val primeMethodFingerprint = fingerprint { internal val BytecodePatchContext.primeMethod by gettingFirstMutableMethodDeclaratively(
instructions( "com.android.vending",
addString("com.android.vending"), "com.google.android.GoogleCamera"
addString("com.google.android.GoogleCamera") )
)
}

View file

@ -1,36 +1,21 @@
package app.revanced.patches.shared.layout.branding package app.revanced.patches.shared.layout.branding
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.*
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.patches.all.misc.packagename.setOrGetFallbackPackageName import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch 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.BasePreferenceScreen
import app.revanced.patches.shared.misc.settings.preference.ListPreference 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.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.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.TypeReference 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.Element
import org.w3c.dom.NodeList import org.w3c.dom.NodeList
import java.io.File import java.io.File
@ -81,13 +66,13 @@ internal fun baseCustomBrandingPatch(
originalAppPackageName: String, originalAppPackageName: String,
isYouTubeMusic: Boolean, isYouTubeMusic: Boolean,
numberOfPresetAppNames: Int, numberOfPresetAppNames: Int,
mainActivityOnCreateFingerprint: Fingerprint, getMainActivityOnCreate: BytecodePatchContext.() -> MutableMethod,
mainActivityName: String, mainActivityName: String,
activityAliasNameWithIntents: String, activityAliasNameWithIntents: String,
preferenceScreen: BasePreferenceScreen.Screen, preferenceScreen: BasePreferenceScreen.Screen,
block: ResourcePatchBuilder.() -> Unit, block: ResourcePatchBuilder.() -> Unit,
executeBlock: ResourcePatchContext.() -> Unit = {} executeBlock: ResourcePatchContext.() -> Unit = {}
): ResourcePatch = resourcePatch( ) = resourcePatch(
name = "Custom branding", name = "Custom branding",
description = "Adds options to change the app icon and app name. " + description = "Adds options to change the app icon and app name. " +
"Branding cannot be changed for mounted (root) installations." "Branding cannot be changed for mounted (root) installations."
@ -125,7 +110,7 @@ internal fun baseCustomBrandingPatch(
addBrandLicensePatch, addBrandLicensePatch,
bytecodePatch { bytecodePatch {
apply { apply {
mainActivityOnCreateFingerprint.method.addInstruction( getMainActivityOnCreate().addInstruction(
0, 0,
"invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setBranding()V" "invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->setBranding()V"
) )

View file

@ -1,24 +1,18 @@
package app.revanced.patches.shared.misc.audio package app.revanced.patches.shared.misc.audio
import app.revanced.patcher.fingerprint import app.revanced.patcher.*
import app.revanced.patcher.literal
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal val formatStreamModelToStringFingerprint = fingerprint { internal val formatStreamModelToStringMethodMatch = firstMethodComposite {
name("toString")
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Ljava/lang/String;") returnType("Ljava/lang/String;")
custom { method, _ -> instructions(
method.name == "toString" "isDefaultAudioTrack="(String::contains),
} "audioTrackId="(String::contains)
strings(
// Strings are partial matches.
"isDefaultAudioTrack=",
"audioTrackId="
) )
} }
internal val selectAudioStreamFingerprint = fingerprint { internal val selectAudioStreamMethodMatch = firstMethodComposite {
instructions( instructions(45666189L())
literal(45666189L)
)
} }

View file

@ -1,6 +1,5 @@
package app.revanced.patches.shared.misc.audio package app.revanced.patches.shared.misc.audio
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.addInstructionsWithLabels 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.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch 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.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen 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.ImmutableField
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter 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 = private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/patches/ForceOriginalAudioPatch;" "Lapp/revanced/extension/shared/patches/ForceOriginalAudioPatch;"
@ -35,7 +35,7 @@ internal fun forceOriginalAudioPatch(
block: BytecodePatchBuilder.() -> Unit = {}, block: BytecodePatchBuilder.() -> Unit = {},
executeBlock: BytecodePatchContext.() -> Unit = {}, executeBlock: BytecodePatchContext.() -> Unit = {},
fixUseLocalizedAudioTrackFlag: BytecodePatchContext.() -> Boolean, fixUseLocalizedAudioTrackFlag: BytecodePatchContext.() -> Boolean,
mainActivityOnCreateFingerprint: Fingerprint, getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod,
subclassExtensionClassDescriptor: String, subclassExtensionClassDescriptor: String,
preferenceScreen: BasePreferenceScreen.Screen preferenceScreen: BasePreferenceScreen.Screen
) = bytecodePatch( ) = bytecodePatch(
@ -57,7 +57,7 @@ internal fun forceOriginalAudioPatch(
) )
) )
mainActivityOnCreateFingerprint.method.addInstruction( getMainActivityOnCreateMethod().addInstruction(
0, 0,
"invoke-static { }, $subclassExtensionClassDescriptor->setEnabled()V" "invoke-static { }, $subclassExtensionClassDescriptor->setEnabled()V"
) )
@ -65,90 +65,91 @@ internal fun forceOriginalAudioPatch(
// Disable feature flag that ignores the default track flag // Disable feature flag that ignores the default track flag
// and instead overrides to the user region language. // and instead overrides to the user region language.
if (fixUseLocalizedAudioTrackFlag()) { if (fixUseLocalizedAudioTrackFlag()) {
selectAudioStreamFingerprint.method.insertLiteralOverride( selectAudioStreamMethodMatch.method.insertLiteralOverride(
selectAudioStreamFingerprint.instructionMatches.first().index, selectAudioStreamMethodMatch.indices.first(),
"$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z" "$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z"
) )
} }
formatStreamModelToStringFingerprint.let { val isDefaultAudioTrackMethod =
val isDefaultAudioTrackMethod = it.originalMethod.findMethodFromToString("isDefaultAudioTrack=") formatStreamModelToStringMethodMatch.immutableMethod.findMethodFromToString("isDefaultAudioTrack=")
val audioTrackDisplayNameMethod = it.originalMethod.findMethodFromToString("audioTrackDisplayName=") val audioTrackDisplayNameMethod =
val audioTrackIdMethod = it.originalMethod.findMethodFromToString("audioTrackId=") formatStreamModelToStringMethodMatch.immutableMethod.findMethodFromToString("audioTrackDisplayName=")
val audioTrackIdMethod =
formatStreamModelToStringMethodMatch.immutableMethod.findMethodFromToString("audioTrackId=")
it.classDef.apply { formatStreamModelToStringMethodMatch.classDef.apply {
// Add a new field to store the override. // Add a new field to store the override.
val helperFieldName = "patch_isDefaultAudioTrackOverride" val helperFieldName = "patch_isDefaultAudioTrackOverride"
fields.add( fields.add(
ImmutableField( ImmutableField(
type, type,
helperFieldName, helperFieldName,
"Ljava/lang/Boolean;", "Ljava/lang/Boolean;",
// Boolean is a 100% immutable class (all fields are final) // Boolean is a 100% immutable class (all fields are final)
// and safe to write to a shared field without volatile/synchronization, // and safe to write to a shared field without volatile/synchronization,
// but without volatile the field can show stale data // but without volatile the field can show stale data
// and the same field is calculated more than once by different threads. // and the same field is calculated more than once by different threads.
AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value, AccessFlags.PRIVATE.value or AccessFlags.VOLATILE.value,
null, null,
null, null,
null null
).toMutable() ).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. // Modify isDefaultAudioTrack() to call extension helper method.
val helperMethodClass = type isDefaultAudioTrackMethod.apply {
val helperMethodName = "patch_isDefaultAudioTrack" val index = indexOfFirstInstructionOrThrow(Opcode.RETURN)
val helperMethod = ImmutableMethod( val register = getInstruction<OneRegisterInstruction>(index).registerA
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. addInstructions(
isDefaultAudioTrackMethod.apply { index,
val index = indexOfFirstInstructionOrThrow(Opcode.RETURN) """
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructions(
index,
"""
invoke-direct { p0, v$register }, $helperMethodClass->$helperMethodName(Z)Z invoke-direct { p0, v$register }, $helperMethodClass->$helperMethodName(Z)Z
move-result v$register move-result v$register
""" """
) )
}
} }
} }

View file

@ -20,9 +20,9 @@ internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/
*/ */
fun sharedExtensionPatch( fun sharedExtensionPatch(
extensionName: String, extensionName: String,
vararg hooks: () -> ExtensionHook, vararg hooks: ExtensionHook,
) = bytecodePatch { ) = bytecodePatch {
dependsOn(sharedExtensionPatch(*hooks)) dependsOn(sharedExtensionPatch(hooks = hooks))
extendWith("extensions/$extensionName.rve") extendWith("extensions/$extensionName.rve")
} }
@ -34,7 +34,7 @@ fun sharedExtensionPatch(
* commonly for the onCreate method of exported activities. * commonly for the onCreate method of exported activities.
*/ */
fun sharedExtensionPatch( fun sharedExtensionPatch(
vararg hooks: () -> ExtensionHook, vararg hooks: ExtensionHook,
) = bytecodePatch { ) = bytecodePatch {
extendWith("extensions/shared.rve") extendWith("extensions/shared.rve")
@ -45,7 +45,7 @@ fun sharedExtensionPatch(
afterDependents { afterDependents {
// The hooks are made in afterDependents to ensure that the context is hooked before any other patches. // 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. // Modify Utils method to include the patches release version.
/** /**
@ -87,9 +87,9 @@ class ExtensionHook internal constructor(
private val getContextRegister: Method.() -> String, private val getContextRegister: Method.() -> String,
private val predicate: DeclarativePredicate<Method>, private val predicate: DeclarativePredicate<Method>,
) { ) {
context(context: BytecodePatchContext) context(_: BytecodePatchContext)
operator fun invoke(extensionClassDescriptor: String) { operator fun invoke(extensionClassDescriptor: String) {
val method = context.firstMutableMethodDeclaratively(predicate = predicate) val method = firstMutableMethodDeclaratively(predicate = predicate)
val insertIndex = method.getInsertIndex() val insertIndex = method.getInsertIndex()
val contextRegister = method.getContextRegister() val contextRegister = method.getContextRegister()

View file

@ -1,6 +1,5 @@
package app.revanced.patches.shared.misc.gms package app.revanced.patches.shared.misc.gms
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instructions import app.revanced.patcher.extensions.instructions
import app.revanced.patcher.extensions.replaceInstruction 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.instruction.formats.Instruction21c
import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableStringReference 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 com.android.tools.smali.dexlib2.util.MethodUtil
import org.w3c.dom.Element import org.w3c.dom.Element
import org.w3c.dom.Node 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 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 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 getPrimeMethod The "prime" method that needs to be patched.
* @param earlyReturnFingerprints The fingerprints of methods that need to be returned early. * @param getEarlyReturnMethods The methods that need to be returned early.
* @param mainActivityOnCreateFingerprint The fingerprint of the main activity onCreate method. * @param getMainActivityOnCreateMethod The main activity onCreate method.
* @param extensionPatch The patch responsible for the extension. * @param extensionPatch The patch responsible for the extension.
* @param gmsCoreSupportResourcePatchFactory The factory for the corresponding resource patch * @param gmsCoreSupportResourcePatchFactory The factory for the corresponding resource patch
* that is used to patch the resources. * 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( fun gmsCoreSupportPatch(
fromPackageName: String, fromPackageName: String,
toPackageName: String, toPackageName: String,
primeMethodFingerprint: Fingerprint? = null, getPrimeMethod: (BytecodePatchContext.() -> MutableMethod)? = null,
earlyReturnFingerprints: Set<Fingerprint> = setOf(), getEarlyReturnMethods: BytecodePatchContext.() -> Set<MutableMethod> = { setOf() },
mainActivityOnCreateFingerprint: Fingerprint, getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod,
extensionPatch: Patch, extensionPatch: Patch,
gmsCoreSupportResourcePatchFactory: (gmsCoreVendorGroupIdOption: Option<String>) -> Patch, gmsCoreSupportResourcePatchFactory: (gmsCoreVendorGroupIdOption: Option<String>) -> Patch,
executeBlock: BytecodePatchContext.() -> Unit = {}, executeBlock: BytecodePatchContext.() -> Unit = {},
@ -165,18 +165,18 @@ fun gmsCoreSupportPatch(
} }
fun transformPrimeMethod(packageName: String) { fun transformPrimeMethod(packageName: String) {
primeMethodFingerprint!!.method.apply { val primeMethod = getPrimeMethod!!()
var register = 2
val index = instructions.indexOfFirst { var register = 2
if (it.getReference<StringReference>()?.string != fromPackageName) return@indexOfFirst false
register = (it as OneRegisterInstruction).registerA val index = primeMethod.instructions.indexOfFirst {
return@indexOfFirst true if (it.getReference<StringReference>()?.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 // endregion
@ -198,18 +198,10 @@ fun gmsCoreSupportPatch(
} }
// Specific method that needs to be patched. // 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. // Return these methods early to prevent the app from crashing.
earlyReturnFingerprints.forEach { getEarlyReturnMethods().forEach { it.returnEarly() }
it.method.apply {
if (returnType == "Z") {
returnEarly(false)
} else {
returnEarly()
}
}
}
serviceCheckFingerprint.method.returnEarly() serviceCheckFingerprint.method.returnEarly()
// Google Play Utility is not present in all apps, so we need to check if it's present. // 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) originalPackageNameExtensionFingerprint.method.returnEarly(fromPackageName)
// Verify GmsCore is installed and whitelisted for power optimizations and background usage. // Verify GmsCore is installed and whitelisted for power optimizations and background usage.
mainActivityOnCreateFingerprint.method.addInstruction( getMainActivityOnCreateMethod().addInstruction(
0, 0,
"invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" + "invoke-static/range { p0 .. p0 }, $EXTENSION_CLASS_DESCRIPTOR->" +
"checkGmsCore(Landroid/app/Activity;)V" "checkGmsCore(Landroid/app/Activity;)V"

View file

@ -1,69 +1,39 @@
package app.revanced.patches.shared.misc.privacy package app.revanced.patches.shared.misc.privacy
import app.revanced.patcher.InstructionLocation.MatchAfterImmediately import app.revanced.patcher.*
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 com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal val youTubeCopyTextFingerprint = fingerprint { internal val youTubeCopyTextFingerprintMethodMatch = firstMethodComposite {
returns("V") returnType("V")
parameters("L", "Ljava/util/Map;") parameterTypes("L", "Ljava/util/Map;")
instructions( instructions(
opcode(Opcode.IGET_OBJECT), Opcode.IGET_OBJECT(),
addString("text/plain", location = MatchAfterWithin(2)), after(0..2, "text/plain"()),
methodCall( after(0..2, method("newPlainText")),
smali = "Landroid/content/ClipData;->newPlainText(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Landroid/content/ClipData;", after(0..2, Opcode.MOVE_RESULT_OBJECT()),
location = MatchAfterWithin(2) after(0..2, method("setPrimaryClip"))
),
opcode(Opcode.MOVE_RESULT_OBJECT, location = MatchAfterWithin(2)),
methodCall(
smali = "Landroid/content/ClipboardManager;->setPrimaryClip(Landroid/content/ClipData;)V",
location = MatchAfterWithin(2)
)
) )
} }
internal val youTubeSystemShareSheetFingerprint = fingerprint { internal val youTubeSystemShareSheetMethodMatch = firstMethodComposite {
returns("V") returnType("V")
parameters("L", "Ljava/util/Map;") parameterTypes("L", "Ljava/util/Map;")
instructions( instructions(
methodCall( method("setClassName"),
smali = "Landroid/content/Intent;->setClassName(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;" after(0..4, method("iterator")),
), after(0..15, allOf(Opcode.IGET_OBJECT(), type("Ljava/lang/String;"))),
after(0..15, method("putExtra"))
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)
)
) )
} }
internal val youTubeShareSheetFingerprint = fingerprint { internal val youTubeShareSheetMethodMatch = firstMethodComposite {
returns("V") returnType("V")
parameters("L", "Ljava/util/Map;") parameterTypes("L", "Ljava/util/Map;")
instructions( instructions(
opcode(Opcode.IGET_OBJECT), Opcode.IGET_OBJECT(),
checkCast("Ljava/lang/String;", location = MatchAfterImmediately()), after(allOf(Opcode.CHECK_CAST(), type("Ljava/lang/String;"))),
opcode(Opcode.GOTO, location = MatchAfterImmediately()), after(Opcode.GOTO()),
method("putExtra"),
methodCall(smali = "Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;"), "YTShare_Logging_Share_Intent_Endpoint_Byte_Array"()
addString("YTShare_Logging_Share_Intent_Endpoint_Byte_Array")
) )
} }

View file

@ -1,6 +1,6 @@
package app.revanced.patches.shared.misc.privacy 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.addInstructions
import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.extensions.getInstruction
import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.BytecodePatchBuilder
@ -60,8 +60,8 @@ internal fun sanitizeSharingLinksPatch(
} }
) )
fun Fingerprint.hookUrlString(matchIndex: Int) { fun MatchBuilder.hookUrlString(matchIndex: Int) {
val index = instructionMatches[matchIndex].index val index = indices[matchIndex]
val urlRegister = method.getInstruction<OneRegisterInstruction>(index).registerA val urlRegister = method.getInstruction<OneRegisterInstruction>(index).registerA
method.addInstructions( method.addInstructions(
@ -73,8 +73,8 @@ internal fun sanitizeSharingLinksPatch(
) )
} }
fun Fingerprint.hookIntentPutExtra(matchIndex: Int) { fun MatchBuilder.hookIntentPutExtra(matchIndex: Int) {
val index = instructionMatches[matchIndex].index val index = indices[matchIndex]
val urlRegister = method.getInstruction<FiveRegisterInstruction>(index).registerE val urlRegister = method.getInstruction<FiveRegisterInstruction>(index).registerE
method.addInstructionsAtControlFlowLabel( method.addInstructionsAtControlFlowLabel(
@ -87,12 +87,12 @@ internal fun sanitizeSharingLinksPatch(
} }
// YouTube share sheet copy link. // YouTube share sheet copy link.
youTubeCopyTextFingerprint.hookUrlString(0) youTubeCopyTextFingerprintMethodMatch.hookUrlString(0)
// YouTube share sheet other apps. // YouTube share sheet other apps.
youTubeShareSheetFingerprint.hookIntentPutExtra(3) youTubeShareSheetMethodMatch.hookIntentPutExtra(3)
// Native system share sheet. // Native system share sheet.
youTubeSystemShareSheetFingerprint.hookIntentPutExtra(3) youTubeSystemShareSheetMethodMatch.hookIntentPutExtra(3)
} }
} }

View file

@ -1,51 +1,48 @@
package app.revanced.patches.shared.misc.spoof package app.revanced.patches.shared.misc.spoof
import app.revanced.patcher.accessFlags
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstruction
import app.revanced.patcher.literal import app.revanced.patcher.custom
import app.revanced.patcher.methodCall import app.revanced.patcher.extensions.methodReference
import app.revanced.patcher.addString 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.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val buildInitPlaybackRequestFingerprint = fingerprint { internal val buildInitPlaybackRequestMatch = firstMethodComposite("Content-Type", "Range") {
returns("Lorg/chromium/net/UrlRequest\$Builder;") returnType("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;
instructions( 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; ) // UrlRequest; or UrlRequest$Builder;
custom { methodDef, _ -> custom {
// Different targets have slightly different parameters // Different targets have slightly different parameters
// Earlier targets have parameters: // Earlier targets have parameters:
@ -75,11 +72,11 @@ internal val buildRequestFingerprint = fingerprint {
// Lorg/chromium/net/UrlRequest$Callback; // Lorg/chromium/net/UrlRequest$Callback;
// L // L
val parameterTypes = methodDef.parameterTypes val parameterTypes = parameterTypes
val parameterTypesSize = parameterTypes.size val parameterTypesSize = parameterTypes.size
(parameterTypesSize == 6 || parameterTypesSize == 7 || parameterTypesSize == 8) && (parameterTypesSize == 6 || parameterTypesSize == 7 || parameterTypesSize == 8) &&
parameterTypes[1] == "Ljava/util/Map;" // URL headers. 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" } custom { method, _ -> method.name == "parseFrom" }
} }
internal val createStreamingDataFingerprint = fingerprint { internal val createStreamingDataMethodMatch = firstMethodComposite {
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
parameters("L") parameterTypes("L")
opcodes( instructions(
Opcode.IPUT_OBJECT, Opcode.IPUT_OBJECT(),
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT(),
Opcode.IF_NEZ, Opcode.IF_NEZ(),
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT(),
Opcode.IPUT_OBJECT, Opcode.IPUT_OBJECT(),
) )
custom { method, classDef -> custom {
classDef.fields.any { field -> immutableClassDef.fields.any { field ->
field.name == "a" && field.type.endsWith("/StreamingDataOuterClass\$StreamingData;") 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) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
parameters("Z", "L") parameterTypes("Z", "L")
instructions( 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 const val DISABLED_BY_SABR_STREAMING_URI_STRING = "DISABLED_BY_SABR_STREAMING_URI"
internal val mediaFetchEnumConstructorFingerprint = fingerprint { internal val mediaFetchEnumConstructorMethodMatch = firstMethodComposite {
returns("V") returnType("V")
strings( instructions(
"ENABLED", "ENABLED"(),
"DISABLED_FOR_PLAYBACK", "DISABLED_FOR_PLAYBACK"(),
DISABLED_BY_SABR_STREAMING_URI_STRING 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. // 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 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. // Flag and Platypus code is also present in newer versions of YouTube Music.
internal val mediaFetchHotConfigFingerprint = fingerprint { internal val mediaFetchHotConfigMethodMatch = firstMethodComposite {
instructions( instructions(45645570L())
literal(45645570L)
)
} }
// YT 20.10+, YT Music 8.11 - 8.14. // 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. // Flag is missing in YT Music 8.15+, and it is not known if a replacement flag/feature exists.
internal val mediaFetchHotConfigAlternativeFingerprint = fingerprint { internal val mediaFetchHotConfigAlternativeMethodMatch = firstMethodComposite {
instructions( instructions(45683169L())
literal(45683169L)
)
} }
// Feature flag that enables different code for parsing and starting video playback, // 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. // then videos will never start playback and load forever.
// Flag does not seem to affect playback if spoofing is off. // Flag does not seem to affect playback if spoofing is off.
internal val playbackStartDescriptorFeatureFlagFingerprint = fingerprint { internal val playbackStartDescriptorFeatureFlagMethodMatch = firstMethodComposite() {
parameters() parameterTypes()
returns("Z") returnType("Z")
instructions( instructions(45665455L())
literal(45665455L)
)
} }
internal fun indexOfNewUrlRequestBuilderInstruction(method: Method) = method.indexOfFirstInstruction { internal fun indexOfNewUrlRequestBuilderInstruction(method: Method) = method.indexOfFirstInstruction {
val reference = getReference<MethodReference>() val reference = methodReference ?: return@indexOfFirstInstruction false
opcode == Opcode.INVOKE_VIRTUAL && reference?.definingClass == "Lorg/chromium/net/CronetEngine;"
opcode == Opcode.INVOKE_VIRTUAL && reference.definingClass == "Lorg/chromium/net/CronetEngine;"
&& reference.name == "newUrlRequestBuilder" && reference.name == "newUrlRequestBuilder"
&& reference.parameterTypes.size == 3 && reference.parameterTypes.size == 3
&& reference.parameterTypes[0] == "Ljava/lang/String;" && reference.parameterTypes[0] == "Ljava/lang/String;"

View file

@ -1,25 +1,13 @@
package app.revanced.patches.shared.misc.spoof package app.revanced.patches.shared.misc.spoof
import app.revanced.patcher.Fingerprint import app.revanced.patcher.extensions.*
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.fingerprint import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.BytecodePatchBuilder import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.bytecodePatch 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.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.util.findFreeRegister import app.revanced.util.*
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 com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation 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.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter 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 = internal const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/spoof/SpoofVideoStreamsPatch;" "Lapp/revanced/extension/shared/spoof/SpoofVideoStreamsPatch;"
@ -39,7 +29,7 @@ private var buildRequestMethodUrlRegister = -1
internal fun spoofVideoStreamsPatch( internal fun spoofVideoStreamsPatch(
extensionClassDescriptor: String, extensionClassDescriptor: String,
mainActivityOnCreateFingerprint: Fingerprint, getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod,
fixMediaFetchHotConfig: BytecodePatchBuilder.() -> Boolean = { false }, fixMediaFetchHotConfig: BytecodePatchBuilder.() -> Boolean = { false },
fixMediaFetchHotConfigAlternative: BytecodePatchBuilder.() -> Boolean = { false }, fixMediaFetchHotConfigAlternative: BytecodePatchBuilder.() -> Boolean = { false },
fixParsePlaybackResponseFeatureFlag: BytecodePatchBuilder.() -> Boolean = { false }, fixParsePlaybackResponseFeatureFlag: BytecodePatchBuilder.() -> Boolean = { false },
@ -56,7 +46,7 @@ internal fun spoofVideoStreamsPatch(
apply { apply {
addResources("shared", "misc.fix.playback.spoofVideoStreamsPatch") addResources("shared", "misc.fix.playback.spoofVideoStreamsPatch")
mainActivityOnCreateFingerprint.method.addInstruction( getMainActivityOnCreateMethod().addInstruction(
0, 0,
"invoke-static { }, $extensionClassDescriptor->setClientOrderToUse()V" "invoke-static { }, $extensionClassDescriptor->setClientOrderToUse()V"
) )
@ -72,48 +62,44 @@ internal fun spoofVideoStreamsPatch(
// region Block /initplayback requests to fall back to /get_watch requests. // region Block /initplayback requests to fall back to /get_watch requests.
buildInitPlaybackRequestFingerprint.let { buildInitPlaybackRequestMatch.method.apply {
it.method.apply { val moveUriStringIndex = buildInitPlaybackRequestMatch.indices.first()
val moveUriStringIndex = it.instructionMatches.first().index val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
addInstructions( addInstructions(
moveUriStringIndex + 1, moveUriStringIndex + 1,
""" """
invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String; invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister move-result-object v$targetRegister
""" """
) )
}
} }
// endregion // endregion
// region Block /get_watch requests to fall back to /player requests. // region Block /get_watch requests to fall back to /player requests.
buildPlayerRequestURIFingerprint.let { buildPlayerRequestURIMethodMatch.method.apply {
it.method.apply { val invokeToStringIndex = buildPlayerRequestURIMethodMatch.indices.first()
val invokeToStringIndex = it.instructionMatches.first().index val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
addInstructions( addInstructions(
invokeToStringIndex, invokeToStringIndex,
""" """
invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri; invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
move-result-object v$uriRegister move-result-object v$uriRegister
""" """
) )
}
} }
// endregion // endregion
// region Get replacement streams at player requests. // region Get replacement streams at player requests.
buildRequestFingerprint.method.apply { buildRequestMethodMatch.method.apply {
buildRequestMethod = this buildRequestMethod = this
val newRequestBuilderIndex = buildRequestFingerprint.instructionMatches.first().index val newRequestBuilderIndex = buildRequestMethodMatch.indices.first()
buildRequestMethodUrlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD buildRequestMethodUrlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD
val freeRegister = findFreeRegister(newRequestBuilderIndex, buildRequestMethodUrlRegister) val freeRegister = findFreeRegister(newRequestBuilderIndex, buildRequestMethodUrlRegister)
@ -130,21 +116,21 @@ internal fun spoofVideoStreamsPatch(
// region Replace the streaming data with the replacement streams. // region Replace the streaming data with the replacement streams.
createStreamingDataFingerprint.method.apply { createStreamingDataMethodMatch.method.apply {
val setStreamDataMethodName = "patch_setStreamingData" val setStreamDataMethodName = "patch_setStreamingData"
val resultMethodType = createStreamingDataFingerprint.classDef.type val resultMethodType = createStreamingDataMethodMatch.classDef.type
val videoDetailsIndex = createStreamingDataFingerprint.instructionMatches.last().index val videoDetailsIndex = createStreamingDataMethodMatch.indices.last()
val videoDetailsRegister = getInstruction<TwoRegisterInstruction>(videoDetailsIndex).registerA val videoDetailsRegister = getInstruction<TwoRegisterInstruction>(videoDetailsIndex).registerA
val videoDetailsClass = getInstruction(videoDetailsIndex).getReference<FieldReference>()!!.type val videoDetailsClass = getInstruction(videoDetailsIndex).getReference<FieldReference>()!!.type
addInstruction( addInstruction(
videoDetailsIndex + 1, videoDetailsIndex + 1,
"invoke-direct { p0, v$videoDetailsRegister }, " + "invoke-direct { p0, v$videoDetailsRegister }, " +
"$resultMethodType->$setStreamDataMethodName($videoDetailsClass)V", "$resultMethodType->$setStreamDataMethodName($videoDetailsClass)V",
) )
val protobufClass = protobufClassParseByteBufferFingerprint.method.definingClass val protobufClass = protobufClassParseByteBufferFingerprint.method.definingClass
val setStreamingDataIndex = createStreamingDataFingerprint.instructionMatches.first().index val setStreamingDataIndex = createStreamingDataMethodMatch.indices.first()
val playerProtoClass = getInstruction(setStreamingDataIndex + 1) val playerProtoClass = getInstruction(setStreamingDataIndex + 1)
.getReference<FieldReference>()!!.definingClass .getReference<FieldReference>()!!.definingClass
@ -158,7 +144,7 @@ internal fun spoofVideoStreamsPatch(
).getReference<FieldReference>() ).getReference<FieldReference>()
// Use a helper method to avoid the need of picking out multiple free registers from the hooked code. // 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( ImmutableMethod(
resultMethodType, resultMethodType,
setStreamDataMethodName, setStreamDataMethodName,
@ -270,25 +256,21 @@ internal fun spoofVideoStreamsPatch(
// region Fix iOS livestream current time. // region Fix iOS livestream current time.
hlsCurrentTimeFingerprint.let { hlsCurrentTimeMethodMatch.method.insertLiteralOverride(
it.method.insertLiteralOverride( hlsCurrentTimeMethodMatch.indices.first(),
it.instructionMatches.first().index, "$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z"
"$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z" )
)
}
// endregion // endregion
// region Disable SABR playback. // region Disable SABR playback.
// If SABR is disabled, it seems 'MediaFetchHotConfig' may no longer need an override (not confirmed). // If SABR is disabled, it seems 'MediaFetchHotConfig' may no longer need an override (not confirmed).
val (mediaFetchEnumClass, sabrFieldReference) = with(mediaFetchEnumConstructorFingerprint.method) { val (mediaFetchEnumClass, sabrFieldReference) = with(mediaFetchEnumConstructorMethodMatch.method) {
val stringIndex = mediaFetchEnumConstructorFingerprint.stringMatches.first { val disabledBySABRStreamingUrlString = mediaFetchEnumConstructorMethodMatch.indices.last()
it.string == DISABLED_BY_SABR_STREAMING_URI_STRING
}.index
val mediaFetchEnumClass = definingClass val mediaFetchEnumClass = definingClass
val sabrFieldIndex = indexOfFirstInstructionOrThrow(stringIndex) { val sabrFieldIndex = indexOfFirstInstructionOrThrow(disabledBySABRStreamingUrlString) {
opcode == Opcode.SPUT_OBJECT && opcode == Opcode.SPUT_OBJECT &&
getReference<FieldReference>()?.type == mediaFetchEnumClass getReference<FieldReference>()?.type == mediaFetchEnumClass
} }
@ -327,30 +309,24 @@ internal fun spoofVideoStreamsPatch(
// region turn off stream config replacement feature flag. // region turn off stream config replacement feature flag.
if (fixMediaFetchHotConfig()) { if (fixMediaFetchHotConfig()) {
mediaFetchHotConfigFingerprint.let { mediaFetchHotConfigMethodMatch.method.insertLiteralOverride(
it.method.insertLiteralOverride( mediaFetchHotConfigMethodMatch.indices.first(),
it.instructionMatches.first().index, "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z"
"$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" )
)
}
} }
if (fixMediaFetchHotConfigAlternative()) { if (fixMediaFetchHotConfigAlternative()) {
mediaFetchHotConfigAlternativeFingerprint.let { mediaFetchHotConfigAlternativeMethodMatch.method.insertLiteralOverride(
it.method.insertLiteralOverride( mediaFetchHotConfigAlternativeMethodMatch.indices.first(),
it.instructionMatches.first().index, "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z"
"$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z" )
)
}
} }
if (fixParsePlaybackResponseFeatureFlag()) { if (fixParsePlaybackResponseFeatureFlag()) {
playbackStartDescriptorFeatureFlagFingerprint.let { playbackStartDescriptorFeatureFlagMethodMatch.method.insertLiteralOverride(
it.method.insertLiteralOverride( playbackStartDescriptorFeatureFlagMethodMatch.indices.first(),
it.instructionMatches.first().index, "$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z"
"$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z" )
)
}
} }
// endregion // endregion

View file

@ -1,10 +1,10 @@
package app.revanced.patches.twitter.misc.extension.hooks 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 import app.revanced.patches.shared.misc.extension.extensionHook
internal val applicationInitHook = internal val applicationInitHook = extensionHook {
extensionHook { name("onCreate")
custom { method, classDef -> definingClass("Lcom/twitter/app/TwitterApplication;")
classDef.type == "Lcom/twitter/app/TwitterApplication;" && method.name == "onCreate" }
}
}

View file

@ -15,7 +15,7 @@ val customBrandingPatch = baseCustomBrandingPatch(
originalAppPackageName = YOUTUBE_PACKAGE_NAME, originalAppPackageName = YOUTUBE_PACKAGE_NAME,
isYouTubeMusic = false, isYouTubeMusic = false,
numberOfPresetAppNames = 5, numberOfPresetAppNames = 5,
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, getMainActivityOnCreate = mainActivityOnCreateFingerprint,
mainActivityName = YOUTUBE_MAIN_ACTIVITY_NAME, mainActivityName = YOUTUBE_MAIN_ACTIVITY_NAME,
activityAliasNameWithIntents = "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity", activityAliasNameWithIntents = "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity",
preferenceScreen = PreferenceScreen.GENERAL_LAYOUT, preferenceScreen = PreferenceScreen.GENERAL_LAYOUT,

View file

@ -12,12 +12,6 @@ import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode 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 { internal val infocardsIncognitoFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Ljava/lang/Boolean;") returns("Ljava/lang/Boolean;")

View file

@ -3,7 +3,6 @@ package app.revanced.patches.youtube.misc.gms
import app.revanced.patcher.patch.Option import app.revanced.patcher.patch.Option
import app.revanced.patches.all.misc.resources.addResources import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch 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.gms.gmsCoreSupportPatch
import app.revanced.patches.shared.misc.settings.preference.IntentPreference import app.revanced.patches.shared.misc.settings.preference.IntentPreference
import app.revanced.patches.shared.primeMethodFingerprint import app.revanced.patches.shared.primeMethodFingerprint
@ -20,11 +19,11 @@ import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
val gmsCoreSupportPatch = gmsCoreSupportPatch( val gmsCoreSupportPatch = gmsCoreSupportPatch(
fromPackageName = YOUTUBE_PACKAGE_NAME, fromPackageName = YOUTUBE_PACKAGE_NAME,
toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME, toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME,
primeMethodFingerprint = primeMethodFingerprint, getPrimeMethod = primeMethodFingerprint,
earlyReturnFingerprints = setOf( getEarlyReturnMethods = setOf(
castContextFetchFingerprint, castContextFetchFingerprint,
), ),
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, getMainActivityOnCreateMethod = mainActivityOnCreateFingerprint,
extensionPatch = sharedExtensionPatch, extensionPatch = sharedExtensionPatch,
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch, gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
) { ) {

View file

@ -17,7 +17,7 @@ import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
val spoofVideoStreamsPatch = spoofVideoStreamsPatch( val spoofVideoStreamsPatch = spoofVideoStreamsPatch(
extensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;", extensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/spoof/SpoofVideoStreamsPatch;",
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, getMainActivityOnCreateMethod = mainActivityOnCreateFingerprint,
fixMediaFetchHotConfig = { fixMediaFetchHotConfig = {
is_19_34_or_greater is_19_34_or_greater
}, },

View file

@ -27,7 +27,7 @@ val forceOriginalAudioPatch = forceOriginalAudioPatch(
) )
}, },
fixUseLocalizedAudioTrackFlag = { is_20_07_or_greater }, fixUseLocalizedAudioTrackFlag = { is_20_07_or_greater },
mainActivityOnCreateFingerprint = mainActivityOnCreateFingerprint, getMainActivityOnCreateMethod = mainActivityOnCreateFingerprint,
subclassExtensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/ForceOriginalAudioPatch;", subclassExtensionClassDescriptor = "Lapp/revanced/extension/youtube/patches/ForceOriginalAudioPatch;",
preferenceScreen = PreferenceScreen.VIDEO, preferenceScreen = PreferenceScreen.VIDEO,
) )