2022-08-14 17:32:32 +02:00
|
|
|
package app.revanced.patches.youtube.layout.tabletminiplayer.patch
|
|
|
|
|
2023-08-27 04:26:14 +02:00
|
|
|
import app.revanced.extensions.toErrorResult
|
2022-08-14 17:32:32 +02:00
|
|
|
import app.revanced.patcher.annotation.Description
|
|
|
|
import app.revanced.patcher.annotation.Name
|
2022-10-05 04:03:10 +02:00
|
|
|
import app.revanced.patcher.data.BytecodeContext
|
2023-06-07 03:46:13 +02:00
|
|
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
2022-08-14 17:32:32 +02:00
|
|
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
2022-09-21 04:11:16 +02:00
|
|
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
2022-10-05 04:03:10 +02:00
|
|
|
import app.revanced.patcher.patch.BytecodePatch
|
2023-08-27 04:26:14 +02:00
|
|
|
import app.revanced.patcher.patch.PatchResult
|
|
|
|
import app.revanced.patcher.patch.PatchResultError
|
|
|
|
import app.revanced.patcher.patch.PatchResultSuccess
|
2022-08-14 17:32:32 +02:00
|
|
|
import app.revanced.patcher.patch.annotations.DependsOn
|
|
|
|
import app.revanced.patcher.patch.annotations.Patch
|
|
|
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
2023-02-22 06:06:53 +01:00
|
|
|
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
|
|
|
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
2022-08-14 17:32:32 +02:00
|
|
|
import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility
|
2023-08-27 04:26:14 +02:00
|
|
|
import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.*
|
2022-08-14 17:32:32 +02:00
|
|
|
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
2022-08-22 03:58:04 +02:00
|
|
|
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
2023-08-27 04:26:14 +02:00
|
|
|
import org.jf.dexlib2.Opcode
|
|
|
|
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
2022-08-14 17:32:32 +02:00
|
|
|
|
|
|
|
@Patch
|
2022-08-22 03:58:04 +02:00
|
|
|
@DependsOn([IntegrationsPatch::class, SettingsPatch::class])
|
2023-07-10 20:02:05 +02:00
|
|
|
@Name("Tablet mini player")
|
2022-08-14 17:32:32 +02:00
|
|
|
@Description("Enables the tablet mini player layout.")
|
|
|
|
@TabletMiniPlayerCompatibility
|
|
|
|
class TabletMiniPlayerPatch : BytecodePatch(
|
|
|
|
listOf(
|
2023-06-28 15:43:45 +02:00
|
|
|
MiniPlayerDimensionsCalculatorParentFingerprint,
|
2023-03-19 23:24:31 +01:00
|
|
|
MiniPlayerResponseModelSizeCheckFingerprint,
|
2023-08-27 04:26:14 +02:00
|
|
|
MiniPlayerOverrideParentFingerprint
|
2022-08-14 17:32:32 +02:00
|
|
|
)
|
|
|
|
) {
|
2023-08-27 04:26:14 +02:00
|
|
|
override fun execute(context: BytecodeContext): PatchResult {
|
2022-10-05 04:03:10 +02:00
|
|
|
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
|
|
|
SwitchPreference(
|
|
|
|
"revanced_tablet_miniplayer",
|
2023-02-22 06:06:53 +01:00
|
|
|
StringResource("revanced_tablet_miniplayer_title", "Enable tablet mini player"),
|
|
|
|
StringResource("revanced_tablet_miniplayer_summary_on", "Mini player is enabled"),
|
|
|
|
StringResource("revanced_tablet_miniplayer_summary_off", "Mini player is disabled")
|
2022-10-05 04:03:10 +02:00
|
|
|
)
|
|
|
|
)
|
2022-08-22 03:58:04 +02:00
|
|
|
|
2023-03-19 23:24:31 +01:00
|
|
|
// First resolve the fingerprints via the parent fingerprint.
|
2023-08-27 04:26:14 +02:00
|
|
|
MiniPlayerDimensionsCalculatorParentFingerprint.result ?: return MiniPlayerDimensionsCalculatorParentFingerprint.toErrorResult()
|
2023-06-28 15:43:45 +02:00
|
|
|
val miniPlayerClass = MiniPlayerDimensionsCalculatorParentFingerprint.result!!.classDef
|
2022-08-14 17:32:32 +02:00
|
|
|
|
|
|
|
/*
|
2023-03-19 23:24:31 +01:00
|
|
|
* No context parameter method.
|
2022-08-14 17:32:32 +02:00
|
|
|
*/
|
2022-10-05 04:03:10 +02:00
|
|
|
MiniPlayerOverrideNoContextFingerprint.resolve(context, miniPlayerClass)
|
2022-08-14 17:32:32 +02:00
|
|
|
val (method, _, parameterRegister) = MiniPlayerOverrideNoContextFingerprint.addProxyCall()
|
2023-03-19 23:24:31 +01:00
|
|
|
|
|
|
|
// Insert right before the return instruction.
|
2022-08-14 17:32:32 +02:00
|
|
|
val secondInsertIndex = method.implementation!!.instructions.size - 1
|
2023-03-19 23:24:31 +01:00
|
|
|
method.insertOverride(
|
|
|
|
secondInsertIndex, parameterRegister
|
|
|
|
/** same register used to return **/
|
|
|
|
)
|
2022-08-14 17:32:32 +02:00
|
|
|
|
2023-08-27 04:26:14 +02:00
|
|
|
/*
|
|
|
|
* Method with context parameter.
|
|
|
|
*/
|
|
|
|
MiniPlayerOverrideParentFingerprint.result?.let {
|
|
|
|
if (!MiniPlayerOverrideFingerprint.resolve(context, it.classDef))
|
|
|
|
throw MiniPlayerOverrideFingerprint.toErrorResult()
|
|
|
|
} ?: return MiniPlayerOverrideParentFingerprint.toErrorResult()
|
|
|
|
|
2023-05-02 03:36:17 +02:00
|
|
|
/*
|
|
|
|
* Override every return instruction with the proxy call.
|
|
|
|
*/
|
2023-08-27 04:26:14 +02:00
|
|
|
MiniPlayerOverrideFingerprint.result!!.mutableMethod.apply {
|
|
|
|
implementation!!.let { implementation ->
|
|
|
|
val returnIndices = implementation.instructions
|
|
|
|
.withIndex()
|
|
|
|
.filter { (_, instruction) -> instruction.opcode == Opcode.RETURN }
|
|
|
|
.map { (index, _) -> index }
|
2023-05-02 03:36:17 +02:00
|
|
|
|
2023-08-27 04:26:14 +02:00
|
|
|
if (returnIndices.isEmpty()) throw PatchResultError("No return instructions found.")
|
2023-05-02 03:36:17 +02:00
|
|
|
|
2023-08-27 04:26:14 +02:00
|
|
|
// This method clobbers register p0 to return the value, calculate to override.
|
|
|
|
val returnedRegister = implementation.registerCount - parameters.size
|
2023-05-02 03:36:17 +02:00
|
|
|
|
2023-08-27 04:26:14 +02:00
|
|
|
// Hook the returned register on every return instruction.
|
|
|
|
returnIndices.forEach { index -> insertOverride(index, returnedRegister) }
|
2023-05-02 03:36:17 +02:00
|
|
|
}
|
2023-08-27 04:26:14 +02:00
|
|
|
}
|
2023-05-02 03:36:17 +02:00
|
|
|
|
2022-08-14 17:32:32 +02:00
|
|
|
/*
|
2023-03-19 23:24:31 +01:00
|
|
|
* Size check return value override.
|
2022-08-14 17:32:32 +02:00
|
|
|
*/
|
2023-03-19 23:24:31 +01:00
|
|
|
MiniPlayerResponseModelSizeCheckFingerprint.addProxyCall()
|
2023-08-27 04:26:14 +02:00
|
|
|
|
|
|
|
return PatchResultSuccess()
|
2022-08-14 17:32:32 +02:00
|
|
|
}
|
|
|
|
|
2023-03-19 23:24:31 +01:00
|
|
|
// Helper methods.
|
2022-08-14 17:32:32 +02:00
|
|
|
private companion object {
|
|
|
|
fun MethodFingerprint.addProxyCall(): Triple<MutableMethod, Int, Int> {
|
|
|
|
val (method, scanIndex, parameterRegister) = this.unwrap()
|
|
|
|
method.insertOverride(scanIndex, parameterRegister)
|
|
|
|
|
|
|
|
return Triple(method, scanIndex, parameterRegister)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun MutableMethod.insertOverride(index: Int, overrideRegister: Int) {
|
|
|
|
this.addInstructions(
|
|
|
|
index,
|
|
|
|
"""
|
|
|
|
invoke-static {v$overrideRegister}, Lapp/revanced/integrations/patches/TabletMiniPlayerOverridePatch;->getTabletMiniPlayerOverride(Z)Z
|
|
|
|
move-result v$overrideRegister
|
2023-06-07 03:46:13 +02:00
|
|
|
"""
|
2022-08-14 17:32:32 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun MethodFingerprint.unwrap(): Triple<MutableMethod, Int, Int> {
|
|
|
|
val result = this.result!!
|
2022-09-21 04:11:16 +02:00
|
|
|
val scanIndex = result.scanResult.patternScanResult!!.endIndex
|
2022-08-14 17:32:32 +02:00
|
|
|
val method = result.mutableMethod
|
|
|
|
val instructions = method.implementation!!.instructions
|
|
|
|
val parameterRegister = (instructions[scanIndex] as OneRegisterInstruction).registerA
|
|
|
|
|
|
|
|
return Triple(method, scanIndex, parameterRegister)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|