make it work with latest agp
This commit is contained in:
parent
6fb4082bf8
commit
e185702fd4
3 changed files with 65 additions and 39 deletions
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue