diff --git a/src/main/kotlin/app/revanced/patches/all/misc/transformation/AbstractTransformInstructionsPatch.kt b/src/main/kotlin/app/revanced/patches/all/misc/transformation/AbstractTransformInstructionsPatch.kt index 71699f1983..a4c447e9dc 100644 --- a/src/main/kotlin/app/revanced/patches/all/misc/transformation/AbstractTransformInstructionsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/all/misc/transformation/AbstractTransformInstructionsPatch.kt @@ -10,7 +10,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction @Suppress("MemberVisibilityCanBePrivate") abstract class AbstractTransformInstructionsPatch : BytecodePatch() { - abstract fun filterMap( classDef: ClassDef, method: Method, diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/PlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/PlaybackSpeedPatch.kt index 3f7c17e7b4..6a73e60fcf 100644 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/PlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/PlaybackSpeedPatch.kt @@ -1,49 +1,82 @@ package app.revanced.patches.tiktok.interaction.speed import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.tiktok.interaction.speed.fingerprints.SpeedControlParentFingerprint +import app.revanced.patches.tiktok.interaction.speed.fingerprints.GetSpeedFingerprint +import app.revanced.patches.tiktok.interaction.speed.fingerprints.OnRenderFirstFrameFingerprint +import app.revanced.patches.tiktok.interaction.speed.fingerprints.SetSpeedFingerprint import app.revanced.util.exception +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11x import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( name = "Playback speed", - description = "Enables the playback speed option for all videos.", + description = "Enables the playback speed option for all videos and " + + "retains the speed configurations in between videos.", compatiblePackages = [ CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]), CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"]) ] ) @Suppress("unused") -object PlaybackSpeedPatch : BytecodePatch(setOf(SpeedControlParentFingerprint)) { +object PlaybackSpeedPatch : BytecodePatch( + setOf( + GetSpeedFingerprint, + OnRenderFirstFrameFingerprint, + SetSpeedFingerprint + ) +) { override fun execute(context: BytecodeContext) { - SpeedControlParentFingerprint.result?.mutableMethod?.apply { - val targetMethodCallIndex = indexOfFirstInstruction { - if (opcode == Opcode.INVOKE_STATIC) { - val paramsTypes = ((this as Instruction35c).reference as MethodReference).parameterTypes - paramsTypes.size == 1 && paramsTypes[0].contains("/Aweme;") - } else false - } + SetSpeedFingerprint.result?.let { onVideoSwiped -> + // Remember the playback speed of the current video. + GetSpeedFingerprint.result?.mutableMethod?.apply { + val injectIndex = indexOfFirstInstruction { getReference()?.returnType == "F" } + 2 + val register = getInstruction(injectIndex - 1).registerA - val isSpeedEnableMethod = context - .toMethodWalker(this) - .nextMethod(targetMethodCallIndex, true) - .getMethod() as MutableMethod + addInstruction( + injectIndex, + "invoke-static { v$register }," + + " Lapp/revanced/tiktok/speed/SpeedPatch;->rememberPlaybackSpeed(F)V" + ) + } ?: throw GetSpeedFingerprint.exception - isSpeedEnableMethod.addInstructions( + // By default, the playback speed will reset to 1.0 at the start of each video. + // Instead, override it with the desired playback speed. + OnRenderFirstFrameFingerprint.result?.mutableMethod?.addInstructions( 0, """ - const/4 v0, 0x1 - return v0 + # Video playback location (e.g. home page, following page or search result page) retrieved using getEnterFrom method. + const/4 v0, 0x1 + invoke-virtual {p0, v0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getEnterFrom(Z)Ljava/lang/String; + move-result-object v0 + + # Model of current video retrieved using getCurrentAweme method. + invoke-virtual {p0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getCurrentAweme()Lcom/ss/android/ugc/aweme/feed/model/Aweme; + move-result-object v1 + + # Desired playback speed retrieved using getPlaybackSpeed method. + invoke-static {}, Lapp/revanced/tiktok/speed/SpeedPatch;->getPlaybackSpeed()F + move-result-object v2 + invoke-static { v0, v1, v2 }, ${onVideoSwiped.method} + """ + ) ?: throw OnRenderFirstFrameFingerprint.exception + + // Force enable the playback speed option for all videos. + onVideoSwiped.mutableClass.methods.find { method -> method.returnType == "Z" }?.addInstructions( + 0, """ - ) - } ?: throw SpeedControlParentFingerprint.exception + const/4 v0, 0x1 + return v0 + """ + ) ?: throw PatchException("Failed to force enable the playback speed option.") + } ?: throw SetSpeedFingerprint.exception } -} \ No newline at end of file +} diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/GetSpeedFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/GetSpeedFingerprint.kt new file mode 100644 index 0000000000..f9845d4dc7 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/GetSpeedFingerprint.kt @@ -0,0 +1,9 @@ +package app.revanced.patches.tiktok.interaction.speed.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +internal object GetSpeedFingerprint : MethodFingerprint( + customFingerprint = { methodDef, _ -> + methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onFeedSpeedSelectedEvent" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/OnRenderFirstFrameFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/OnRenderFirstFrameFingerprint.kt new file mode 100644 index 0000000000..59f930efea --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/OnRenderFirstFrameFingerprint.kt @@ -0,0 +1,9 @@ +package app.revanced.patches.tiktok.interaction.speed.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +internal object OnRenderFirstFrameFingerprint : MethodFingerprint( + customFingerprint = { methodDef, _ -> + methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onRenderFirstFrame" + } +) diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SetSpeedFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SetSpeedFingerprint.kt new file mode 100644 index 0000000000..97e566b97a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SetSpeedFingerprint.kt @@ -0,0 +1,16 @@ +package app.revanced.patches.tiktok.interaction.speed.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + +internal object SetSpeedFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, + parameters = listOf( + "Ljava/lang/String;", + "Lcom/ss/android/ugc/aweme/feed/model/Aweme;", + "F" + ), + strings = listOf("enterFrom") +) diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt deleted file mode 100644 index 7edae32e14..0000000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.tiktok.interaction.speed.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -internal object SpeedControlParentFingerprint : MethodFingerprint( - strings = listOf( - "onStopTrackingTouch, hasTouchMove=", - ", isCurVideoPaused: ", - "already_shown_edge_speed_guide" - ) -) \ No newline at end of file