mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2024-11-10 09:07:46 +01:00
fix(spotify/disable-capture-restriction): dynamically find indices (#759)
This commit is contained in:
parent
0299a87e67
commit
ee8cda5a4c
3 changed files with 50 additions and 17 deletions
|
@ -8,46 +8,79 @@ import app.revanced.patcher.extensions.instruction
|
||||||
import app.revanced.patcher.extensions.replaceInstruction
|
import app.revanced.patcher.extensions.replaceInstruction
|
||||||
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.patcher.util.proxy.mutableTypes.MutableMethod
|
|
||||||
import app.revanced.patches.spotify.audio.annotation.DisableCaptureRestrictionCompatibility
|
import app.revanced.patches.spotify.audio.annotation.DisableCaptureRestrictionCompatibility
|
||||||
import app.revanced.patches.spotify.audio.fingerprints.DisableCaptureRestrictionAudioDriverFingerprint
|
import app.revanced.patches.spotify.audio.fingerprints.DisableCaptureRestrictionAudioDriverFingerprint
|
||||||
import app.revanced.patches.spotify.audio.resource.patch.DisableCaptureRestrictionResourcePatch
|
import app.revanced.patches.spotify.audio.resource.patch.DisableCaptureRestrictionResourcePatch
|
||||||
import org.jf.dexlib2.iface.instruction.Instruction
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
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.reference.MethodReference
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@Name("disable-capture-restriction")
|
@Name("disable-capture-restriction")
|
||||||
@DependsOn([DisableCaptureRestrictionResourcePatch::class])
|
@DependsOn([DisableCaptureRestrictionResourcePatch::class])
|
||||||
@Description("Allows capturing Spotify's audio output while screen sharing or screen recording.")
|
@Description("Allows capturing Spotify's audio output while screen sharing or screen recording.")
|
||||||
@DisableCaptureRestrictionCompatibility
|
@DisableCaptureRestrictionCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.2")
|
||||||
class DisableCaptureRestrictionBytecodePatch : BytecodePatch(
|
class DisableCaptureRestrictionBytecodePatch : BytecodePatch(
|
||||||
listOf(
|
listOf(
|
||||||
DisableCaptureRestrictionAudioDriverFingerprint
|
DisableCaptureRestrictionAudioDriverFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
private fun MutableMethod.replaceConstant4Instruction(index: Int, instruction: Instruction, with: Int) {
|
|
||||||
val register = (instruction as OneRegisterInstruction).registerA
|
|
||||||
this.replaceInstruction(
|
|
||||||
index, "const/4 v$register, $with"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
val method = DisableCaptureRestrictionAudioDriverFingerprint.result!!.mutableMethod
|
val method = DisableCaptureRestrictionAudioDriverFingerprint.result!!.mutableMethod
|
||||||
|
|
||||||
// Replace constant that contains the capture policy parameter for AudioAttributesBuilder.setAllowedCapturePolicy()
|
var invokePosition: Int? = null
|
||||||
val instruction = method.instruction(CONST_INSTRUCTION_POSITION)
|
var invokeParamRegister: Int? = null
|
||||||
method.replaceConstant4Instruction(CONST_INSTRUCTION_POSITION, instruction, ALLOW_CAPTURE_BY_ALL)
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
// Find INVOKE_VIRTUAL opcode with call to AudioAttributesBuilder.setAllowedCapturePolicy(I)
|
||||||
|
for ((index, instruction) in method.implementation!!.instructions.withIndex()) {
|
||||||
|
if(instruction.opcode != Opcode.INVOKE_VIRTUAL)
|
||||||
|
continue
|
||||||
|
|
||||||
|
val methodName = ((instruction as ReferenceInstruction).reference as MethodReference).name
|
||||||
|
if (methodName != "setAllowedCapturePolicy")
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Store register of the integer parameter for setAllowedCapturePolicy
|
||||||
|
invokeParamRegister = (instruction as FiveRegisterInstruction).registerD
|
||||||
|
invokePosition = index
|
||||||
|
}
|
||||||
|
|
||||||
|
if(invokePosition == null || invokeParamRegister == null)
|
||||||
|
return PatchResultError("Cannot find setAllowedCapturePolicy method call")
|
||||||
|
|
||||||
|
// Walk back to the const/4 instruction that sets the parameter register
|
||||||
|
var matchFound = false
|
||||||
|
for (index in invokePosition downTo 0) {
|
||||||
|
val instruction = method.instruction(index)
|
||||||
|
if(instruction.opcode != Opcode.CONST_4)
|
||||||
|
continue
|
||||||
|
|
||||||
|
val register = (instruction as OneRegisterInstruction).registerA
|
||||||
|
if(register != invokeParamRegister)
|
||||||
|
continue
|
||||||
|
|
||||||
|
// Replace parameter value
|
||||||
|
method.replaceInstruction(
|
||||||
|
index, "const/4 v$register, $ALLOW_CAPTURE_BY_ALL"
|
||||||
|
)
|
||||||
|
matchFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (matchFound)
|
||||||
|
PatchResultSuccess()
|
||||||
|
else
|
||||||
|
PatchResultError("Const instruction not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val CONST_INSTRUCTION_POSITION = 2
|
|
||||||
const val ALLOW_CAPTURE_BY_ALL = 0x01
|
const val ALLOW_CAPTURE_BY_ALL = 0x01
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,7 +9,7 @@ import app.revanced.patches.spotify.audio.annotation.DisableCaptureRestrictionCo
|
||||||
@Name("disable-capture-restriction-audio-driver-fingerprint")
|
@Name("disable-capture-restriction-audio-driver-fingerprint")
|
||||||
|
|
||||||
@DisableCaptureRestrictionCompatibility
|
@DisableCaptureRestrictionCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.2")
|
||||||
object DisableCaptureRestrictionAudioDriverFingerprint : MethodFingerprint(
|
object DisableCaptureRestrictionAudioDriverFingerprint : MethodFingerprint(
|
||||||
customFingerprint = { methodDef ->
|
customFingerprint = { methodDef ->
|
||||||
methodDef.definingClass == "Lcom/spotify/playback/playbacknative/AudioDriver;" && methodDef.name == "constructAudioAttributes"
|
methodDef.definingClass == "Lcom/spotify/playback/playbacknative/AudioDriver;" && methodDef.name == "constructAudioAttributes"
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.w3c.dom.Element
|
||||||
@Name("disable-capture-restriction-resource-patch")
|
@Name("disable-capture-restriction-resource-patch")
|
||||||
@Description("Sets allowAudioPlaybackCapture in manifest to true.")
|
@Description("Sets allowAudioPlaybackCapture in manifest to true.")
|
||||||
@DisableCaptureRestrictionCompatibility
|
@DisableCaptureRestrictionCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.2")
|
||||||
class DisableCaptureRestrictionResourcePatch : ResourcePatch {
|
class DisableCaptureRestrictionResourcePatch : ResourcePatch {
|
||||||
override fun execute(context: ResourceContext): PatchResult {
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
// create an xml editor instance
|
// create an xml editor instance
|
||||||
|
|
Loading…
Reference in a new issue