perf(resource-mapping): map resources with multiple threads

This commit is contained in:
oSumAtrIX 2022-09-26 04:12:09 +02:00
parent fddd61fe54
commit a7e4da018b
12 changed files with 99 additions and 65 deletions

View File

@ -14,7 +14,7 @@ import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.spotify.premium_navbar_tab.annotations.PremiumNavbarTabCompatibility
import app.revanced.patches.spotify.premium_navbar_tab.fingerprints.AddPremiumNavbarTabFingerprint
import app.revanced.patches.spotify.premium_navbar_tab.fingerprints.AddPremiumNavbarTabParentFingerprint
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
@ -23,7 +23,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
@Description("Removes the premium tab from the navbar.")
@PremiumNavbarTabCompatibility
@Version("0.0.1")
@DependsOn([ResourceIdMappingProviderResourcePatch::class])
@DependsOn([ResourceMappingResourcePatch::class])
class PremiumNavbarTabPatch : BytecodePatch(
listOf(
AddPremiumNavbarTabParentFingerprint
@ -39,7 +39,7 @@ class PremiumNavbarTabPatch : BytecodePatch(
val methodInstructions = method.implementation!!.instructions
val lastInstructionIdx = methodInstructions.size - 1
val premiumTabId = ResourceIdMappingProviderResourcePatch.resourceMappings.single{it.type == "id" && it.name == "premium_tab"}.id
val premiumTabId = ResourceMappingResourcePatch.resourceMappings.single{it.type == "id" && it.name == "premium_tab"}.id
var removeAmount = 2
// 2nd const remove method

View File

@ -22,7 +22,7 @@ import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensi
import app.revanced.patches.youtube.ad.general.bytecode.extensions.MethodExtensions.toDescriptor
import app.revanced.patches.youtube.ad.general.bytecode.utils.MethodUtils.createMutableMethod
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
@ -41,7 +41,7 @@ import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
@Patch
@DependsOn([ResourceIdMappingProviderResourcePatch::class, IntegrationsPatch::class, SettingsPatch::class])
@DependsOn([ResourceMappingResourcePatch::class, IntegrationsPatch::class, SettingsPatch::class])
@Name("general-ads")
@Description("Removes general ads.")
@GeneralAdsCompatibility
@ -61,7 +61,7 @@ class GeneralBytecodeAdsPatch : BytecodePatch() {
"promoted_video_item_land",
"promoted_video_item_full_bleed",
).map { name ->
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.name == name }.id
ResourceMappingResourcePatch.resourceMappings.single { it.name == name }.id
}
private val stringReferences = arrayOf(

View File

@ -15,7 +15,7 @@ import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayBu
import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.AutoNavInformerFingerprint
import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.LayoutConstructorFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
@ -25,7 +25,7 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
import org.jf.dexlib2.iface.reference.MethodReference
@Patch
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, ResourceIdMappingProviderResourcePatch::class])
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, ResourceMappingResourcePatch::class])
@Name("hide-autoplay-button")
@Description("Hides the autoplay button in the video player.")
@AutoplayButtonCompatibility
@ -53,7 +53,7 @@ class HideAutoplayButtonPatch : BytecodePatch(
val layoutGenMethodInstructions = layoutGenMethod.implementation!!.instructions
// resolve the offsets such as ...
val autoNavPreviewStubId = ResourceIdMappingProviderResourcePatch.resourceMappings.single {
val autoNavPreviewStubId = ResourceMappingResourcePatch.resourceMappings.single {
it.name == "autonav_preview_stub"
}.id
// where to insert the branch instructions and ...

View File

@ -18,13 +18,13 @@ import app.revanced.patches.youtube.layout.pivotbar.createbutton.annotations.Cre
import app.revanced.patches.youtube.layout.pivotbar.createbutton.fingerprints.PivotBarCreateButtonViewFingerprint
import app.revanced.patches.youtube.layout.pivotbar.fingerprints.PivotBarFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference
@Patch
@DependsOn([IntegrationsPatch::class, ResourceIdMappingProviderResourcePatch::class, SettingsPatch::class])
@DependsOn([IntegrationsPatch::class, ResourceMappingResourcePatch::class, SettingsPatch::class])
@Name("hide-create-button")
@Description("Hides the create button in the navigation bar.")
@CreateButtonCompatibility

View File

@ -22,7 +22,7 @@ import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlock
import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.*
import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
import app.revanced.patches.youtube.misc.videoid.patch.VideoIdPatch
import app.revanced.patches.youtube.layout.autocaptions.fingerprints.StartVideoInformerFingerprint
@ -178,9 +178,9 @@ class SponsorBlockBytecodePatch : BytecodePatch(
val controlsMethodResult = PlayerControlsBytecodePatch.showPlayerControlsFingerprintResult
val controlsLayoutStubResourceId =
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "controls_layout_stub" }.id
ResourceMappingResourcePatch.resourceMappings.single { it.type == "id" && it.name == "controls_layout_stub" }.id
val zoomOverlayResourceId =
ResourceIdMappingProviderResourcePatch.resourceMappings.single { it.type == "id" && it.name == "video_zoom_overlay_stub" }.id
ResourceMappingResourcePatch.resourceMappings.single { it.type == "id" && it.name == "video_zoom_overlay_stub" }.id
methods@ for (method in controlsMethodResult.mutableClass.methods) {
val instructions = method.implementation?.instructions!!

View File

@ -9,7 +9,7 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.impl.ResourcePatch
import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference
import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource
@ -20,7 +20,7 @@ import app.revanced.util.resources.ResourceUtils.copyXmlNode
@Name("sponsorblock-resource-patch")
@SponsorBlockCompatibility
@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class, ResourceIdMappingProviderResourcePatch::class])
@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class, ResourceMappingResourcePatch::class])
@Version("0.0.1")
class SponsorBlockResourcePatch : ResourcePatch() {
companion object {
@ -107,7 +107,7 @@ class SponsorBlockResourcePatch : ResourcePatch() {
}
}.close() // close afterwards
reelButtonGroupResourceId = ResourceIdMappingProviderResourcePatch.resourceMappings.single {
reelButtonGroupResourceId = ResourceMappingResourcePatch.resourceMappings.single {
it.type == "id" && it.name == "reel_persistent_edu_button_group"
}.id

View File

@ -15,6 +15,7 @@ import app.revanced.patches.youtube.misc.customplaybackspeed.fingerprints.SpeedA
import app.revanced.patches.youtube.misc.customplaybackspeed.fingerprints.SpeedLimiterFingerprint
import app.revanced.patches.youtube.misc.customplaybackspeed.fingerprints.VideoSpeedPatchFingerprint
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import org.jf.dexlib2.builder.instruction.BuilderArrayPayload
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@ -27,7 +28,7 @@ import kotlin.math.roundToInt
@Patch
@Name("custom-playback-speed")
@Description("Adds more video playback speed options.")
@DependsOn([IntegrationsPatch::class])
@DependsOn([IntegrationsPatch::class, ResourceMappingResourcePatch::class])
@CustomPlaybackSpeedCompatibility
@Version("0.0.1")
class CustomPlaybackSpeedPatch : BytecodePatch(

View File

@ -1,40 +0,0 @@
package app.revanced.patches.youtube.misc.mapping.patch
import app.revanced.extensions.doRecursively
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.ResourceData
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.impl.ResourcePatch
import org.w3c.dom.Element
@Name("resource-id-mapping-provider-resource-patch-dependency")
@Description("Acts as a provider/dependency for resource mappings.")
@Version("0.0.1")
class ResourceIdMappingProviderResourcePatch : ResourcePatch() {
companion object {
internal lateinit var resourceMappings: List<ResourceElement>
private set
}
override fun execute(data: ResourceData): PatchResult {
data.xmlEditor["res/values/public.xml"].use { editor ->
resourceMappings = buildList {
editor.file.documentElement.doRecursively { node ->
if (node !is Element) return@doRecursively
val nameAttribute = node.getAttribute("name")
val typeAttribute = node.getAttribute("type")
if (node.nodeName != "public" || nameAttribute.startsWith("APKTOOL")) return@doRecursively
val id = node.getAttribute("id").substring(2).toLong(16)
add(ResourceElement(typeAttribute, nameAttribute, id))
}
}
}
return PatchResultSuccess()
}
}
data class ResourceElement(val type: String, val name: String, val id: Long)

View File

@ -0,0 +1,73 @@
package app.revanced.patches.youtube.misc.mapping.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.impl.ResourceData
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.impl.ResourcePatch
import org.w3c.dom.Element
import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
@Name("resource-mapping")
@Description("Creates a map of public resources.")
@Version("0.0.1")
class ResourceMappingResourcePatch : ResourcePatch() {
companion object {
internal lateinit var resourceMappings: List<ResourceElement>
private set
private val THREAD_COUNT = Runtime.getRuntime().availableProcessors()
private val threadPoolExecutor = Executors.newFixedThreadPool(THREAD_COUNT)
}
override fun execute(data: ResourceData): PatchResult {
// save the file in memory to concurrently read from
val resourceXmlFile = data["res/values/public.xml"].readBytes()
// create a synchronized list to store the resource mappings
val mappings = Collections.synchronizedList(mutableListOf<ResourceElement>())
for (threadIndex in 0 until THREAD_COUNT) {
threadPoolExecutor.execute thread@{
data.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) {
// make sure to not to go out of bounds when rounding errors occur at calculating the jobSize
if (i >= resourcesLength) return@thread
val node = resources.item(i)
if (node !is Element) continue
val nameAttribute = node.getAttribute("name")
val typeAttribute = node.getAttribute("type")
if (node.nodeName != "public" || nameAttribute.startsWith("APKTOOL")) continue
val id = node.getAttribute("id").substring(2).toLong(16)
mappings.add(ResourceElement(typeAttribute, nameAttribute, id))
}
}
}
}
threadPoolExecutor
.also { it.shutdown() }
.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)
resourceMappings = mappings
return PatchResultSuccess()
}
}
data class ResourceElement(val type: String, val name: String, val id: Long)

View File

@ -11,14 +11,14 @@ import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility
import app.revanced.patches.youtube.misc.playercontrols.fingerprints.BottomControlsInflateFingerprint
import app.revanced.patches.youtube.misc.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Name("player-controls-bytecode-patch")
@DependsOn([ResourceIdMappingProviderResourcePatch::class])
@DependsOn([ResourceMappingResourcePatch::class])
@Description("Manages the code for the player controls of the YouTube player.")
@PlayerControlsCompatibility
@Version("0.0.1")
@ -28,7 +28,7 @@ class PlayerControlsBytecodePatch : BytecodePatch(
override fun execute(data: BytecodeData): PatchResult {
showPlayerControlsFingerprintResult = PlayerControlsVisibilityFingerprint.result!!
bottomUiContainerResourceId = ResourceIdMappingProviderResourcePatch
bottomUiContainerResourceId = ResourceMappingResourcePatch
.resourceMappings
.single { it.type == "id" && it.name == "bottom_ui_container_stub" }.id

View File

@ -13,7 +13,7 @@ import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.impl.BytecodePatch
import app.revanced.patcher.util.smali.toInstruction
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.LicenseActivityFingerprint
import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ReVancedSettingsActivityFingerprint
@ -94,7 +94,7 @@ class SettingsPatch : BytecodePatch(
internal companion object {
// TODO: hide this somehow
var appearanceStringId: Long = ResourceIdMappingProviderResourcePatch.resourceMappings.find {
var appearanceStringId: Long = ResourceMappingResourcePatch.resourceMappings.find {
it.type == "string" && it.name == "app_theme_appearance_dark"
}!!.id

View File

@ -9,7 +9,7 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.impl.ResourcePatch
import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceIdMappingProviderResourcePatch
import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch
import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference
@ -22,7 +22,7 @@ import java.io.Closeable
@Name("settings-resource-patch")
@SettingsCompatibility
@DependsOn([FixLocaleConfigErrorPatch::class, ResourceIdMappingProviderResourcePatch::class])
@DependsOn([FixLocaleConfigErrorPatch::class, ResourceMappingResourcePatch::class])
@Version("0.0.1")
class SettingsResourcePatch : ResourcePatch(), Closeable {