mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-06-12 13:17:46 +02:00
feat(YouTube): add Spoof streaming data
patch
This commit is contained in:
@ -276,6 +276,7 @@ object VisualPreferencesIconsPatch : BaseResourcePatch(
|
||||
"revanced_preference_screen_seekbar",
|
||||
"revanced_preference_screen_settings_menu",
|
||||
"revanced_preference_screen_shorts_player",
|
||||
"revanced_preference_screen_spoof_streaming_data",
|
||||
"revanced_preference_screen_toolbar",
|
||||
"revanced_preference_screen_video_description",
|
||||
"revanced_preference_screen_video_filter",
|
||||
|
@ -0,0 +1,261 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildInitPlaybackRequestFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildMediaDataSourceFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildPlayerRequestURIFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildRequestFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.CreateStreamingDataFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.NerdsStatsVideoFormatBuilderFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.ProtobufClassParseByteBufferFingerprint
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
object SpoofStreamingDataPatch : BaseBytecodePatch(
|
||||
name = "Spoof streaming data",
|
||||
description = "Adds options to spoof the streaming data to allow video playback.",
|
||||
dependencies = setOf(
|
||||
SettingsPatch::class,
|
||||
SpoofUserAgentPatch::class,
|
||||
),
|
||||
compatiblePackages = Constants.COMPATIBLE_PACKAGE,
|
||||
fingerprints = setOf(
|
||||
BuildInitPlaybackRequestFingerprint,
|
||||
BuildMediaDataSourceFingerprint,
|
||||
BuildPlayerRequestURIFingerprint,
|
||||
BuildRequestFingerprint,
|
||||
CreateStreamingDataFingerprint,
|
||||
ProtobufClassParseByteBufferFingerprint,
|
||||
|
||||
// Nerds stats video format.
|
||||
NerdsStatsVideoFormatBuilderFingerprint,
|
||||
)
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"$MISC_PATH/SpoofStreamingDataPatch;"
|
||||
private const val REQUEST_CLASS_DESCRIPTOR =
|
||||
"Lorg/chromium/net/UrlRequest;"
|
||||
private const val REQUEST_BUILDER_CLASS_DESCRIPTOR =
|
||||
"Lorg/chromium/net/UrlRequest\$Builder;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
|
||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||
|
||||
BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
moveUriStringIndex + 1,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$targetRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Block /get_watch requests to fall back to /player requests.
|
||||
|
||||
BuildPlayerRequestURIFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val invokeToStringIndex = BuildPlayerRequestURIFingerprint.indexOfToStringInstruction(this)
|
||||
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
invokeToStringIndex,
|
||||
"""
|
||||
invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
|
||||
move-result-object v$uriRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Fetch replacement streams.
|
||||
|
||||
BuildRequestFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val buildRequestIndex =
|
||||
BuildRequestFingerprint.indexOfBuildUrlRequestInstruction(this)
|
||||
val requestBuilderRegister = getInstruction<FiveRegisterInstruction>(buildRequestIndex).registerC
|
||||
|
||||
val newRequestBuilderIndex =
|
||||
BuildRequestFingerprint.indexOfNewUrlRequestBuilderInstruction(this)
|
||||
val urlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD
|
||||
|
||||
// Replace "requestBuilder.build()" with integrations call.
|
||||
replaceInstruction(
|
||||
buildRequestIndex,
|
||||
"invoke-static { v$requestBuilderRegister }, " +
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->" +
|
||||
"buildRequest($REQUEST_BUILDER_CLASS_DESCRIPTOR)" +
|
||||
REQUEST_CLASS_DESCRIPTOR
|
||||
)
|
||||
|
||||
val entrySetIndex = BuildRequestFingerprint.indexOfEntrySetInstruction(this)
|
||||
val mapRegister = if (entrySetIndex < 0)
|
||||
urlRegister + 1
|
||||
else
|
||||
getInstruction<FiveRegisterInstruction>(entrySetIndex).registerC
|
||||
|
||||
var smaliInstructions =
|
||||
"invoke-static { v$urlRegister, v$mapRegister }, " +
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->" +
|
||||
"setHeader(Ljava/lang/String;Ljava/util/Map;)V"
|
||||
|
||||
if (entrySetIndex < 0) smaliInstructions = """
|
||||
move-object/from16 v$mapRegister, p1
|
||||
|
||||
""" + smaliInstructions
|
||||
|
||||
// Copy request headers for streaming data fetch.
|
||||
addInstructions(newRequestBuilderIndex + 2, smaliInstructions)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Replace the streaming data.
|
||||
|
||||
CreateStreamingDataFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val setStreamingDataIndex = result.scanResult.patternScanResult!!.startIndex
|
||||
val setStreamingDataField = getInstruction(setStreamingDataIndex).getReference<FieldReference>().toString()
|
||||
|
||||
val playerProtoClass = getInstruction(setStreamingDataIndex + 1).getReference<FieldReference>()!!.definingClass
|
||||
val protobufClass = ProtobufClassParseByteBufferFingerprint.resultOrThrow().mutableMethod.definingClass
|
||||
|
||||
val getStreamingDataField = getInstructions().find { instruction ->
|
||||
instruction.opcode == Opcode.IGET_OBJECT &&
|
||||
instruction.getReference<FieldReference>()?.definingClass == playerProtoClass
|
||||
}?.getReference<FieldReference>()
|
||||
?: throw PatchException("Could not find getStreamingDataField")
|
||||
|
||||
val videoDetailsIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
val videoDetailsClass = getInstruction(videoDetailsIndex).getReference<FieldReference>()!!.type
|
||||
|
||||
val insertIndex = videoDetailsIndex + 1
|
||||
val videoDetailsRegister = getInstruction<TwoRegisterInstruction>(videoDetailsIndex).registerA
|
||||
|
||||
val overrideRegister = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
val freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isSpoofingEnabled()Z
|
||||
move-result v$freeRegister
|
||||
if-eqz v$freeRegister, :disabled
|
||||
|
||||
# Get video id.
|
||||
# From YouTube 17.34.36 to YouTube 19.16.39, the field names and field types are the same.
|
||||
iget-object v$freeRegister, v$videoDetailsRegister, $videoDetailsClass->c:Ljava/lang/String;
|
||||
if-eqz v$freeRegister, :disabled
|
||||
|
||||
# Get streaming data.
|
||||
invoke-static { v$freeRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStreamingData(Ljava/lang/String;)Ljava/nio/ByteBuffer;
|
||||
move-result-object v$freeRegister
|
||||
if-eqz v$freeRegister, :disabled
|
||||
|
||||
# Parse streaming data.
|
||||
sget-object v$overrideRegister, $playerProtoClass->a:$playerProtoClass
|
||||
invoke-static { v$overrideRegister, v$freeRegister }, $protobufClass->parseFrom(${protobufClass}Ljava/nio/ByteBuffer;)$protobufClass
|
||||
move-result-object v$freeRegister
|
||||
check-cast v$freeRegister, $playerProtoClass
|
||||
|
||||
# Set streaming data.
|
||||
iget-object v$freeRegister, v$freeRegister, $getStreamingDataField
|
||||
if-eqz v0, :disabled
|
||||
iput-object v$freeRegister, p0, $setStreamingDataField
|
||||
""",
|
||||
ExternalLabel("disabled", getInstruction(insertIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Remove /videoplayback request body to fix playback.
|
||||
// This is needed when using iOS client as streaming data source.
|
||||
|
||||
BuildMediaDataSourceFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getInstructions().lastIndex
|
||||
|
||||
addInstructions(
|
||||
targetIndex,
|
||||
"""
|
||||
# Field a: Stream uri.
|
||||
# Field c: Http method.
|
||||
# Field d: Post data.
|
||||
# From YouTube 17.34.36 to YouTube 19.16.39, the field names and field types are the same.
|
||||
move-object/from16 v0, p0
|
||||
iget-object v1, v0, $definingClass->a:Landroid/net/Uri;
|
||||
iget v2, v0, $definingClass->c:I
|
||||
iget-object v3, v0, $definingClass->d:[B
|
||||
invoke-static { v1, v2, v3 }, $INTEGRATIONS_CLASS_DESCRIPTOR->removeVideoPlaybackPostBody(Landroid/net/Uri;I[B)[B
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $definingClass->d:[B
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Append spoof info.
|
||||
|
||||
NerdsStatsVideoFormatBuilderFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
for (index in implementation!!.instructions.size - 1 downTo 0) {
|
||||
val instruction = getInstruction(index)
|
||||
if (instruction.opcode != Opcode.RETURN_OBJECT)
|
||||
continue
|
||||
|
||||
val register = (instruction as OneRegisterInstruction).registerA
|
||||
|
||||
addInstructions(
|
||||
index, """
|
||||
invoke-static {v$register}, $INTEGRATIONS_CLASS_DESCRIPTOR->appendSpoofedClient(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$register
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* Add settings
|
||||
*/
|
||||
SettingsPatch.addPreference(
|
||||
arrayOf(
|
||||
"SETTINGS: SPOOF_STREAMING_DATA"
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.updatePatchStatus(this)
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata
|
||||
|
||||
import app.revanced.patches.shared.spoofuseragent.BaseSpoofUserAgentPatch
|
||||
|
||||
object SpoofUserAgentPatch : BaseSpoofUserAgentPatch("com.google.android.youtube")
|
@ -0,0 +1,16 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object BuildInitPlaybackRequestFingerprint : MethodFingerprint(
|
||||
returnType = "Lorg/chromium/net/UrlRequest\$Builder;",
|
||||
opcodes = listOf(
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IGET_OBJECT, // Moves the request URI string to a register to build the request with.
|
||||
),
|
||||
strings = listOf(
|
||||
"Content-Type",
|
||||
"Range",
|
||||
),
|
||||
)
|
@ -0,0 +1,22 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object BuildMediaDataSourceFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
returnType = "V",
|
||||
parameters = listOf(
|
||||
"Landroid/net/Uri;",
|
||||
"J",
|
||||
"I",
|
||||
"[B",
|
||||
"Ljava/util/Map;",
|
||||
"J",
|
||||
"J",
|
||||
"Ljava/lang/String;",
|
||||
"I",
|
||||
"Ljava/lang/Object;"
|
||||
)
|
||||
)
|
@ -0,0 +1,26 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildPlayerRequestURIFingerprint.indexOfToStringInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object BuildPlayerRequestURIFingerprint : MethodFingerprint(
|
||||
returnType = "Ljava/lang/String;",
|
||||
strings = listOf(
|
||||
"key",
|
||||
"asig",
|
||||
),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
indexOfToStringInstruction(methodDef) >= 0
|
||||
},
|
||||
) {
|
||||
fun indexOfToStringInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>().toString() == "Landroid/net/Uri;->toString()Ljava/lang/String;"
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildRequestFingerprint.indexOfBuildUrlRequestInstruction
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildRequestFingerprint.indexOfEntrySetInstruction
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildRequestFingerprint.indexOfNewUrlRequestBuilderInstruction
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints.BuildRequestFingerprint.indexOfRequestFinishedListenerInstruction
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object BuildRequestFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.implementation != null &&
|
||||
indexOfRequestFinishedListenerInstruction(methodDef) >= 0 &&
|
||||
!methodDef.definingClass.startsWith("Lorg/") &&
|
||||
indexOfNewUrlRequestBuilderInstruction(methodDef) >= 0 &&
|
||||
indexOfBuildUrlRequestInstruction(methodDef) >= 0 &&
|
||||
// YouTube 17.34.36 ~ YouTube 18.35.36
|
||||
(indexOfEntrySetInstruction(methodDef) >= 0 ||
|
||||
// YouTube 18.36.39 ~
|
||||
methodDef.parameters[1].type == "Ljava/util/Map;")
|
||||
}
|
||||
) {
|
||||
fun indexOfRequestFinishedListenerInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>().toString() == "Lorg/chromium/net/ExperimentalUrlRequest${'$'}Builder;->setRequestFinishedListener(Lorg/chromium/net/RequestFinishedInfo${'$'}Listener;)Lorg/chromium/net/ExperimentalUrlRequest${'$'}Builder;"
|
||||
}
|
||||
|
||||
fun indexOfNewUrlRequestBuilderInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>().toString() == "Lorg/chromium/net/CronetEngine;->newUrlRequestBuilder(Ljava/lang/String;Lorg/chromium/net/UrlRequest${'$'}Callback;Ljava/util/concurrent/Executor;)Lorg/chromium/net/UrlRequest${'$'}Builder;"
|
||||
}
|
||||
|
||||
fun indexOfBuildUrlRequestInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>().toString() == "Lorg/chromium/net/ExperimentalUrlRequest${'$'}Builder;->build()Lorg/chromium/net/ExperimentalUrlRequest;"
|
||||
}
|
||||
|
||||
fun indexOfEntrySetInstruction(methodDef: Method) =
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.INVOKE_INTERFACE &&
|
||||
getReference<MethodReference>().toString() == "Ljava/util/Map;->entrySet()Ljava/util/Set;"
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
internal object CreateStreamingDataFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
returnType = "V",
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IPUT_OBJECT
|
||||
),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.SGET_OBJECT &&
|
||||
getReference<FieldReference>()?.name == "playerThreedRenderer"
|
||||
} >= 0
|
||||
},
|
||||
)
|
@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object NerdsStatsVideoFormatBuilderFingerprint : MethodFingerprint(
|
||||
returnType = "Ljava/lang/String;",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;"),
|
||||
strings = listOf("codecs=\""),
|
||||
)
|
@ -0,0 +1,19 @@
|
||||
package app.revanced.patches.youtube.utils.fix.streamingdata.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object ProtobufClassParseByteBufferFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.STATIC,
|
||||
parameters = listOf("L", "Ljava/nio/ByteBuffer;"),
|
||||
returnType = "L",
|
||||
opcodes = listOf(
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
),
|
||||
customFingerprint = { methodDef, _ -> methodDef.name == "parseFrom" },
|
||||
)
|
@ -3,6 +3,8 @@ package app.revanced.patches.youtube.utils.gms
|
||||
import app.revanced.patches.shared.gms.BaseGmsCoreSupportPatch
|
||||
import app.revanced.patches.shared.gms.BaseGmsCoreSupportResourcePatch.Companion.ORIGINAL_PACKAGE_NAME_YOUTUBE
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.SpoofStreamingDataPatch
|
||||
import app.revanced.patches.youtube.utils.fix.streamingdata.SpoofUserAgentPatch
|
||||
import app.revanced.patches.youtube.utils.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.utils.mainactivity.fingerprints.MainActivityFingerprint
|
||||
import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
||||
@ -13,6 +15,8 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
mainActivityOnCreateFingerprint = MainActivityFingerprint,
|
||||
integrationsPatchDependency = IntegrationsPatch::class,
|
||||
dependencies = setOf(
|
||||
SpoofStreamingDataPatch::class,
|
||||
SpoofUserAgentPatch::class,
|
||||
SettingsPatch::class
|
||||
),
|
||||
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
||||
|
Reference in New Issue
Block a user