From 0b090583286b8f6c3104b3e00a08aa3c7d0abc9b Mon Sep 17 00:00:00 2001 From: inotia00 Date: Sun, 30 Jul 2023 08:46:51 +0900 Subject: [PATCH] feat(youtube): add support version `v18.29.38` --- .../patch/ButtonContainerPatch.kt | 3 +- ...tchWhileActivityWithInFlagsFingerprint.kt} | 2 +- ...tchWhileActivityWithOutFlagsFingerprint.kt | 37 ++++++++ .../patch/NewSplashAnimationPatch.kt | 94 ++++++++++++++++--- .../patch/HideFilmstripOverlayPatch.kt | 55 +++++++---- .../utils/annotations/YouTubeCompatibility.kt | 3 +- .../utils/litho/patch/LithoFilterPatch.kt | 2 +- .../resourceid/patch/SharedResourceIdPatch.kt | 2 + .../settings/resource/patch/SettingsPatch.kt | 11 ++- 9 files changed, 167 insertions(+), 42 deletions(-) rename src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/{SplashAnimationBuilderFingerprint.kt => WatchWhileActivityWithInFlagsFingerprint.kt} (87%) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/WatchWhileActivityWithOutFlagsFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/buttomplayer/buttoncontainer/patch/ButtonContainerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/buttomplayer/buttoncontainer/patch/ButtonContainerPatch.kt index c1fe4224e..37cbe1f38 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/buttomplayer/buttoncontainer/patch/ButtonContainerPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/buttomplayer/buttoncontainer/patch/ButtonContainerPatch.kt @@ -12,7 +12,6 @@ import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility import app.revanced.patches.youtube.utils.litho.patch.LithoFilterPatch import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch -import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch.Companion.belowAndroid1820 import app.revanced.util.integrations.Constants.PATCHES_PATH @Patch @@ -29,7 +28,7 @@ import app.revanced.util.integrations.Constants.PATCHES_PATH class ButtonContainerPatch : ResourcePatch { override fun execute(context: ResourceContext): PatchResult { - if (belowAndroid1820) { + if (SettingsPatch.below1820) { LithoFilterPatch.addFilter("$PATCHES_PATH/ads/ActionButtonsFilter;") SettingsPatch.addPreference( arrayOf( diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/SplashAnimationBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/WatchWhileActivityWithInFlagsFingerprint.kt similarity index 87% rename from src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/SplashAnimationBuilderFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/WatchWhileActivityWithInFlagsFingerprint.kt index 7a4bf9660..f20ea5aa2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/SplashAnimationBuilderFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/WatchWhileActivityWithInFlagsFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.youtube.misc.splashanimation.fingerprints import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.util.bytecode.isWide32LiteralExists -object SplashAnimationBuilderFingerprint : MethodFingerprint( +object WatchWhileActivityWithInFlagsFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("Landroid/os/Bundle;"), customFingerprint = { methodDef, _ -> diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/WatchWhileActivityWithOutFlagsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/WatchWhileActivityWithOutFlagsFingerprint.kt new file mode 100644 index 000000000..135266846 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/fingerprints/WatchWhileActivityWithOutFlagsFingerprint.kt @@ -0,0 +1,37 @@ +package app.revanced.patches.youtube.misc.splashanimation.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.utils.resourceid.patch.SharedResourceIdPatch.Companion.DarkSplashAnimation +import app.revanced.util.bytecode.isWideLiteralExists +import com.android.tools.smali.dexlib2.Opcode + +object WatchWhileActivityWithOutFlagsFingerprint : MethodFingerprint( + returnType = "V", + parameters = listOf("Landroid/os/Bundle;"), + opcodes = listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.CONST_4, + Opcode.CONST_4, + Opcode.IF_NE, // target + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, // target + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ // target + ), + customFingerprint = { methodDef, _ -> + methodDef.definingClass.endsWith("/WatchWhileActivity;") + && methodDef.name == "onCreate" + && methodDef.isWideLiteralExists(DarkSplashAnimation) + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/patch/NewSplashAnimationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/patch/NewSplashAnimationPatch.kt index 280531295..82d13b93c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/patch/NewSplashAnimationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/splashanimation/patch/NewSplashAnimationPatch.kt @@ -1,6 +1,5 @@ package app.revanced.patches.youtube.misc.splashanimation.patch -import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version @@ -9,44 +8,79 @@ 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.PatchResult +import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.splashanimation.fingerprints.SplashAnimationBuilderFingerprint +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.youtube.misc.splashanimation.fingerprints.WatchWhileActivityWithInFlagsFingerprint +import app.revanced.patches.youtube.misc.splashanimation.fingerprints.WatchWhileActivityWithOutFlagsFingerprint import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility +import app.revanced.patches.youtube.utils.resourceid.patch.SharedResourceIdPatch +import app.revanced.patches.youtube.utils.resourceid.patch.SharedResourceIdPatch.Companion.DarkSplashAnimation import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch import app.revanced.util.bytecode.getWide32LiteralIndex +import app.revanced.util.bytecode.getWideLiteralIndex import app.revanced.util.integrations.Constants.MISC_PATH import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @Patch @Name("Enable new splash animation") @Description("Enables a new type of splash animation on Android 12+ devices.") -@DependsOn([SettingsPatch::class]) +@DependsOn( + [ + SettingsPatch::class, + SharedResourceIdPatch::class + ] +) @YouTubeCompatibility @Version("0.0.1") class NewSplashAnimationPatch : BytecodePatch( - listOf(SplashAnimationBuilderFingerprint) + listOf( + WatchWhileActivityWithInFlagsFingerprint, + WatchWhileActivityWithOutFlagsFingerprint + ) ) { override fun execute(context: BytecodeContext): PatchResult { - SplashAnimationBuilderFingerprint.result?.let { + WatchWhileActivityWithInFlagsFingerprint.result + ?: WatchWhileActivityWithOutFlagsFingerprint.result + ?: throw PatchResultError("Failed to resolve fingerprints") + + /** + * ~YouTube v18.27.36 + */ + WatchWhileActivityWithInFlagsFingerprint.result?.let { it.mutableMethod.apply { var targetIndex = getWide32LiteralIndex(45407550) + 3 if (getInstruction(targetIndex).opcode == Opcode.MOVE_RESULT) targetIndex += 1 - val targetRegister = getInstruction(targetIndex).registerA - - addInstructions( - targetIndex, """ - invoke-static {}, $MISC_PATH/SplashAnimationPatch;->enableNewSplashAnimation()Z - move-result v$targetRegister - """ - ) + inject(targetIndex) } - } ?: return SplashAnimationBuilderFingerprint.toErrorResult() + } + + /** + * YouTube v18.28.xx~ + */ + WatchWhileActivityWithOutFlagsFingerprint.result?.let { + it.mutableMethod.apply { + for (index in getWideLiteralIndex(DarkSplashAnimation) - 1 downTo 0) { + if (getInstruction(index).opcode != Opcode.IF_EQZ) + continue + + arrayOf( + index, + index - 8, + index - 14 + ).forEach { insertIndex -> inject(insertIndex) } + + break + } + } + } /** * Add settings @@ -61,4 +95,36 @@ class NewSplashAnimationPatch : BytecodePatch( return PatchResultSuccess() } + companion object { + fun MutableMethod.inject( + index: Int + ) { + if (getInstruction(index).opcode == Opcode.IF_NE) + injectInt(index) + else + injectBoolean(index) + } + + private fun MutableMethod.injectBoolean(index: Int) { + val register = getInstruction(index).registerA + + addInstructions( + index, """ + invoke-static {}, $MISC_PATH/SplashAnimationPatch;->enableNewSplashAnimationBoolean()Z + move-result v$register + """ + ) + } + + private fun MutableMethod.injectInt(index: Int) { + val register = getInstruction(index).registerA + + addInstructions( + index, """ + invoke-static {}, $MISC_PATH/SplashAnimationPatch;->enableNewSplashAnimationInt()I + move-result v$register + """ + ) + } + } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/filmstripoverlay/patch/HideFilmstripOverlayPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/filmstripoverlay/patch/HideFilmstripOverlayPatch.kt index 93f508c4a..0c6c9fb85 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/filmstripoverlay/patch/HideFilmstripOverlayPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/filmstripoverlay/patch/HideFilmstripOverlayPatch.kt @@ -5,7 +5,6 @@ import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve @@ -77,36 +76,52 @@ class HideFilmstripOverlayPatch : BytecodePatch( val jumpIndex = setOnClickListenerIndex + 3 val initialIndex = setOnClickListenerIndex - 1 - val fixRegister = getInstruction(initialIndex).registerE - var fixValue = 12 - var isFound = false - for (index in initialIndex downTo insertIndex) { - if (getInstruction(index).opcode != Opcode.CONST_16) continue + if (SettingsPatch.upward1828) { + for (index in insertIndex .. initialIndex) { + if (getInstruction(index).opcode != Opcode.CONST_16 && getInstruction(index).opcode != Opcode.CONST) continue - val register = getInstruction(index).registerA + val register = getInstruction(index).registerA + val value = getInstruction(index).wideLiteral.toInt() - if (register != fixRegister) continue + val line = + when (getInstruction(index).opcode) { + Opcode.CONST_16 -> """ + const/16 v$register, $value + + """.trimIndent() + Opcode.CONST -> """ + const v$register, $value + + """.trimIndent() + else -> "" + } - fixValue = getInstruction(index).wideLiteral.toInt() - isFound = true - break + fixComponent += line + } + } else { + val fixRegister = getInstruction(initialIndex).registerE + + for (index in initialIndex downTo insertIndex) { + if (getInstruction(index).opcode != Opcode.CONST_16) continue + + val register = getInstruction(index).registerA + + if (register != fixRegister) continue + + val fixValue = getInstruction(index).wideLiteral.toInt() + fixComponent = "const/16 v$fixRegister, $fixValue" + break + } } addInstructionsWithLabels( - insertIndex, """ + insertIndex, fixComponent + """ invoke-static {}, $PLAYER->hideFilmstripOverlay()Z move-result v$insertRegister if-nez v$insertRegister, :hidden """, ExternalLabel("hidden", getInstruction(jumpIndex)) ) - - if (isFound) { - addInstruction( - insertIndex, - "const/16 v$fixRegister, $fixValue" - ) - } } } ?: return YouTubeControlsOverlayFingerprint.toErrorResult() @@ -127,6 +142,8 @@ class HideFilmstripOverlayPatch : BytecodePatch( } private companion object { + var fixComponent: String = "" + fun MutableMethod.injectHook() { addInstructionsWithLabels( 0, """ diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/annotations/YouTubeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/annotations/YouTubeCompatibility.kt index 70bd9a265..3552844b0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/annotations/YouTubeCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/annotations/YouTubeCompatibility.kt @@ -12,7 +12,8 @@ import app.revanced.patcher.annotation.Package "18.23.36", "18.24.37", "18.25.40", - "18.27.36" + "18.27.36", + "18.29.38" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/litho/patch/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/litho/patch/LithoFilterPatch.kt index 026ad6797..efb5c7775 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/litho/patch/LithoFilterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/litho/patch/LithoFilterPatch.kt @@ -45,7 +45,7 @@ class LithoFilterPatch : BytecodePatch( "sput-object p0, $ADS_PATH/LowLevelFilter;->byteBuffer:Ljava/nio/ByteBuffer;" ) ?: return ByteBufferFingerprint.toErrorResult() - if (SettingsPatch.belowAndroid1820) + if (SettingsPatch.below1820) legacyHook("$ADS_PATH/LithoFilterPatch;->filters") else generalHook("$ADS_PATH/LithoFilterPatch;->filters") diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/patch/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/patch/SharedResourceIdPatch.kt index bcc7c3056..f66f618f2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/patch/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/resourceid/patch/SharedResourceIdPatch.kt @@ -36,6 +36,7 @@ class SharedResourceIdPatch : ResourcePatch { var CompactLink: Long = -1 var ControlsLayoutStub: Long = -1 var CoreContainer: Long = -1 + var DarkSplashAnimation: Long = -1 var DislikeButton: Long = -1 var DonationCompanion: Long = -1 var EasySeekEduContainer: Long = -1 @@ -108,6 +109,7 @@ class SharedResourceIdPatch : ResourcePatch { CompactLink = find(LAYOUT, "compact_link") ControlsLayoutStub = find(ID, "controls_layout_stub") CoreContainer = find(ID, "core_container") + DarkSplashAnimation = find(ID, "dark_splash_animation") DislikeButton = find(ID, "dislike_button") DonationCompanion = find(LAYOUT, "donation_companion") EasySeekEduContainer = find(ID, "easy_seek_edu_container") diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/resource/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/resource/patch/SettingsPatch.kt index 917500e4b..355b436f8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/settings/resource/patch/SettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/settings/resource/patch/SettingsPatch.kt @@ -70,10 +70,12 @@ class SettingsPatch : AbstractSettingsResourcePatch( if (node.nodeName != "integer" || !node.getAttribute("name") .startsWith("google_play_services_version") - ) - continue + ) continue - belowAndroid1820 = node.textContent.toInt() <= 232100000 + val playServicesVersion = node.textContent.toInt() + + below1820 = playServicesVersion <= 232100000 + upward1828 = playServicesVersion >= 232900000 break } @@ -182,7 +184,8 @@ class SettingsPatch : AbstractSettingsResourcePatch( private val threadPoolExecutor = Executors.newFixedThreadPool(THREAD_COUNT) internal lateinit var contexts: ResourceContext - internal var belowAndroid1820: Boolean = false + internal var below1820: Boolean = false + internal var upward1828: Boolean = false internal fun addPreference(settingArray: Array) { contexts.addPreference(settingArray)