diff --git a/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/Fingerprints.kt index ac3a1c43a5..0232dc82a3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/Fingerprints.kt @@ -2,18 +2,11 @@ package app.revanced.patches.primevideo.ads import app.revanced.patcher.fingerprint import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode internal val enterServerInsertedAdBreakStateFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC) parameters("Lcom/amazon/avod/fsm/Trigger;") returns("V") - opcodes( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_4, - Opcode.CONST_4 - ) custom { method, classDef -> method.name == "enter" && classDef.type == "Lcom/amazon/avod/media/ads/internal/state/ServerInsertedAdBreakState;" } @@ -22,12 +15,19 @@ internal val enterServerInsertedAdBreakStateFingerprint = fingerprint { internal val doTriggerFingerprint = fingerprint { accessFlags(AccessFlags.PROTECTED) returns("V") - opcodes( - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.RETURN_VOID - ) custom { method, classDef -> method.name == "doTrigger" && classDef.type == "Lcom/amazon/avod/fsm/StateBase;" } +} + +internal val onSeekPastUnwatchedAdFingerprint = fingerprint { + custom {method, classDef -> + method.name == "onSeekPastUnwatchedAd" && classDef.endsWith("SeekbarControllerImpl;") + } +} + +internal val onSeekBehindUnwatchedAdFingerprint = fingerprint { + custom {method, classDef -> + method.name == "onSeekBehindUnwatchedAd" && classDef.endsWith("SeekbarControllerImpl;") + } } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/SkipAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/SkipAdsPatch.kt index c204c729e2..1b51dd9175 100644 --- a/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/SkipAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/primevideo/ads/SkipAdsPatch.kt @@ -4,15 +4,18 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.primevideo.misc.extension.sharedExtensionPatch +import app.revanced.util.* import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") val skipAdsPatch = bytecodePatch( name = "Skip ads", description = "Automatically skips video stream ads.", ) { - compatibleWith("com.amazon.avod.thirdpartyclient"("3.0.412.2947")) + compatibleWith("com.amazon.avod.thirdpartyclient"("3.0.430.1747")) dependsOn(sharedExtensionPatch) @@ -22,24 +25,30 @@ val skipAdsPatch = bytecodePatch( // Force doTrigger() access to public so we can call it from our extension. doTriggerFingerprint.method.accessFlags = AccessFlags.PUBLIC.value; - val getPlayerIndex = enterServerInsertedAdBreakStateFingerprint.patternMatch!!.startIndex enterServerInsertedAdBreakStateFingerprint.method.apply { // Get register that stores VideoPlayer: // invoke-virtual ->getPrimaryPlayer() // move-result-object { playerRegister } - val playerRegister = getInstruction(getPlayerIndex + 1).registerA + val playerIndex = indexOfFirstInstructionOrThrow() { + opcode == Opcode.INVOKE_VIRTUAL && getReference()?.name == "getPrimaryPlayer" + } + val playerRegister = getInstruction(playerIndex + 1).registerA // Reuse the params from the original method: // p0 = ServerInsertedAdBreakState // p1 = AdBreakTrigger addInstructions( - getPlayerIndex + 2, + playerIndex + 2, """ invoke-static { p0, p1, v$playerRegister }, Lapp/revanced/extension/primevideo/ads/SkipAdsPatch;->enterServerInsertedAdBreakState(Lcom/amazon/avod/media/ads/internal/state/ServerInsertedAdBreakState;Lcom/amazon/avod/media/ads/internal/state/AdBreakTrigger;Lcom/amazon/avod/media/playback/VideoPlayer;)V return-void """ ) } + + // Return early from these callbacks to prevent unwanted overlays from ad breaks. + onSeekBehindUnwatchedAdFingerprint.method.returnEarly() + onSeekPastUnwatchedAdFingerprint.method.returnEarly() } }