From 6346699d8dbda70738ec1b814d7a6c3de200885e Mon Sep 17 00:00:00 2001 From: inotia00 Date: Tue, 11 Jul 2023 21:44:21 +0900 Subject: [PATCH] feat(youtube/hide-button-container): changed to expose 'Experimental Flags' on YouTube v18.20.39 https://github.com/inotia00/ReVanced_Extended/issues/1103 --- .../patch/litho/ComponentParserPatch.kt | 25 +++++++---- .../patch/ButtonContainerPatch.kt | 11 +++++ .../utils/litho/patch/LithoFilterPatch.kt | 10 ++++- .../settings/resource/patch/SettingsPatch.kt | 41 +++++++++++++++++++ .../youtube/settings/xml/revanced_prefs.xml | 10 +++++ 5 files changed, 87 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/shared/patch/litho/ComponentParserPatch.kt b/src/main/kotlin/app/revanced/patches/shared/patch/litho/ComponentParserPatch.kt index f0f92bd46..8e29bf5e9 100644 --- a/src/main/kotlin/app/revanced/patches/shared/patch/litho/ComponentParserPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/patch/litho/ComponentParserPatch.kt @@ -44,6 +44,9 @@ class ComponentParserPatch : BytecodePatch( EmptyComponentBuilderFingerprint.result?.let { it.mutableMethod.apply { + val byteBufferClassIndex = it.scanResult.patternScanResult!!.startIndex + byteBufferClassLabel = getInstruction(byteBufferClassIndex).reference.toString() + val targetIndex = getStringIndex("Failed to convert Element to Flatbuffers: %s") + 2 val builderMethodDescriptor = getInstruction(targetIndex).reference @@ -120,6 +123,7 @@ class ComponentParserPatch : BytecodePatch( } internal companion object { + lateinit var byteBufferClassLabel: String lateinit var emptyComponentLabel: String lateinit var insertMethod: MutableMethod @@ -163,18 +167,23 @@ class ComponentParserPatch : BytecodePatch( } } - fun objectHook( + // only for YouTube v18.20.39 + fun legacyHook( descriptor: String ) { insertMethod.apply { addInstructionsWithLabels( - 0, """ - move-object/from16 v0, p2 - sget-object v1, $definingClass->buffer:Ljava/nio/ByteBuffer; - invoke-static {v0, v1}, $descriptor(Ljava/lang/Object;Ljava/nio/ByteBuffer;)Z - move-result v0 - if-eqz v0, :unfiltered - """ + emptyComponentLabel, ExternalLabel("unfiltered", getInstruction(0)) + insertIndex, + """ + move-object/from16 v$freeRegister, p3 + iget-object v$freeRegister, v$freeRegister, ${parameters[2]}->b:Ljava/lang/Object; + if-eqz v$freeRegister, :unfiltered + check-cast v$freeRegister, $byteBufferClassLabel + iget-object v$freeRegister, v$freeRegister, $byteBufferClassLabel->b:Ljava/nio/ByteBuffer; + invoke-static {v$stringBuilderRegister, v$identifierRegister, v$objectRegister, v$freeRegister}, $descriptor(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/lang/Object;Ljava/nio/ByteBuffer;)Z + move-result v$freeRegister + if-eqz v$freeRegister, :unfiltered + """ + emptyComponentLabel, ExternalLabel("unfiltered", getInstruction(insertIndex)) ) } } 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 d3f5d4c7b..34aaea812 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,6 +12,7 @@ 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 @@ -28,6 +29,16 @@ import app.revanced.util.integrations.Constants.PATCHES_PATH class ButtonContainerPatch : ResourcePatch { override fun execute(context: ResourceContext): PatchResult { + if (belowAndroid1820) { + LithoFilterPatch.addFilter("$PATCHES_PATH/ads/ActionButtonsFilter;") + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE: BOTTOM_PLAYER_SETTINGS", + "SETTINGS: EXPERIMENTAL_BUTTON_CONTAINER" + ) + ) + } + LithoFilterPatch.addFilter("$PATCHES_PATH/ads/ButtonsFilter;") /** 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 153c04fcb..026ad6797 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 @@ -13,17 +13,20 @@ import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patches.shared.patch.litho.ComponentParserPatch import app.revanced.patches.shared.patch.litho.ComponentParserPatch.Companion.generalHook +import app.revanced.patches.shared.patch.litho.ComponentParserPatch.Companion.legacyHook import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility import app.revanced.patches.youtube.utils.litho.fingerprints.ByteBufferFingerprint import app.revanced.patches.youtube.utils.litho.fingerprints.LithoFilterFingerprint import app.revanced.patches.youtube.utils.playertype.patch.PlayerTypeHookPatch +import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch import app.revanced.util.integrations.Constants.ADS_PATH import java.io.Closeable @DependsOn( [ ComponentParserPatch::class, - PlayerTypeHookPatch::class + PlayerTypeHookPatch::class, + SettingsPatch::class ] ) @YouTubeCompatibility @@ -42,7 +45,10 @@ class LithoFilterPatch : BytecodePatch( "sput-object p0, $ADS_PATH/LowLevelFilter;->byteBuffer:Ljava/nio/ByteBuffer;" ) ?: return ByteBufferFingerprint.toErrorResult() - generalHook("$ADS_PATH/LithoFilterPatch;->filters") + if (SettingsPatch.belowAndroid1820) + legacyHook("$ADS_PATH/LithoFilterPatch;->filters") + else + generalHook("$ADS_PATH/LithoFilterPatch;->filters") LithoFilterFingerprint.result?.mutableMethod?.apply { removeInstructions(2, 4) // Remove dummy filter. 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 24565db90..6d1e2d580 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 @@ -24,6 +24,8 @@ import app.revanced.util.resources.ResourceUtils.copyResources import org.w3c.dom.Element import java.io.File import java.nio.file.Paths +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit @Patch @Name("settings") @@ -46,6 +48,41 @@ class SettingsPatch : AbstractSettingsResourcePatch( super.execute(context) contexts = context + /** + * Check if the YouTube version is v18.20.39 + */ + val resourceXmlFile = context["res/values/integers.xml"].readBytes() + + for (threadIndex in 0 until THREAD_COUNT) { + threadPoolExecutor.execute thread@{ + context.xmlEditor[resourceXmlFile.inputStream()].use { editor -> + val resources = editor.file.documentElement.childNodes + val resourcesLength = resources.length + val jobSize = resourcesLength / THREAD_COUNT + + val batchStart = jobSize * threadIndex + val batchEnd = jobSize * (threadIndex + 1) + element@ for (i in batchStart until batchEnd) { + if (i >= resourcesLength) return@thread + + val node = resources.item(i) + if (node !is Element) continue + + if (node.nodeName != "integer" || !node.getAttribute("name").startsWith("google_play_services_version")) + continue + + belowAndroid1820 = node.textContent.toInt() <= 232100000 + + break + } + } + } + } + + threadPoolExecutor + .also { it.shutdown() } + .awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS) + /** * create directory for the untranslated language resources */ @@ -139,7 +176,11 @@ class SettingsPatch : AbstractSettingsResourcePatch( } companion object { + private val THREAD_COUNT = Runtime.getRuntime().availableProcessors() + private val threadPoolExecutor = Executors.newFixedThreadPool(THREAD_COUNT) + internal lateinit var contexts: ResourceContext + internal var belowAndroid1820: Boolean = false internal fun addPreference(settingArray: Array) { contexts.addPreference(settingArray) diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml index e4ec9ca61..7a7480428 100644 --- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml +++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml @@ -38,6 +38,16 @@ SETTINGS: BUTTON_CONTAINER --> + + +