make it work with latest agp

This commit is contained in:
oSumAtrIX 2026-02-07 20:37:59 +01:00
parent 6fb4082bf8
commit e185702fd4
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
3 changed files with 65 additions and 39 deletions

View file

@ -5,7 +5,7 @@ import app.revanced.patcher.patch.BytecodePatchContext
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 BytecodePatchContext.lithoFilterMethod by gettingFirstMethodDeclaratively { internal val BytecodePatchContext.lithoFilterInitMethod by gettingFirstMethodDeclaratively {
definingClass { endsWith("/LithoFilterPatch;") } definingClass { endsWith("/LithoFilterPatch;") }
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
} }

View file

@ -31,7 +31,8 @@ lateinit var addLithoFilter: (String) -> Unit
*/ */
private var filterCount = 0 private var filterCount = 0
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/shared/patches/litho/LithoFilterPatch;" internal const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/shared/patches/litho/LithoFilterPatch;"
/** /**
* A patch that allows to filter Litho components based on their identifier or path. * A patch that allows to filter Litho components based on their identifier or path.
@ -96,17 +97,24 @@ internal fun lithoFilterPatch(
apply { apply {
// Remove dummy filter from extenion static field // Remove dummy filter from extenion static field
// and add the filters included during patching. // and add the filters included during patching.
lithoFilterMethod.apply { lithoFilterInitMethod.apply {
removeInstructions(2, 4) // Remove dummy filter. // Remove the array initialization with the dummy filter.
removeInstructions(6)
addInstructions(
0,
"new-array v1, v1, [Lapp/revanced/extension/shared/patches/litho/Filter;"
)
// Fill the array with the filters added during patching.
addLithoFilter = { classDescriptor -> addLithoFilter = { classDescriptor ->
addInstructions( addInstructions(
2, 1,
""" """
new-instance v1, $classDescriptor new-instance v0, $classDescriptor
invoke-direct { v1 }, $classDescriptor-><init>()V invoke-direct { v0 }, $classDescriptor-><init>()V
const/16 v2, ${filterCount++} const/16 v2, ${filterCount++}
aput-object v1, v0, v2 aput-object v0, v1, v2
""", """,
) )
} }
@ -114,7 +122,7 @@ internal fun lithoFilterPatch(
// Tell the extension whether to extract the identifier from the buffer. // Tell the extension whether to extract the identifier from the buffer.
if (getExtractIdentifierFromBuffer()) { if (getExtractIdentifierFromBuffer()) {
lithoFilterMethod.classDef.fields.first { it.name == "EXTRACT_IDENTIFIER_FROM_BUFFER" } lithoFilterInitMethod.classDef.fields.first { it.name == "EXTRACT_IDENTIFIER_FROM_BUFFER" }
.initialValue = ImmutableBooleanEncodedValue.forBoolean(true).toMutable() .initialValue = ImmutableBooleanEncodedValue.forBoolean(true).toMutable()
} }
@ -138,7 +146,7 @@ internal fun lithoFilterPatch(
// Find class and methods to create an empty component. // Find class and methods to create an empty component.
val builderMethodDescriptor = emptyComponentMethod.immutableClassDef.methods.single { val builderMethodDescriptor = emptyComponentMethod.immutableClassDef.methods.single {
// The only static method in the class. // The only static method in the class.
method -> method ->
AccessFlags.STATIC.isSet(method.accessFlags) AccessFlags.STATIC.isSet(method.accessFlags)
} }
@ -203,8 +211,9 @@ internal fun lithoFilterPatch(
} }
afterDependents { afterDependents {
// Save the number of filters added. // Set the array size to the actual filter count of the array
lithoFilterMethod.replaceInstruction(0, "const/16 v0, $filterCount") // initialized at the beginning of the patch.
lithoFilterInitMethod.addInstructions(0, "const/16 v1, $filterCount")
} }
block() block()

View file

@ -39,7 +39,8 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
import com.android.tools.smali.dexlib2.util.MethodUtil import com.android.tools.smali.dexlib2.util.MethodUtil
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/VideoInformation;" private const val EXTENSION_CLASS_DESCRIPTOR =
"Lapp/revanced/extension/youtube/patches/VideoInformation;"
private const val EXTENSION_PLAYER_INTERFACE = private const val EXTENSION_PLAYER_INTERFACE =
"Lapp/revanced/extension/youtube/patches/VideoInformation\$PlaybackController;" "Lapp/revanced/extension/youtube/patches/VideoInformation\$PlaybackController;"
private const val EXTENSION_VIDEO_QUALITY_MENU_INTERFACE = private const val EXTENSION_VIDEO_QUALITY_MENU_INTERFACE =
@ -99,7 +100,8 @@ val videoInformationPatch = bytecodePatch(
val initThisIndex = playerInitMethod.indexOfFirstInstructionOrThrow { val initThisIndex = playerInitMethod.indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>" opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
} }
playerInitInsertRegister = playerInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC playerInitInsertRegister =
playerInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC
playerInitInsertIndex = initThisIndex + 1 playerInitInsertIndex = initThisIndex + 1
// Create extension interface methods. // Create extension interface methods.
@ -116,7 +118,8 @@ val videoInformationPatch = bytecodePatch(
val initThisIndex = mdxInitMethod.indexOfFirstInstructionOrThrow { val initThisIndex = mdxInitMethod.indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>" opcode == Opcode.INVOKE_DIRECT && getReference<MethodReference>()?.name == "<init>"
} }
mdxInitInsertRegister = mdxInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC mdxInitInsertRegister =
mdxInitMethod.getInstruction<FiveRegisterInstruction>(initThisIndex).registerC
mdxInitInsertIndex = initThisIndex + 1 mdxInitInsertIndex = initThisIndex + 1
// Hook the MDX director for use through the extension. // Hook the MDX director for use through the extension.
@ -134,13 +137,15 @@ val videoInformationPatch = bytecodePatch(
videoLengthMethodMatch.method.apply { videoLengthMethodMatch.method.apply {
val videoLengthRegisterIndex = videoLengthMethodMatch[-1] - 2 val videoLengthRegisterIndex = videoLengthMethodMatch[-1] - 2
val videoLengthRegister = getInstruction<OneRegisterInstruction>(videoLengthRegisterIndex).registerA val videoLengthRegister =
val dummyRegisterForLong = videoLengthRegister + 1 // required for long values since they are wide getInstruction<OneRegisterInstruction>(videoLengthRegisterIndex).registerA
val dummyRegisterForLong =
videoLengthRegister + 1 // Required for long values since they are wide.
addInstruction( addInstruction(
videoLengthMethodMatch[-1], videoLengthMethodMatch[-1],
"invoke-static {v$videoLengthRegister, v$dummyRegisterForLong}, " + "invoke-static {v$videoLengthRegister, v$dummyRegisterForLong}, " +
"$EXTENSION_CLASS_DESCRIPTOR->setVideoLength(J)V", "$EXTENSION_CLASS_DESCRIPTOR->setVideoLength(J)V",
) )
} }
} }
@ -162,7 +167,7 @@ val videoInformationPatch = bytecodePatch(
addPlayerResponseMethodHook( addPlayerResponseMethodHook(
Hook.ProtoBufferParameterBeforeVideoId( Hook.ProtoBufferParameterBeforeVideoId(
"$EXTENSION_CLASS_DESCRIPTOR->" + "$EXTENSION_CLASS_DESCRIPTOR->" +
"newPlayerResponseSignature(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;", "newPlayerResponseSignature(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
), ),
) )
@ -276,7 +281,8 @@ val videoInformationPatch = bytecodePatch(
speedSelectionInsertMethod = this speedSelectionInsertMethod = this
speedSelectionInsertIndex = index + 1 speedSelectionInsertIndex = index + 1
speedSelectionValueRegister = getInstruction<TwoRegisterInstruction>(index).registerA speedSelectionValueRegister =
getInstruction<TwoRegisterInstruction>(index).registerA
} }
} }
@ -350,8 +356,10 @@ val videoInformationPatch = bytecodePatch(
videoQualitySetterMethod.immutableClassDef.getSetVideoQualityMethod().let { videoQualitySetterMethod.immutableClassDef.getSetVideoQualityMethod().let {
it it
// This instruction refers to the field with the type that contains the setQuality method. // This instruction refers to the field with the type that contains the setQuality method.
val onItemClickListenerClassReference = it.getInstruction<ReferenceInstruction>(0).reference val onItemClickListenerClassReference =
val setQualityFieldReference = it.getInstruction<ReferenceInstruction>(1).fieldReference!! it.getInstruction<ReferenceInstruction>(0).reference
val setQualityFieldReference =
it.getInstruction<ReferenceInstruction>(1).fieldReference!!
firstClassDef(setQualityFieldReference.type).apply { firstClassDef(setQualityFieldReference.type).apply {
// Add interface and helper methods to allow extension code to call obfuscated methods. // Add interface and helper methods to allow extension code to call obfuscated methods.
@ -404,7 +412,11 @@ val videoInformationPatch = bytecodePatch(
} }
} }
private fun addSeekInterfaceMethods(targetClass: MutableClassDef, seekToMethod: Method, seekToRelativeMethod: Method) { private fun addSeekInterfaceMethods(
targetClass: MutableClassDef,
seekToMethod: Method,
seekToRelativeMethod: Method
) {
// Add the interface and methods that extension calls. // Add the interface and methods that extension calls.
targetClass.interfaces.add(EXTENSION_PLAYER_INTERFACE) targetClass.interfaces.add(EXTENSION_PLAYER_INTERFACE)
@ -452,9 +464,11 @@ private fun addSeekInterfaceMethods(targetClass: MutableClassDef, seekToMethod:
} }
} }
private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) = addInstruction(insertIndex, "invoke-static { $register }, $descriptor") private fun MutableMethod.insert(insertIndex: Int, register: String, descriptor: String) =
addInstruction(insertIndex, "invoke-static { $register }, $descriptor")
private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) = insert(insertIndex, "p1, p2", descriptor) private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) =
insert(insertIndex, "p1, p2", descriptor)
/** /**
* Hook the player controller. Called when a video is opened or the current video is changed. * Hook the player controller. Called when a video is opened or the current video is changed.
@ -465,11 +479,12 @@ private fun MutableMethod.insertTimeHook(insertIndex: Int, descriptor: String) =
* @param targetMethodClass The descriptor for the class to invoke when the player controller is created. * @param targetMethodClass The descriptor for the class to invoke when the player controller is created.
* @param targetMethodName The name of the static method to invoke when the player controller is created. * @param targetMethodName The name of the static method to invoke when the player controller is created.
*/ */
internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) = playerInitMethod.insert( internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) =
playerInitInsertIndex++, playerInitMethod.insert(
"v$playerInitInsertRegister", playerInitInsertIndex++,
"$targetMethodClass->$targetMethodName($EXTENSION_PLAYER_INTERFACE)V", "v$playerInitInsertRegister",
) "$targetMethodClass->$targetMethodName($EXTENSION_PLAYER_INTERFACE)V",
)
/** /**
* Hook the MDX player director. Called when playing videos while casting to a big screen device. * Hook the MDX player director. Called when playing videos while casting to a big screen device.
@ -477,11 +492,12 @@ internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) =
* @param targetMethodClass The descriptor for the class to invoke when the player controller is created. * @param targetMethodClass The descriptor for the class to invoke when the player controller is created.
* @param targetMethodName The name of the static method to invoke when the player controller is created. * @param targetMethodName The name of the static method to invoke when the player controller is created.
*/ */
internal fun onCreateHookMdx(targetMethodClass: String, targetMethodName: String) = mdxInitMethod.insert( internal fun onCreateHookMdx(targetMethodClass: String, targetMethodName: String) =
mdxInitInsertIndex++, mdxInitMethod.insert(
"v$mdxInitInsertRegister", mdxInitInsertIndex++,
"$targetMethodClass->$targetMethodName($EXTENSION_PLAYER_INTERFACE)V", "v$mdxInitInsertRegister",
) "$targetMethodClass->$targetMethodName($EXTENSION_PLAYER_INTERFACE)V",
)
/** /**
* Hook the video time. * Hook the video time.
@ -498,10 +514,11 @@ fun videoTimeHook(targetMethodClass: String, targetMethodName: String) = timeMet
/** /**
* Hook when the video speed is changed for any reason _except when the user manually selects a new speed_. * Hook when the video speed is changed for any reason _except when the user manually selects a new speed_.
*/ */
fun videoSpeedChangedHook(targetMethodClass: String, targetMethodName: String) = setPlaybackSpeedMethod.addInstruction( fun videoSpeedChangedHook(targetMethodClass: String, targetMethodName: String) =
setPlaybackSpeedMethodIndex++, setPlaybackSpeedMethod.addInstruction(
"invoke-static { p1 }, $targetMethodClass->$targetMethodName(F)V", setPlaybackSpeedMethodIndex++,
) "invoke-static { p1 }, $targetMethodClass->$targetMethodName(F)V",
)
/** /**
* Hook the video speed selected by the user. * Hook the video speed selected by the user.