migrate batch
This commit is contained in:
parent
69a71fbd3a
commit
a103eb5b7a
26 changed files with 334 additions and 438 deletions
|
|
@ -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,
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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;")
|
||||||
}
|
}
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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 },
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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;")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;"
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -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")
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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")
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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;"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;")
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue