add suport YouTube v18.06.35

This commit is contained in:
inotia00 2023-02-18 14:18:23 +09:00
parent 9030abe616
commit 8427f28208
25 changed files with 315 additions and 194 deletions

View File

@ -3,7 +3,7 @@ package app.revanced.patches.shared.annotation
import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.youtube", arrayOf("18.05.40"))]) @Compatibility([Package("com.google.android.youtube", arrayOf("18.06.35"))])
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
internal annotation class YouTubeCompatibility internal annotation class YouTubeCompatibility

View File

@ -1,13 +1,10 @@
package app.revanced.patches.shared.fingerprints package app.revanced.patches.shared.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
object MainstreamVideoAdsFingerprint : MethodFingerprint( object MainstreamVideoAdsFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PRIVATE or AccessFlags.FINAL,
parameters = listOf("L","Z"), parameters = listOf("L","Z"),
opcodes = listOf( opcodes = listOf(
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,

View File

@ -10,7 +10,6 @@ import org.jf.dexlib2.Opcode
object PivotBarCreateButtonViewFingerprint : MethodFingerprint( object PivotBarCreateButtonViewFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL, access = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Z"),
customFingerprint = { methodDef -> customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal && it.opcode.ordinal == Opcode.CONST.ordinal &&

View File

@ -8,6 +8,7 @@ import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
@ -26,34 +27,30 @@ class GeneralVideoAdsPatch : BytecodePatch(
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
val LegacyVideoAdsResult = LegacyVideoAdsFingerprint.result ?: return LegacyVideoAdsFingerprint.toErrorResult() val legacyVideoAdsResult = LegacyVideoAdsFingerprint.result ?: return LegacyVideoAdsFingerprint.toErrorResult()
LegacyVideoAdsMethod = legacyVideoAdsMethod =
context.toMethodWalker(LegacyVideoAdsResult.method) context.toMethodWalker(legacyVideoAdsResult.method)
.nextMethod(13, true) .nextMethod(13, true)
.getMethod() as MutableMethod .getMethod() as MutableMethod
MainstreamVideoAdsFingerprint.resolve(context, MainstreamVideoAdsParentFingerprint.result!!.classDef) MainstreamVideoAdsParentFingerprint.result?.let { parentResult ->
MainstreamVideoAdsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let {
val MainstreamAdsResult = MainstreamVideoAdsFingerprint.result ?: return MainstreamVideoAdsFingerprint.toErrorResult() mainstreamVideoAdsResult = it
} ?: return MainstreamVideoAdsFingerprint.toErrorResult()
MainstreamVideoAdsMethod = MainstreamAdsResult.mutableMethod } ?: return MainstreamVideoAdsParentFingerprint.toErrorResult()
InsertIndex = MainstreamAdsResult.scanResult.patternScanResult!!.endIndex
return PatchResultSuccess() return PatchResultSuccess()
} }
internal companion object { internal companion object {
var InsertIndex: Int = 0 lateinit var legacyVideoAdsMethod: MutableMethod
lateinit var mainstreamVideoAdsResult: MethodFingerprintResult
lateinit var LegacyVideoAdsMethod: MutableMethod
lateinit var MainstreamVideoAdsMethod: MutableMethod
fun injectLegacyAds( fun injectLegacyAds(
descriptor: String descriptor: String
) { ) {
LegacyVideoAdsMethod.addInstructions( legacyVideoAdsMethod.addInstructions(
0, """ 0, """
invoke-static {}, $descriptor invoke-static {}, $descriptor
move-result v1 move-result v1
@ -64,13 +61,16 @@ class GeneralVideoAdsPatch : BytecodePatch(
fun injectMainstreamAds( fun injectMainstreamAds(
descriptor: String descriptor: String
) { ) {
MainstreamVideoAdsMethod.addInstructions( val mainstreamVideoAdsMethod = mainstreamVideoAdsResult.mutableMethod
InsertIndex, """ val insertIndex = mainstreamVideoAdsResult.scanResult.patternScanResult!!.endIndex
mainstreamVideoAdsMethod.addInstructions(
insertIndex, """
invoke-static {}, $descriptor invoke-static {}, $descriptor
move-result v1 move-result v1
if-nez v1, :show_video_ads if-nez v1, :show_video_ads
return-void return-void
""", listOf(ExternalLabel("show_video_ads", MainstreamVideoAdsMethod.instruction(InsertIndex))) """, listOf(ExternalLabel("show_video_ads", mainstreamVideoAdsMethod.instruction(insertIndex)))
) )
} }

View File

@ -20,7 +20,9 @@ import app.revanced.patches.youtube.layout.fullscreen.fullscreenpanels.fingerpri
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.integrations.Constants.FULLSCREEN_LAYOUT import app.revanced.util.integrations.Constants.FULLSCREEN_LAYOUT
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
import org.jf.dexlib2.iface.instruction.formats.Instruction35c import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch @Patch
@ -57,6 +59,29 @@ class HideFullscreenPanelsPatch : BytecodePatch(
} }
} ?: return FullscreenViewAdderFingerprint.toErrorResult() } ?: return FullscreenViewAdderFingerprint.toErrorResult()
LayoutConstructorFingerprint.result?.mutableMethod?.let { method ->
val instructions = method.implementation!!.instructions
val registerIndex = instructions.indexOfFirst {
it.opcode == Opcode.CONST_STRING &&
(it as BuilderInstruction21c).reference.toString() == "1.0x"
}
val dummyRegister = (instructions[registerIndex] as Instruction21c).registerA
val invokeIndex = method.implementation!!.instructions.indexOfFirst {
it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal &&
((it as? BuilderInstruction35c)?.reference.toString() ==
"Landroid/widget/FrameLayout;->addView(Landroid/view/View;)V")
}
method.addInstructions(
invokeIndex, """
invoke-static {}, $FULLSCREEN_LAYOUT->hideFullscreenPanel()Z
move-result v$dummyRegister
if-nez v$dummyRegister, :hidden
""", listOf(ExternalLabel("hidden", method.instruction(invokeIndex + 1)))
)
} ?: return LayoutConstructorFingerprint.toErrorResult()
/* /*
* Add settings * Add settings
*/ */
@ -70,22 +95,6 @@ class HideFullscreenPanelsPatch : BytecodePatch(
SettingsPatch.updatePatchStatus("hide-fullscreen-panels") SettingsPatch.updatePatchStatus("hide-fullscreen-panels")
LayoutConstructorFingerprint.result?.mutableMethod?.let { method ->
val invokeIndex = method.implementation!!.instructions.indexOfFirst {
it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal &&
((it as? BuilderInstruction35c)?.reference.toString() ==
"Landroid/widget/FrameLayout;->addView(Landroid/view/View;)V")
}
method.addInstructions(
invokeIndex, """
invoke-static {}, $FULLSCREEN_LAYOUT->hideFullscreenPanel()Z
move-result v15
if-nez v15, :hidden
""", listOf(ExternalLabel("hidden", method.instruction(invokeIndex + 1)))
)
} ?: return LayoutConstructorFingerprint.toErrorResult()
return PatchResultSuccess() return PatchResultSuccess()
} }
} }

View File

@ -0,0 +1,20 @@
package app.revanced.patches.youtube.layout.general.crowdfundingbox.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object CrowdfundingBoxFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT
),
customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal &&
(it as? WideLiteralInstruction)?.wideLiteral == SharedResourcdIdPatch.donationCompanionResourceId
} == true
}
)

View File

@ -1,90 +1,66 @@
package app.revanced.patches.youtube.layout.general.crowdfundingbox.patch package app.revanced.patches.youtube.layout.general.crowdfundingbox.patch
import app.revanced.extensions.findMutableMethodOf import app.revanced.extensions.toErrorResult
import app.revanced.extensions.injectHideCall
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch import app.revanced.patches.youtube.layout.general.crowdfundingbox.fingerprints.CrowdfundingBoxFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import org.jf.dexlib2.Opcode import app.revanced.util.integrations.Constants.GENERAL_LAYOUT
import org.jf.dexlib2.iface.instruction.formats.Instruction22c import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
@Patch @Patch
@Name("hide-crowdfunding-box") @Name("hide-crowdfunding-box")
@Description("Hides the crowdfunding box between the player and video description.") @Description("Hides the crowdfunding box between the player and video description.")
@DependsOn( @DependsOn(
[ [
ResourceMappingPatch::class, SettingsPatch::class,
SettingsPatch::class SharedResourcdIdPatch::class
] ]
) )
@YouTubeCompatibility @YouTubeCompatibility
@Version("0.0.1") @Version("0.0.1")
class CrowdfundingBoxPatch : BytecodePatch() { class CrowdfundingBoxPatch : BytecodePatch(
listOf(
// list of resource names to get the id of CrowdfundingBoxFingerprint
private val resourceIds = arrayOf( )
"donation_companion" ) {
).map { name ->
ResourceMappingPatch.resourceMappings.single { it.name == name }.id
}
private var patchSuccessArray = Array(resourceIds.size) {false}
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
with(method.implementation) {
this?.instructions?.forEachIndexed { index, instruction ->
when (instruction.opcode) {
Opcode.CONST -> {
when ((instruction as Instruction31i).wideLiteral) {
resourceIds[0] -> { // crowdfunding
val insertIndex = index + 3
val iPutInstruction = instructions.elementAt(insertIndex)
if (iPutInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed
val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) CrowdfundingBoxFingerprint.result?.let {
with (it.mutableMethod) {
val insertIndex = it.scanResult.patternScanResult!!.endIndex
val register = (instruction(insertIndex) as TwoRegisterInstruction).registerA
val viewRegister = (iPutInstruction as Instruction22c).registerA addInstruction(
mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "layout/GeneralLayoutPatch", "hideCrowdfundingBox") insertIndex,
patchSuccessArray[0] = true; "invoke-static {v$register}, $GENERAL_LAYOUT->hideCrowdfundingBox(Landroid/view/View;)V"
}
}
}
else -> return@forEachIndexed
}
}
}
}
}
val errorIndex: Int = patchSuccessArray.indexOf(false)
if (errorIndex == -1) {
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: GENERAL_LAYOUT_SETTINGS",
"SETTINGS: HIDE_CROWDFUNDING_BOX"
) )
}
} ?: return CrowdfundingBoxFingerprint.toErrorResult()
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: GENERAL_LAYOUT_SETTINGS",
"SETTINGS: HIDE_CROWDFUNDING_BOX"
) )
)
SettingsPatch.updatePatchStatus("hide-crowdfunding-box") SettingsPatch.updatePatchStatus("hide-crowdfunding-box")
return PatchResultSuccess() return PatchResultSuccess()
} else
return PatchResultError("Instruction not found: $errorIndex")
} }
} }

View File

@ -8,8 +8,8 @@ import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint( object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint(
"V", returnType = "V",
AccessFlags.PUBLIC or AccessFlags.FINAL, access = AccessFlags.PUBLIC or AccessFlags.FINAL,
customFingerprint = { methodDef -> customFingerprint = { methodDef ->
methodDef.implementation?.instructions?.any { methodDef.implementation?.instructions?.any {
it.opcode.ordinal == Opcode.CONST.ordinal && it.opcode.ordinal == Opcode.CONST.ordinal &&

View File

@ -9,5 +9,5 @@ object MiniPlayerOverrideFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
access = AccessFlags.PUBLIC or AccessFlags.STATIC, access = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf(Opcode.RETURN), // anchor to insert the instruction opcodes = listOf(Opcode.INVOKE_STATIC), // anchor to insert the instruction
) )

View File

@ -0,0 +1,12 @@
package app.revanced.patches.youtube.layout.general.tabletminiplayer.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object MiniPlayerOverrideParentFingerprint : MethodFingerprint(
returnType = "L",
access = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"),
strings = listOf("VIDEO_QUALITIES_QUICK_MENU_BOTTOM_SHEET_FRAGMENT")
)

View File

@ -5,6 +5,7 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
@ -19,6 +20,7 @@ import app.revanced.patches.youtube.layout.general.tabletminiplayer.fingerprints
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourcdIdPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.integrations.Constants.GENERAL_LAYOUT import app.revanced.util.integrations.Constants.GENERAL_LAYOUT
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch @Patch
@ -35,31 +37,33 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
class TabletMiniPlayerPatch : BytecodePatch( class TabletMiniPlayerPatch : BytecodePatch(
listOf( listOf(
MiniPlayerDimensionsCalculatorFingerprint, MiniPlayerDimensionsCalculatorFingerprint,
MiniPlayerResponseModelSizeCheckFingerprint MiniPlayerResponseModelSizeCheckFingerprint,
MiniPlayerOverrideParentFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
MiniPlayerDimensionsCalculatorFingerprint.result?.let { parentResult -> MiniPlayerDimensionsCalculatorFingerprint.result?.let { parentResult ->
// first resolve the fingerprints via the parent fingerprint MiniPlayerOverrideNoContextFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
val miniPlayerClass = parentResult.classDef val (method, _, parameterRegister) = result.addProxyCall()
method.insertOverride(method.implementation!!.instructions.size - 1, parameterRegister)
arrayOf( } ?: return MiniPlayerOverrideNoContextFingerprint.toErrorResult()
MiniPlayerOverrideNoContextFingerprint,
MiniPlayerOverrideFingerprint,
MiniPlayerResponseModelSizeCheckFingerprint
).map {
it to (it.also { it.resolve(context, miniPlayerClass) }.result ?: return it.toErrorResult())
}.forEach { (fingerprint, result) ->
if (fingerprint == MiniPlayerOverrideNoContextFingerprint) {
val (method, _, parameterRegister) = result.addProxyCall()
method.insertOverride(method.implementation!!.instructions.size - 1, parameterRegister)
} else {
val (_, _, _) = result.addProxyCall()
}
}
} ?: return MiniPlayerDimensionsCalculatorFingerprint.toErrorResult() } ?: return MiniPlayerDimensionsCalculatorFingerprint.toErrorResult()
MiniPlayerOverrideParentFingerprint.result?.let { parentResult ->
MiniPlayerOverrideFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
(context.toMethodWalker(result.method)
.nextMethod(result.scanResult.patternScanResult!!.startIndex, true)
.getMethod() as MutableMethod)
.instructionProxyCall()
} ?: return MiniPlayerOverrideFingerprint.toErrorResult()
} ?: return MiniPlayerOverrideParentFingerprint.toErrorResult()
MiniPlayerResponseModelSizeCheckFingerprint.result?.let {
val (_, _, _) = it.addProxyCall()
} ?: return MiniPlayerResponseModelSizeCheckFingerprint.toErrorResult()
/* /*
* Add settings * Add settings
*/ */
@ -94,6 +98,17 @@ class TabletMiniPlayerPatch : BytecodePatch(
) )
} }
fun MutableMethod.instructionProxyCall() {
val insertInstructions = this.implementation!!.instructions
for ((index, instruction) in insertInstructions.withIndex()) {
if (instruction.opcode != Opcode.RETURN) continue
val parameterRegister = (instruction as OneRegisterInstruction).registerA
this.insertOverride(index, parameterRegister)
this.insertOverride(insertInstructions.size - 1, parameterRegister)
break;
}
}
fun MethodFingerprintResult.unwrap(): Triple<MutableMethod, Int, Int> { fun MethodFingerprintResult.unwrap(): Triple<MutableMethod, Int, Int> {
val scanIndex = this.scanResult.patternScanResult!!.endIndex val scanIndex = this.scanResult.patternScanResult!!.endIndex
val method = this.mutableMethod val method = this.mutableMethod

View File

@ -17,9 +17,12 @@ import app.revanced.patches.shared.fingerprints.LayoutConstructorFingerprint
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.integrations.Constants.PLAYER_LAYOUT import app.revanced.util.integrations.Constants.PLAYER_LAYOUT
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.iface.instruction.Instruction import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
import org.jf.dexlib2.iface.reference.MethodReference import org.jf.dexlib2.iface.reference.MethodReference
@Patch @Patch
@ -46,6 +49,12 @@ class HideAutoplayButtonPatch : BytecodePatch(
LayoutConstructorFingerprint.result?.mutableMethod?.let { method -> LayoutConstructorFingerprint.result?.mutableMethod?.let { method ->
with (method.implementation!!.instructions) { with (method.implementation!!.instructions) {
val registerIndex = indexOfFirst {
it.opcode == Opcode.CONST_STRING &&
(it as BuilderInstruction21c).reference.toString() == "1.0x"
}
val dummyRegister = (this[registerIndex] as Instruction21c).registerA
// where to insert the branch instructions and ... // where to insert the branch instructions and ...
val insertIndex = this.indexOfFirst { val insertIndex = this.indexOfFirst {
(it as? WideLiteralInstruction)?.wideLiteral == autoNavPreviewStubId (it as? WideLiteralInstruction)?.wideLiteral == autoNavPreviewStubId
@ -60,8 +69,8 @@ class HideAutoplayButtonPatch : BytecodePatch(
method.addInstructions( method.addInstructions(
insertIndex, """ insertIndex, """
invoke-static {}, $PLAYER_LAYOUT->hideAutoPlayButton()Z invoke-static {}, $PLAYER_LAYOUT->hideAutoPlayButton()Z
move-result v15 move-result v$dummyRegister
if-nez v15, :hidden if-nez v$dummyRegister, :hidden
""", listOf(ExternalLabel("hidden", jumpInstruction)) """, listOf(ExternalLabel("hidden", jumpInstruction))
) )
} }

View File

@ -24,6 +24,7 @@ class SharedResourcdIdPatch : ResourcePatch {
var bottompaneloverlaytextLabelId: Long = -1 var bottompaneloverlaytextLabelId: Long = -1
var bottomUiContainerResourceId: Long = -1 var bottomUiContainerResourceId: Long = -1
var controlsLayoutStubResourceId: Long = -1 var controlsLayoutStubResourceId: Long = -1
var donationCompanionResourceId: Long = -1
var educationTextViewResourceId: Long = -1 var educationTextViewResourceId: Long = -1
var emptycolorLabelId: Long = -1 var emptycolorLabelId: Long = -1
var floatybarQueueLabelId: Long = -1 var floatybarQueueLabelId: Long = -1
@ -53,6 +54,7 @@ class SharedResourcdIdPatch : ResourcePatch {
bottompaneloverlaytextLabelId = findSharedResourceId("id", "bottom_panel_overlay_text") bottompaneloverlaytextLabelId = findSharedResourceId("id", "bottom_panel_overlay_text")
bottomUiContainerResourceId = findSharedResourceId("id", "bottom_ui_container_stub") bottomUiContainerResourceId = findSharedResourceId("id", "bottom_ui_container_stub")
controlsLayoutStubResourceId = findSharedResourceId("id", "controls_layout_stub") controlsLayoutStubResourceId = findSharedResourceId("id", "controls_layout_stub")
donationCompanionResourceId = findSharedResourceId("layout", "donation_companion")
educationTextViewResourceId = findSharedResourceId("id", "user_education_text_view") educationTextViewResourceId = findSharedResourceId("id", "user_education_text_view")
emptycolorLabelId = findSharedResourceId("color", "inline_time_bar_colorized_bar_empty_color_dark") emptycolorLabelId = findSharedResourceId("color", "inline_time_bar_colorized_bar_empty_color_dark")
floatybarQueueLabelId = findSharedResourceId("string", "floaty_bar_queue_status") floatybarQueueLabelId = findSharedResourceId("string", "floaty_bar_queue_status")

View File

@ -1,11 +1,8 @@
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object DislikeFingerprint : MethodFingerprint( object DislikeFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
strings = listOf("like/dislike") strings = listOf("like/dislike")
) )

View File

@ -1,11 +1,8 @@
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object LikeFingerprint : MethodFingerprint( object LikeFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
strings = listOf("like/like") strings = listOf("like/like")
) )

View File

@ -1,11 +1,8 @@
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object RemoveLikeFingerprint : MethodFingerprint( object RemoveLikeFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR,
strings = listOf("like/removelike") strings = listOf("like/removelike")
) )

View File

@ -10,6 +10,13 @@ object ShortsTextComponentParentFingerprint : MethodFingerprint(
access = AccessFlags.PROTECTED or AccessFlags.FINAL, access = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L", "L"), parameters = listOf("L", "L"),
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.GOTO,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.CHECK_CAST, Opcode.CHECK_CAST,
Opcode.IGET_BOOLEAN, Opcode.IGET_BOOLEAN,

View File

@ -1,17 +1,17 @@
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
object TextComponentSpecFingerprint : MethodFingerprint( object TextComponentSpecFingerprint : MethodFingerprint(
returnType = "L", returnType = "V",
access = AccessFlags.STATIC.getValue(), access = AccessFlags.PROTECTED or AccessFlags.FINAL,
opcodes = listOf(Opcode.CMPL_FLOAT), parameters = listOf("L"),
customFingerprint = { methodDef -> opcodes = listOf(
methodDef.implementation!!.instructions.any { Opcode.INVOKE_STATIC_RANGE,
((it as? NarrowLiteralInstruction)?.narrowLiteral == 16842907) Opcode.MOVE_RESULT_OBJECT,
} Opcode.INVOKE_DIRECT
} )
) )

View File

@ -0,0 +1,11 @@
package app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object TextComponentSpecParentFingerprint : MethodFingerprint(
returnType = "V",
access = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
strings = listOf("TextComponent")
)

View File

@ -7,10 +7,11 @@ import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.toMethodWalker import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
@ -20,7 +21,13 @@ import app.revanced.patches.youtube.misc.returnyoutubedislike.fingerprints.*
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.patches.youtube.misc.videoid.mainstream.patch.MainstreamVideoIdPatch import app.revanced.patches.youtube.misc.videoid.mainstream.patch.MainstreamVideoIdPatch
import app.revanced.util.integrations.Constants.UTILS_PATH import app.revanced.util.integrations.Constants.UTILS_PATH
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction3rc
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.iface.reference.FieldReference
import org.jf.dexlib2.iface.reference.MethodReference
@Patch @Patch
@Name("return-youtube-dislike") @Name("return-youtube-dislike")
@ -39,7 +46,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
LikeFingerprint, LikeFingerprint,
RemoveLikeFingerprint, RemoveLikeFingerprint,
ShortsTextComponentParentFingerprint, ShortsTextComponentParentFingerprint,
TextComponentSpecFingerprint TextComponentSpecParentFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
@ -60,7 +67,7 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
} }
ShortsTextComponentParentFingerprint.result?.let { ShortsTextComponentParentFingerprint.result?.let {
with(context with (context
.toMethodWalker(it.method) .toMethodWalker(it.method)
.nextMethod(it.scanResult.patternScanResult!!.endIndex, true) .nextMethod(it.scanResult.patternScanResult!!.endIndex, true)
.getMethod() as MutableMethod .getMethod() as MutableMethod
@ -69,30 +76,57 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
val insertIndex = insertInstructions.size - 1 val insertIndex = insertInstructions.size - 1
val insertRegister = (insertInstructions.elementAt(insertIndex) as OneRegisterInstruction).registerA val insertRegister = (insertInstructions.elementAt(insertIndex) as OneRegisterInstruction).registerA
addInstructions( this.insertShorts(insertIndex, insertRegister)
insertIndex, """
invoke-static {v$insertRegister}, ${INTEGRATIONS_RYD_CLASS_DESCRIPTOR}->onShortsComponentCreated(Landroid/text/Spanned;)Landroid/text/Spanned;
move-result-object v$insertRegister
"""
)
} }
with (it.mutableMethod) {
val insertInstructions = this.implementation!!.instructions
val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2
val insertRegister = (insertInstructions.elementAt(insertIndex - 1) as OneRegisterInstruction).registerA
this.insertShorts(insertIndex, insertRegister)
}
} ?: return ShortsTextComponentParentFingerprint.toErrorResult() } ?: return ShortsTextComponentParentFingerprint.toErrorResult()
val createComponentResult = TextComponentSpecFingerprint.result ?: return PatchResultError("Failed to find TextComponentSpecFingerprint method.") TextComponentSpecParentFingerprint.result?.let { parentResult ->
val createComponentMethod = createComponentResult.mutableMethod TextComponentSpecFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let {
with (it.mutableMethod) {
val startIndex = it.scanResult.patternScanResult!!.startIndex
val endIndex = it.scanResult.patternScanResult!!.endIndex
val conversionContextParam = 5 val dummyRegister = (instruction(startIndex) as BuilderInstruction3rc).registerCount +
val textRefParam = createComponentMethod.parameters.size - 2 (instruction(startIndex) as BuilderInstruction3rc).startRegister - 1
val targetRegister = (instruction(endIndex) as Instruction35c).registerC
createComponentMethod.addInstructions( val instructions = implementation!!.instructions
0, val targetString =
""" ((instructions.elementAt(startIndex) as ReferenceInstruction).reference as MethodReference).parameterTypes.first().toString()
move-object/from16 v7, p$conversionContextParam
move-object/from16 v8, p$textRefParam for ((index, instruction) in instructions.withIndex()) {
invoke-static {v7, v8}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V if (instruction.opcode != Opcode.IGET_OBJECT) continue
"""
) val indexReference = (instruction as ReferenceInstruction).reference as FieldReference
if (indexReference.type != targetString) continue
targetReference = indexReference
targetIndex = index
break
}
if (targetIndex == 0) return TextComponentSpecFingerprint.toErrorResult()
val conversionContextParam = 0
addInstructions(
endIndex + 1, """
move-object/from16 v$dummyRegister, p$conversionContextParam
iget-object v$dummyRegister, v$dummyRegister, ${definingClass}->${targetReference.name}:${targetReference.type}
invoke-static {v$dummyRegister, v$targetRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V
"""
)
}
} ?: return TextComponentSpecFingerprint.toErrorResult()
} ?: return TextComponentSpecParentFingerprint.toErrorResult()
MainstreamVideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V") MainstreamVideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
@ -108,6 +142,9 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
private companion object { private companion object {
const val INTEGRATIONS_RYD_CLASS_DESCRIPTOR = const val INTEGRATIONS_RYD_CLASS_DESCRIPTOR =
"$UTILS_PATH/ReturnYouTubeDislikePatch;" "$UTILS_PATH/ReturnYouTubeDislikePatch;"
var targetIndex: Int = 0
private lateinit var targetReference: FieldReference
} }
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind) private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
@ -119,4 +156,13 @@ class ReturnYouTubeDislikePatch : BytecodePatch(
DISLIKE(-1), DISLIKE(-1),
REMOVE_LIKE(0) REMOVE_LIKE(0)
} }
private fun MutableMethod.insertShorts(index: Int, register: Int) {
addInstructions(
index, """
invoke-static {v$register}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onShortsComponentCreated(Landroid/text/Spanned;)Landroid/text/Spanned;
move-result-object v$register
"""
)
}
} }

View File

@ -3,17 +3,10 @@ package app.revanced.patches.youtube.video.quality.bytecode.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object VideoQualitySetterFingerprint : MethodFingerprint( object VideoQualitySetterFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL, access = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("[L", "I", "I", "Z", "I"), parameters = listOf("L"),
opcodes = listOf( strings = listOf("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT")
Opcode.IF_EQZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IPUT_BOOLEAN,
)
) )

View File

@ -0,0 +1,17 @@
package app.revanced.patches.youtube.video.quality.bytecode.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object VideoQualitySettingsFingerprint : MethodFingerprint(
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT
)
)

View File

@ -0,0 +1,12 @@
package app.revanced.patches.youtube.video.quality.bytecode.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object VideoQualitySettingsParentFingerprint : MethodFingerprint(
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("[L", "I", "Z"),
strings = listOf("menu_item_video_quality")
)

View File

@ -3,16 +3,9 @@ package app.revanced.patches.youtube.video.quality.bytecode.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
object VideoUserQualityChangeFingerprint : MethodFingerprint( object VideoUserQualityChangeFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.FINAL, access = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L","L","I","J"), customFingerprint = { it.name == "onItemClick" }
opcodes = listOf(
Opcode.MOVE,
Opcode.MOVE_WIDE,
Opcode.INVOKE_INTERFACE_RANGE,
Opcode.RETURN_VOID
)
) )

View File

@ -13,9 +13,7 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patches.shared.annotation.YouTubeCompatibility import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.youtube.misc.videoid.legacy.patch.LegacyVideoIdPatch import app.revanced.patches.youtube.misc.videoid.legacy.patch.LegacyVideoIdPatch
import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoQualityReferenceFingerprint import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.*
import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoQualitySetterFingerprint
import app.revanced.patches.youtube.video.quality.bytecode.fingerprints.VideoUserQualityChangeFingerprint
import app.revanced.util.integrations.Constants.VIDEO_PATH import app.revanced.util.integrations.Constants.VIDEO_PATH
import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.FieldReference import org.jf.dexlib2.iface.reference.FieldReference
@ -26,36 +24,44 @@ import org.jf.dexlib2.iface.reference.FieldReference
@Version("0.0.1") @Version("0.0.1")
class VideoQualityBytecodePatch : BytecodePatch( class VideoQualityBytecodePatch : BytecodePatch(
listOf( listOf(
VideoQualitySetterFingerprint VideoQualitySetterFingerprint,
VideoQualitySettingsParentFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext): PatchResult { override fun execute(context: BytecodeContext): PatchResult {
VideoQualitySetterFingerprint.result?.let { parentResult -> VideoQualitySetterFingerprint.result?.let { parentResult ->
VideoQualityReferenceFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result -> VideoQualityReferenceFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result ->
val instructions = result.method.implementation!!.instructions val instructions = result.method.implementation!!.instructions
val qualityFieldReference =
qualityFieldReference =
(instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference (instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference
val qIndexMethodName = qIndexMethodName =
context.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name context.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name
parentResult.mutableMethod.addInstructions(
0, """
iget-object v0, p0, ${result.classDef.type}->${qualityFieldReference.name}:${qualityFieldReference.type}
const-string v1, "$qIndexMethodName"
invoke-static {p1, p2, v0, v1}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I
move-result p2
""",
)
} ?: return VideoQualityReferenceFingerprint.toErrorResult() } ?: return VideoQualityReferenceFingerprint.toErrorResult()
VideoUserQualityChangeFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.addInstruction( VideoUserQualityChangeFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.addInstruction(
0, 0,
"invoke-static {p3}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userChangedQuality(I)V" "invoke-static {p3}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userChangedQuality(I)V"
) ?: return VideoUserQualityChangeFingerprint.toErrorResult() ) ?: return VideoUserQualityChangeFingerprint.toErrorResult()
} ?: return VideoQualitySetterFingerprint.toErrorResult() } ?: return VideoQualitySetterFingerprint.toErrorResult()
VideoQualitySettingsParentFingerprint.result?.let { parentResult ->
VideoQualitySettingsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.let {
relayFieldReference = (it.implementation!!.instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference
} ?: return VideoQualitySettingsFingerprint.toErrorResult()
parentResult.mutableMethod.addInstructions(
0, """
iget-object v0, p0, ${parentResult.classDef.type}->${relayFieldReference.name}:${relayFieldReference.type}
iget-object v1, v0, ${relayFieldReference.type}->${qualityFieldReference.name}:${qualityFieldReference.type}
const-string v2, "$qIndexMethodName"
invoke-static {p1, p2, v1, v2}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I
move-result p2
"""
)
} ?: return VideoQualitySettingsParentFingerprint.toErrorResult()
LegacyVideoIdPatch.injectCall("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V") LegacyVideoIdPatch.injectCall("$INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
return PatchResultSuccess() return PatchResultSuccess()
@ -63,5 +69,11 @@ class VideoQualityBytecodePatch : BytecodePatch(
private companion object { private companion object {
const val INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR = const val INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR =
"$VIDEO_PATH/VideoQualityPatch;" "$VIDEO_PATH/VideoQualityPatch;"
private lateinit var qIndexMethodName: String
private lateinit var relayFieldReference: FieldReference
private lateinit var qualityFieldReference: FieldReference
} }
} }